- 論壇徽章:
- 0
|
[求助]如何將c++builder中的報表轉(zhuǎn)化成excel文件?
用C++Builder存取Excel
-----------------------------------------------------------------------------
----
C++Builder是Borland公司繼Delphi之后又一成功的產(chǎn)品,她集VB、VC++ 及 Delphi 的優(yōu)點于一體而深得C語言愛好者的青睞。由于多數(shù)操作者愛用 MicroSoft公司的Excel組織數(shù)據(jù),為此本文介紹了用C++Builder存取Excel 文件的兩種方法。
---- 一.用OLE技術操縱Excel
---- OLE(對象鏈接與嵌入)是微軟提出的標準,是應用程序間交換數(shù)據(jù)、相互操作的一種方式,MS OFFICE 提供了很強的 OLE 服務功能,VB、Delphi 及C++Builder等語言都可以以客戶方式向Excel提交命令,以存取其數(shù)據(jù),其中VB和Delphi最為簡單,在語法上就采用類VBA的語句,本報九九年第48期的《在Delphi中操作Excel》一文曾介紹了Delphi的做法。我們原以為C++Builder照搬Delphi,結果語法編譯都未能通過,查不到這方面具體介紹的資料。經(jīng)反復試驗方知:原來C++Builder采用間接的辦法,利用變體類Variant所提供的四個“方法”向OLE服務程序提交操縱命令:
Variant Variant::OlePropertyGet(屬性名,參數(shù)….);
// 取對象屬性
Void Variant::OlePropertySet(屬性名,參數(shù)….);
// 設置對象屬性
Variant Variant::OleFunction(函數(shù)名,參數(shù)….);
// 運行對象的函數(shù)
void Variant::OleProcedure(過程名,參數(shù)….);
// 運行對象的過程
其頭文件“vcl\utilcls.h”必須嵌在用戶程序中,
對于這四個長長的方法名可在程序中用宏語句重新定義一下:
#define PG OlePropertyGet
#define PS OlePropertySet
#define FN OleFunction
#define PR OleProcedure
例如對于VB的提交語句:
Ex.ActiveWorkBook.ActiveSheet.Cells(1,2).Value=3
為便于理解在C++Builder對應的語句可分解為如下四句:
Variant t1=Ex.OlePropertyGet("ActiveWorkBook" ;
Variant t2=t1.OlePropertyGet("ActiveSheet" ;
Variant t3=t2.OlePropertyGet("Cells,1,2);
t3.OlePropertySet("Value",3);
可去掉中間變量將這四句合為一句,就是:
Ex.PG("ActiveWorkBook" .PG("ActiveSheet" .
PG("Cells",1,2).PS("Value",3);
我們將下面的VB程序片段改成對應的C++Builder程序以供參考:
Private Sub Command1_Click() ' Visual Basic程序片段
Dim Ex As Object,Wb As Object, Sh1 As Object
Set Ex = CreateObject("Excel.Application"
Ex.WorkBooks.Open("c:\book1.xls"
Set Wb = Ex.Activeworkbook
Set Sh1 = Wb.ActiveSheet
Text1.Text = Sh1.Cells(1, 1).Value
For i = 1 To 10: For j = 1 To 10
Sh1.Cells(i, j).Value = i * 100 + j
Next j: Next i
Wb.save: Wb.Close: Ex.Quit
End Sub ' - - - - - -- - - - - - - - - - -
#include "Unit1.h" // C++Builder程序片段
#include "vcl\utilcls.h" // util classes實用類說明
// …省寫此處原一段代碼
// 請在此處插入上面提及的四個宏定義語句
void __fastcall TForm1::Button1Click(TObject *Sender)
{ Variant Ex,Wb,Sh1;
Ex=Variant::CreateObject("Excel.Application" ;
Ex.PG("WorkBooks" .PR("Open","c:\\book1.xls" ;
Wb=Ex.PG("ActiveWorkBook" ; Sh1=Wb.PG("ActiveSheet");
Edit1->;Text=Sh1.PG("Cells",1,1).PG("Value");
for (int i=1;i<=10;i++)
for (int j=1;j<=10;j++)
Sh1.PG("Cells",i,j).PS("Value",i*100+j);
Wb.PR("Save"); Wb.PR("Close");
}
---- 使用這種方法的程序運行時,必須保證系統(tǒng)中同時有MS OFFICE;下面我們再介紹另一種脫離MS OFFICE也能存取Excel表格的方法。
---- 二.用ODBC數(shù)據(jù)庫技術存取Excel
---- ODBC就是開放式數(shù)據(jù)庫鏈接標準,不同種類的數(shù)據(jù)庫只需提供各自的ODBC 驅(qū)動程序就可按相同的命令操縱,微軟同樣為Excel提供了ODBC驅(qū)動程序,我們可在程序中象數(shù)據(jù)庫一樣存取Excel表格。定義好ODBC數(shù)據(jù)源后,實際試驗中并沒有如想象的那樣簡單,在控件Table的屬性TableName中總是檢索不到表名,同樣也沒有相關的資料可供查閱。通過對Excel的分析,終于發(fā)現(xiàn)了問題的關鍵所在:ODBC的表名并不就是Excel的工作表名(如Sheet1),在Excel 表格中必須對要求操作的行列區(qū)域定義一個“名稱”作為數(shù)據(jù)庫的表名,該區(qū)域的首行各列必須是字段名(否則首行數(shù)據(jù)會當成字段名),可以定義多個表名。具體操作步驟如下:
---- 1.在Excel上定義“表名”:
---- 運行Excel程序,打開或新建一表格,按下鼠標左鍵選擇一片區(qū)域(起始行先填上字段名),再將鼠標位置點到左上角的地址欄,輸入一表名如ABC,或者在菜單上選:“插入(I)”-“名稱(N)”-“定義(D)”,再輸入表名(若已定義, 可在此處刪除掉),存盤退出(假定文件名取為c:\Book.xls),若嫌字段名行多余,存盤前可隱藏掉;
---- 2.定義ODBC數(shù)據(jù)源:
---- 從Windows桌面“我的電腦"進入“控制面板”,雙擊“32位ODBC”圖標,運行“用戶DSN”中的“添加(D)"后選“Excel Driver(*.xls)", 再點“完成”便彈出對話框,在“數(shù)據(jù)源名(N)"右邊填一名稱,如:excel01,在“版本(V)"上選“Excel97", 點中“選項”取消“只讀”,在“選定工作目錄”中,選定Excel文件名(本例 c:\Book1.xls),再點“確定”直至退出;
---- 3.設置Database控件避免登錄檢查:
---- 運行C++Builder,在Form1中加上Data Access的三個控件:Database1、 DataSource1、Table1,加入Database1的目的是為了避免打開數(shù)據(jù)庫時出現(xiàn)登錄框,為此雙擊此控件彈出一對話框,在Alias name中選ODBC數(shù)據(jù)源名(本例為Excel01),在Name中填上一新的別名(本例取Excel02),再點“Defaults” 出現(xiàn)一批參數(shù)缺省值,最后取消Options中的兩項“Login prompt"與"Keep inactive connect”,點OK退出;
---- 4.設置其它控件屬性:
---- 將Table1的屬性DatabaseName選為步驟3中的新別名Excel02,再將另一屬性TableName選為步驟1的表名(本例為ABC);將控件DataSource1的屬性 DataSet選為Table1;雙擊Form1,在FormCreate事件子程序內(nèi)加上一句 Table1- >;Open( );
---- 5.查看數(shù)據(jù)庫內(nèi)容:
---- 為了直接看到Excel數(shù)據(jù),在Form1中再加上Data Controls的控件DBGrid1 和DBNavigator1,將兩者的屬性DataSource都選為DataSource1,雙擊Table1 的屬性Active將值改為true,等待數(shù)秒就可看到DBGrid1中出現(xiàn)數(shù)據(jù),最后恢復Tabel1- >;Active為false;
---- 注意:程序編譯前,必須將剛打開的表關閉,即:使Table1- >;Active為false, 否則程序運行時報告出錯,因為Excel表總是被ODBC以“獨占”方式打開;
---- 我們使用的是C++ Builder 4.0專業(yè)版,電子表格為Excel 97
-----------------------------------------------------------------------------
用C++Builder操縱Excel
-----------------------------------------------------------------------------
Microsoft Excel作為一個功能強大的電子表格處理軟件,已經(jīng)得到了廣泛的應用。在數(shù)據(jù)庫應用軟件開發(fā)過程中,如果能實現(xiàn)數(shù)據(jù)庫與Excel文件的數(shù)據(jù)交換,那么一方面能增加數(shù)據(jù)庫數(shù)據(jù)的來源,另一方面也能方便用戶對數(shù)據(jù)庫數(shù)據(jù)的進一步處理。
C++ Builder是一個可視化快速應用程序開發(fā)工具,它提供的OLE Automation機制使得開發(fā)人員在應用程序中就能調(diào)用Excel,實現(xiàn)數(shù)據(jù)交換。
在C++ Builder中調(diào)用Excel,首先要為Excel建立一個OLE對象,然后通過設定該對象的屬性和調(diào)用該對象的方法來操縱Excel。C++ Builder通過CreateOleObject()來建立OLE對象;用OlePropertySet(propname,value)來設置OLE對象的屬性;用OlePropertyGet(propname)獲得OLE對象的屬性;通過OleFunction(oleFuncName,[val,...])和OleProcedure(oleProcName,[val,...])來調(diào)用OLE對象的方法。
C++ Builder中使用OLE自動化操縱Excel,必須掌握Excel的自動化對象及VBA關于Excel的對象方法和屬性,這些都在Microsoft Office(完全安裝)的VBAXL8.HLP幫助文件中可以找到,在此就不再贅述。下面以將數(shù)據(jù)庫中的數(shù)據(jù)轉(zhuǎn)到Excel工作薄中為例,說明C++ Builder操縱Excel的具體方法。
首先新建一個表單Form1,保存單元文件Unit1.cpp,保存工程文件Project1.bpr。然后在表單中加入數(shù)據(jù)訪問控件TTable,將Name屬性設為Table1,DatabaseName屬性設為BCDEMOS,TableName屬性設為Country.db。在表單中加入一個按鈕控件TButton,將其Name屬性設為Button1,Caption屬性設為 “轉(zhuǎn)換為Excel文件”。雙擊Button1,在Button1Click()函數(shù)中加入如下代碼:
Variant ex,newxls;
int i,j=1;
try
{
ex=CreateOleObject(″Excel.Application″); //啟動Excel
}
catch(...)
{
ShowMessage(″無法啟動Excel″);
}
ex.OlePropertySet(″Visible″,(Variant)true); //使Excel啟動后可見
newxls=(ex.OleFunction(″Workbooks″)).OleFunction(″Add″);//新建一個工作薄
Table1-〉Active=true;
//打開數(shù)據(jù)庫
Table1-〉First();
for(i=0;i〈Table1-〉FieldCount;i++)
//將字段名寫到工作薄的第一行
{
(ex.OleFunction(″Cells″)).OlePropertySet(″Item″,(Variant)1,(Variant)(i+1),(Variant)Table1-〉Fields-〉FieldName);
}
while(!Table1-〉Eof)
//將數(shù)據(jù)庫中的記錄依次寫到工作薄中
{
j=j+1;
for(i=0;i〈Table1-〉FieldCount;i++)
{
(ex.OleFunction(″Cells″)).OlePropertySet(″Item″,(Variant)j,(Variant)(i+1),
(Variant)Table1-〉Fields-〉AsString);
}
Table1-〉Next();
}
newxls.OleFunction(″SaveAs″,(Variant)filename);
//保存工作薄,filename是工作薄的全文件名
ex.OleFunction(″Quit″);
//退出Excel,釋放OLE對象
注意,要使用OLE自動化對象,在編譯之前還必須在Unit1.cpp文件前面加上#include ″ComObj.hpp″。
運行程序就可以實現(xiàn)將數(shù)據(jù)庫中的數(shù)據(jù)轉(zhuǎn)換到Excel工作薄中。同樣的道理,使用OlePropertyGet()函數(shù),也可以將Excel工作薄中的數(shù)據(jù)讀到數(shù)據(jù)庫中去。
以上代碼在Windows 98操作系統(tǒng)、C++ Builder 3.0下調(diào)試運行通過。
摘自《賽迪網(wǎng)》 趙天平/文
|
|