Microsoft ACE ドライバーを使用して Excel スプレッドシートを開いた後、一部の計算結果が変更されたように見えるという問題が発生しています。
以下のコードは、問題を再現します。
最初の 2 つの呼び出しDoCalculation
で同じ結果が得られます。OpenSpreadSheet
次に、ACE ドライバーを使用して Excel 2003 スプレッドシートを開いたり閉じたりする関数を呼び出します。OpenSpreadSheet
への最後の呼び出しに影響があるとは思わないでしょうがDoCalculation
、実際には結果が変わることがわかります。これは、プログラムが生成する出力です。
1,59142713593566
1,59142713593566
1,59142713593495
小数点以下 3 桁の違いに注意してください。これは大きな違いのようには見えませんが、私たちの製品コードでは計算が複雑で、結果の違いは非常に大きくなります。
ACE ドライバーの代わりに JET ドライバーを使用しても違いはありません。タイプをdoubleからdecimalに変更すると、エラーはなくなります。しかし、これは製品コードのオプションではありません。
Windows 7 64 ビットで実行しており、アセンブリは .NET 4.5 x86 用にコンパイルされています。32 ビットの Office を実行しているため、64 ビットの ACE ドライバーを使用することはできません。
なぜこれが起こっているのか、どうすれば修正できるのか誰か知っていますか?
次のコードは私の問題を再現します:
static void Main(string[] args)
{
DoCalculation();
DoCalculation();
OpenSpreadSheet();
DoCalculation();
}
static void DoCalculation()
{
// Multiply two randomly chosen number 10.000 times.
var d1 = 1.0003123132;
var d3 = 0.999734234;
double res = 1;
for (int i = 0; i < 10000; i++)
{
res *= d1 * d3;
}
Console.WriteLine(res);
}
public static void OpenSpreadSheet()
{
var cn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;data source=c:\temp\workbook1.xls;Extended Properties=Excel 8.0");
var cmd = new OleDbCommand("SELECT [Column1] FROM [Sheet1$]", cn);
cn.Open();
using (cn)
{
using (OleDbDataReader reader = cmd.ExecuteReader())
{
// Do nothing
}
}
}