VC匯出資料到EXCEL
我們製作應用軟體的時候,經常要把結果以報表的形式輸出,當前使用較為廣泛的當然是Excel表格,本文簡略介紹在VC++6.0中如何使用Excel2003的庫函式並對其進行程式設計。先建立一個對話方塊工程,命名為VCExcel。在對話方塊中新增一個按鈕,控制元件ID為ID_RUNEXCEL,介面如下(是不是很搞笑哇,不過沒關係,它照樣能實現強大的功能!)。
再在該按鈕上新增訊息BN_CLICKED,其訊息對映函式為OnRunexcel(),下面我們的工作就是要完成這個OnRunexcel()函式。在這裡我們通過一個例項來說明VC是如何呼叫Excel2003的介面程式設計的。
我們要程式設計輸出一個如下表格。
格式如下:
1、表頭的字型為宋體,加粗,顏色為白色,底色為深藍,垂直水平居中對齊;
2、表中正文內容字型為宋體,顏色為深藍,底色為灰色,垂直水平居中對齊;
3、全部邊框,文字自動換行。
在BOOL CVCExcelApp::InitInstance()之中,int nResponse = dlg.DoModal()語句之後加入如下程式碼:
if(!AfxOleInit())///初始化COM庫
{
AfxMessageBox("初始化COM失敗");
return FALSE;
}
為了能呼叫Excel的介面我們開啟MFC ClassWizard->Automation->Add Class->From a type library,選擇[Excel的安裝路徑]\EXCEL.exe,然後把所有的類都新增進去,標頭檔案為excel.h,原始檔為excel.cpp。當然,你也可以只把一些比較常用的類如_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range加進去,因為網上流傳的絕大部分教程都只新增這幾個類,這完全根據你個人的需要。但在本例中我們至少還要用到Interior類(設定底色),Font類(設定字型),而且這樣做又簡單又方便擴充套件功能,不管三七二十一全部弄進去吧!但這樣做會有一個問題,有可能產生類的名字衝突,例如本來你自己寫了一個類叫Font,當你全部新增時又再次加入了Font類,這樣就重複定義了,不過可以通過名字空間來解決這個問題。再在VCExcelDlg.cpp檔案的頭部新增(如果系統已經自動新增就不要重複添加了):
#include "VCExcel.h"
#include "comdef.h"
這樣一來我們的程式就可以自由呼叫EXCEL了,一切準備就緒。
下面先在CVCExcelDlg中新增如下成員變數,用來操控Excel應用程式、工作簿和單元格。
Range m_ExlRge;
_Worksheet m_ExlSheet;
Worksheets m_ExlSheets;
_Workbook m_ExlBook;
Workbooks m_ExlBooks;
_Application m_ExlApp;
我們利用載入Excel模板來生成要求的表格,在本工程Debug資料夾中建立一個Excel檔案,命名為Template.xls。我們的OnRunexcel()程式碼如下(詳見註釋):
void CVCExcelDlg::OnRunexcel()
{
// TODO: Add your control notification handler code here
//用m_ExlApp物件建立Excel2003程序
if(!m_ExlApp.CreateDispatch("Excel.Application",NULL))
{
AfxMessageBox("建立Excel服務失敗!");
return;
}
//設定為可見
m_ExlApp.SetVisible(TRUE);
///////////////////下面得到應用程式所在的路徑///////////////////
CString theAppPath,theAppName;
char Path[MAX_PATH];
GetModuleFileName(NULL,Path,MAX_PATH);//得到應用程式的全路徑
theAppPath=(CString)Path;
theAppName=AfxGetApp()->m_pszAppName;
theAppName+=".exe";
//把最後的檔名去掉
int length1,length2;
length1=theAppPath.GetLength();
length2=theAppName.GetLength();
theAppPath.Delete(length1-length2,length2);
////////////////////////////////////////////////////////////////
CString TempPath="";
TempPath=theAppPath+"Template.xls";//EXCEL模板的路徑
m_ExlBooks.AttachDispatch(m_ExlApp.GetWorkbooks(),TRUE);
m_ExlBook.AttachDispatch(m_ExlBooks.Add((_variant_t)TempPath),TRUE);//載入EXCEL模板
m_ExlSheets.AttachDispatch(m_ExlBook.GetSheets(),TRUE);//載入Sheet頁面
//新增新的Sheet頁面
m_ExlSheets.Add(vtMissing,vtMissing,_variant_t((long)1),vtMissing);
//刪除第二個Sheet頁面
m_ExlSheet.AttachDispatch(m_ExlSheets.GetItem(_variant_t((long)2)),TRUE);
m_ExlSheet.Delete();
//把第一個Sheet頁面的名字改變為TestSheet
m_ExlSheet.AttachDispatch(m_ExlSheets.GetItem(_variant_t((long)1)),TRUE);
m_ExlSheet.SetName("TestSheet");
///////合併第一行單元格A1至D1//////
//載入要合併的單元格
m_ExlRge.AttachDispatch(m_ExlSheet.GetRange(_variant_t("A1"),_variant_t("D1")),TRUE);
m_ExlRge.Merge(_variant_t((long)0));
////////設定表格內容////////
m_ExlRge.AttachDispatch(m_ExlSheet.GetCells(),TRUE);//載入所有單元格
m_ExlRge.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t("數學系研究生課程統計"));
m_ExlRge.SetItem(_variant_t((long)2),_variant_t((long)1),_variant_t("課程名"));
m_ExlRge.SetItem(_variant_t((long)2),_variant_t((long)2),_variant_t("課時"));
m_ExlRge.SetItem(_variant_t((long)2),_variant_t((long)3),_variant_t("難度"));
m_ExlRge.SetItem(_variant_t((long)2),_variant_t((long)4),_variant_t("教學方式"));
m_ExlRge.SetItem(_variant_t((long)3),_variant_t((long)1),_variant_t("泛函分析"));
m_ExlRge.SetItem(_variant_t((long)3),_variant_t((long)2),_variant_t("60"));
m_ExlRge.SetItem(_variant_t((long)3),_variant_t((long)3),_variant_t("普通"));
m_ExlRge.SetItem(_variant_t((long)3),_variant_t((long)4),_variant_t("老師講課"));
m_ExlRge.SetItem(_variant_t((long)4),_variant_t((long)1),_variant_t("微分流形"));
m_ExlRge.SetItem(_variant_t((long)4),_variant_t((long)2),_variant_t("40"));
m_ExlRge.SetItem(_variant_t((long)4),_variant_t((long)3),_variant_t("變態難"));
m_ExlRge.SetItem(_variant_t((long)4),_variant_t((long)4),_variant_t("自學"));
m_ExlRge.SetItem(_variant_t((long)5),_variant_t((long)1),_variant_t("二階橢圓型方程與方程組"));
m_ExlRge.SetItem(_variant_t((long)5),_variant_t((long)2),_variant_t("60"));
m_ExlRge.SetItem(_variant_t((long)5),_variant_t((long)3),_variant_t("很難"));
m_ExlRge.SetItem(_variant_t((long)5),_variant_t((long)4),_variant_t("討論"));
m_ExlRge.AttachDispatch(m_ExlSheet.GetUsedRange());//載入已使用的單元格
m_ExlRge.SetWrapText(_variant_t((long)1));//設定單元格內的文字為自動換行
//設定齊方式為水平垂直居中
//水平對齊:預設=1,居中=-4108,左=-4131,右=-4152
//垂直對齊:預設=2,居中=-4108,左=-4160,右=-4107
m_ExlRge.SetHorizontalAlignment(_variant_t((long)-4108));
m_ExlRge.SetVerticalAlignment(_variant_t((long)-4108));
///////設定整體的字型、字號及顏色//////
Font ft;
ft.AttachDispatch(m_ExlRge.GetFont());
ft.SetName(_variant_t("宋體"));//字型
ft.SetColorIndex(_variant_t((long)11));//字的顏色
ft.SetSize(_variant_t((long)12));//字號
///////////設定標題字型及顏色//////////
m_ExlRge.AttachDispatch(m_ExlSheet.GetRange(_variant_t("A1"),_variant_t("D1")));
ft.AttachDispatch(m_ExlRge.GetFont());
ft.SetBold(_variant_t((long)1));//粗體
ft.SetSize(_variant_t((long)13));
ft.SetColorIndex(_variant_t((long)2));
CellFormat cf;
cf.AttachDispatch(m_ExlRge.GetCells());
//////////////設定底色/////////////////
Interior it;
it.AttachDispatch(m_ExlRge.GetInterior());
it.SetColorIndex(_variant_t((long)11));//標題底色
////表格內容的底色////
m_ExlRge.AttachDispatch(m_ExlSheet.GetRange(_variant_t("A2"),_variant_t("D5")));
it.AttachDispatch(m_ExlRge.GetInterior());
it.SetColorIndex(_variant_t((long)15));
//////////////為表格設定邊框/////////////
Range UnitRge;
CString CellName;
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
CellName.Format("%c%d",j+64,i);//單元格的名稱
UnitRge.AttachDispatch(m_ExlRge.GetRange(_variant_t(CellName),_variant_t(CellName)));//載入單元格
//LineStyle=線型 Weight=線寬 ColorIndex=線的顏色(-4105為自動)
UnitRge.BorderAround(_variant_t((long)1),_variant_t((long)2),_variant_t((long)-4105),vtMissing);//設定邊框
}
}
//釋放物件(相當重要!)
m_ExlRge.ReleaseDispatch();
m_ExlSheet.ReleaseDispatch();
m_ExlSheets.ReleaseDispatch();
m_ExlBook.ReleaseDispatch();
m_ExlBooks.ReleaseDispatch();
//m_ExlApp一定要釋放,否則程式結束後還會有一個Excel程序駐留在記憶體中,而且程式重複執行的時候會出錯
m_ExlApp.ReleaseDispatch();
//退出程式 m_ExlApp.Quit();
}
小結:一年前就想寫這個東西了,因為網上講VC與Office程式設計的資料實在是太少了,即使有也很片面(VB講這方面的東西卻又多又全,鬱悶~),想當初做這個東西的時候上網查資料快查瘋掉了,最後還是一堆問題沒有解決。哈哈,現在無聊靜下心來一研究發現原來VC蹂躪Excel也不是一件難事啊,在這個例子裡面包含了很多常用的功能,相信做一般的報表是沒什麼問題的。要是做更復雜的報表怎麼辦呢?一個例子也不可能包括方方面面呀,那確實,因此有很多東西是需要讀者自己探討的。下面我告訴大家一個方法,細心的讀者可能已經發現有些引數不知道是從哪裡蹦出來的,例如:水平對齊:預設=1,居中=-4108,左=-4131,右=-4152。這就要用到Office的巨集錄製功能(什麼?你沒聽過?網上去查吧^__^),把你要的操作用巨集錄製下來,然後用VB開啟,單步除錯的時候就能發現這些祕密了!上面例子中的引數都是DoDo在巨集裡面找到滴,哈哈,是不是很簡單?快去試試吧~
Range range = mWorkSheet.GetRange(COleVariant( "A1 "),COleVariant( "C4 "));//設定待操作的單元格範圍
range.SetNumberFormatLocal(COleVariant( "@ ")); //設定你的巨集中實現的單元格格式設定 為文字格式