在没有安装MicrosoftExcel的情况下,可以使用ADO(ActiveX Data Objects)技术来操作Excel文件。ADO允许将Excel文件当作数据库来处理,从而实现数据的读取和写入。这种方法不需要Excel应用程序,并且执行速度较快,但不支持格式化和公式计算。
连接字符串有两种类型,分别对应于二进制格式(xls)和XML格式(xlsx)的Excel文件。
Binary format (xls): Provider=Microsoft.JET.OLEDB.4.0;Data Source=data.xls;Extended Properties="Excel 8.0"
XML format (xlsx): Provider=Microsoft.ACE.OLEDB.12.0;Data Source=data.xlsx;Extended Properties="Excel 12.0 Xml"
如果输入文件没有包含列名的标题行,则需要在扩展属性中添加"HDR=NO"。
首先,需要创建一个连接对象:
C++ TESTHR(pCon.CreateInstance(__uuidof(Connection)));
TESTHR(pCon->Open(connStr, "", "", NULL));
然后,创建命令对象和表格。注意,表格的名称就是工作表的名称:
C++ 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);
创建记录集并添加记录:
C++ 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);
// ... 其他字段赋值
}
TESTHR(pRec->Update());
TESTHR(pRec->Close());
创建并打开记录集:
C++ TESTHR(pRec.CreateInstance(__uuidof(Recordset)));
TESTHR(pRec->Open("SELECT * FROM [Sheet1$]", connStr, adOpenStatic, adLockOptimistic, adCmdText));
如果不知道工作表的名称,可以通过索引查找:
C++ 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;
C++ 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();
}