3

次の問題に遭遇しました:

Delphi プログラムから OLE を介して Excel を自動化し、セルの NumberFormat プロパティを設定しようとすると、Excel はローカライズされた形式の形式文字列を想定しています。

通常、Excel でマクロを記録して書式を確認する場合、Excel は次のように想定しています: Cells(1, 2).NumberFormat = "#,##0.00"

つまり、桁区切り記号は「,」で、小数点記号は「.」です。

実際には、ローカライズ版の Excel を使用しています。私のロケールでは、千単位の区切り記号は " " で、小数点記号は "," です。

したがって、私の Delphi プログラムから NumberFormat を設定するときはいつでも、「# ##0,00」のように指定する必要があります。

私の質問は次のとおりです。プログラムでこれらの値をハードコードすると、英語または別のローカライズ版の Excel でプログラムを使用すると例外が発生することは明らかです。NumberFormat プロパティを設定する「普遍的な」方法はありますか? (デフォルトの英語ロケールを使用していますか?)

ありがとう!

更新:このページでより洗練された方法を見つけました: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=920&mode=print ロシア語です (私も話せません)。しかし、コードは簡単に理解できます。

4

3 に答える 3

4

Excel には、次の 2 つのフィールドがあります。

  • NumberFormat

  • NumberFormatLocal

NumberFormat は、米国標準では常にロケール不変の形式を取り、NumberFormatLocal は、設定されたロケールでの形式を想定しています。

例えば

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

ドイツ語の設定 (10 進数 sep: および 1000 sep: .) を使用すると、$A$1 および $A$4 の正しい書式設定された数値が得られます。ウィンドウの地域設定を好きなように変更して試してみると、フォーマットが機能している場合はテストできます。

Delphi 5 を使用していて、次のように Excel を起動するコードがあると仮定します (そして、ComObj.pas にアクセスできます)。

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.DispatchInvoke を呼び出す ComObj.VarDispInvoke を経由します。そこには、3 番目のパラメーターとして lcid を取得する Dispatch.Invoke への呼び出しがあります。これは 0 に設定されています。これへのコメントの最初のリンクに示されている手法を使用して、独自のユニットを作成し、ComObj からすべてのコードを独自のユニットにコピーする (または ComObj を直接変更する) ことができます。ユニットの初期化で VarDispProc 変数を設定することを忘れないでください。最後の部分はすべての場合に機能するとは限りません (おそらくモジュールの順序に依存します) が、コードで変数を設定できます。

 VarDispProc := @VarDispInvoke;

ここで、VarDispInvoke を ComObj コピー モジュールのインターフェイス セクションに配置する必要があります。最初のリンクのコードは、上記の Delphi サンプルでは呼び出されていない別のメソッドを変更しているため、直接は機能しません。
また、numberformat 呼び出しのロケールを変更するだけで十分です (副作用を避けるため)。
上記の例と説明されている変更は、私のドイツ語の Excel の正解で機能します。変更または DispCallLocaleId への呼び出しがなければ、あなたが説明したのと同じ問題が発生します。

于 2012-06-08T11:46:07.163 に答える