65.9K
CodeProject 正在变化。 阅读更多。
Home

如何通过 ADO 在 C++ 中读写 Excel 文件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (21投票s)

2010 年 11 月 10 日

CPOL
viewsIcon

114944

downloadIcon

6436

使用 ADO 在 C++ 中访问 XLS 和 XLSX 文件。

引言

有时软件开发者需要将一些数据导出到 Excel 格式,或者从 Excel 文件中读取一些单元格。 一种无需 Excel 自动化即可实现的方法是与 ADO 交互。在这种情况下,Excel 文件被视为数据库。 这种方法不需要 Microsoft Excel 并且速度足够快,但它不支持格式和公式。

连接字符串

有两种类型的连接字符串。 第一个是二进制格式 (xls)

Provider=Microsoft.JET.OLEDB.4.0;Data Source=data.xls;Extended Properties="Excel 8.0"

第二个是 XML 格式 (xlsx)

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=data.xlsx;
Extended Properties="Excel 12.0 Xml" 

如果输入文件没有包含列名的标题,则在扩展属性中添加 ";HDR=NO"。

写入

首先创建一个 Connection 对象

TESTHR(pCon.CreateInstance(__uuidof(Connection)));
TESTHR(pCon->Open(connStr, "", "", NULL)); 

之后,创建 Command 对象和表。 请注意,表名是工作表的名称

TESTHR(pCmd.CreateInstance(__uuidof(Command)));
pCmd->ActiveConnection = pCon;       
pCmd->CommandText = "CREATE TABLE MySheet
    (A int, B varchar, C int, D int, E int, F int, G int, H int, I int, J varchar)";   
pCmd->Execute(NULL, NULL, adCmdText); 

创建 Recordset 并添加带有值的记录

TESTHR(pRec.CreateInstance(__uuidof(Recordset)));
pRec->Open("SELECT * FROM MySheet", _variant_t((IDispatch*)pCon), 
	adOpenKeyset, adLockOptimistic, adCmdText);

for(int i = 0; i < writeRows; ++i)
{
    TESTHR(pRec->AddNew());

    char str[11] = {0}; for(int j = 0; j < 10; ++j) str[j] = 'a' + (rand() % 26);

    pRec->Fields->GetItem("A")->Value = _variant_t(i);            
    pRec->Fields->GetItem("B")->Value = _variant_t(str);            
    pRec->Fields->GetItem("C")->Value = _variant_t(i);
    pRec->Fields->GetItem("D")->Value = _variant_t(i);
    pRec->Fields->GetItem("E")->Value = _variant_t(i);
    pRec->Fields->GetItem("F")->Value = _variant_t(i);
    pRec->Fields->GetItem("G")->Value = _variant_t(i);
    pRec->Fields->GetItem("H")->Value = _variant_t(i);
    pRec->Fields->GetItem("I")->Value = _variant_t(i);
    pRec->Fields->GetItem("J")->Value = _variant_t(str);            
}
TESTHR(pRec->Update());
TESTHR(pRec->Close());

读取

创建并打开 Recordset

TESTHR(pRec.CreateInstance(__uuidof(Recordset)));       
TESTHR(pRec->Open("SELECT * FROM [Sheet1$]", connStr, 
	adOpenStatic, adLockOptimistic, adCmdText));

如果工作表的名称未知,则可以通过索引查找它

TESTHR(pCon.CreateInstance(__uuidof(Connection)));
TESTHR(pCon->Open(connStr, "", "", NULL));
    
pSchema = pCon->OpenSchema(adSchemaTables);      

for(int i = 0; i < sheetIndex; ++i) pSchema->MoveNext();

std::string sheetName = 
	(char*)(_bstr_t)pSchema->Fields->GetItem("TABLE_NAME")->Value.bstrVal;

提取单元格的值

while(!pRec->adoEOF)
{
    for(long i = 0; i < pRec->Fields->GetCount(); ++i)
    {
        if(i > 0) stream << ";";                    
        _variant_t v = pRec->Fields->GetItem(i)->Value;
        if(v.vt == VT_R8)                                           
            stream << v.dblVal;
        if(v.vt == VT_BSTR)
            stream << (char*)(_bstr_t)v.bstrVal;                                
    }                                    
    stream << std::endl;
    pRec->MoveNext();
} 

历史

  • 2010 年 11 月 10 日:初始发布
© . All rights reserved.