C语言 vs2022 Win32API COM 读取 Excel 表格的工具类
时间: 2023-11-28 22:50:34 浏览: 134
以下是一个简单的工具类,可以在 C++ 中使用 Win32API 和 COM 技术读取 Excel 表格:
```cpp
#include <Windows.h>
#include <ole2.h>
#include <stdio.h>
#include <tchar.h>
class ExcelReader {
public:
ExcelReader() : m_pExcelApp(NULL), m_pWorkbooks(NULL), m_pWorkbook(NULL), m_pSheet(NULL) {}
~ExcelReader() { Close(); }
bool Open(const TCHAR* szFile, const TCHAR* szSheet = NULL) {
if (szFile == NULL || szFile[0] == _T('\0')) {
return false;
}
// 初始化 COM 库
CoInitialize(NULL);
// 打开 Excel 应用程序
m_pExcelApp = NULL;
if (FAILED(CoCreateInstance(CLSIDExcelApplication, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&m_pExcelApp))) {
return false;
}
// 显示 Excel 应用程序
m_pExcelApp->PutVisible(VARIANT_TRUE);
// 获取 Workbooks 对象
m_pWorkbooks = m_pExcelApp->GetWorkbooks();
if (m_pWorkbooks == NULL) {
return false;
}
// 打开工作簿
m_pWorkbook = m_pWorkbooks->Open(szFile);
if (m_pWorkbook == NULL) {
return false;
}
// 获取 Sheets 对象
m_pSheets = m_pWorkbook->GetSheets();
if (m_pSheets == NULL) {
return false;
}
// 选择指定的工作表
if (szSheet != NULL && szSheet[0] != _T('\0')) {
m_pSheet = m_pSheets->GetItem(COleVariant(szSheet));
if (m_pSheet == NULL) {
return false;
}
}
else {
m_pSheet = m_pSheets->GetItem(COleVariant((short)1));
}
return true;
}
void Close() {
if (m_pSheet != NULL) {
m_pSheet->Release();
m_pSheet = NULL;
}
if (m_pSheets != NULL) {
m_pSheets->Release();
m_pSheets = NULL;
}
if (m_pWorkbook != NULL) {
m_pWorkbook->Close(VARIANT_TRUE);
m_pWorkbook->Release();
m_pWorkbook = NULL;
}
if (m_pWorkbooks != NULL) {
m_pWorkbooks->Release();
m_pWorkbooks = NULL;
}
if (m_pExcelApp != NULL) {
m_pExcelApp->Quit();
m_pExcelApp->Release();
m_pExcelApp = NULL;
}
// 反初始化 COM 库
CoUninitialize();
}
int GetRowCount() const {
if (m_pSheet == NULL) {
return 0;
}
COleVariant vResult;
COleVariant vProp((short)7); // XlRangeValueDataType.xlRangeValueDefault
// 获取行数
LPDISPATCH pDisp = m_pSheet->GetUsedRange();
if (pDisp == NULL) {
return 0;
}
IDispatch* pRow = NULL;
IDispatch* pColumns = NULL;
int nRowCount = 0;
int nColumnCount = 0;
try {
pRow = pDisp->GetIDispatch(TRUE);
pColumns = pDisp->GetIDispatch(FALSE);
COleVariant vRowCount;
vRowCount.vt = VT_I4;
vRowCount.lVal = 1;
COleVariant vColumnCount;
vColumnCount.vt = VT_I4;
vColumnCount.lVal = 1;
DISPID dispid;
LPOLESTR lpszMember = _T("Rows");
if (FAILED(pColumns->GetIDsOfNames(IID_NULL, &lpszMember, 1, LOCALE_USER_DEFAULT, &dispid))) {
throw;
}
if (FAILED(pColumns->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, NULL, &vResult, NULL, NULL))) {
throw;
}
IDispatch* pRows = vResult.pdispVal;
DISPPARAMS dispparams = { NULL, NULL, 0, 0 };
if (FAILED(pRows->Invoke(DISPID_ITEM, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparams, &vResult, NULL, NULL))) {
throw;
}
nRowCount = vResult.lVal;
lpszMember = _T("Columns");
if (FAILED(pRow->GetIDsOfNames(IID_NULL, &lpszMember, 1, LOCALE_USER_DEFAULT, &dispid))) {
throw;
}
if (FAILED(pRow->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, NULL, &vResult, NULL, NULL))) {
throw;
}
IDispatch* pColumns = vResult.pdispVal;
if (FAILED(pColumns->Invoke(DISPID_ITEM, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparams, &vResult, NULL, NULL))) {
throw;
}
nColumnCount = vResult.lVal;
}
catch (...) {
if (pRow != NULL) {
pRow->Release();
}
if (pColumns != NULL) {
pColumns->Release();
}
if (pDisp != NULL) {
pDisp->Release();
}
return 0;
}
if (pRow != NULL) {
pRow->Release();
}
if (pColumns != NULL) {
pColumns->Release();
}
if (pDisp != NULL) {
pDisp->Release();
}
return nRowCount;
}
int GetColumnCount() const {
if (m_pSheet == NULL) {
return 0;
}
COleVariant vResult;
COleVariant vProp((short)7); // XlRangeValueDataType.xlRangeValueDefault
// 获取列数
LPDISPATCH pDisp = m_pSheet->GetUsedRange();
if (pDisp == NULL) {
return 0;
}
IDispatch* pRow = NULL;
IDispatch* pColumns = NULL;
int nRowCount = 0;
int nColumnCount = 0;
try {
pRow = pDisp->GetIDispatch(TRUE);
pColumns = pDisp->GetIDispatch(FALSE);
COleVariant vRowCount;
vRowCount.vt = VT_I4;
vRowCount.lVal = 1;
COleVariant vColumnCount;
vColumnCount.vt = VT_I4;
vColumnCount.lVal = 1;
DISPID dispid;
LPOLESTR lpszMember = _T("Rows");
if (FAILED(pColumns->GetIDsOfNames(IID_NULL, &lpszMember, 1, LOCALE_USER_DEFAULT, &dispid))) {
throw;
}
if (FAILED(pColumns->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, NULL, &vResult, NULL, NULL))) {
throw;
}
IDispatch* pRows = vResult.pdispVal;
DISPPARAMS dispparams = { NULL, NULL, 0, 0 };
if (FAILED(pRows->Invoke(DISPID_ITEM, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparams, &vResult, NULL, NULL))) {
throw;
}
nRowCount = vResult.lVal;
lpszMember = _T("Columns");
if (FAILED(pRow->GetIDsOfNames(IID_NULL, &lpszMember, 1, LOCALE_USER_DEFAULT, &dispid))) {
throw;
}
if (FAILED(pRow->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, NULL, &vResult, NULL, NULL))) {
throw;
}
IDispatch* pColumns = vResult.pdispVal;
if (FAILED(pColumns->Invoke(DISPID_ITEM, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparams, &vResult, NULL, NULL))) {
throw;
}
nColumnCount = vResult.lVal;
}
catch (...) {
if (pRow != NULL) {
pRow->Release();
}
if (pColumns != NULL) {
pColumns->Release();
}
if (pDisp != NULL) {
pDisp->Release();
}
return 0;
}
if (pRow != NULL) {
pRow->Release();
}
if (pColumns != NULL) {
pColumns->Release();
}
if (pDisp != NULL) {
pDisp->Release();
}
return nColumnCount;
}
bool ReadCell(int nRow, int nCol, CString& strValue) const {
if (m_pSheet == NULL) {
return false;
}
COleVariant vResult;
COleVariant vProp((short)7); // XlRangeValueDataType.xlRangeValueDefault
// 读取单元格的值
COleVariant vRow((short)nRow);
COleVariant vCol((short)nCol);
LPDISPATCH pDisp = m_pSheet->GetCells();
if (pDisp == NULL) {
return false;
}
IDispatch* pCell = NULL;
try {
if (FAILED(pDisp->Invoke(DISPID_ITEM, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &vRow, &vResult, NULL, NULL))) {
throw;
}
pCell = vResult.pdispVal;
DISPID dispid;
LPOLESTR lpszMember = _T("Item");
if (FAILED(pCell->GetIDsOfNames(IID_NULL, &lpszMember, 1, LOCALE_USER_DEFAULT, &dispid))) {
throw;
}
DISPPARAMS dispparams = { NULL, NULL, 0, 0 };
if (FAILED(pCell->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparams, &vResult, NULL, NULL))) {
throw;
}
if (vResult.vt == VT_BSTR) {
strValue = CString(vResult.bstrVal);
}
else {
strValue.Empty();
}
}
catch (...) {
if (pCell != NULL) {
pCell->Release();
}
if (pDisp != NULL) {
pDisp->Release();
}
return false;
}
if (pCell != NULL) {
pCell->Release();
}
if (pDisp != NULL) {
pDisp->Release();
}
return true;
}
private:
IDispatch* m_pExcelApp; // Excel 应用程序对象
IDispatch* m_pWorkbooks; // Workbooks 对象
IDispatch* m_pWorkbook; // Workbook 对象
IDispatch* m_pSheets; // Sheets 对象
IDispatch* m_pSheet; // Worksheet 对象
};
```
使用示例:
```cpp
ExcelReader reader;
if (!reader.Open(_T("C:\\test.xls"), _T("Sheet1"))) {
printf("Open file failed!\n");
return;
}
int nRowCount = reader.GetRowCount();
int nColumnCount = reader.GetColumnCount();
for (int i = 1; i <= nRowCount; i++) {
for (int j = 1; j <= nColumnCount; j++) {
CString strValue;
if (reader.ReadCell(i, j, strValue)) {
printf("%s\t", strValue);
}
}
printf("\n");
}
reader.Close();
```
需要注意的是,该工具类依赖于 Microsoft Office Excel 应用程序,因此需要在使用前确保已经安装了 Excel 并且系统中有相应的 COM 组件。同时,该工具类只能在 Windows 平台下使用,无法在 Linux、macOS 等其他操作系统上编译和运行。
阅读全文