劉慧英,李瑩瑩,孫景峰
(西北工業(yè)大學 自 動化學院,陜西 西 安 7 10129)
各領域每天都有大量的報表需要編制,各類報表的測試項目、參數很多,試驗數據類型多樣化(包括圖像、表格、實驗報告文檔等),因此運用計算機技術加強試驗數據自動化管理,提高試驗管理的質量,為各類系統,尤其是軍用系統,提供準確可靠、高質量的試驗數據和判斷依據,對增強我國綜合國力具有十分重要的戰(zhàn)略意義和現實意義。
在報表的自動生成方面,文獻[1]采用VBA編程。VBA是實現Word文檔自動生成的強有力的編程工具,但在軟件重用性與代碼安全性上存在缺陷和漏洞,不能滿足繼承和封裝的要求。文獻[2]采用Delphi來實現。Delphi與BDE的無縫集成,以及Delphi提供的現成數據庫操作控件,使得Delphi在數據庫支持上有很大優(yōu)勢,但其在兼容性和穩(wěn)定性等方面存在著許多的不足。文獻[3]介紹了用VC++與VBA實現復雜報表自動生成的方法,但是該方法不支持文字、圖片等其他內容的插入[4]。
本文在VC++開發(fā)平臺上,使用C++語言,利用COM編程技術,在源代碼中調用Word中的 OLE自動化對象,結合XML的DOM技術實現報表界面的動態(tài)加載,最終實現復雜報表的自動生成。
OLE(Object Linking and Embedding,對象鏈接與嵌入)是一種為Windows設計的交互進程通信技術,它建立在COM(Component Object Model,組件對象模型)基礎之上。要調用Word提供的OLE自動化對象,可以通過Word提供的對象庫實現。
XML(Extensible Markup Language,可擴展標記語言)允許用戶按照XML規(guī)則自定義標簽,但它對規(guī)則的要求十分嚴格。微軟提供一個MSXML.DLL的動態(tài)鏈接庫,它也是一個COM對象庫,里面封裝了進行XML解析所需要的所有必要的對象。MSXML解析器根據XML文檔生成一個DOM(Document Object Model,文檔對象模型)樹結構,使程序能夠讀XML文檔并根據XML文檔內容創(chuàng)建一個節(jié)點的邏輯結構。DOM使用戶能夠把文檔看成是一個有結構的信息樹,其包含兩個關鍵的抽象:一個樹狀的層次,樹狀層次包括了所有這些節(jié)點,節(jié)點本身也可以包含其他節(jié)點;另一個用來表示文檔內容和結構的節(jié)點集合[5]。
本報表程序實現了界面動態(tài)加載,即可以默認自動輸出報表,也可以在界面加載過程中手動修改數據,其流程如下:首先需要創(chuàng)建相關XML文件,解析XML文件生成DOM樹結構,不同的動態(tài)數組存放相應類型的控件信息,將DOM節(jié)點與控件動態(tài)數組關聯起來。
創(chuàng)建一個唯一的模態(tài)對話框,即父界面對話框,其內容加載是按照配置文件“UICfg.XML”中的節(jié)點內容進行的。父界面對話框的主要功能是選擇本次報表所包含的試驗及加載封面、綜述等界面。
然后遍歷選擇的第一個試驗對應的XML文件節(jié)點動態(tài)的創(chuàng)建子界面及控件,將控件指針存入動態(tài)數組中,用戶對生成的子界面對話框進行操作,并將控件中的數據利用GetText、PutText、InlineShapes 等 庫 函 數 讀 取 到 在 XML 文 件中,為下面報表生成時從XML文件中讀取數據做準備,清除界面控件元素,清除控件動態(tài)數組內容,因為下個實驗也要用到這些動態(tài)數組。
檢查是否最后一個實驗的動態(tài)界面已經生產完畢,否則生成下一個試驗的子界面,是則結束界面的動態(tài)加載,準備輸出報表。報表界面動態(tài)加載流程如圖1所示。
圖1 報表界面動態(tài)加載流程Fig.1 Flow chart of the reface dynamically loaded
報表界面動態(tài)加載完成后即開始報表內容的自動輸出, 運用Word中的 Bookmarks、Document、Rang等智能指針創(chuàng)建報表模板,然后遍歷DOM樹結構的節(jié)點,將其值寫入模板指定的位置,判斷是否最后一個試驗的DOM樹結構遍歷結束,如果否則繼續(xù)遍歷下個試驗的DOM樹結構,是則報表輸出完成。報表自動輸出流程如圖2所示。
圖2 報表自動輸出流程Fig.1 Flow chart of the report automatically generation
VC++通過COM技術調用Word自動化服務器中的OLE自 動 化 對 象 , 如 :_Application、_Document、Range、Selection、Bookmark、_ParagraphFormat等,實現文字、表格、圖片插入,頁面設置,標題的設置以及目錄的生成。所以工程中必須導入Word類庫[6],具體操作如下:在VC++中選擇菜單“項目”,點擊“添加類”,在彈出的對話框中選擇按Type Lib中的MFC類,點擊“添加”即打開從類庫中添加類向導界面,在Office安裝目錄下找到Word類庫文件MSWORD.OLB,選擇需要的接口并將其導入,如圖3所示。
圖3 導入Word類庫Fig.3 Importing the word class library
本文的應用實例為電磁兼容試驗報表生成,鑒于電磁兼容各類試驗中測試項目、參數有重復處,為避免反復輸入相同的信息或做重復的格式修改,可利用XML文檔遵循嚴格式和標準的特性,在原有的文檔基礎上稍做修改得到其他配置文件。
DOMDocument對象是XML DOM的基礎,可以利用它所暴露的屬性和方法來瀏覽、查詢和修改XML文檔的內容和結構。
IXMLDOMNode是XML DOM中的基本的對象,元素,屬性,注釋,過程指令和其他的文檔組件都可以認為是IXMLDOMNode。
IXMLDOMNodeList實際上是一個節(jié)點 (Node)對象的集合,節(jié)點的增加、刪除和變化都可以在集合中立刻反映出來,可以通過“for...next”結構來遍歷所有的節(jié)點。
選擇XML文檔作為配置文件,應用時需在工程中加載msxml4.dll。在程序中加入:#import"msxml4.dll"。
在應用程序中添加DOMDocument對象,如下:
HRESULT hr;
IXMLDomDocument*m_XMLDoc;
IXMLDOMNode*m_XDN;
Hr=CoInitialize(NULL);//COM的初始化
//得到關于IXMLDOMDocument接口的指針m_XMLDoc。
hr =CoCreateInstance (CLSID_DOMDocument,NULL,CLSCTX_INPPROC_SERVER,
ID_IXMLDOMDocument,(void**)&m_XMLDoc);
//得到關于IXMLDOMNode接口的指針m_XDN。
hr=pXMLDoc->QueryInterface(IID_IXMLDOMNode,(void**)&m_XDN);
加載配置文件的核心代碼如下所示,其中Cover.xml為實例中的封面配置文件。
CString strfilepathtemp=Rprfilepath+"Cover.xml";//獲取配置文件路徑
m_RptXmlDoc->load((COleVariant)strfilepathtemp);//加載配置文件
在插入文字或者表格之前,必須首先獲得文檔光標的位置,以便在模板指定的位置上插入相應的內容。下面列出部分程序中用到的WORD中指針,這些指針應用于Bookmarks的定位。
//定義書簽
Word::BookmarkPtr bookmark;
Word::BookmarksPtr bookmarks;
//WORD中指針
Word::ColumnPtr m_word_col;//列指針
Word::ColumnsPtr m_word_cols;//列集指針
Word::CellPtr m_word_cell;//單元格
Word::RowsPtr m_word_rows;//行集指針
Word::RowPtr m_word_row;//行指針
設置圖片的“版式”為嵌入式,則該圖片在Word文檔中就可以用InlineShape表示,InlineShape對象被視為字符,可將其象字符一樣放置于一行文本中。InlineShape對象是InlineShapes集合中的一個成員,采用InlineShapes集合中AddPicture方法添加圖片。主要代碼如下:
Word::InlineShapesPtr shapes;
Word::InlineShapePtr shape;
COleVariant vOpt (DISP_E_PARAMNOTFOUND,VT_ERROR);
shapes=m_word_range->GetInlineShapes();
shape=shapes->AddPicture(_bstr_t(strtable),vOpt,vOpt,vOpt);
1)默認表格的填寫
首先找到將要填寫的表格所對應的XML文件,讀取它所有的節(jié)點屬性,判斷表格的類型(下面代碼中省略),表格指針指向當前的行與列,使用PutText函數,按節(jié)點樹逐層輸出XML文件中的信息。
MSXML::IXMLDOMNodeListPtr L2nodelist;
L2nodelist=m_RptXmlElem->GetchildNodes();
//讀取節(jié)點屬性
patb=m_RptXmlElem->Getattributes();
CString strtemp1=m_RptXmlNode->Gettext();//strtemp1
AddNewTable(1,1);
int rownum=m_word_rows->GetCount();
//表格指針指向當前的行與列
m_word_rows=m_word_table->GetRows();
m_word_cols=m_word_table->GetColumns();
m_word_cell=m_word_table->Cell(rownum,1);
m_word_range=m_word_cell->GetRange();
m_word_range->PutText((_bstr_t)strtemp1);
2)其他表格的填寫
在操作過程中對表格的修改會改變默認表格的輸出,直接在界面編輯框中輸入的信息,將被界面中“保存”按鈕讀并存入XML文件中,為其新建節(jié)點,更新XML文件,到程序輸出時再次調用PutText函數,讀取所有節(jié)點。
該報表自動生成技術已應用于某電磁兼容試驗數據自動化管理系統的報表自動生成子模塊中,目前運行良好。圖4顯示了程序生成電磁兼容檢查報告的封面信息。
圖4 報表自動輸出結果Fig.4 Result of the report automatically generation
報表程序界面采用動態(tài)加載,既可以按照模板輸出默認報表,也可以動態(tài)添加元素,根據需要生成不同特性的報表。
與傳統報表生成模型相比,本文提出的報表自動生技術運用COM技術,采用XML文件作為配置文件,用戶可以按照標準自己定義新的XML文件,使該報表模塊能夠移植到其他系統中;XML分析程序更加要挑剔語法和結構,其每次的分析結果都是一致的,解析程序不論在性能還是穩(wěn)定性方面都更容易實現;同時因為解析程序不需要花時間重建不完整的文檔,提高了報表的生成效率。
[1]金良鋒,周文詳.WORD試驗報告的自動生成[J].中國測試技術,2007,33(4):112-115.JIN Liang-feng,ZHOU Wen-xiang.Auto generation of experiment report in WORD form[J].China Measurement Technology,2007,33(4):112-115.
[2]魯保玉,楊新芳.用Delphi生成Word報告及動態(tài)結構表格[J].計算機應用與軟件,2007,24(3):180-183.LU Bao-yu,YANG Xin-fang.Using delphi creates the word report and the dynamical structured form[J].Computer Applications and Software,2007,24(3):180-183.
[3]朱敏,沈同圣,王學偉,等.VC++與VBA結合實現復雜報表[J].計算機應用與軟件,2005,22(2):42-43,101.ZHU Min,SHEN Tong-shen,WANG Xue-wei,et al.Realize complicated reports via VC++and VBA[J].Computer Applications and Software,2005,22(2):42-43,101.
[4]熊瑜容,柴 毅 ,王淑娟,等.基于VC++的Word文檔自動生成技術[J].計算機時代,2010(1):52-54.XIONG Yu-rong,CHAI Yi,WANG Shu-juan,et al.Word document automatically generated technology based on VC++[J].Computer Era,2010(1):52-54.
[5]郭玉霞.VC++使用DOM操作XML文檔 [J].河北工業(yè)科技,2008,25(4):250-251.GUO Yu-xia.Application of VC++DOM object to operate XML document[J].Hebei Journal of Industrial Science and Technology,2008,25(4):250-251.
[6]陳特放,方斌.VC平臺下基于OLE的Word自動化操作應用[J].計算機應用與軟件,2009,26(9):123-125.CHEN Te-fang,FANG Bin.Applying OLE-based word automation on VC platform[J].Computer Applications and Software,2009,26(9):123-125.