精华内容
下载资源
问答
  • word文档查重

    2018-07-23 09:16:57
    支持word文档查重,协助进行各类标书word文件查询重复部分。
  • NPOI创建DOCX常用操作,网上一直没有什么可用的例子供大家参考。我特意写了这个帮助类,亲测可用。
  • java 实现 word 文档的在线预览,资源包含代码和jar包,下载放入项目既可以使用
  • 本代码实现使用Java程序读取word文档成网页,将word文档按原样在网页输出。项目编码为UTF-8,文件编码也是utf8,再不要说乱码这种骚话了,选择utf8加载项目就不会乱码
  • 如何将一个word文档按页分割成多个word文档,很有参考价值
  • C#操作Word文档(根据模板生成文档、替换内容、插入表格等)
  • 这里有两个项目一个是下载的,一个是打开wrod文档的比较简单可以合成使用
  • asp .net 实现word文档在线预览

    热门讨论 2015-05-26 23:29:10
    最近由于项目需要,特利用vs2010整理了word文档在线预览,此处主要是用office-toolswf-flexpaper实现,在此把这一功能整理成了word文档和一个小例子,希望对您有用。
  • 用我们自己指定的word模板,生成新的word,代码填写内容到新的word中,可以插入图片、插入文件、插入音频、视频,有不懂的可以联系我。运行已编译成功,希望大家学习。
  • java生成word文档完美解决方案.
  • Android 使用模板生成Word文档,支持手机直接查看word,很强大、直接拿来用
  • 经常做Oa系统的人,难免经常遇到word文档处理的问题,现在针对已经存在的word文档,需要添加水印,设置保护信息,防止别人下载后更改文档内容
  • word文档操作

    热门讨论 2011-11-14 11:13:40
    这里演示了一个word操作的最最简单的例子,开发环境是windows XP + VC6(MFC APP) + word2010, 实现了打开一个文档,向其写入指定的内容,再关闭文档的功能。这里最主要的关键点还是在于先封装一个word操作类,这个...
  • java XML解析方式实现自动生成word文档,文档中主要描述word模板的使用方法,文件中带有案例代码,可以方便理解
  • Java导出Word文档的实现

    万次阅读 多人点赞 2020-10-18 16:17:13
    在日常的开发工作中,我们时常会遇到导出Word文档报表的需求,比如公司的财务报表、医院的患者统计报表、电商平台的销售报表等等。 导出Word方式多种多样,通常有以下几种方式: 1. 使用第三方Java工具类库Hutool...

     

    前言

    在日常的开发工作中,我们时常会遇到导出Word文档报表的需求,比如公司的财务报表、医院的患者统计报表、电商平台的销售报表等等。

    导出Word方式多种多样,通常有以下几种方式:

        1. 使用第三方Java工具类库Hutool的Word工具类,参考网址为https://www.hutool.cn/docs/#/poi/Word生成-Word07Writer;

        2. 利用Apache POI和FreeMarker模板引擎;

        3. 第三方报表工具。

    上面的几种方式虽然可以实现Word文档的导出,但有以下缺点

        第一种方式操作简单,但也只能生成简单的Word文档,无法生成有表格的Word文档;

        第二种方式可以生成复杂的Word文档,但是还要进行Word转xml,xml转ftl的双重转换,不适合内容经常变更的Word文档;

        第三种方式有时候不适合对格式要求严格的文档。

    那么,有没有既简单又高效的导出Word的方法呢?答案是肯定有的。接下来我就来介绍一种用Java语言实现的,通过XDocReportFreeMarker模板引擎生成Word文档的方法。

    准备环境

    开发语言:

    Java7及以上的版本。

    开发工具:

    Eclipse/Idea。

    第三方依赖库:

    XDocReport、POI、Freemarker。

    模板语言:

    FreeMarker。

    Word编辑器:

    Microsoft 365或其他版本较高的Word编辑器。

    示例Word模板

                         

    制作模板

    Word模板如上图,可以看到,结构比较简单,包括两个部分,第一部分是纯文字和数字,第二部分主要是表格。我们在实际的开发过程中生成的报表几乎都是动态生成的,所以模板中的数字和表格里的数据都要替换成我们后台的实际数据。

    替换Word模板中的动态变量,我们需要掌握两个知识点:

        1.Word文档中的Word域,word域是引导Word在文档中自动插入文字、图形、页码或其他信息的一组代码。在这里我们可以把         Word域理解成标识符,这个标识符表示Word文档中要被替换的内容;

        2.FreeMarker模板下的变量表达式,比如用${city}替换Word示例模板中的北京市。

    了解了以上两个概念后,我们就可以动手编辑Word模板了,步骤如下:

    1. 首先在Word模板中选中要替换的文本,在这儿拿标题中的"北京市"为例,然后键盘使用 Ctrl + F9 组合键将其设置为域,此时文本会被"{}"包围,接着鼠标右键选择【编辑域(E)...】:

    2. 在弹出的对话框中,类别选择“邮件合并”,域名选择 "MergeField",域属性中的域名填入模版表达式${city},点击【确定】按钮:

    3. 编辑后的效果如下:

    4. 掌握替换文本的方法后,我们可以把Word模板第一部分需要替换的内容都替换成模板变量:

    Word模板中表格数据的处理

    表格中的数据实质上就是对集合的遍历。

    表格数据的处理其实和上面对文本内容的处理是类似的,只不过要在Word模板中加上集合的变量,Java代码中也要有对集合进行特对的处理(这个在后面的代码展示部分会说)。

    具体操作步骤如下:

    1. 选定表格中要替换的文本,然后键盘使用 Ctrl + F9 组合键将其设置为域,接着鼠标右键选择【编辑域(E)...】:

    2. 在弹出的对话框中,类别选择“邮件合并”,域名选择 "MergeField",域属性中的域名填入模版表达式${goods.num},点击【确定】按钮;

    3. 重复步骤2,替换表格中的其他文本内容:

    后台代码

    添加依赖到pom.xml文件

    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>4.1.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>4.1.1</version>
    </dependency>
    <dependency>
        <groupId>org.jxls</groupId>
        <artifactId>jxls</artifactId>
        <version>2.6.0</version>
        <exclusions>
            <exclusion>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.jxls</groupId>
        <artifactId>jxls-poi</artifactId>
        <version>1.2.0</version>
    </dependency>
    <dependency>
        <groupId>fr.opensagres.xdocreport</groupId>
        <artifactId>fr.opensagres.xdocreport.core</artifactId>
        <version>2.0.2</version>
    </dependency>
    <dependency>
        <groupId>fr.opensagres.xdocreport</groupId>
        <artifactId>fr.opensagres.xdocreport.document</artifactId>
        <version>2.0.2</version>
    </dependency>
    <dependency>
        <groupId>fr.opensagres.xdocreport</groupId>
        <artifactId>fr.opensagres.xdocreport.template</artifactId>
        <version>2.0.2</version>
    </dependency>
    <dependency>
        <groupId>fr.opensagres.xdocreport</groupId>
        <artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
        <version>2.0.2</version>
    </dependency>
    <dependency>
        <groupId>fr.opensagres.xdocreport</groupId>
        <artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId>
        <version>2.0.2</version>
    </dependency>
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.23</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.5</version>
    </dependency>

    编写Java代码

    package com.tzsj.test;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    import org.junit.Test;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import fr.opensagres.xdocreport.core.XDocReportException;
    import fr.opensagres.xdocreport.document.IXDocReport;
    import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
    import fr.opensagres.xdocreport.template.IContext;
    import fr.opensagres.xdocreport.template.TemplateEngineKind;
    import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
    import io.renren.entity.Goods;
    
    @Controller
    @RequestMapping("/word")
    public class WordTest {
    	@Test
    	public void test() throws IOException, XDocReportException {
    		generateWord();
    	}
    	
    	public void generateWord() throws IOException, XDocReportException {
    		//获取Word模板,模板存放路径在项目的resources目录下
    	    InputStream ins = this.getClass().getResourceAsStream("/模板.docx");
            //注册xdocreport实例并加载FreeMarker模板引擎
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins,     
                                   TemplateEngineKind.Freemarker);
            //创建xdocreport上下文对象
            IContext context = report.createContext();
            
            //创建要替换的文本变量
            context.put("city", "北京市");
            context.put("startDate", "2020-09-17");
            context.put("endDate", "2020-10-16");
            context.put("totCnt", 3638763);
            context.put("totAmt", "6521");
            context.put("onCnt", 2874036);
            context.put("onAmt", "4768");
            context.put("offCnt", 764727);
            context.put("offAmt", "1753");
            context.put("typeCnt", 36);
            
            List<Goods> goodsList = new ArrayList<Goods>();
            Goods goods1 = new Goods();
            goods1.setNum(1);
            goods1.setType("臭美毁肤");
            goods1.setSv(675512);
            goods1.setSa("589");
            Goods goods2 = new Goods();
            goods2.setNum(2);
            goods2.setType("女装");
            goods2.setSv(602145);
            goods2.setSa("651");
            Goods goods3 = new Goods();
            goods3.setNum(3);
            goods3.setType("手机");
            goods3.setSv(587737);
            goods3.setSa("866");
            Goods goods4 = new Goods();
            goods4.setNum(4);
            goods4.setType("家具家装");
            goods4.setSv(551193);
            goods4.setSa("783");
            Goods goods5 = new Goods();
            goods5.setNum(5);
            goods5.setType("食物饮品");
            goods5.setSv(528604);
            goods5.setSa("405");
            goodsList.add(goods1);
            goodsList.add(goods2);
            goodsList.add(goods3);
            goodsList.add(goods4);
            goodsList.add(goods5);
            context.put("goods", goodsList);
            
            //创建字段元数据
            FieldsMetadata fm = report.createFieldsMetadata();
            //Word模板中的表格数据对应的集合类型
            fm.load("goods", Goods.class, true);
           
            //输出到本地目录
            FileOutputStream out = new FileOutputStream(new File("D://商品销售报表.docx"));
            report.process(context, out);
    	}
    
    }
    

    Word模板中生成序号

    给表格数据添加序号是通过后台代码生成的,比如上面的"goods1.setNum(1)"这段代码,其实也可以在Word模板中设置对应的域变量来实现序号的填充。

    语法如下:

    @before-row[#list sequence as item]
        item?index
    @after-row[/#list]

    在表格中添加上面的表达式,XDocReport就会自动解析并生成序号,表格中的其他字段也需要进行相应的改动:

    提示:

    1. 序号的表达式要拆成三个域,如下图,要把这三部分分别设置成域;

         设置完成的结果参考上面表格中的序号表达式,表达式中"item?index+1"是因为序号是从0开始的,所以要加1

    2. 表格中除序号的列需要改成item.xxx而不是之前的goods.xxx:

    3. 生成效果如下:

    建议:序号最好在后台生成,用序号表达式生成的序号列会占用比较大的空间,对资源有所浪费。

    补充

    1. JavaWeb项目中通常是通过浏览器下载的方式来下载Word文档,此时只需要把之前下载到本地的代码改成浏览器端下载的代码即可:

    //输出到本地目录
    //FileOutputStream out = new FileOutputStream(new File("D://商品销售报表.docx"));
    //report.process(context, out);
    
    //浏览器端下载
    response.setCharacterEncoding("utf-8");  
    response.setContentType("application/msword");  
    String fileName = "商品销售报表.docx";  
    response.setHeader("Content-Disposition", "attachment;filename="  
    				    .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));  
    report.process(context, response.getOutputStream());

    2. Word模板中的表格的长度最好充满Word文档的左右两边,否则如果表格下面还有其他文本内容,下面的文本内容会自动填充到表格的缝隙处,而且会对下面的文本内容进行覆盖。

    加餐

    其实,导出Word模板,上面的模板和代码已经够用了,但也有少数模板需要添加图片和图形(比如饼状图)。

    制作图片

    图片的生成不使用编辑域,使用模板图片和Word的书签功能,而且需要在元数据中加入图片类型的代码,以下为具体步骤:

    1. 在Word模版中需要插入图片的位置插入一张模版图片,然后鼠标单击模板图片插入一个书签,设置书签名称,比如img1, 最后点击【添加】按钮:

     2. 如果需要插入多个图片,就在需要插入图片的位置插入多个模板图片并插入书签设置对应的书签名称即可,后台代码如下: 

    package com.tzsj.test;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import org.junit.Test;
    import fr.opensagres.xdocreport.core.XDocReportException;
    import fr.opensagres.xdocreport.document.IXDocReport;
    import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
    import fr.opensagres.xdocreport.template.IContext;
    import fr.opensagres.xdocreport.template.TemplateEngineKind;
    import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
    
    public class ImgTest {
    
    	@Test
    	public void test() throws IOException, XDocReportException {
    		generateWordForImg();
    	}
    	
    	
    	public void generateWordForImg() throws IOException, XDocReportException {
    		//获取Word模板,模板存放路径在项目的resources目录下
    	    InputStream ins = this.getClass().getResourceAsStream("/图片.docx");
            //注册xdocreport实例并加载FreeMarker模板引擎
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins, 
                                   TemplateEngineKind.Freemarker);
            //创建xdocreport上下文对象
            IContext context = report.createContext();
            
            FieldsMetadata fm = report.createFieldsMetadata();
            //元数据中加入图片
            fm.addFieldAsImage("img1");
            fm.addFieldAsImage("img2");
            
            //获取图片
            InputStream img1 = this.getClass().getResourceAsStream("/11.jpg");
            InputStream img2 = this.getClass().getResourceAsStream("/33.jpg");
            
            //把图片添加到上下文对象
            context.put("img1", img1);
            context.put("img2", img2);
            
            //输出到本地目录
            FileOutputStream out = new FileOutputStream(new File("D://图片报表.docx"));
            report.process(context, out);
    	}
    
    }
    

     3. 导出效果如下:

    制作图形

    要在Word文档中生成柱状图、饼状图等图形,需要在项目中引入第三方绘图工具,在这里使用xchart来演示在Word中生成饼状图图形。

    生成饼状图和生成图片的方法很类似,具体步骤如下:

    1. 在Word模版中需要插入图片的位置插入一张模版图片,然后鼠标单击模板图片插入一个书签,设置书签名称,比如chart,最后点击【添加】按钮:

    2. 编写代码:

    2.1 在pom.xml文件中添加xchart的依赖:

    <dependency>
    	<groupId>org.knowm.xchart</groupId>
    	<artifactId>xchart</artifactId>
    	<version>3.5.4</version>
    </dependency>

    2.2 后台代码:

    package com.tzsj.test;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import org.junit.Test;
    import org.knowm.xchart.BitmapEncoder;
    import org.knowm.xchart.PieChart;
    import org.knowm.xchart.PieChartBuilder;
    import fr.opensagres.xdocreport.core.XDocReportException;
    import fr.opensagres.xdocreport.document.IXDocReport;
    import fr.opensagres.xdocreport.document.images.ByteArrayImageProvider;
    import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
    import fr.opensagres.xdocreport.template.IContext;
    import fr.opensagres.xdocreport.template.TemplateEngineKind;
    import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
    
    public class ChartTest {
    
    	@Test
    	public void test() throws IOException, XDocReportException {
    		generateWordForChart();
    	}
    	
    	
    	public void generateWordForChart() throws IOException, XDocReportException {
    		//获取Word模板,模板存放路径在项目的resources目录下
    	    InputStream ins = this.getClass().getResourceAsStream("/饼图.docx");
            //注册xdocreport实例并加载FreeMarker模板引擎
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins,                 
                                     TemplateEngineKind.Freemarker);
            
            //创建xdocreport上下文对象
            IContext context = report.createContext();
            
            FieldsMetadata fm = report.createFieldsMetadata();
            //元数据中加入图片
            fm.addFieldAsImage("chart");
            
            PieChart chart = new PieChartBuilder().width(800).height(620)
                                    .title("销售饼图").build();
            
            //给饼图设置对应的值
            chart.addSeries("臭美毁肤", 589);
            chart.addSeries("女装", 651);
            chart.addSeries("手机", 866);
            chart.addSeries("家居家装", 783);
            chart.addSeries("食物饮品", 405);
            
            //生成饼图
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            BitmapEncoder.saveBitmap(chart, baos, BitmapEncoder.BitmapFormat.JPG);
            
            //把饼图添加到上下文对象
            context.put("chart", new ByteArrayImageProvider(baos.toByteArray()));
            
            //输出到本地目录
            FileOutputStream out = new FileOutputStream(new File("D://饼图报表.docx"));
            report.process(context, out);
    	}
    
    
    }
    

    3. 导出效果如下:

    总结

    这就是用Java语言实现,结合XDocReportFreeMarker模板引擎生成Word文档的方法。希望能给致力于开发的小伙伴带来一丝丝帮助。

    如果您在浏览过程中遇到什么问题,请在下方评论区给我留言。

    本人入驻的其他平台:

    • 微信公众号弹指时间 。
    • 网易音乐人弹指时间

    展开全文
  • java poi 通过模板生成word文档

    热门讨论 2014-07-22 17:10:34
    java使用poi,根据模板,生成word文档.
  • WinForm嵌入Word文档控件开发

    热门讨论 2013-06-04 10:41:34
    因为看到论坛中很多人想把Word文档中嵌入WinForm中,虽然WebBrowser控件可以实现这个功能,但是使用这个控件不能对Word进行很好的控制,这个资源通过自定义控件来实现嵌入Word文档,大家可以下载下来研究下的
  • 完整项目,直接可以导入到myeclipse中运行,代码有详细注释,在readme.txt文件里面有注意事项。
  • 微软公司的office word软件是一个通用的功能强大的文字处理软件,本实例是采用QT5开发的类似于word文字处理的软件,代码完整,方便学习,可以编辑出精美的文档
  • Word类生成word文档(可批量生成)

    热门讨论 2012-05-13 10:42:57
    利用Word类生成word文档,简洁的代码,不一样的效果,可以批量生产word文档
  • java生成word的实例 java导出Word文档的实例 项目说明
  • 利用VBA代码将一个word文档按页分割成多个word文档
  • 完美解决方案:Java生成复杂Word文档

    热门讨论 2011-07-18 19:31:06
    客户要求用程序生成标准的word文档,要能打印,而且不能变形,以前用过很多解决方案,都在客户严格要求下牺牲的无比惨烈。  POI读word文档还行,写文档实在不敢恭维,复杂的样式很难控制不提,想象一下一个20多页,...
  • 通过目录找出对应的标题, 通过两个标题的位置得到之间的段落(得到了段落Range,但是我只处理了text,没有处理table和picture,这些都可以从Range中取出)
  • PHP读取word文档 导入word文档

    千次阅读 2019-10-26 15:50:48
    PHP读取word文档 导入word文档PHP读取word文档 导入word文档openoffice把word转html用phpquery读取html的内容 PHP读取word文档 导入word文档 用openoffice和phpquery实现word文档的导入 读取word文档数据 前一段时间...

    PHP读取word文档 导入word文档

    前一段时间在工作中遇见了一个棘手的需求,客户要求把word里的数据导入,对数据进行统计。
    刚开始觉得挺简单用phpword应该能够实现,后在网上各处询问也没发现phpword能够导入word,
    然后我就转换了思路,先用libreoffice把word转换成html

    libreoffice把word转html

    安装libreoffice就不多做介绍
    openoffice命令
    用这个命令就可以把word文档转为html

    用phpquery读取html的内容

    获取到html了下面就是读取里边的内容了 大家应该都用过jquery,jQuery可以在html中获取html里的内容
    可以在php后端我们改如何操作呢,用phpQuery就可以让php处理html代码像jQuery一样方便。
    项目地址:https://code.google.com/p/phpquery/

    github地址:https://github.com/TobiaszCudnik/phpquery

    DEMO

    下载库文件:https://code.google.com/p/phpquery/downloads/list

    我下的是onefile版:phpQuery-0.9.5.386-onefile.zip

    官方demo:https://code.google.com/p/phpquery/source/browse/branches/dev/demo.php

    然后在项目中引用。
    phpquery
    phpquery的文档特别少,但是和jquery的差别并不大
    pq($param, $context = null);

    pq(); 相当于 jQuery的$();。它主要完成三件事情:

    1. 载入标记资源:

    // 输入到载入的文档:
    // 对于最开始输入的字符串不接收文本类型的节点:pq(’

    ’)
    // 从$pq->getDocumentID()根据ID载入到文档: pq(’
    ’, $pq->getDocumentID())
    // 根据DOM节点的归属将同样的文档载入:pq(’
    ’, DOMNode)
    // 从phpQuery 对象载入文档: pq(’
    ’, $pq)

    1. 运行查询

    // 根据最后一个选择的文档执行查询:pq(‘div.myClass’)
    // 根据$pq->getDocumentID()的ID从文档中进行查询:pq(‘div.myClass’, $pq->getDocumentID())
    // 在同样的文档上根据DOM节点的归属进行查询并且使用节点作为查询的根节点:pq(‘div.myClass’, DOMNode)
    // 在文档上使用phpQuery对象进行查询
    // 同时使用对象的栈作为根节点进行查询: pq(‘div.myClass’, $pq)

    1. 使用phpQuery对象对DOM节点进行原型化操作

    foreach(pq(‘li’) as $li) // $ li是纯DOM节点, 将它变为phpQuery对象: pq($li);。

    原创文章,码字不易,转载请注明出处

    展开全文
  • POI读取word文档的文字内容和图片内容

    千次下载 热门讨论 2014-09-04 13:55:55
    POI读取word文档的文字内容和图片内容
  • 大致的思路是先用office2003或者2007编辑好word的样式,然后另存为xml,将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板并输出‘.doc’ word文档。经测试这样方式生成的word文档完全符合office标准,...
  • word文档批量处理大师6.0.7破解版

    热门讨论 2012-09-14 14:58:00
    word文档批量处理大师6.0.7破解版 测试可用 功能上不是很好。
  • java生成word文档

    万次阅读 2019-05-15 10:25:41
    最近工作需要从数据库查询数据,代码生成word文档,便在网上查询了一下办法。之前类似的工作也曾经做过,当时是在word模板中设置标记,在代码中填充标记。当前网络上简便的方法也是类似,word文档不是凭空生成的,...

    最近工作需要从数据库查询数据,代码生成word文档,便在网上查询了一下办法。之前类似的工作也曾经做过,当时是在word模板中设置标记,在代码中填充标记。当前网络上简便的方法也是类似,word文档不是凭空生成的,需要先设计一个word模板,在文档中需要从数据库取值的地方,用${参数名}代替(如图一)。
    java代码生成Word文档示例
    图一
    下面提一下主角,freemarker,一个基于模板和源数据来生成目标文本的引擎工具。这个工具的其他功能我们这里不做关心,只需要从官网下载我们需要的jar包即可。http://freemarker.org/freemarkerdownload.html上面目前可以下载2.3.5的版本。引入jar包之后,我们的代码中需要引用:

    import freemarker.template.Configuration;
    import freemarker.template.Template;
    import freemarker.template.TemplateException;
    

    java代码生成Word文档示例
    图二

    我们再回到word模板,将其另存为xml格式(如图二),文件名可以中文,也可以是英文。然后将xml文件的后缀名修改为ftl格式,就变成了freemarker的标准格式。可以用类似EditPlus等工具打开ftl文件,要编辑表格参数部分,在表格的第二行数据参数部分,搜索和对应的加入list标签(如图三)。

    java代码生成Word文档示例 java代码生成Word文档示例 java代码生成Word文档示例
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

    list指令执行在list开始标签和list结束标签(list中间的部分)之间的代码,其中每个值只指定一个参数(比如表格有五行,只需要定义一行的参数就可以了如图一,会自动迭代赋值),对于每次迭代,循环变量将会引用当前项的值。循环变量仅仅存在于list标签体内。图三list标签中的wordList是程序中定义的list名称,word是这个list的别名,别名用来标记参数引用的是哪个list中的值(如图三),所以还需要修改之前表格中的参数 p a r a 等 为 {para}等为 para{word.para}格式。

    下面是完整的代码:

    public class WordTest {
    private Configuration configuration = new Configuration(); 
    // 加载模板信息
    private Template readWord() {
    // 加载文档模板FTL文件所存在的位置
    configuration.setClassForTemplateLoading(this.getClass(),"/com/test");
    //web工程还可以使用加载方法configuration.setServletContextForTemplateLoading(Object servletContext, String path);
    configuration.setDefaultEncoding("UTF-8");
    Template tempWord = null;
    try {
    // 获取模板信息
    tempWord = configuration.getTemplate("文档示例.ftl");
    } catch (IOException e) {
    e.printStackTrace();
    }
    return tempWord;
    }
    // 填充模板参数
    private void getFillData(Map dataMap) {
    // 根据模板中的参数填充内容,可以不按顺序,参数名称要对上
    dataMap.put("wordname", "文档标题");
    dataMap.put("user", "userName");
    dataMap.put("password", "56fdh6ror8");
    dataMap.put("wordDescription", "本文档供开发人员和测试人员参考。调用服务请求时,需要先传递开发者编号和开发者密钥,系统会先对编号和密钥解析验证,如果不通过,不会继续处理信息。");
    // list的内容对应表格,表格行数与list的size对应,正常应用中list数据从数据库获取,本示例设置一个size=5的list
    List> wordList = new ArrayList>();
    for (int i = 0; i < 5; i++) {
    Map map = new HashMap();
    map.put("para", i);
    map.put("type", "参数" + i);
    if(4 == i){
    map.put("empty", "可空");
    }else{
    map.put("empty", "不可空");
    }
    wordList.add(map);
    }
    dataMap.put("wordList", wordList);
    }
    // 创建新word文档
    public void createWord() {
    Map dataMap = new HashMap();
    // 组装填充模板数据
    getFillData(dataMap);
    // 文档输出目录
    File outFile = new File("WebRoot/word/测试文档.doc");
    Writer out = null;
    try {
    out = new BufferedWriter(new OutputStreamWriter(
    new FileOutputStream(outFile)));
    } catch (FileNotFoundException e1) {
    e1.printStackTrace();
    }
    try {
    // 模板填充后,输出到指定目录
    readWord().process(dataMap, out);
    } catch (TemplateException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    // 调用方法
    public static void main(String[] args) {
    WordTest test = new WordTest();
    test.createWord();
    }
    }
    

    测试代码模板与代码放在同级目录下面,工程应用中可以放到其他目录中使用不同的方法获取,本示例生成的word文档放到了WebRoot目录下(见图四)。

    java代码生成Word文档示例
    在这里插入图片描述
    最后生成的目标word文档样式(见图五)。
    java代码生成Word文档示例

    在这里插入图片描述

    当代码写完时发现测试出现了bug 下面分享一下解决问题的方式

    青年:新产品中的监测模块每天会生成新的监测数据,对于这些监测数据可提供word文档下载。按理说用poi是可以解决的,但是目前的痛点在于,监测数据的种类很多,每种监测数据的word模板也各不相同,并且在将来文档模板内容以及排版样式还会有变化。使用poi的方式,会使工作量剧增,将来扩展也存在很大的问题,大师你看该怎么办?

    禅师:这个问题很有意思,目前生成文档的主流方式确实是使用poi。针对你的这种特殊需求确实需要就事论事,我的建议使用freemarker模板生成word。

    青年:freemarker是模板引擎,他是把由模板语言写成的模板生成文本文件,思路上是符合需求的。只要在word文档中需要展示的数据用模板语言标记即可,可是问题是freemarker可以把word模板直接生成word文件吗?我的word模板如图:
    在这里插入图片描述

    禅师:肯定不能把word模板直接作为freemarker的模板生成word的。需要把word模板另存为xml文件,用这个xml文件作为freemarker的模板生成word,如图:
    在这里插入图片描述

    我给你一个(demo-mydoc点击下载),只要在template文件夹下放入这个xml模板,运行Test.java文件就可以。

    青年:大师,出问题了,我严格按照你的要求运行时发生了如下的错误:

    freemarker.core.ParseException: Parsing error in template "company.xml" in line 3, column 20887:
    Encountered "<", but was expecting one of:
        <STRING_LITERAL>
        <RAW_STRING>
        "false"
        "true"
        <INTEGER>
        <DECIMAL>
        "."
        "+"
        "-"
        "!"
        "["
        "("
        "{"
        <ID>
    	at freemarker.core.FMParser.generateParseException(FMParser.java:4672)
    	at freemarker.core.FMParser.jj_consume_token(FMParser.java:4543)
    	at freemarker.core.FMParser.UnaryExpression(FMParser.java:340)
    	at freemarker.core.FMParser.MultiplicativeExpression(FMParser.java:452)
    	at freemarker.core.FMParser.AdditiveExpression(FMParser.java:402)
    

    可是我有时模板中只有一个参数的时候,比如 n a m e , 就 可 以 正 确 的 显 示 , 一 旦 多 个 参 数 的 时 候 就 报 错 , 甚 至 有 时 重 写 一 遍 模 板 , 哪 怕 只 有 一 个 参 数 {name},就可以正确的显示,一旦多个参数的时候就报错,甚至有时重写一遍模板,哪怕只有一个参数 name{name}的时候也报错,怎么会时而可以运行时而报错,像躲迷藏似的,确实让人抓狂,大师能不能指点一二。

    禅师哈哈一笑后说:年轻人写代码的时候要有耐心,尤其在程序报错的时候更要加倍耐心。我们可以看到报错的原因是因为:freemarker.core.ParseException: Parsing error in template “company.xml” in line 3, column 20887,肯定是模板解析出现问题,也就是解析没成功呗,给你一个查看xml的工具(firstobject xml editor点击下载),看看模板变量是否有问题。

    青年用firstobject xml editor工具打开模板文件,按F8格式化,双击左边w:body,定位到该标签如图:
    在这里插入图片描述

    在<w:body>中果然看到问题所在:${name}被<w:r>分隔成了若干块,如图:
    在这里插入图片描述

    这种情况下,freemarker是解析不出模板命令的,改正做法就保留一个完整的<w:r>${name}</w:r>,其余的都删除,如图:

    在这里插入图片描述

    其余的模板命令以此类推。然后把xml模板放到demo中,运行得到如图结果:

    在这里插入图片描述

    禅师:干的不错,看来问题就出在了word模板另存为xml模板的时候,这应该是word软件的一个bug。

    青年:感谢大师,现在心情舒畅多了!

    总结:
    1.word模板另存为xml文档,由于word软件本身的原因,会把模板命令比如$(“name”)分隔成若干块,导致freemarker无法解析。

    2.需要用firstobject xml editor工具查看xml模板,手动修改,保留完整的模板命令块。

    3.将手动修改好的xml拷进demo中,可成功运行。

    4.xml格式的word换行标记<w:br/>

    展开全文
  • C#操作word文档 C#实现Word中表格信息读取

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 397,773
精华内容 159,109
关键字:

word文档