我在网上看过但没找到任何答案。所以我把它放在这里。
代码段:(案例1不起作用..)
_bstr_t strCnn(L"Provider='Microsoft.ACE.OLEDB.12.0';DataSource=C:\\Book.xlsx;Extended Properties=\"Excel 12.0 Xml; HDR = YES\"");
hr = pConn->Open(strCnn, "", "", adConnectUnspecified); // success
**LPCSTR strQuery = "select * FROM Table1"; // case1: Not working**
LPCSTR strQuery = "select * FROM [Sheet1$]"; // case2: working
LPCSTR strQuery = "select * FROM [Sheet1$A1:D10]"; // case3: working
hr = pRst->Open(CComVariant(strQuery), _variant_t((IDispatch *)pConn, true),
adOpenStatic, adLockOptimistic,adCmdText); // fails for case 1
这在excel中是否可行?或者上面的代码有问题。
注意:我已尝试使用Microsoft Access,并且将表格名称的绑定recorset在那里工作正常。
答案 0 :(得分:2)
简短版本是:
您需要一个命名范围,或一个命名的工作表,或者表格的完整地址'数据范围和标题;并且与Excel表相关联的命名范围的明显存在具有误导性。
我想这需要一些解释,从:
开始
它不是命名范围,它不是工作表,并且SQL无法将其解析为Excel范围对象。回顾一下:
Excel'表'不是那些东西,所以它作为数据库引擎的表是不可见的。
是的,它出现在“名称管理器”中。命名范围的对话框:但是'表1'不是命名范围的名称,也不是工作表的名称,也不是指定具有SQL可识别的地址的范围:并且它必须是这三个事项之一才能作为OLEDB和ODBC的数据库表可见可用于Excel的数据库驱动程序。
您创建的对象'表1'是一个 ListObject ,您可以在Excel VBA IDE的调试窗口中查询它:
Thisworkbook.Worksheets("Sheet1").ListObjects("Table1").Name
所以你需要的是ListObject的范围地址,这很简单...
实际上,它根本不简单。
... ListObject有一个DataBodyRange
属性,它覆盖了标题下面的数据行;以及引用标题的HeaderRowRange
。作为范围,两者都有一个地址;并且您需要UNION
来获取您的SQL可以作为命名表读取的单个地址。
或者使用Sheet1.ListObjects("Table1").Sort.Rng.address
因为每个ListObject都有一个Sort
对象属性,无论它是否已排序;并且Rng
属性是整个范围,有一个骑士无视一致的对象名称,并且没有关于列或列的提示。地址正在排序。
...而且这些信息对于您的问题和编码毫无用处:您无法将任何内容放入SQL查询中来解析表格'表格。 object作为有效表。
您必须提取并解析完整表格的地址'运行SQL之前的范围。 ADO和ODBC Excel驱动程序将处理表格的连续范围地址' SheetName $ A1:Z1024 '但他们无法从Excel的表格中提取该地址。对象
为这个令人失望的答案道歉。
顺便说一下,你做知道用任何的可用ODBC和OLEDB SQL驱动程序查询Excel会给你带来内存泄漏吗?至少,如果你是从VBA这样做的话,我会建议你不要重复运行它,除非你在你的代码上运行Purify或类似工具并解决问题。