International date formatting issues in OLE Excel output

大城市里の小女人 提交于 2019-12-22 12:56:17

问题


In a product I am currently working with Excel spreadsheets are generated using OLE from Delphi. The spreadsheets include a number of dates where the application loads the shortdate format from the system settings and applies this to the cells. This works perfectly except when the system formats are set to one of at least Russian, Bashkir, Tatar, Yakut, Kazak and Uzbek (there may be others I have not tried).

The code is-

xlws.Cells[irow,icol] := ActivityData.Target_Date;
xlvalidrange := xlws.Range[xlws.Cells[irow,icol],xlws.Cells[irow,icol]];
xlvalidrange.NumberFormat:= LocShortDateFormat;

In this case (whilst debugging) the ActivityData.Target_Date is 41192, which is the format that Excel stores dates and times, with LocShortDateFormat equal to 'dd.MM.yyyy'. This matches the store date format shown in Windows for Russian and is retrieved programmatically using the code-

LocShortDateFormat := ShortDateFormat;

Opening the spreadsheet with this format shows the message-

Excel found unreadable content in Spreadsheet.xlsx Do you want to recover the contents of this workbook?

Doing this the data is shown simply as the number 41192 with NO format in the cell. Even more curiously, manually applying the format string of 'dd.MM.yyyy' then shows 'dd.MM.yyyy' in the cell in place of the data.

The same applies for any of the standard date/time string formatting characters. The data can be manually changed to a date format by selecting the "Date" category and a corresponding type as the format and then displays correctly, so this isn't an issue of the data, rather the format string.

The formatting string used by Excel when manually selecting the correct date format is ДД.ММ.ГГГГ - manually changing the formatting string used whilst debugging produces the correct output in the generated spreadsheet and the unreadable content message disappears.

Oddly Chinese, Japanese, Serbian and Macendonian (as a sample of non English character set languages) all do work with the standard date/time formatting characters.

In Excel itself the standard characters don't seem to function normally even when the spreadsheet is new and has not been created programmatically, i.e. new spreadsheet created from within the Excel application.

This being the case, it seems not to be a Delphi or Windows problem (C# Windows forms had no problem correctly formatting dates using the standard characters even with the Russian locale), but it still leaves the problem of how to get return the correct formatting strings within Delphi.

I'm not keen on doing a series of conditional "if" statements testing for locales known to be problematic, but this seems to be the only way to deal with the problem based on the research I have done so far.

Is there any way to ask Excel to use the local date formatting via OLE without providing a formatting string, or to get the strings Excel uses to format dates in that localisation in order to provide the string in the correct format?


回答1:


Yes, you can get the various internationalization/localization characters and strings using the International property on the Excel application instance. Late bound example:

function GetExcel_International(const aExcel: OleVariant; const aIndex: Integer): string;
begin
  try
    Result := aExcel.International[aIndex];
  except
    ...
  end;
end;

We use it to get the various characters that make up the formatting strings:

ExcelYearCharacter := GetExcel_International(FExcelApplication, xlYearCode);
ExcelMonthCharacter := GetExcel_International(FExcelApplication, xlMonthCode);
ExcelDayCharacter := GetExcel_International(FExcelApplication, xlDayCode);
ExcelHourCharacter := GetExcel_International(FExcelApplication, xlHourCode);
ExcelMinuteCharacter := GetExcel_International(FExcelApplication, xlMinuteCode);

We then use these to convert from the Windows to the Excel format:

function ConvertWindowsLocalDateStringToExcel(const aString: string): string;
begin
  Result := StringReplace(aString, UpperCase(WindowsYearCharacter),
            UpperCase(ExcelYearCharacter), [rfReplaceAll]);
  Result := StringReplace(Result, LowerCase(WindowsYearCharacter),
            LowerCase(ExcelYearCharacter), [rfReplaceAll]);

  Result := StringReplace(Result, UpperCase(WindowsMonthCharacter),
            UpperCase(ExcelMonthCharacter), [rfReplaceAll]);
  Result := StringReplace(Result, LowerCase(WindowsMonthCharacter),
            LowerCase(ExcelMonthCharacter), [rfReplaceAll]);

  Result := StringReplace(Result, UpperCase(WindowsDayCharacter),
            UpperCase(ExcelDayCharacter), [rfReplaceAll]);
  Result := StringReplace(Result, LowerCase(WindowsDayCharacter),
            LowerCase(ExcelDayCharacter), [rfReplaceAll]);
end;

All the xl... constants come from one of our own units, but you should be able to find them in the early bound Delphi OLE server wrappers as well. For example in the ExcelXP unit in the ...\OCX\Servers folder of your Delphi / RAD Studio installation.

More information about the Application.International property can be found at: http://msdn.microsoft.com/en-us/library/office/bb177675(v=office.12).aspx




回答2:


My Solution was as follows :

First I make a var of type TDate. Then I fill the var from the table and afterwards I insert it, like so:

var
  tReportDate : TDate;

....<br><br>
    tReportDate := FieldByName('DateReport').AsDateTime;<br>
    ExcelApp.Cells[StartColumnid, 1].Value := tReportDate;

This solved my case. It was for an international project and used by all kind of locations.

Hopes this can help.



来源:https://stackoverflow.com/questions/16946077/international-date-formatting-issues-in-ole-excel-output

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!