刘慧英,李莹莹,孙景峰
(西北工业大学 自 动化学院,陕西 西 安 7 10129)
各领域每天都有大量的报表需要编制,各类报表的测试项目、参数很多,试验数据类型多样化(包括图像、表格、实验报告文档等),因此运用计算机技术加强试验数据自动化管理,提高试验管理的质量,为各类系统,尤其是军用系统,提供准确可靠、高质量的试验数据和判断依据,对增强我国综合国力具有十分重要的战略意义和现实意义。
在报表的自动生成方面,文献[1]采用VBA编程。VBA是实现Word文档自动生成的强有力的编程工具,但在软件重用性与代码安全性上存在缺陷和漏洞,不能满足继承和封装的要求。文献[2]采用Delphi来实现。Delphi与BDE的无缝集成,以及Delphi提供的现成数据库操作控件,使得Delphi在数据库支持上有很大优势,但其在兼容性和稳定性等方面存在着许多的不足。文献[3]介绍了用VC++与VBA实现复杂报表自动生成的方法,但是该方法不支持文字、图片等其他内容的插入[4]。
本文在VC++开发平台上,使用C++语言,利用COM编程技术,在源代码中调用Word中的 OLE自动化对象,结合XML的DOM技术实现报表界面的动态加载,最终实现复杂报表的自动生成。
OLE(Object Linking and Embedding,对象链接与嵌入)是一种为Windows设计的交互进程通信技术,它建立在COM(Component Object Model,组件对象模型)基础之上。要调用Word提供的OLE自动化对象,可以通过Word提供的对象库实现。
XML(Extensible Markup Language,可扩展标记语言)允许用户按照XML规则自定义标签,但它对规则的要求十分严格。微软提供一个MSXML.DLL的动态链接库,它也是一个COM对象库,里面封装了进行XML解析所需要的所有必要的对象。MSXML解析器根据XML文档生成一个DOM(Document Object Model,文档对象模型)树结构,使程序能够读XML文档并根据XML文档内容创建一个节点的逻辑结构。DOM使用户能够把文档看成是一个有结构的信息树,其包含两个关键的抽象:一个树状的层次,树状层次包括了所有这些节点,节点本身也可以包含其他节点;另一个用来表示文档内容和结构的节点集合[5]。
本报表程序实现了界面动态加载,即可以默认自动输出报表,也可以在界面加载过程中手动修改数据,其流程如下:首先需要创建相关XML文件,解析XML文件生成DOM树结构,不同的动态数组存放相应类型的控件信息,将DOM节点与控件动态数组关联起来。
创建一个唯一的模态对话框,即父界面对话框,其内容加载是按照配置文件“UICfg.XML”中的节点内容进行的。父界面对话框的主要功能是选择本次报表所包含的试验及加载封面、综述等界面。
然后遍历选择的第一个试验对应的XML文件节点动态的创建子界面及控件,将控件指针存入动态数组中,用户对生成的子界面对话框进行操作,并将控件中的数据利用GetText、PutText、InlineShapes 等 库 函 数 读 取 到 在 XML 文 件中,为下面报表生成时从XML文件中读取数据做准备,清除界面控件元素,清除控件动态数组内容,因为下个实验也要用到这些动态数组。
检查是否最后一个实验的动态界面已经生产完毕,否则生成下一个试验的子界面,是则结束界面的动态加载,准备输出报表。报表界面动态加载流程如图1所示。
图1 报表界面动态加载流程Fig.1 Flow chart of the reface dynamically loaded
报表界面动态加载完成后即开始报表内容的自动输出, 运用Word中的 Bookmarks、Document、Rang等智能指针创建报表模板,然后遍历DOM树结构的节点,将其值写入模板指定的位置,判断是否最后一个试验的DOM树结构遍历结束,如果否则继续遍历下个试验的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实际上是一个节点 (Node)对象的集合,节点的增加、删除和变化都可以在集合中立刻反映出来,可以通过“for...next”结构来遍历所有的节点。
选择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文件,读取它所有的节点属性,判断表格的类型(下面代码中省略),表格指针指向当前的行与列,使用PutText函数,按节点树逐层输出XML文件中的信息。
MSXML::IXMLDOMNodeListPtr L2nodelist;
L2nodelist=m_RptXmlElem->GetchildNodes();
//读取节点属性
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文件中,为其新建节点,更新XML文件,到程序输出时再次调用PutText函数,读取所有节点。
该报表自动生成技术已应用于某电磁兼容试验数据自动化管理系统的报表自动生成子模块中,目前运行良好。图4显示了程序生成电磁兼容检查报告的封面信息。
图4 报表自动输出结果Fig.4 Result of the report automatically generation
报表程序界面采用动态加载,既可以按照模板输出默认报表,也可以动态添加元素,根据需要生成不同特性的报表。
与传统报表生成模型相比,本文提出的报表自动生技术运用COM技术,采用XML文件作为配置文件,用户可以按照标准自己定义新的XML文件,使该报表模块能够移植到其他系统中;XML分析程序更加要挑剔语法和结构,其每次的分析结果都是一致的,解析程序不论在性能还是稳定性方面都更容易实现;同时因为解析程序不需要花时间重建不完整的文档,提高了报表的生成效率。
[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报告及动态结构表格[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].河北工业科技,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.