劉慧英,李瑩瑩,孫景峰
(西北工業(yè)大學(xué) 自 動(dòng)化學(xué)院,陜西 西 安 7 10129)
各領(lǐng)域每天都有大量的報(bào)表需要編制,各類報(bào)表的測(cè)試項(xiàng)目、參數(shù)很多,試驗(yàn)數(shù)據(jù)類型多樣化(包括圖像、表格、實(shí)驗(yàn)報(bào)告文檔等),因此運(yùn)用計(jì)算機(jī)技術(shù)加強(qiáng)試驗(yàn)數(shù)據(jù)自動(dòng)化管理,提高試驗(yàn)管理的質(zhì)量,為各類系統(tǒng),尤其是軍用系統(tǒng),提供準(zhǔn)確可靠、高質(zhì)量的試驗(yàn)數(shù)據(jù)和判斷依據(jù),對(duì)增強(qiáng)我國綜合國力具有十分重要的戰(zhàn)略意義和現(xiàn)實(shí)意義。
在報(bào)表的自動(dòng)生成方面,文獻(xiàn)[1]采用VBA編程。VBA是實(shí)現(xiàn)Word文檔自動(dòng)生成的強(qiáng)有力的編程工具,但在軟件重用性與代碼安全性上存在缺陷和漏洞,不能滿足繼承和封裝的要求。文獻(xiàn)[2]采用Delphi來實(shí)現(xiàn)。Delphi與BDE的無縫集成,以及Delphi提供的現(xiàn)成數(shù)據(jù)庫操作控件,使得Delphi在數(shù)據(jù)庫支持上有很大優(yōu)勢(shì),但其在兼容性和穩(wěn)定性等方面存在著許多的不足。文獻(xiàn)[3]介紹了用VC++與VBA實(shí)現(xiàn)復(fù)雜報(bào)表自動(dòng)生成的方法,但是該方法不支持文字、圖片等其他內(nèi)容的插入[4]。
本文在VC++開發(fā)平臺(tái)上,使用C++語言,利用COM編程技術(shù),在源代碼中調(diào)用Word中的 OLE自動(dòng)化對(duì)象,結(jié)合XML的DOM技術(shù)實(shí)現(xiàn)報(bào)表界面的動(dòng)態(tài)加載,最終實(shí)現(xiàn)復(fù)雜報(bào)表的自動(dòng)生成。
OLE(Object Linking and Embedding,對(duì)象鏈接與嵌入)是一種為Windows設(shè)計(jì)的交互進(jìn)程通信技術(shù),它建立在COM(Component Object Model,組件對(duì)象模型)基礎(chǔ)之上。要調(diào)用Word提供的OLE自動(dòng)化對(duì)象,可以通過Word提供的對(duì)象庫實(shí)現(xiàn)。
XML(Extensible Markup Language,可擴(kuò)展標(biāo)記語言)允許用戶按照XML規(guī)則自定義標(biāo)簽,但它對(duì)規(guī)則的要求十分嚴(yán)格。微軟提供一個(gè)MSXML.DLL的動(dòng)態(tài)鏈接庫,它也是一個(gè)COM對(duì)象庫,里面封裝了進(jìn)行XML解析所需要的所有必要的對(duì)象。MSXML解析器根據(jù)XML文檔生成一個(gè)DOM(Document Object Model,文檔對(duì)象模型)樹結(jié)構(gòu),使程序能夠讀XML文檔并根據(jù)XML文檔內(nèi)容創(chuàng)建一個(gè)節(jié)點(diǎn)的邏輯結(jié)構(gòu)。DOM使用戶能夠把文檔看成是一個(gè)有結(jié)構(gòu)的信息樹,其包含兩個(gè)關(guān)鍵的抽象:一個(gè)樹狀的層次,樹狀層次包括了所有這些節(jié)點(diǎn),節(jié)點(diǎn)本身也可以包含其他節(jié)點(diǎn);另一個(gè)用來表示文檔內(nèi)容和結(jié)構(gòu)的節(jié)點(diǎn)集合[5]。
本報(bào)表程序?qū)崿F(xiàn)了界面動(dòng)態(tài)加載,即可以默認(rèn)自動(dòng)輸出報(bào)表,也可以在界面加載過程中手動(dòng)修改數(shù)據(jù),其流程如下:首先需要?jiǎng)?chuàng)建相關(guān)XML文件,解析XML文件生成DOM樹結(jié)構(gòu),不同的動(dòng)態(tài)數(shù)組存放相應(yīng)類型的控件信息,將DOM節(jié)點(diǎn)與控件動(dòng)態(tài)數(shù)組關(guān)聯(lián)起來。
創(chuàng)建一個(gè)唯一的模態(tài)對(duì)話框,即父界面對(duì)話框,其內(nèi)容加載是按照配置文件“UICfg.XML”中的節(jié)點(diǎn)內(nèi)容進(jìn)行的。父界面對(duì)話框的主要功能是選擇本次報(bào)表所包含的試驗(yàn)及加載封面、綜述等界面。
然后遍歷選擇的第一個(gè)試驗(yàn)對(duì)應(yīng)的XML文件節(jié)點(diǎn)動(dòng)態(tài)的創(chuàng)建子界面及控件,將控件指針存入動(dòng)態(tài)數(shù)組中,用戶對(duì)生成的子界面對(duì)話框進(jìn)行操作,并將控件中的數(shù)據(jù)利用GetText、PutText、InlineShapes 等 庫 函 數(shù) 讀 取 到 在 XML 文 件中,為下面報(bào)表生成時(shí)從XML文件中讀取數(shù)據(jù)做準(zhǔn)備,清除界面控件元素,清除控件動(dòng)態(tài)數(shù)組內(nèi)容,因?yàn)橄聜€(gè)實(shí)驗(yàn)也要用到這些動(dòng)態(tài)數(shù)組。
檢查是否最后一個(gè)實(shí)驗(yàn)的動(dòng)態(tài)界面已經(jīng)生產(chǎn)完畢,否則生成下一個(gè)試驗(yàn)的子界面,是則結(jié)束界面的動(dòng)態(tài)加載,準(zhǔn)備輸出報(bào)表。報(bào)表界面動(dòng)態(tài)加載流程如圖1所示。
圖1 報(bào)表界面動(dòng)態(tài)加載流程Fig.1 Flow chart of the reface dynamically loaded
報(bào)表界面動(dòng)態(tài)加載完成后即開始報(bào)表內(nèi)容的自動(dòng)輸出, 運(yùn)用Word中的 Bookmarks、Document、Rang等智能指針創(chuàng)建報(bào)表模板,然后遍歷DOM樹結(jié)構(gòu)的節(jié)點(diǎn),將其值寫入模板指定的位置,判斷是否最后一個(gè)試驗(yàn)的DOM樹結(jié)構(gòu)遍歷結(jié)束,如果否則繼續(xù)遍歷下個(gè)試驗(yàn)的DOM樹結(jié)構(gòu),是則報(bào)表輸出完成。報(bào)表自動(dòng)輸出流程如圖2所示。
圖2 報(bào)表自動(dòng)輸出流程Fig.1 Flow chart of the report automatically generation
VC++通過COM技術(shù)調(diào)用Word自動(dòng)化服務(wù)器中的OLE自 動(dòng) 化 對(duì) 象 , 如 :_Application、_Document、Range、Selection、Bookmark、_ParagraphFormat等,實(shí)現(xiàn)文字、表格、圖片插入,頁面設(shè)置,標(biāo)題的設(shè)置以及目錄的生成。所以工程中必須導(dǎo)入Word類庫[6],具體操作如下:在VC++中選擇菜單“項(xiàng)目”,點(diǎn)擊“添加類”,在彈出的對(duì)話框中選擇按Type Lib中的MFC類,點(diǎn)擊“添加”即打開從類庫中添加類向?qū)Ы缑妫贠ffice安裝目錄下找到Word類庫文件MSWORD.OLB,選擇需要的接口并將其導(dǎo)入,如圖3所示。
圖3 導(dǎo)入Word類庫Fig.3 Importing the word class library
本文的應(yīng)用實(shí)例為電磁兼容試驗(yàn)報(bào)表生成,鑒于電磁兼容各類試驗(yàn)中測(cè)試項(xiàng)目、參數(shù)有重復(fù)處,為避免反復(fù)輸入相同的信息或做重復(fù)的格式修改,可利用XML文檔遵循嚴(yán)格式和標(biāo)準(zhǔn)的特性,在原有的文檔基礎(chǔ)上稍做修改得到其他配置文件。
DOMDocument對(duì)象是XML DOM的基礎(chǔ),可以利用它所暴露的屬性和方法來瀏覽、查詢和修改XML文檔的內(nèi)容和結(jié)構(gòu)。
IXMLDOMNode是XML DOM中的基本的對(duì)象,元素,屬性,注釋,過程指令和其他的文檔組件都可以認(rèn)為是IXMLDOMNode。
IXMLDOMNodeList實(shí)際上是一個(gè)節(jié)點(diǎn) (Node)對(duì)象的集合,節(jié)點(diǎn)的增加、刪除和變化都可以在集合中立刻反映出來,可以通過“for...next”結(jié)構(gòu)來遍歷所有的節(jié)點(diǎn)。
選擇XML文檔作為配置文件,應(yīng)用時(shí)需在工程中加載msxml4.dll。在程序中加入:#import"msxml4.dll"。
在應(yīng)用程序中添加DOMDocument對(duì)象,如下:
HRESULT hr;
IXMLDomDocument*m_XMLDoc;
IXMLDOMNode*m_XDN;
Hr=CoInitialize(NULL);//COM的初始化
//得到關(guān)于IXMLDOMDocument接口的指針m_XMLDoc。
hr =CoCreateInstance (CLSID_DOMDocument,NULL,CLSCTX_INPPROC_SERVER,
ID_IXMLDOMDocument,(void**)&m_XMLDoc);
//得到關(guān)于IXMLDOMNode接口的指針m_XDN。
hr=pXMLDoc->QueryInterface(IID_IXMLDOMNode,(void**)&m_XDN);
加載配置文件的核心代碼如下所示,其中Cover.xml為實(shí)例中的封面配置文件。
CString strfilepathtemp=Rprfilepath+"Cover.xml";//獲取配置文件路徑
m_RptXmlDoc->load((COleVariant)strfilepathtemp);//加載配置文件
在插入文字或者表格之前,必須首先獲得文檔光標(biāo)的位置,以便在模板指定的位置上插入相應(yīng)的內(nèi)容。下面列出部分程序中用到的WORD中指針,這些指針應(yīng)用于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;//行指針
設(shè)置圖片的“版式”為嵌入式,則該圖片在Word文檔中就可以用InlineShape表示,InlineShape對(duì)象被視為字符,可將其象字符一樣放置于一行文本中。InlineShape對(duì)象是InlineShapes集合中的一個(gè)成員,采用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)默認(rèn)表格的填寫
首先找到將要填寫的表格所對(duì)應(yīng)的XML文件,讀取它所有的節(jié)點(diǎn)屬性,判斷表格的類型(下面代碼中省略),表格指針指向當(dāng)前的行與列,使用PutText函數(shù),按節(jié)點(diǎn)樹逐層輸出XML文件中的信息。
MSXML::IXMLDOMNodeListPtr L2nodelist;
L2nodelist=m_RptXmlElem->GetchildNodes();
//讀取節(jié)點(diǎn)屬性
patb=m_RptXmlElem->Getattributes();
CString strtemp1=m_RptXmlNode->Gettext();//strtemp1
AddNewTable(1,1);
int rownum=m_word_rows->GetCount();
//表格指針指向當(dāng)前的行與列
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)其他表格的填寫
在操作過程中對(duì)表格的修改會(huì)改變默認(rèn)表格的輸出,直接在界面編輯框中輸入的信息,將被界面中“保存”按鈕讀并存入XML文件中,為其新建節(jié)點(diǎn),更新XML文件,到程序輸出時(shí)再次調(diào)用PutText函數(shù),讀取所有節(jié)點(diǎn)。
該報(bào)表自動(dòng)生成技術(shù)已應(yīng)用于某電磁兼容試驗(yàn)數(shù)據(jù)自動(dòng)化管理系統(tǒng)的報(bào)表自動(dòng)生成子模塊中,目前運(yùn)行良好。圖4顯示了程序生成電磁兼容檢查報(bào)告的封面信息。
圖4 報(bào)表自動(dòng)輸出結(jié)果Fig.4 Result of the report automatically generation
報(bào)表程序界面采用動(dòng)態(tài)加載,既可以按照模板輸出默認(rèn)報(bào)表,也可以動(dòng)態(tài)添加元素,根據(jù)需要生成不同特性的報(bào)表。
與傳統(tǒng)報(bào)表生成模型相比,本文提出的報(bào)表自動(dòng)生技術(shù)運(yùn)用COM技術(shù),采用XML文件作為配置文件,用戶可以按照標(biāo)準(zhǔn)自己定義新的XML文件,使該報(bào)表模塊能夠移植到其他系統(tǒng)中;XML分析程序更加要挑剔語法和結(jié)構(gòu),其每次的分析結(jié)果都是一致的,解析程序不論在性能還是穩(wěn)定性方面都更容易實(shí)現(xiàn);同時(shí)因?yàn)榻馕龀绦虿恍枰〞r(shí)間重建不完整的文檔,提高了報(bào)表的生成效率。
[1]金良鋒,周文詳.WORD試驗(yàn)報(bào)告的自動(dòng)生成[J].中國測(cè)試技術(shù),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報(bào)告及動(dòng)態(tài)結(jié)構(gòu)表格[J].計(jì)算機(jī)應(yīng)用與軟件,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]朱敏,沈同圣,王學(xué)偉,等.VC++與VBA結(jié)合實(shí)現(xiàn)復(fù)雜報(bào)表[J].計(jì)算機(jī)應(yīng)用與軟件,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文檔自動(dòng)生成技術(shù)[J].計(jì)算機(jī)時(shí)代,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平臺(tái)下基于OLE的Word自動(dòng)化操作應(yīng)用[J].計(jì)算機(jī)應(yīng)用與軟件,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.