1

序章

VS2008、xlw 2.0、Excel 2003 で開発されたレガシー プラグイン プロジェクト (C++) を継承しました。

私はそれを xlw 4.0 ヘッダーに移植することができました (Excel 2007 のサポートが追加されたときに、一部のメソッドの名前が変更されました)。古いコードは手で書かれたものであり、機能しているものを変更するつもりはなく、合理的な構造とコード ロジックをそのためだけに持っているため、(まだ) 何も生成していません。

このコードは、Excel 2003 で期待どおりに動作します。今日、Excel 2010 で試してみたところ、非常に不可解な (そして恐ろしい) バグが見つかりました。

不可解な行動

XlfOper & として (VBA マクロから) 数値 (n 行、1 列) の列 (構成による小さな正の整数) を受け取り、それを (古いスタイルの) 配列に変換したいと考えています。コードは基本的に各行を通過し、指定された行に対応する XlfOper で AsInt() メソッドを呼び出します。何かのようなもの:

for (long iy = 0; iy < numcols; ++iy)
{
for (long ix = 0; ix < numrows; ++ix)
    convertXflOper( x(ix, iy), a1D[iy*numrows + ix] ); 
}

ここで、a1D はこの特定のプロジェクトで使用される 1 次元配列型で、convertXflOper はこれらの型用のテンプレート関数です。

void convertXflOper (const XlfOper &x, long & y)
{
    y = x.AsInt();
}

特定の行で、Excel ワークブックに番号 10 があります。

Excel 2003 では、これは 10 に変換されます。Excel 2010 では、これは 9 に変換されます。

私はそれをデバッグしましたが、問題は実際には 10 ではなく、2 倍の近似値を読み取っていることです。(即時ウィンドウの)出力は

x.lpxloper4_->val.num
9.9999999999999982 // wrong: I am not asking for 10.0, I am asking for 10

Excel 2010、および

x.lpxloper4_->val.num
10.000000000000000 // right: an integer is an integer

Excel 2003 で。つまり、C++ コードは、きれいな (またはそうでない) とはいえ、問題はないようです。AsInt() メソッドはキャストのように動作し、static_cast<long>(9.9999999999999982)10 ではなく 9 です。

質問

このことは、主に見落としがちだったため、私をひどく悩ませました.他の多くの整数値については、Excel 2003 と 2010 の両方で正しく機能します。

整数を double として扱う必要があると考えているという点で、Excel インターフェイスで何が間違っていますか? 誰が、いつ、どこで、誰が知っているのか、これが起こらないことをどのように確認できますか? これを修正する最善の方法は何ですか?

4

1 に答える 1

2

Excelは内部的に整数を保持しません-すべての数値(整数、日付、時刻、通貨など)はdoubleとして保持されます。したがって、Oper val.numは常にdoubleであり、xltypeNumのoperは常にdoubleです。
(操作者はval.wに整数を保持できますが、XLMマクロフロー制御のように、何十年もの間廃止されており、実際には満たされそうにないものの一部としてのみ使用できます)。
Excel 2007で9.9999999を取得する理由がわかりません。どのように値をOperに渡しますか?

于 2012-12-07T16:02:41.627 に答える