可以通過COM API調用才是正解,不過需要編寫COM接口類,Excel對象庫的接口太多了……不過可以用工具自動生成。
我最近也在用VC操作Excel,在VC中可以這樣做,在任何一個cpp文件中加入下面三行:
1 #import "C:\Program Files\Common Files\Microsoft Shared\OFFICE11\MSO.DLL" rename("RGB","rgb") rename("DocumentProperties", "document_properties") 2 #import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB" 3 #import "D:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE" rename("RGB","rgb") rename("DialogBox", "dialog_box")
然后編譯。
注意,這樣編譯是通不過的,不過沒關系,在Debug目錄中你會看到mso.tlh、mso.tli、vb6ext.tlh、vb6ext.tli、excel.tlh、excel.tli六個文件,它們就是VC編譯器通過類型庫信息自動生成的接口類型定義和一些輔助類。把它們復制到你的源代碼目錄,然后打開vb6ext.tlh,進行修改:
1 #include <comdef.h> 2 #include "mso.tlh" //加入這一行 3 4 namespace VBIDE 5 { 6 using namespace Office;//加入這一行 7 ...
再修改excel.tlh文件:
1 #include <comdef.h> 2 #include "mso.tlh" //加入這一行 3 #include "vbe6ext.tlh" //加入這一行 4 5 namespace Excel 6 { 7 using namespace VBIDE;//加入這一行
這時把那三行#import刪除,換成#include "excel.tlh"就可以用了:
1 #include "stdafx.h" 2 #include "excel.tlh" 3 #include <iostream> 4 5 int _tmain(int argc, _TCHAR* argv[]) 6 7 { 8 CoInitializeEx( 0, COINIT_APARTMENTTHREADED ); 9 Excel::_ApplicationPtr xApp; 10 xApp.CreateInstance(__uuidof(Excel::Application)); 11 Excel::_WorkbookPtr xBook = xApp->Workbooks->Open(L"test.xsl"); 12 Excel::_WorksheetPtr xSheet = xBook->ActiveSheet; 13 14 _bstr_t text = xSheet->Range[L"A1"][vtMissing]->Text;//讀取單元格內容,_bstr_t封裝了COM寬字符串BSTR 15 std::cout << static_cast<char const *>(text);//_bstr_t類定義了到char const *的類型轉換,會把unicode字符串轉換為當前代碼頁的多字節編碼字符串 16 return 0; 17 }
把Excel作為數據庫直接通過ODBC方式讀取
1 #include <odbcinst.h> 2 #include <afxdb.h> 3 4 5 CString strXlsFileName = "X:\\XXX.xls"; 6 CString strSql; 7 strSql.Format(L"DRIVER={MICROSOFT EXCEL DRIVER (*.xls)};DSN='';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s", strXlsFileName, strXlsFileName); 8 9 CDatabase *pCDatabase = new CDatabase; 10 pCDatabase->OpenEx(strSql, CDatabase::noOdbcDialog); 11 12 CString strSheetName = "你要操作的表名稱"; 13 CString strSql; 14 strSql.Format(L"SELECT * FROM [%s$A1:IV65536]", strSheetName); 15 16 CRecordset *pCRecordset = new CRecordset(pCDatabase); 17 pCRecordset->Open(CRecordset::forwardOnly, strSql, CRecordset::readOnly); 18 19 CString strField; 20 pCRecordset->GetFieldValue((short)0, strField);//讀取第1行第1列的單元格內容 21 pCRecordset->GetFieldValue((short)3, strField);//第1行第4列 22 pCRecordset->MoveNext();//游標指向下一行,再用GetFieldValue就可以讀取下一行的內容