CLSIDFromProgID(L"Excel.Application", &clsid) 使用WIN32 API 读取Excel表格 封装工具类
时间: 2023-12-30 10:05:49 浏览: 281
可以使用以下步骤封装一个工具类:
1. 在类的头文件中添加必要的头文件和类声明:
```c++
#include <Windows.h>
#include <ole2.h>
#include <olectl.h>
#include <atlbase.h>
class ExcelReader {
public:
ExcelReader();
~ExcelReader();
bool OpenFile(const wchar_t* fileName);
void CloseFile();
bool ReadCell(int row, int col, wchar_t* value, int len);
private:
void Init();
void Uninit();
bool GetActiveSheet();
bool GetCell(int row, int col, IDispatch** cell);
bool GetCellValue(IDispatch* cell, wchar_t* value, int len);
CComPtr<IDispatch> m_pExcelApp;
CComPtr<IDispatch> m_pWorkbook;
CComPtr<IDispatch> m_pActiveSheet;
};
```
2. 在类的实现文件中添加必要的函数实现:
```c++
ExcelReader::ExcelReader() {
Init();
}
ExcelReader::~ExcelReader() {
Uninit();
}
void ExcelReader::Init() {
CoInitialize(NULL);
CLSID clsid;
HRESULT hr = CLSIDFromProgID(L"Excel.Application", &clsid);
if (SUCCEEDED(hr)) {
hr = m_pExcelApp.CoCreateInstance(clsid);
if (SUCCEEDED(hr)) {
m_pExcelApp->PutVisible(VARIANT_FALSE);
}
}
}
void ExcelReader::Uninit() {
CloseFile();
m_pExcelApp.Release();
CoUninitialize();
}
bool ExcelReader::OpenFile(const wchar_t* fileName) {
if (!m_pExcelApp) {
return false;
}
CloseFile();
VARIANT result;
VariantInit(&result);
VARIANT file_name;
VariantInit(&file_name);
file_name.vt = VT_BSTR;
file_name.bstrVal = SysAllocString(fileName);
HRESULT hr = m_pExcelApp->GetWorkbooks()->Open(
file_name,
VARIANT(),
VARIANT(),
VARIANT(),
VARIANT(),
VARIANT(),
VARIANT(),
VARIANT(),
VARIANT(),
VARIANT(),
VARIANT(),
VARIANT(),
VARIANT(),
&result
);
VariantClear(&file_name);
if (SUCCEEDED(hr)) {
m_pWorkbook.Attach(result.pdispVal);
return GetActiveSheet();
}
return false;
}
void ExcelReader::CloseFile() {
m_pActiveSheet.Release();
m_pWorkbook.Release();
}
bool ExcelReader::ReadCell(int row, int col, wchar_t* value, int len) {
if (!m_pActiveSheet) {
return false;
}
CComPtr<IDispatch> cell;
if (!GetCell(row, col, &cell)) {
return false;
}
return GetCellValue(cell, value, len);
}
bool ExcelReader::GetActiveSheet() {
if (!m_pWorkbook) {
return false;
}
VARIANT result;
VariantInit(&result);
HRESULT hr = m_pWorkbook->GetActiveSheet(&result);
if (SUCCEEDED(hr)) {
m_pActiveSheet.Attach(result.pdispVal);
return true;
}
return false;
}
bool ExcelReader::GetCell(int row, int col, IDispatch** cell) {
if (!m_pActiveSheet) {
return false;
}
VARIANT result;
VariantInit(&result);
VARIANT vtRow;
vtRow.vt = VT_INT;
vtRow.intVal = row;
VARIANT vtCol;
vtCol.vt = VT_INT;
vtCol.intVal = col;
HRESULT hr = m_pActiveSheet->Invoke(
DISPID_VALUE,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYGET,
&result,
NULL,
NULL,
NULL
);
if (SUCCEEDED(hr)) {
CComPtr<IDispatch> range(result.pdispVal);
hr = range->Invoke(
DISPID_VALUE,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
&result,
NULL,
NULL,
NULL
);
if (SUCCEEDED(hr)) {
*cell = result.pdispVal;
return true;
}
}
return false;
}
bool ExcelReader::GetCellValue(IDispatch* cell, wchar_t* value, int len) {
VARIANT result;
VariantInit(&result);
HRESULT hr = cell->Invoke(
DISPID_VALUE,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYGET,
&result,
NULL,
NULL,
NULL
);
if (SUCCEEDED(hr)) {
if (result.vt == VT_BSTR) {
wcsncpy_s(value, len, result.bstrVal, _TRUNCATE);
VariantClear(&result);
return true;
}
}
return false;
}
```
3. 使用工具类读取 Excel 表格:
```c++
int main() {
ExcelReader reader;
if (!reader.OpenFile(L"example.xlsx")) {
printf("Failed to open file.\n");
return 1;
}
wchar_t value[256] = { 0 };
if (reader.ReadCell(1, 1, value, sizeof(value) / sizeof(wchar_t))) {
wprintf(L"Value of A1: %s\n", value);
}
reader.CloseFile();
return 0;
}
```
这个工具类使用了 ATL 库来简化 COM 的使用,使用者只需要创建一个 ExcelReader 对象,调用 OpenFile 方法打开一个 Excel 文件,再调用 ReadCell 方法读取指定单元格的值即可。
阅读全文