序章
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 インターフェイスで何が間違っていますか? 誰が、いつ、どこで、誰が知っているのか、これが起こらないことをどのように確認できますか? これを修正する最善の方法は何ですか?