Excel 2010与Excel 2003中的整数表示法(C++插件)

Representation of integers in Excel 2010 vs Excel 2003 (C++ plugin)

本文关键字:Excel C++ 插件 表示 整数 2010 2003      更新时间:2023-10-16

简介

我继承了一个使用VS2008、xlw2.0和Excel2003开发的遗留插件项目(C++)。

我已经设法将它移植到xlw 4.0头中(当添加对Excel2007的支持时,一些方法更改了名称,诸如此类)。我还没有生成任何东西,因为旧代码是手工编写的,我不会改变正在工作的东西,并且只有为了它才有合理的结构和代码逻辑。

该代码在Excel2003下可以正常工作。我今天试用了excel 2010,发现了一个最令人费解(也最可怕)的错误。

困惑行为

我(从VBA宏)接收一列(n行,1列)数字(通过构造的小正整数)作为XlfOper&我想把它转换成一个(老式)数组。代码基本上是遍历每一行,然后在对应于给定行的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是该特定项目中使用的一维数组类型,convertXflOper是一个模板函数,用于以下类型:

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

在给定的一行,我在excel工作簿中有数字10。

在Excel 2003下,这将转换为10。在Excel 2010下,这将转换为9。

我已经调试过了,问题是它的读数不是10,而是它的两倍近似值

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)是9,而不是10。

问题

这件事会让我非常痛苦,主要是因为它很容易被忽视:对于许多其他整数值,它在Excel2003和2010中都能正确工作。

我在excel接口中做错了什么,因为它认为整数必须被视为双精度?谁知道何时何地,我怎么能确定这不会发生?解决这个问题的最佳方法是什么?

Excel内部不保存整数-所有数字(整数、日期、时间、货币等)都是双精度的。所以Oper val.num总是一个double,xltypeNum的操作符总是一个duble
(运算器可以保存val.w中的整数,但只能作为XLM宏流量控制等功能的一部分,这些功能已经过时了几十年,在实践中不太可能实现)
我不知道为什么你在Excel 2007中得到9.9999999-你是如何将值传递给Oper的?