C++操作Excel學習筆記


C++操作Excel學習筆記

 

一:

【當前博文轉載自http://blog.csdn.net/fullsail/article/details/4067416

C++讀取Excel文件方式比較

C++讀取Excel的XLS文件的方法有很多,但是也許就是因為方法太多,大家在選擇的時候會很疑惑。

由於前兩天要做導表工具,比較了常用的方法,總結一下寫個短文,

 

1.OLE的方式

這個大約是最常用的方式,這個方式其實啟動了一個EXCEL的進程在背后讀寫EXCEL文件,這個方式的最大好處是什么事情都能做。包括設置EXCEL的格式,增加刪除Sheet,讀寫單元格,等等。功能幾乎是最全的,而且使用起來也不是特別的難。

其基本方法都是使用導出的.h文件進行OLE操作,但是由於OLE的接口說明文檔不多,想非常完美的使用她們也不是太容易,好在例子也很多。

網上普遍認為OLE速度慢,EXCEL的OLE讀寫方式也基本一樣。但是讀取速度可以改進,如果在讀取的加載整個Sheet的Range的全部數據,而不是一個個單元格讀取,那么速度還是相對不錯。想想原理也很簡單,整體讀取減少了OLE的交互次數。OLE的寫入方式一般只能幾個進行比較方便,所以速度可能要快很多。

我自己的親身體會是,一個EXCEL文件,100多列的字段,如果采用一個個單元格的讀取方式,1s大約3條左右的記錄,如果整體讀取,速度可以提高幾十倍。

OLE讀寫EXCEL方式功能很強大,讀取速度還可以,但寫入速度不高,當然這個方式不可能移植的,而且你必須安裝了EXCEL。

 

2.Basic EXCEL 方式

這是CodeProject上的一個推薦開源工程了,

http://www.codeproject.com/KB/office/BasicExcel.aspx

作者是基於EXCEL的文件格式進行的處理。但是為什么叫Basic EXCEL呢。

他不支持很多東西,公式,文件格式,表格合並等(有人說中文支持也不好),所以可以認為他只支持最基本的EXCEL表格,

我自己的嘗試是如果這個EXCEL文件有其他元素(公式,格式等),使用Basic EXCEL讀取會失敗。

OLE讀寫EXCEL方式功能比較弱,由於是直接根據文件格式操作,讀寫速度都不錯,你也不需要按照EXCEL,另外這個方式是可以移植的,但是有一些成本,其代碼比較晦澀難懂,而且沒有注釋,另外即使在Windows平台上,告警也很多。

 

3.Sourceforge 上的幾個EXCEL庫。

Sourceforge 上有幾個開源的的EXCEL庫,但是完善的不多,有的是為了PHP讀寫EXCEL准備的,包括libXLS,XLSlib,SmartEXCEL等。我下載了幾個實驗了一下,在Widonws都沒有編譯成功。也罷了。

 

4.ODBC的方式

這個親身沒有嘗試過,但是按照原理,應該只能讀寫。

速度嗎,ODBC的速度本來就是出名的慢了。

http://www.vckbase.com/document/viewdoc/?id=421

 

值得一提的是Basic EXCEL的作者原來在CodeProject上有一個給予ODBC方式的封裝CSpreadSheet 。如果有興趣,大家可以去看看。其實內心還是很佩服這個作者的。

http://www.codeproject.com/KB/database/cspreadsheet.aspx

 

5.ADO的方式

ADO的方式聽說應該就是使用OLEDB的方式。和OLE的方式應該沒有本質區別。我看了看例子也和OLE很像

  

6.LibXL

LibXL 是一個收費的EXCEL的庫。

http://www.libxl.com/

按照他的說明,他可以不依賴EXCEL讀取XLS文件。包括設置格式等。看例子操作應該很簡單。但是是否可以移植到Linux平台,我估計難度也不小。呵呵。

由於要收費,沒有法子測試了。

 

7.網上一些號稱不用OLE讀取EXCEL例子

初步看了一下,這個應該是網上探索EXCEL格式文檔的例子。可以實際操作的方式不強。

 

二:

【當前博文轉載自http://www.byywee.com/page/M0/S599/599654.html

VS2010 C++ 操縱Excel表格的編程實現

經由過程VC實現對Excel表格的操縱的辦法有多種,如:經由過程ODBC數據庫實現,經由過程解析Excel表格文件,經由過程OLE/COM的實現。本文首要研究經由過程OLE/COM實現對Excel表格的操縱。

 

本文源碼的應用景象申明:

Windows XP SP3

Microsoft Visual Studio 2010

Microsoft Office Excel 2007

 

1、添加OLE/COM支撐。

起首,應用法度必須添加對OLE/COM的支撐,才干導入OLE/COM組件。

本文應用的是MFC對話框法度,在創建工程的領導中選中Automation選項即可為法度主動添加響應的頭文件和OLE庫初始化代碼。

經由過程查看源代碼,可以知道在stdafx.h的頭文件中,添加了OLE/COM很多類所需添加的頭文件。

#include         // MFC 主動化類

同時,在應用法度類的InitInstance函數中,添加了OLE/COM的初始化代碼,如下所示:

// 初始化 OLE 庫

if (!AfxOleInit())

{

 

AfxMessageBox(IDP_OLE_INIT_FAILED); 

return FALSE; 

}
 

2、導入並封裝Excel中的接口

Excel作為OLE/COM庫插件,定義好了各類交互的接口,這些接口是跨說話的接口。VC可以經由過程導入這些接口,並經由過程接口來對Excel的操縱。

因為本文只關懷對Excel表格中的數據的讀取,首要存眷幾個_ApplicationWorkbooks_WorkbookWorksheets_WorksheetRange等幾個接口。Excel的各類接口的屬性、辦法可以經由過程MSDNOffice Development進行查詢。

VS2010導入OLE/COM組件的接口的步調為:Project->Class Wizard->Add Class->MFC Class From TypeLib,先選擇要導入的組件地點的路徑,即Excel.exe地點的路徑,然后再選擇要導入的Excel類型庫中的接口。

在完成接口導入后,VS2010將主動為導入的接口創建響應的實現類,用於對接口屬性和辦法的實現。因為標准的C++沒有屬性接見器,只能添加一個兩個存取函數來實現對屬性的接見,經由過程在屬性名稱前加上get_put_前綴分別實現對屬性的讀寫操縱。即,由VC主動完成C++類對接口的封裝。

文所導入的接口對應的類和頭文件的申明如下所示:

 Excel接口 導入類  頭文件  申明
_Application

CApplicaton

Application.h

Excel應用法度。

Workbooks CWorkbooks Workbooks.h 工作簿的容器,里面包含了Excel應用法度打開的所有工作簿
_Workbook CWorkbook

Workbook.h

單個工作簿。
Worksheets CWorksheets Worksheets.h

單個工作簿中的Sheet表格的容器,包含該工作簿中的所有Sheet。

_Worksheet CWorksheet Worksheet.h 單個Sheet表格。
Range CRange Range.h 必然命量的單位格,可對單位格進行單個或多個單位格進行操縱。

 

3、導入Excel的全部類型庫

接口對應類只是對接口的屬性和辦法進行了封裝,而Excel中的數據類型,如列舉類型卻並為並不克不及應用,是,為了更便利的操縱Excel,還須要導入Excel的數據類型。 

經由過程查看導入接口對應的頭文件可以發明,在所有導入接口的頭文件中,都邑有這么行:

#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace

這行代碼的感化是導入Excel全部類型庫到工程中。

VS2010主動產生的導入代碼存在以下幾個題目:

1)若是導入了多個接口,每個頭文件都邑把類型庫導入一次,若是引用多個頭文件,會導致類型庫反復導入。

2Excel類型庫中有些類型會跟MFC類庫的某些類型沖突。

3Excel類型庫的某些類型跟其他OfficeVB的某些庫相干,若是不導入相干庫,將導致這些類型無法應用。。

以上三點題目的解決辦法如下:

1)僅在_Application接口對應頭文件中導入Excel類型庫。

2)對沖突的類型進行重定名。

3)在導入Excel類型庫之前,先導入OfficeVB的相干庫。

更改后的導入類型庫的代碼如下:

 

#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \ 

rename("RGB", "MSORGB") \ 

rename("DocumentProperties", "MSODocumentProperties") 

using namespace Office; 

 

#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB" 

using namespace VBIDE; 

 

#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" \ 

rename("DialogBox", "ExcelDialogBox") \ 

rename("RGB", "ExcelRGB") \ 

rename("CopyFile", "ExcelCopyFile") \ 

rename("ReplaceText", "ExcelReplaceText") \

no_auto_exclude 

Using namesapce Excel;

 

編譯法度后,會在DebugRelease目次下生成三個文件mso.tlhvbe6ext.tlhexcel.tlh。經由過程打開文件可知,該三個文件的定名空間分別是OfficeVBIDEExcel。導入了Excel的全部類型庫后,就可以應用Excel中的所有類型了。
 

4、操縱Excel步調 

操縱Excel的首要步調如下: 

1)創建一個Excel應用法度。 

2)獲得Workbook的容器。 

3)打開一個Workbook或者創建一個Workbook。 

4)獲得Workbook中的Worksheet的容器。 

5)打開一個Worksheet或者創建一個WorkSheet。 

6)經由過程RangeWorkSheet中的單位格進行讀寫操縱。 

7)保存Excel。 

8)開釋資料。
 

5、批量處理懲罰Excel表格 

VC經由過程OLE/COM操縱Excel,是經由過程過程間的組件技巧。是以,每次讀寫Excel中的單位格時,都要進行過程間的切換。當數據量大,若是一個單位格一個單位格的讀取,首要的時候都花費在過程切換中。是以讀取多個單位格,將可有效的進步法度的運行效力。 

對多個單位格的讀寫操縱可以經由過程CRange中以下兩個成員函數來完成。 

VARIANT get_Value2()

void put_Value2(VARIANT& newValue)

此中,輸入參數newValue只要輸入一個二維數組,即可實現向Excel中一次寫入多個單位格的值。 

此中,VARIANT中實現二維數據的辦法可參考 

http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html 

當然,在對CRange類進行操縱之前,要設置CRange類對應的單位格。
 

6Excel表格的保存 

1)若是要保存打開的工作簿,應用CWorkbook類的Save函數就可以保存工作簿,原文件將被覆蓋。 

2)若是是新創建的工作簿,或者是要另存為,可應用CWorkbook類的SaveAs函數。

 

SaveAs的參數斗勁多。此中,第1個參數是設置要保存文件的路徑;第2個參數是設置文件的格局,可在MSDN中查看列舉類型XlFileFormat來懂得Excel的文件格局。經過測試,在本文所用的測試景象中,Excel2003的文件格局是xlExcel8Excel2007的文件格局是xlExcel4
 

7、獲取當前Excel的版本 

可以經由過程CApplicationget_Version函數來獲得Excel的版本,此中,Excel2007的主版本號是12Excel2003的主版本號是11
 

8、示例源代碼 

首要代碼如下: 

C++操作Excel學習筆記(二) C++操作Excel學習筆記(二)View Code

m_ListCtrl.SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);

CApplication ExcelApp;
CWorkbooks books;
CWorkbook book;
CWorksheets sheets;
CWorksheet sheet;
CRange range;
LPDISPATCH lpDisp = NULL;

//創建Excel 辦事器(啟動Excel)
if(!ExcelApp.CreateDispatch(_T("Excel.Application"),NULL))
{
AfxMessageBox(_T("啟動Excel辦事器失敗!"));
return -1;
}


CString strExcelVersion = ExcelApp.get_Version();
int iStart = 0;
strExcelVersion = strExcelVersion.Tokenize(_T("."), iStart);
if (_T("11") == strExcelVersion)
{
AfxMessageBox(_T("當前Excel的版本是2003。"));
}
else if (_T("12") == strExcelVersion)
{
AfxMessageBox(_T("當前Excel的版本是2007。"));
}
else
{
AfxMessageBox(_T("當前Excel的版本是其他版本。"));
}

ExcelApp.put_Visible(TRUE);
ExcelApp.put_UserControl(FALSE);


books.AttachDispatch(ExcelApp.get_Workbooks());


CString strBookPath = _T("C:\\tmp.xls");
try
{

lpDisp = books.Open(strBookPath, 
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing,
vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, 
vtMissing, vtMissing, vtMissing, vtMissing);
book.AttachDispatch(lpDisp);
}
catch(...)
{

lpDisp = books.Add(vtMissing);
book.AttachDispatch(lpDisp);
}



sheets.AttachDispatch(book.get_Sheets());


CString strSheetName = _T("NewSheet");
try
{

lpDisp = sheets.get_Item(_variant_t(strSheetName));
sheet.AttachDispatch(lpDisp);
}
catch(...)
{

lpDisp = sheets.Add(vtMissing, vtMissing, _variant_t((long)1), vtMissing);
sheet.AttachDispatch(lpDisp);
sheet.put_Name(strSheetName);
}

system("pause");


lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t("J10"));
range.AttachDispatch(lpDisp);

VARTYPE vt = VT_I4; 
SAFEARRAYBOUND sabWrite[2]; 
sabWrite[0].cElements = 10;
sabWrite[0].lLbound = 0;
sabWrite[1].cElements = 10;
sabWrite[1].lLbound = 0;

COleSafeArray olesaWrite;
olesaWrite.Create(vt, sizeof(sabWrite)/sizeof(SAFEARRAYBOUND), sabWrite);


long (*pArray)[2] = NULL;
olesaWrite.AccessData((void **)&pArray);
memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));


olesaWrite.UnaccessData();
pArray = NULL;


long index[2] = {0, 0};
long lFirstLBound = 0;
long lFirstUBound = 0;
long lSecondLBound = 0;
long lSecondUBound = 0;
olesaWrite.GetLBound(1, &lFirstLBound);
olesaWrite.GetUBound(1, &lFirstUBound);
olesaWrite.GetLBound(2, &lSecondLBound);
olesaWrite.GetUBound(2, &lSecondUBound);
for (long i = lFirstLBound; i <= lFirstUBound; i++)
{
index[0] = i;
for (long j = lSecondLBound; j <= lSecondUBound; j++)
{
index[1] = j;
long lElement = i * sabWrite[1].cElements + j; 
olesaWrite.PutElement(index, &lElement);
}
}


VARIANT varWrite = (VARIANT)olesaWrite;
range.put_Value2(varWrite);

system("pause");


CString strSaveAsName = _T("C:\\new.xlsx");
CString strSuffix = strSaveAsName.Mid(strSaveAsName.ReverseFind(_T(""."")));
XlFileFormat NewFileFormat = xlOpenXMLWorkbook;
if (0 == strSuffix.CompareNoCase(_T(".xls")))
{
NewFileFormat = xlExcel8;
}
book.SaveAs(_variant_t(strSaveAsName), _variant_t((long)NewFileFormat), vtMissing, vtMissing, vtMissing, 
vtMissing, 0, vtMissing, vtMissing, vtMissing, 
vtMissing, vtMissing);

system("pause");


VARIANT varRead = range.get_Value2();
COleSafeArray olesaRead(varRead);

VARIANT varItem;
CString strItem;
lFirstLBound = 0;
lFirstUBound = 0;
lSecondLBound = 0;
lSecondUBound = 0;
olesaRead.GetLBound(1, &lFirstLBound);
olesaRead.GetUBound(1, &lFirstUBound);
olesaRead.GetLBound(2, &lSecondLBound);
olesaRead.GetUBound(2, &lSecondUBound);
memset(index, 0, 2 * sizeof(long));
m_ListCtrl.InsertColumn(0, _T(""), 0, 100);
for (long j = lSecondLBound; j<= lSecondUBound; j++)
{
CString strColName = _T("");
strColName.Format(_T("%d"), j);
m_ListCtrl.InsertColumn(j, strColName, 0, 100);
}
for (long i = lFirstLBound; i <= lFirstUBound; i++)
{
CString strRowName = _T("");
strRowName.Format(_T("%d"), i);
m_ListCtrl.InsertItem(i-1, strRowName);

index[0] = i;
for (long j = lSecondLBound; j <= lSecondUBound; j++)
{
index[1] = j;
olesaRead.GetElement(index, &varItem);

switch (varItem.vt)
{
case VT_R8:
{
strItem.Format(_T("%d"), (int)varItem.dblVal);
}

case VT_BSTR:
{
strItem = varItem.bstrVal;
}

case VT_I4:
{
strItem.Format(_T("%ld"), (int)varItem.lVal);
}

default:
{

}
}

m_ListCtrl.SetItemText(i-1, j, strItem);
}
}




sheet.ReleaseDispatch();
sheets.ReleaseDispatch();
book.ReleaseDispatch();
books.ReleaseDispatch();
ExcelApp.Quit();
ExcelApp.ReleaseDispatch();
 

示例源代碼的工程文件的下載鏈接如下:

http://files.cnblogs.com/xianyunhe/ReadWriteExcel.rar
 

參考材料 

1http://www.cnblogs.com/xianyunhe/archive/2011/09/13/2174703.html

2http://hfp0601.blog.163.com/blog/static/228483522011031104718762/ 

3http://www.cppblog.com/sleepwom/archive/2009/10/03/97804.html 

4http://www.rondebruin.nl/saveas.html

 

 

三:

由於學習對Excel的操作是臨時學的,有很多東西只是一知半解,但好歹是能運行了,相關內容可以參照前兩篇學習筆記。

本文中使用的是OLE方式讀寫,環境是VS2008和Office2003。現在的編譯器有自動完成功能,很容易找到相應的成員函數。查看函數原型有助於理解參數的意義,但仍是有些參數也搞不明白是什么作用,或者如何設置。Excel相關的預定義枚舉類型,都是Xl開頭,比如XlHAlign,是水平對齊,可以用XlHAlign::找到居中、靠右、靠左等應該設置的值。

步驟如下:

1.新建MFC工程,Project - Add Class - MFC Class From TypeLib,選擇File,在Office安裝目錄下找到EXCEL.EXE,選擇相應的接口(參考學習筆記二)。

 

2.VS2008會在工程中加入相應的頭文件。打開頭文件,把#import "D:\\Program Files\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace 一行改成:

#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE11\\MSO.DLL" \
 rename("RGB", "MSORGB") \
 rename("DocumentProperties", "MSODocumentProperties") \
 rename("SearchPath","MsoSearchPath") \
 rename_namespace("Office")
using namespace Office;

#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"

using namespace VBIDE;

#import "C:\\Program Files\\Microsoft Office\\Office11\\EXCEL.EXE" \
 rename("DialogBox", "ExcelDialogBox") \
 rename("RGB","ExcelRGB") \
 rename("CopyFile", "ExcelCopyFile") \
 rename("ReplaceText", "ExcelReplaceText") \
 no_auto_exclude

using namespace Excel;
#undef ExitWindows
#undef DialogBox
#undef RGB

注意“\”字符后面不能放空格

 

3.由於許多Word的對象與Excel對象的名字是相同的,因此兩者同時使用是,必須使用名字空間將其區分。方法簡單,比如自定義名字空間是_excel,則把接口頭文件中

class C***

{...};

改成

namespace _excel

{

class C***

{...};

};

 

4.完成,現在可以編程了。

 

下面是個簡單的例子,包括合並單元格、設置單元格內容、設置單元格格式、設置邊框、獲取單元格內容、保存工作簿等功能

頭文件部分

#include // 為了方便操作 VARIANT 類型變量,使用 CComVariant 模板類

#include "CApplication.h"
#include "CBorders.h"
#include "CFont0.h"
#include "Cnterior.h"
#include "CRange.h"
#include "CWorkbook.h"
#include "CWorkbooks.h"
#include "CWorksheet.h"
#include "CWorksheets.h"

 

實現部分

void CMyExcelDlg::OnBnClickedOk()
{
 _excel::CApplication app;
 _excel::CBorders borders;
 _excel::CFont0 font;
 _excel::Cnterior interior;//背景色
 _excel::CRange range;
 _excel::CWorkbook workbook;
 _excel::CWorkbooks workbooks;
 _excel::CWorksheet worksheet;
 _excel::CWorksheets worksheets;
 CoInitialize(NULL);//初始化COM,最后還有CoUninitialize
 COleVariant covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);

 if(!app.CreateDispatch(_T("EXCEL.application"))) //啟動WORD
 {
  AfxMessageBox(_T("居然你連OFFICE都沒有安裝嗎?"));
  return;
 }
 app.put_Visible(TRUE);//設置表可見性
 app.put_DisplayFullScreen(FALSE);//設置全屏顯示
 app.put_DisplayAlerts(FALSE);//屏蔽警告
 
 //打開工作簿
 CString strPath;
 strPath = "C:\\Documents and Settings\\Administrator\\桌面\\MyExcel\\excel.xls";
 workbooks = app.get_Workbooks();
 try
 {
  workbook = workbooks.Add(_variant_t(strPath));
 }
 catch (CException* e)
 {
  workbook = workbooks.Add(vtMissing);//找不到就新建一個
 }
 

 //獲取工作表worksheet(三種方法)
 worksheet = workbook.get_ActiveSheet();
 worksheets = workbook.get_Sheets();
 //worksheet = worksheets.get_Item((_variant_t("sheet2")));
 //worksheet = worksheets.get_Item((_variant_t(1)));

 

 //新建工作表(此方法錯,可能是參數問題)

 worksheets.Add(vtMissing,vtMissing,_variant_t((long)1),_variant_t(XlSheetType::xlWorksheet));//第三個參數是新表的數量

  //獲取區域

 range = worksheet.get_Range(_variant_t("A1"), _variant_t("A3"));
 //合並單元格
 range.Merge(_variant_t((long)0));

 

 //設置單元格內容
 range = worksheet.get_Range(_variant_t("B2"), _variant_t("C5"));
 range.put_Value2(_variant_t("hey"));//參數是二維數組可以批量設置單元格值

 

 //設置單元格格式
 range = worksheet.get_Range(_variant_t("F2"), _variant_t("G5"));
 range.put_HorizontalAlignment(_variant_t(XlHAlign::xlHAlignRight));//水平對齊
 range.put_VerticalAlignment(_variant_t(XlVAlign::xlVAlignBottom));//豎直對齊
 range.put_ColumnWidth(_variant_t(35));//單位不明

 range.put_RowHeight(_variant_t(24));//磅
 font = range.get_Font();//字體
 font.put_Italic(_variant_t(1));//斜體
 interior =range.get_Interior();//底色
 interior.put_Color(_variant_t(76));

 

//獲取單元格內容
 CString getdata;//定義字符串變量
 _variant_t rValue;
 range = worksheet.get_Range(_variant_t("A1"),_variant_t("A1"));
 rValue = range.get_Value2();
 getdata = rValue.bstrVal;

 

//線框,border會對range中所有單元格都做設置,
 range = worksheet.get_Range(_variant_t("A5"), _variant_t("C9"));
 borders = range.get_Borders();
 borders.put_LineStyle(_variant_t(XlLineStyle::xlDouble));
 
 range = worksheet.get_Range(_variant_t("A12"), _variant_t("C13"));
 range.BorderAround(_variant_t(XlLineStyle::xlDashDot), 2, 8, vtMissing);//外框線

 

//另存為
 covOptional = COleVariant((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
 COleVariant varZero((short)0); 
 COleVariant varTrue(short(1),VT_BOOL); 
 COleVariant varFalse(short(0),VT_BOOL);

 workbook.SaveAs(COleVariant(strPath), COleVariant((long)XlFileFormat::xlWorkbookNormal), vtMissing, vtMissing,
  vtMissing, vtMissing, (long)0, vtMissing,
  vtMissing, vtMissing, vtMissing, vtMissing);
 //workbook.Save();
 
 AfxMessageBox(_T(""));

//所有東西都需要ReleaseDispatch,否則會報錯
 borders.ReleaseDispatch();

 font.ReleaseDispatch();
 interior.ReleaseDispatch();
 range.ReleaseDispatch();
 workbook.ReleaseDispatch();
 workbooks.ReleaseDispatch();
 worksheet.ReleaseDispatch();
 worksheets.ReleaseDispatch();
 app.Quit();//Excel退出
 app.ReleaseDispatch();
 CoUninitialize();//對應CoInitialize
 OnOK();
}

 

四:

【當前博文轉載自 http://blog.csdn.net/sgdgoodboy/article/details/2102628】
【本文前半部分與word相關,發在 C++操作Word學習筆記(三)

 EXCEL篇及命名空間說明

1 Excel組件對象模型    
Microsoft Office Excel 2003文檔中的數據是高度結構化的,因此Excel對象模型也具有層次結構並且簡單明了。Excel 提供了數百個您可能需要與之交互的對象,但是最為重要的是以下四個對象:Application 對象、Workbook 對象、Worksheet 對象和Range 對象。很多工作都是圍繞這四個對象進行的。
Application 對象。Application 對象表示 Excel 應用程序本身。Application 對象提供了大量有關正在運行的應用程序、應用於該實例的選項以及在該實例中打開的當前用戶的對象的信息。
Workbook 對象。Workbook 類表示 Excel 應用程序內的單個工作簿。Application 類的許多成員同時也是 Workbook 類的成員。在這種情況下,屬性應用於特定的工作簿(而非應用於活動工作簿)。
Worksheet 對象。雖然 Worksheet 類提供了大量成員,但大部分屬性、方法和事件都與 Application 和/或 Workbook 類提供的成員相同或相似。Excel 提供 Sheets 集合作為 Workbook 對象的屬性,但 Excel 中沒有 Sheet 類。實際上,Sheets 集合的每個成員不是 Worksheet 對象就是 Chart 對象。
Range 對象。Range 對象是 Excel 應用程序中最常用的對象。在能夠處理 Excel 內的任何范圍之前,必須將它表示為 Range 對象,並處理該對象的方法和屬性。Range 對象表示一個單元格、一行、一列、包含一個或多個單元格塊(可以連續,也可以不連續)的單元格選定范圍,甚至多個工作表中的一組單元格。
對於Microsoft Office Excel 2003,通常可以在..\\Microsoft Office\\OFFICE11\\ EXCEL.exe獲得相關接口類。常用的有_Application, Workbooks, _Workbook, Worksheets, _Worksheet, Range,以及用於生成圖表的_Chart等。

另外,使用MS Graph對象的技術同樣可以生成數據圖表。但是,對象寫入大數據量非常緩慢的。MS Graph工作原理是每寫入一個數據就要對圖表進行更新,因此,MS Graph對於小數據制作圖表是合適的(實現代碼比EXCEL要少),但對於大數據這種工作原理是難以忍受的。盡管如此,EXCEL與MS Graph的接口函數卻是非常相似的。

2 Excel啟動與退出    
使用Application 對象,關聯接口、釋放接口。具體代碼如下:
_Application theExcelApp;
theExcelApp.CreateDispatch("Excel.Application", NULL); //關聯接口
////退出
theExcelApp.Quit();  ////退出
theExcelApp.ReleaseDispatch();  //釋放接口

3 Excel打開記事本(*.txt)        
通常,我們需要從文本(*.txt)文件中載入數據。Excel的Workbooks對象提供了打開文本的函數OpenText ()。OpenText()函數聲明如下:
OpenText(LPCTSTR Filename, const VARIANT& Origin, const VARIANT& StartRow, const VARIANT& DataType, long TextQualifier, const VARIANT& ConsecutiveDelimiter, const VARIANT& Tab, const VARIANT& Semicolon, const VARIANT& Comma, const VARIANT& Space, const VARIANT& Other, const VARIANT& OtherChar, const VARIANT& FieldInfo, const VARIANT& TextVisualLayout, const VARIANT& DecimalSeparator, const VARIANT& ThousandsSeparator, const VARIANT& TrailingMinusNumbers, const VARIANT& Local)
參數說明如下:
Filename 文本路徑。
Origin 文件原始格式。通常值為936,表示簡體中文。
StartRow 導入起始始行。在本報告中第一行為標題行,導入起始行為2。
DataType 數據類型。值設為1。
TextQualifier 文本格式。值為1。
ConsecutiveDelimiter 連續分隔符。值為TRUE
Tab Tab分隔符。值為FALSE。
Semicolon 分號分隔符。值為FALSE。
Comma 逗號分隔符。值為FALSE。
Space 空格分隔符。本電子報告中通常以空格作為分隔符,因此值為TRUE。如若采用其他分隔符,請適當修改。
Other 其它分隔符。值為FALSE。
OtherChar 其他文本識別符號。值為NULL。
FieldInfo 區域信息。同載入文本列數據格式相關。設為VarOpt。
TextVisualLayout 文本可見版式。設為VarOpt。
DecimalSeparator 小數分隔符。設為VarOpt。
ThousandsSeparator 千位分隔符。設為VarOpt。
TrailingMinusNumbers 按負號跟蹤負數。設為TRUE。
Local 本地數據。設為VarOpt。
以上各參數請根據適當需要修改,並根據調試VBA宏代碼獲得參數值。
要說明的是,這種方法載入數據將從B列往后分布。即,如果是TXT文本里有兩列數據,那么載入EXCEL后,這兩列數據將分布在B列與C列,而A列為空。這個原因我也一直不得其解(不知道是我們合作方提供的TXT文本本身設置問題還是別的問題)。這點請讀者注意,也請高手指點。

4 獲取Excel行數目     
載入記事本數據后,需要調用_Worksheet對象獲得數據的行數目。具體代碼如下:
_Worksheet ::GetUsedRange();
獲得已用區域,返回Range對象。注意,這里不能調用_Worksheet ::GetRange();
Range:: GetRows();
獲得行對象。返回Range對象。
Range:: GetCount();
獲得行數目。
獲得行數目在進行生成圖表是很重要的。在生成圖表時,載入源數據的區域時需要獲得行數目。

5 生成Excel圖表及格式         
使用對象。以下要設置其格式。
_Chart:: SetChartType 設置圖表類型。如果使用無數據點平滑線散點圖,值為73。其它圖表類型請自己錄制VBA宏然后調試獲得參數值。
_Chart:: SetSourceData生成圖表的原數據。傳遞一個Range對象。
_Chart:: SetHasLegend 標注。設為FALSE,不顯示標注。
_Chart:: SetHasTitle 標題。設為TRUE,顯示標題。
並假設獲得行數目為432,則SetSourceData的參數值為Range(“B1”, “C432”)。

如果需要對網格線進行格式控制,需要調用以下函數:
_Char::Axes 返回Axis對象
Axis::SetHasMajorGridlines 設置主格線,TRUE
Axis::SetHasMinorGridlines 設置次格線,FALSE
Axis::GetMajorGridlines 獲得主格線對象(前提是設置主格線為TRUE),返回Gridlines對象
Gridlines::GetBorder 獲得邊框對象,返回Borders對象
Borders::SetColorIndex 設置顏色,57表示黑色
Borders::SetLineStyle 設置線條格式,-4118表示虛線
Borders::SetWeight 設置粗細
以上Borders各參數值可根據需要適當修改。

Axis::SetCrossesAt 可設置坐標軸相交位置。通常需要Axis::GetMinimumScale獲得最小刻度值,然后相交於最小刻度值。

6 設置標題文字及曲線格式   
使用AxisTitle ,,Font對象設置文字,包括設置文字上標等。注意,Excel並不提供類似於Word的Selection對象,要進行文字格式控制,通常需要用到Characters對象,即對指定文字進行格式控制。
使用Series,Borders對象可對曲線進行控制。可利用_Char:: SeriesCollection返回一個Series對象。

7 保存    
使用_Workbook:: SaveAs函數。具體參數值設置較為簡單,參看VBA宏代碼即可。此處略。

8 命名空間namespace     
由於許多Word的對象與Excel對象的名字是相同的,因此,必須使用名字空間將其區分。命名空間的使用方法很簡單,在.h和.cpp文件分別添加
namespace mynamespace
{
   //Statement;
}
把名字有沖突的類的聲明與實現放入namespace的作用域里。然后調用類是前面加命名空間作用符。
舉例如下:Word和Excel都有_Application對象,如果不使用命名空間則會發生編譯錯誤。
可在excel.h添加
namespace myExcel
{
     class _Application : public COleDispatchDriver
{
   //Statement;
}
}
在excel.cpp將所有_Application的方法放入到命名空間中。
namespace myExcel
{
(_Application的方法實現代碼)
}
調用Excel的_Application對象類時,使用方法為
myExcel:: _Application _myExcelApp;
即聲明該_Application屬於myExcel命名空間作用域。
關於命名空間在C++教材的“高級主題部分”會有涉及。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM