王朝网络
分享
 
 
 

基于模板和XML在BS结构应用中生成word文件

王朝java/jsp·作者佚名  2006-01-31
宽屏版  字体: |||超大  

现在的各类应用系统中时常会需要动态生成Word文件,解决比较常见的两种方法是:

1. 利用Word提供的COM自动化接口控制Word生成文档

2. 利用Word对html的支持,制作html文件,并设置其contentType为"application/msword",使浏览器调用word打开

第一种方法靠Word进程实际完成文件生成工作,而Word并为设计为在服务器端处理并发调用,所以这种方法只适合单机应用。另外,如果要生成比较复杂的word文件,相应的代码会非常烦琐,排版和调试也需要花大量时间。

第二种方法的致命问题是html文档中无法保存二进制数据,比如图片,如果在服务器端生成一堆文件,即难以在浏览器中显示,也无法让用户直接下载。

比较完善的解决办法是基于WordML来生成word文件。WordML是微软为Word设计的xml架构,其完整语法可以在MSDN上找到。按照这个语法生成xml文件,可以在文档中随意得到各种word支持的格式。特别需要指出的是可以方便的在文件中内嵌图片,其语法基本是这样:

<w:pict>

<v:shapetype id="_x0000_t75" ...>

... VML shape template definition ...

</v:shapetype>

<w:binData w:name="wordml://02000001.jpg">/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPAAA/+4ADkFkb2JlAGTAAAAAAf/b

AIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoKDBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxsc

... 更多Base6编码的图片文件数据

</w:binData>

<v:shape id="_x0000_i1025" type="#_x0000_t75"

style="width:212.4pt;height:159pt">

<v:imagedata src="wordml://02000001.jpg"

o:title="Image title"/>

</v:shape>

</w:pict>

其关键是图片的实际数据以base64编码之后放在<w:binData></w:binData>标记之间。

如果你看了MSDN上的WordML语法,会发现它非常复杂。这不奇怪,因为Word有非常多的功能,但要写程序根据这么多定义来生成文档就比较费事了。不过我们可以利用模板文件来解决这个问题。

同我们动态生成网页一样,要动态生成的word文件也有相当多部分是固定不变的,并且复杂的版面、格式一般都在这些固定不变的部分中。所以借用生成网页的思路,我们可以在word中先根据需要的版面和格式,结合一些虚拟的数据做出模板文件,然后将这个模板文件保存为xml格式,再在xml文件中找到那些虚拟的数据对应的文本,将它们替换为将采用的后台处理技术的数据处理指令,这样我们就可以在服务器端结合模板文件和数据库查询,生成word文件了。

下面举一个例子。假设我们采用JSP进行word文件生成,首先制作模板文件如下:

连宋个人简历

本人概况

姓名

连宋

出生日期

1937年7月7日

性别

证件类型

身份证

学历

大学本科

证件号码

41043219700707011

婚姻状况

已婚

期望月薪

面议

户口所在地

然后将这个文件保存为xml格式,我们将得到如下内容的xml文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<?mso-application progid="Word.Document"?>

<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:st1="urn:schemas-microsoft-com:office:smarttags" w:macrosPresent="no" w:embeddedObjPresent="no" w:ocxPresent="no" xml:space="preserve"><o:SmartTagType o:namespaceuri="urn:schemas-microsoft-com:office:smarttags" o:url="" o:name="chsdate"/><o:DocumentProperties><o:Title>个人简历</o:Title>

... ...

<w:rPr><w:rFonts w:hint="fareast"/><wx:font wx:val="宋体"/></w:rPr><w:t>连宋个人简历</w:t></w:r><w:proofErr w:type="gramStart"/><w:r><w:rPr><w:rFonts w:hint="fareast"/><wx:font wx:val="宋体"/></w:rPr>

... ...

<w:pict><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><v:stroke joinstyle="miter"/><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"/><v:f eqn="sum @0 1 0"/><v:f eqn="sum 0 0 @1"/><v:f eqn="prod @2 1 2"/><v:f eqn="prod @3 21600 pixelWidth"/><v:f eqn="prod @3 21600 pixelHeight"/><v:f eqn="sum @0 0 1"/><v:f eqn="prod @6 1 2"/><v:f eqn="prod @7 21600 pixelWidth"/><v:f eqn="sum @8 21600 0"/><v:f eqn="prod @7 21600 pixelHeight"/><v:f eqn="sum @10 21600 0"/></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/><o:lock v:ext="edit" aspectratio="t"/></v:shapetype><w:binData w:name="wordml://02000001.jpg">/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPAAA/+4ADkFkb2JlAGTAAAAAAf/b

... ...

</w:binData><v:shape id="_x0000_i1025" type="#_x0000_t75" style="width:75pt;height:75pt"><v:imagedata src="wordml://02000001.jpg" o:title="cathy"/></v:shape></w:pict>

... ...

</w:sectPr></wx:sub-section></wx:sect></w:body></w:wordDocument>

接下来首先将这个文件按照xml格式进行排版,然后在其中找到需要动态生成的文字部分(WordML中文字以<w:t></w:t>标记起始),将其替换为从后台取数据生成文字的JSP指令,再在文件头部添加JSP控制指令,得到如下的xml文件:

<%@ page language="java" errorPage="/error.jsp" pageEncoding="GBK" contentType="application/msword;charset=UTF-8" %><%response.setHeader("Content-Disposition", "attachment; filename=resume.doc");%><?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>

<?mso-application progid="Word.Document"?>

<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" w:macrosPresent="no" w:embeddedObjPresent="no" w:ocxPresent="no" xml:space="preserve">

<o:DocumentProperties>

<o:Title>个人简历</o:Title>

... ...

<w:body>

<wx:sect>

<wx:sub-section>

<w:p>

<w:pPr>

<w:pStyle w:val="a5"/>

<w:rPr>

<w:rFonts w:hint="fareast"/>

</w:rPr>

</w:pPr>

<w:r>

<w:rPr>

<w:rFonts w:hint="fareast"/>

<wx:font wx:val="宋体"/>

</w:rPr>

<w:t><c:out value="${command.name}"/>个人简历</w:t>

</w:r>

</w:p>

... ...

<w:pict>

<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">

<v:stroke joinstyle="miter"/>

<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>

<o:lock v:ext="edit" aspectratio="t"/>

</v:shapetype>

<w:binData w:name="wordml://02000001.jpg"><c:out value="${command.portraitBASE64}"/></w:binData>

<v:shape id="_x0000_i1025" type="#_x0000_t75" style="width:75pt;height:75pt">

<v:imagedata src="wordml://02000001.jpg" o:title="portrait"/>

</v:shape>

</w:pict>

... ...

</w:body>

</w:wordDocument>

将这个文件以jsp后缀保存,就可以在J2EE系统中配合后台程序生成word文件了。如果你需要浏览器提示保存这个文件,而不是在浏览器中打开,需要在文件头部加入这句:

response.setHeader("Content-Disposition", "attachment; filename=resume.doc");

有很多免费的第三方库可以用于生成图片文件的BASE64编码,JDK中也有BASE64 Encoder。

更简单的方法是在用word制作模板文件时直接在需要动态生成的部分输入jsp指令,然后再保存为xml文件,但要注意检查word保存为xml文件后有没有将jsp指令拆散或插入格式标记。

以上以JSP+JSTL为例,换成其它后台技术,比如Velocity,或者ASP、PHP,原理也是相同的。

实际上,在需要生成Word文件的应用中,多数时候需要套用固定的格式,这样本文所解释的方法就更加合适。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有