FreeMaker + xml 导出word
首先介绍几种java导出word方案
1、Jacob是Java-COM Bridge的缩写,它在Java与微软的COM组件之间构建一座桥梁。使用Jacob自带的DLL动态链接库,并通过JNI的方式实现了在Java平台上对COM程序的调用。DLL动态链接库的生成需要windows平台的支持。
2、 Apache POI包括一系列的API,它们可以操作基于MicroSoft OLE 2 Compound Document Format的各种格式文件,可以通过这些API在Java中读写Excel、Word等文件。他的excel处理很强大,对于word还局限于读取,目前只能实现一些简单文件的操作,不能设置样式。
3、 Java2word是一个在java程序中调用 MS Office Word 文档的组件(类库)。该组件提供了一组简单的接口,以便java程序调用他的服务操作Word 文档。
这些服务包括: 打开文档、新建文档、查找文字、替换文字,插入文字、插入图片、插入表格,在书签处插入文字、插入图片、插入表格等。填充数据到表格中读取表格数据 ,1.1版增强的功能: 指定文本样式,指定表格样式。如此,则可动态排版word文档。
4、 iText操作Excel还行。对于复杂的大量的word也是噩梦。用法很简单, 但是功能很少, 不能设置打印方向等问题。
5、 JSP输出样式基本不达标,而且要打印出来就更是惨不忍睹。
6、 用XML做就很简单了。Word从2003开始支持XML格式,大致的思路是先用office2003或者2007编辑好word的样式,然后另存为xml,将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板并输出Doc。经测试这样方式生成的word文档完全符合office标准,样式、内容控制非常便利,打印也不会变形,生成的文档和office中编辑文档完全一样。
看过方案后就知道了 第 6 种方案效果好点,下面我们就举个例子介绍下这个方案
首先要制作模板 模板里的需要传入的数据用${data} 填充,在代码里给其赋值即可
模板制作好后 ,点击另存为 xml 文件 如:data.xml
如果xml需要动态填充 可以用
<!-- 循环开始 -->
<#list personnelView as e>
</#list>
<!-- 循环结束 -->
<!-- 循环开始 -->
<#list personnelView as e> // personnelView为循环集合
<w:tr wsp:rsidR="001E023B" wsp:rsidTr="004E45BD">
<w:tblPrEx>
<w:tblCellMar>
<w:top w:w="0" w:type="dxa"/>
<w:bottom w:w="0" w:type="dxa"/>
</w:tblCellMar>
</w:tblPrEx>
<w:trPr>
<w:trHeight w:val="405"/>
</w:trPr>
<w:tc>
<w:tcPr>
<w:tcW w:w="1920" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e_index +1}</w:t> //e_index 为索引从0 开始
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1083" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e.COLUMN_1}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1142" w:type="dxa"/>
<w:gridSpan w:val="3"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:pPr>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e.COLUMN_2}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1578" w:type="dxa"/>
<w:gridSpan w:val="3"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e.COLUMN_3}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1168" w:type="dxa"/>
<w:gridSpan w:val="2"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e.COLUMN_4}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2181" w:type="dxa"/>
<w:gridSpan w:val="3"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e.COLUMN_5}</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</#list>
<!-- 循环结束 -->
二、详细介绍
1、以上呢都是我看别人的东西复制过来的其实都一样FreeMaker 最主要的一个特点就是整理模板数据替换用${data};data就是你的数据
那在java中保存的数据时用map来存放数据
如:Map<String, Object> root = new HashMap<String, Object>();、
如现在要保存一个实体user;
User的对象有id,name,sex,menun(菜单),picstr(头像)这些属性
User userObj=new User();
在保存的时候只要将数据库中的数据封装到user中然后通过root.put(“user”, userObj);
在模板相应的位置中代替这些值如名称:${user.name},性别${user.sex}等
当遇到对象有子集的时候也就是用户有几个菜单时可以使用<#list user.menun as m>在这个中间又可以得到自己想要的东西如${m.menunName}</#list>当然这个是循环的对于它循环的索引直接使用变量名+下划线index即可如:${m_index};
2、这些东西估计大家都会现在说说插入目录问题
因为目录需要内容创建完成之后才能刷新目录所以在此处我寻求好多方法不知道怎么使用最后我折中想了个办法就是在xml转为word完成之后我另存一份word;在另存之前我先刷新目录这样就把目录问题解决了;废话少说例子上:
public void xmlToWord(String docfile, String htmlfile) {
ActiveXComponent app =null;
try {
app=new ActiveXComponent("Word.Application"); // 启动word
app.setProperty("Visible", new Variant(false));
Dispatch docs = app.getProperty("Documents").toDispatch();
Dispatch doc = Dispatch.invoke(
docs,
"Open",
Dispatch.Method,
new Object[] { docfile, new Variant(false),
new Variant(true) }, new int[1]).toDispatch();
Dispatch selection=app.getProperty("Selection").toDispatch();
Dispatch find = Dispatch.call(selection,"Find").toDispatch();
/* 设置要查找的内容 */
Dispatch.put(find,"Text","目录");
/* 向前查找 */
Dispatch.put(find,"Forward","True");
/* 设置格式 */
Dispatch.put(find,"Format","True");
/* 大小写匹配 */
Dispatch.put(find,"MatchCase","True");
/* 全字匹配 */
Dispatch.put(find,"MatchWholeWord","True");
/* 查找并选中 */
Dispatch.call(find,"Execute").getBoolean();
/* 取得ActiveDocument、TablesOfContents、range对象 */
Dispatch ActiveDocument = app.getProperty("ActiveDocument").toDispatch();
Dispatch TablesOfContents = Dispatch.get(ActiveDocument,"TablesOfContents").toDispatch();
Dispatch.call(selection,"MoveRight"); //移动光标到右边
Dispatch.call(selection, "TypeParagraph"); //换行
Dispatch range = Dispatch.get(selection, "Range").toDispatch();
/* 增加目录 */
Dispatch.call(TablesOfContents,"Add",range,new Variant(true),new Variant(1),new Variant(3),new Variant(true),new Variant(""),new Variant(true),new Variant(true));
Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {
htmlfile, new Variant(WORD_DOC) }, new int[1]);
Variant f = new Variant(false);
Dispatch.call(doc, "Close", f);
} finally {
if(app!=null)
app.invoke("Quit", new Variant[] {});
}
}
原理就是我在模板中有一页单独为目录留下来有目录两字,通过查找目录两字并且定位光标到目录之后并且换行;然后添加目录保存即可;
3、图片问题
相信大家都知道在word里面插入一张图片保存为xml的时候图片的位置会产生出很长的一串字符当你看到这个的时候那么替换图片你有希望;观察发现是二进制字符串所以你在准备数据的时候也要提前把需要保存的图片转成二进制字符串(将图片的字节流进行Base64编码)并存到变量中如picstr并在xml中替换${user.picstr}
<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://06000001.png">${user.picstr?if_exists}
</w:binData>
<v:shape id="_x0000_i1025" type="#_x0000_t75" style="width:297pt;height:284.25pt">
<v:imagedata src="wordml://06000001.png" o:title="gisImage"/>
</v:shape>
</w:pict>
这样图的问题呢就解决了。但是大多时候需求不是这样的是有多个图片需要同时出现虽然变量你已经替换但是你会发现图片都出来了但是都是显示的是同一张图片。仔细研究发现图片在替换变量的时候不只是要替换内容的那块同时也要注意名称的地方也就是w:name="wordml://06000001.png">06000001.png这个就是他在word中生存的名称因为图片的不确定性质所以你的名称就无法定下来所以灵机一动把名称也弄成随机变量(这个地方随机变量你可以在java端处理好这边用变量替换或者使用现成的变量那就是使用list循环)因为图片是多个势必你要使用<#list image as i>这个时候${i_index}这个是变化的那么图片名称就改为
<w:binData w:name="${"wordml://0600000"+i_index+1+".jpg"}">${i.picStr?if_exists}
</w:binData>
<v:shape id="_x0000_i1025" type="#_x0000_t75" style="width:297pt;height:284.25pt">
<v:imagedata src="${"wordml://0600000"+i_index+1+".jpg"}" o:title="gisImage2"/>
</v:shape>
在这里啰嗦下一定要注意双引号图片问题完美解决;
4、页眉页脚问题好多人在制定模板的时候都忘记了设置页眉页脚页面设置等问题;一旦模板做好并且把变量替换完成之后那么再使用word就无法打开xml文件了当然你就无法再设置word的东西了所以只能通过代码来添加嘿嘿本人就遇到过;当然有人也说我可以重新做反正也不多我设置好了在替换变量对于这种想法的人我表示理解……;等你的模板什么时候有几十页的时候,或者循环套好几层的时候我看你肿么办。言归正传:
页面页脚添加问题:从新新建一个word把你想要在模板中实现好的所有东西都设置好然后copy这些代码到xml问题解决呵呵:上代码:
<w:style w:type="paragraph" w:styleId="a6">
<w:name w:val="header"/>
<wx:uiName wx:val="页眉"/>
<w:basedOn w:val="a"/>
<w:rsid w:val="00302287"/>
<w:pPr>
<w:pStyle w:val="a6"/>
<w:pBdr>
<w:bottom w:val="single" w:sz="6" wx:bdrwidth="15" w:space="1" w:color="auto"/>
</w:pBdr>
<w:tabs>
<w:tab w:val="center" w:pos="4153"/>
<w:tab w:val="right" w:pos="8306"/>
</w:tabs>
<w:snapToGrid w:val="off"/>
<w:jc w:val="center"/>
</w:pPr>
<w:rPr>
<wx:font wx:val="Times New Roman"/>
<w:sz w:val="18"/>
<w:sz-cs w:val="18"/>
</w:rPr>
</w:style>
<w:style w:type="paragraph" w:styleId="a7">
<w:name w:val="footer"/>
<wx:uiName wx:val="页脚"/>
<w:basedOn w:val="a"/>
<w:rsid w:val="00302287"/>
<w:pPr>
<w:pStyle w:val="a7"/>
<w:tabs>
<w:tab w:val="center" w:pos="4153"/>
<w:tab w:val="right" w:pos="8306"/>
</w:tabs>
<w:snapToGrid w:val="off"/>
<w:jc w:val="left"/>
</w:pPr>
<w:rPr>
<wx:font wx:val="Times New Roman"/>
<w:sz w:val="18"/>
<w:sz-cs w:val="18"/>
</w:rPr>
</w:style>
其实最主要的是下面这段:
<w:hdr w:type="odd">
<wx:pBdrGroup>
<wx:borders>
<wx:bottom wx:val="solid" wx:bdrwidth="15" wx:space="1" wx:color="auto"/>
</wx:borders>
<w:p wsp:rsidR="00302287" wsp:rsidRDefault="00302287">
<w:pPr>
<w:pStyle w:val="a6"/>
</w:pPr>
<w:r>
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
<wx:font wx:val="宋体"/>
</w:rPr>
<w:t>测振报告</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t> </w:t>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
<wx:font wx:val="宋体"/>
</w:rPr>
<w:t>${vibrometerMissionVo.testReport.reportTitle?if_exists}</w:t>
</w:r>
<w:pict>
<v:shapetype id="_x0000_t136" coordsize="21600,21600" o:spt="136" adj="10800" path="m@7,l@8,m@5,21600l@6,21600e">
<v:formulas>
<v:f eqn="sum #0 0 10800"/>
<v:f eqn="prod #0 2 1"/>
<v:f eqn="sum 21600 0 @1"/>
<v:f eqn="sum 0 0 @2"/>
<v:f eqn="sum 21600 0 @3"/>
<v:f eqn="if @0 @3 0"/>
<v:f eqn="if @0 21600 @1"/>
<v:f eqn="if @0 0 @2"/>
<v:f eqn="if @0 @4 21600"/>
<v:f eqn="mid @5 @6"/>
<v:f eqn="mid @8 @5"/>
<v:f eqn="mid @7 @8"/>
<v:f eqn="mid @6 @7"/>
<v:f eqn="sum @6 0 @5"/>
</v:formulas>
<v:path textpathok="t" o:connecttype="custom" o:connectlocs="@9,0;@10,10800;@11,21600;@12,10800" o:connectangles="270,180,90,0"/>
<v:textpath on="t" fitshape="t"/>
<v:handles>
<v:h position="#0,bottomRight" xrange="6629,14971"/>
</v:handles>
<o:lock v:ext="edit" text="t" shapetype="t"/>
</v:shapetype>
<v:shape id="PowerPlusWaterMarkObject3" o:spid="_x0000_s4099" type="#_x0000_t136" style="position:absolute;left:0;text-align:left;margin-left:0;margin-top:0;width:526.9pt;height:58.5pt;rotation:315;z-index:-1;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin" o:allowincell="f" fillcolor="gray" stroked="f">
<v:fill opacity=".5"/>
<v:textpath style="font-family:"黑体";font-size:1pt" string="${watermark}"/>
</v:shape>
</w:pict>
</w:r>
</w:p>
</wx:pBdrGroup>
</w:hdr>
<w:ftr w:type="even">
<w:p wsp:rsidR="00302287" wsp:rsidRDefault="00302287">
<w:pPr>
<w:pStyle w:val="a7"/>
</w:pPr>
</w:p>
</w:ftr>
<w:ftr w:type="odd">
<w:p wsp:rsidR="00302287" wsp:rsidRDefault="00302287">
<w:pPr>
<w:pStyle w:val="a7"/>
</w:pPr>
</w:p>
</w:ftr>
<w:ftr w:type="odd">
<w:p wsp:rsidR="00302287" wsp:rsidRDefault="00302287">
<w:pPr>
<w:pStyle w:val="a4"/>
<w:ind w:left-chars="1190" w:first-line-chars="450"/>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
<w:rFonts w:hint="fareast"/>
<wx:font wx:val="宋体"/>
</w:rPr>
<w:t>第</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t> </w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
</w:rPr>
<w:fldChar w:fldCharType="begin"/>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
</w:rPr>
<w:instrText> PAGE </w:instrText>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
</w:rPr>
<w:fldChar w:fldCharType="separate"/>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
<w:noProof/>
</w:rPr>
<w:t>1</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
</w:rPr>
<w:fldChar w:fldCharType="end"/>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t> </w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
<w:rFonts w:hint="fareast"/>
<wx:font wx:val="宋体"/>
</w:rPr>
<w:t>页</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t> </w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
<w:rFonts w:hint="fareast"/>
<wx:font wx:val="宋体"/>
</w:rPr>
<w:t>共</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
</w:rPr>
<w:fldChar w:fldCharType="begin"/>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
</w:rPr>
<w:instrText> NUMPAGES </w:instrText>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
</w:rPr>
<w:fldChar w:fldCharType="separate"/>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
<w:noProof/>
</w:rPr>
<w:t>1</w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
</w:rPr>
<w:fldChar w:fldCharType="end"/>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t> </w:t>
</w:r>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
<w:rFonts w:hint="fareast"/>
<wx:font wx:val="宋体"/>
</w:rPr>
<w:t>页</w:t>
</w:r>
</w:p>
</w:ftr>
实现出来的样子就是
但是往往人们还需要设置页面边距,页面板式首页不同/奇偶不同等问题
<w:pgSz w:w="12240" w:h="15840" w:code="9"/>
<w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="720" w:footer="720" w:gutter="0"/>
<w:pgNumType w:start="0"/>
<w:titlePg/>
<w:cols w:space="425"/>
<w:docGrid w:type="lines" w:line-pitch="312"/>
关于页面设置方面的代码都会在这里产生你只要细细看就会发现相应的代码
做个简单解释: <w:titlePg/>首页不同,<w:pgNumType w:start="0"/>
页面的起始也为第0页效果为:
以上内容写的有点乱希望大家见谅因为是自己使用过后的一点总结希望对大家有所帮助有需要QQ交流:316681406
另外附送FreeMaker 详细api
相关推荐
内容分为两部分一份代码+解释word文档,另外一份为...在文档中详细介绍了FreeMaker+xml转word碰到的问题如多张图片同时显示问题;目录更新问题,后期处理页眉页脚,页眉设置等问题。总之你想要的问题几乎都有。
springboot+freemaker+mybatis框架整合的案件后台管理系统,包含案件的excel批量添加,案件跟踪修改,案件每日和每月统计,权限管理(自定义角色)等; 相关技术关键字:springboot freemaker quartz mybatis mysql ...
Druid提供了Web监控页面,可以实时查看数据库连接池的状态,有助于性能调优和问题排查。 5. **整合步骤**: - 配置pom.xml文件,引入相关依赖。 - 配置application.properties,设定数据库连接信息和FreeMarker...
例如,开发者可以创建一个新的Word文档,插入文本、图片,设置样式,甚至执行复杂的布局操作。在这个场景下,开发者可能使用Jacob来读取由FreeMarker生成的临时Word文件,并进行进一步处理。 转换Word为PDF的过程...
在实际开发中,可能还需要考虑错误处理、并发生成、模板缓存等问题,以提高效率和健壮性。FreeMarker的强大之处在于其灵活性和可扩展性,可以根据具体需求进行定制,满足各种复杂的文件生成场景。
在JavaWeb开发中,生成Word文档常常用于报告、合同或者数据导出等场景。FreeMarker是一个流行的模板引擎,常用于动态生成HTML或者其他文本格式的文件。在这个案例中,我们将探讨如何利用FreeMarker来生成Word(.doc...
在本案例中,我们关注的是如何使用Freemaker来导出Word文档。这个"Freemaker导出word亲测可用"的项目,显然是一个实际应用的示例,它提供了便捷的方法来生成Word文档,无需复杂的操作。 Freemaker的核心理念是将...
structs2 + spring2 + hibernate3 +freemaker + Ajax 其中包括Jquery+Ajax等最新技术 实现的完整项目实例,从中可以学得很多技术知识,只此一家别 无二家. 想学好java_Web开发的就赶紧下载吧 (己包含了数据库的文件,...
本资源“freemaker导出word的doc_docx_带动态图片及word转pdf工具类_jar_万能整理汇总.rar”显然是一个集合了多种功能的压缩包,旨在帮助开发者高效地使用Freemarker来处理复杂的Word文档生成任务,并且包含了将Word...
总结来说,"freemaker word by xml"是一种利用FreeMarker模板引擎和XML技术在Java环境中动态处理Word文档的方法,它提供了高效且灵活的文档生成解决方案,广泛应用于自动化文档生成和个性化文档定制的场景中。
本篇文章将深入探讨如何使用FreeMarker模板引擎来生成包含图片和动态数据表的Word文档,尤其注重动态行和动态列的处理。 FreeMarker是一个强大的模板语言,用于生成文本输出,如HTML、XML、Word文档等。它与Java...
例如,它可以与 Struts2 结合,后者负责处理业务逻辑和请求转发。 5. **性能优势**:FreeMarker 生成的输出接近静态 HTML 的速度,因为模板在首次加载后会被编译为 Java 字节码,提高了执行效率。 **Struts2 知识...
本资料包“freemaker导出word的doc_docx_带动态图片及word转pdf工具类_jar_万能整理汇总rengm.zip”提供了关于如何使用Freemarker处理动态图片并转换Word为PDF的详细工具和教程。 首先,我们关注“doc_docx”部分。...
查看源码目录中是否包含pom.xml;若包含,则为maven项目,否则为非maven项目 6.数据库:MySql 5.7版本; 技术栈 1. 后端:SpringBoot 2. 前端:Layui+Freemaker 使用说明 1. 使用Navicat或者其它工具,在mysql中...
总的来说,这个示例提供了使用Freemarker和JFreechart生成带有动态图表的Word文档的方法。这对于报告生成、数据分析或其他需要可视化的场景非常有用,因为它允许开发者将动态数据与专业设计的文档模板相结合,创建出...
需要注意的是,实际操作中,图片处理部分可能需要更复杂的逻辑,例如处理图片大小、格式转换等。此外,模板设计时应避免过于复杂的嵌套和循环,以确保模板的可读性和易维护性。在处理大量数据时,考虑优化数据模型和...
同时,需要确保添加了正确的依赖,例如`spring-boot-starter-freemarker`和处理Word转换的库(如Apache POI或docx4j)到项目的`pom.xml`或`build.gradle`文件中。 在实际项目中,选择哪种方式取决于具体的需求和...
本示例中,我们关注的是如何使用FreeMarker来导出单个Word(.doc)格式的文档,并且这个文档中包含了动态生成的表格和list数据。 1. **FreeMarker基础** FreeMarker是一个基于模板的开源Java库,它可以将数据模型...