How to correctly set NumberFormat property when automating different localized versions of Excel
我遇到了以下问题:
从我的Delphi程序中通过OLE自动执行Excel并尝试设置单元格的NumberFormat属性时,Excel期望格式字符串为本地化格式。
通常,当通过在Excel中记录宏来检查格式时,Excel期望这样:
单元格(1,2).NumberFormat ="#,## 0.00"
这意味着千位分隔符为",",十进制分隔符为"。"。
实际上,我使用的是Excel的本地化版本。在我的语言环境中,千位分隔符为"",十进制分隔符为","。
因此,每当从我的Delphi程序中设置NumberFormat时,我都需要将其指定为"### 0,00"。
我的问题是:显然,如果我在程序中对这些值进行硬编码,当我的程序与英语或其他本地化版本的Excel一起使用时,将会出现异常。有没有一种通用的方式来设置NumberFormat属性? (使用默认的英语语言环境吗?)
谢谢!
更新:我在此页面上找到了一种更优雅的方法:
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=920
在Excel中,您有两个字段:
-
NumberFormat
-
NumberFormatLocal
NumberFormat采用美国标准中的区域设置始终为不变的格式,而NumberFormatLocal期望使用具有设置区域设置的格式。
例如
1 2 3 4 5 6 7 8 9 10 11 | Sub test() Dim r As Range Set r = ActiveWorkbook.ActiveSheet.Range("$A$1") r.NumberFormat ="#,##0.00" Set r = ActiveWorkbook.ActiveSheet.Range("$A$2") r.NumberFormat ="#.##0,00" Set r = ActiveWorkbook.ActiveSheet.Range("$A$3") r.NumberFormatLocal ="#,##0.00" Set r = ActiveWorkbook.ActiveSheet.Range("$A$4") r.NumberFormatLocal ="#.##0,00" End Sub |
使用德语设置(十进制Sep:和一千Sep:。)可以为$ A $ 1和$ A $ 4提供正确的格式化数字。如果您将Windows中的区域设置更改为所需的任何设置,则可以对其进行测试,如果格式化有效,则可以尝试。
假设您使用的是Delphi 5,并具有如下代码来启动Excel(并可以访问ComObj.pas):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | var oXL, oWB, oSheet : Variant; LocaleId : Integer; begin oXL := CreateOleObject('Excel.Application'); oXL.Visible := True; oWB := oXL.Workbooks.Add; oSheet := oWB.ActiveSheet; oSheet.Range['$A$1'].NumberFormatLocal := '#.##0,00'; oSheet.Range['$A$2'].NumberFormatLocal := '#,##0.00'; LocaleID:= DispCallLocaleID($0409); try oSheet.Range['$A$3'].NumberFormat := '#.##0,00'; oSheet.Range['$A$4'].NumberFormat := '#,##0.00'; finally DispCallLocaleId( LocaleId); end; end; |
然后默认情况下,每个调用都通过ComObj.VarDispInvoke进行调用,该ComObj.DispatchInvoke。在那里您找到对Dispatch.Invoke的调用,该调用将第三个参数作为lcid。设置为0。您可以使用注释的第一个链接中显示的技术来创建您自己的单元,并将所有代码从ComObj复制到您自己的单元(或直接修改ComObj)。只是不要忘记在单元初始化中设置VarDispProc变量。最后一部分似乎在所有情况下都不起作用(可能取决于模块的顺序),但是您可以在代码中设置变量:
1 | VarDispProc := @VarDispInvoke; |
必须将VarDispInvoke放置在ComObj复制模块的接口部分中。
第一个链接的代码无法直接工作,因为它修改了上面的Delphi示例中未调用的其他方法。
并足以更改numberformat调用的语言环境(以避免产生副作用)。
上面的示例以及描述的修改适用于我的德语excel正确。如果不进行修改或不调用DispCallLocaleId,我将看到与您描述的问题相同的问题。
您也可以直接设置属性值
1 2 | SetDispatchPropValue(oSheet, 'Range['$A$1'].NumberFormatLocal',$0409); |
您可以让excel管理此选项,以避免其他系统出现差异:
1 | .....NumberFormat :='#'+Excel.ThousandsSeparator+'##0'+Excel.DecimalSeparator+'00'; |