精华内容
下载资源
问答
  • xdocreport
    2021-07-06 01:49:16

    本文采用XDocReport集合Freemaiker進行處理

    1. 引入Maven依賴:

    fr.opensagres.xdocreport

    xdocreport

    2.0.1

    org.apache.velocity

    velocity-engine-core

    2.0

    org.freemarker

    freemarker

    2.3.23

    2. 創建Word模版

    新建Word,在光標處通過快捷鍵Ctrl+F9 或 工具欄“插入”->“文檔部件或文本”->“域”

    根據電腦系統不同出現的界面不同,但內容都差不多,${text} 這個text就是后期要替換的變量了。

    51f40cb4e8bdad27aa3fbd063e3e602d.png

    3. Java代碼處理邏輯

    1 String templateFilePath = request.getSession().getServletContext().getRealPath("/WEB-INF/templates/freemarkerTest.docx");2 File file = newFile(templateFilePath);3 InputStream in = newFileInputStream(file);4 IXDocReport report;5 String targetPath = basePath + lawDownDto.getLawsName() + ".docx";6 try{7 report =XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker);8 //設置內容為HTML格式

    9 FieldsMetadata metadata =report.createFieldsMetadata();10 metadata.addFieldAsTextStyling("text", SyntaxKind.Html);11

    12 //創建內容-text為模版中對應都變量名稱

    13 IContext context =report.createContext();14 context.put("text", content);15

    16 //生成文件

    17 OutputStream out = newFileOutputStream(targetPath);18 report.process(context, out);19 } catch(XDocReportException e) {20 e.printStackTrace();21 }

    文件下載:在生成文件邏輯后創建讀取流返回即可。

    =============================================================

    如果文件中有圖片需要處理:

    圖片方案一:單個圖片且位置固定,可通過XDocReport配置模版處理

    圖片方案二:多個圖片且位置不固定,可通過POI結合Freemarker進行處理

    圖片方案一:

    1. 在模版中插入臨時圖片,選中圖片並添加“書簽”,書簽名稱是后續作為替換的變量

    8daabc6a4e348293f591a433e23cc391.png

    2. 代碼中追加邏輯

    在上面代碼10后追加

    //logo為模版中標簽名稱

    metadata.addFieldAsImage("logo");

    report.setFieldsMetadata(metadata);

    在上面代碼14行后追加

    //IImageProvider可通過3種方式創建(File/IO流/ClassPath下文件)具體可參考頂部文檔-Dynamic Image

    IImageProvider logo = new FileImageProvider(new File("1950737_195902644.png"));

    context.put("logo", logo);

    圖片方案二:

    1. 在上面讀取模版之前進行數據替換

    //處理文本中的圖片,使用imgReplace變量替換

    Map param = new HashMap();if(StringUtils.isNotBlank(content)) {

    content=HtmlUtils.htmlUnescape(content);

    List> imgs =getImgStrContent(content);int count = 0;for (HashMapimg : imgs) {

    count++;//處理替換以“/>”結尾的img標簽

    content = content.replace(img.get("img"), "${imgReplace" + count + "}");//處理替換以“>”結尾的img標簽

    content = content.replace(img.get("img1"), "${imgReplace" + count + "}");

    Map header = new HashMap();

    String result= "";

    result= img.get("src");//如果沒有寬高屬性,默認設置為

    if(img.get("width") == null || img.get("height") == null) {

    header.put("width", 150);

    header.put("height", 150);

    }else{

    header.put("width", (int)(Double.parseDouble(img.get("width"))));

    header.put("height", (int) (Double.parseDouble(img.get("height"))));

    }if( StringUtils.isNotBlank(result) ){

    String type1= result.substring(result.lastIndexOf(".") , result.length());

    header.put("type", type1);

    header.put("content",this.imageToInputStream(result));

    }

    param.put("${imgReplace" + count + "}", header);

    }

    }

    //獲取html中的圖片元素信息

    private List>getImgStrContent(String htmlStr) {

    List> pics = new ArrayList>();

    Document doc=Jsoup.parse(htmlStr);if( doc != null){

    Elements imgs= doc.select("img");if( imgs != null && imgs.size() > 0){for(Element img : imgs) {

    HashMap map = new HashMap();if(!"".equals(img.attr("width"))) {

    map.put("width", img.attr("width"));

    }if(!"".equals(img.attr("height"))) {

    map.put("height", img.attr("height"));

    }

    map.put("img", img.toString().substring(0, img.toString().length() - 1) + "/>");

    map.put("img1", img.toString());

    map.put("src", img.attr("src"));

    pics.add(map);

    }

    }

    }returnpics;

    }

    //讀取生成的文件

    readStream = newFileInputStream(targetPath);

    ByteArrayOutputStream docxOs= newByteArrayOutputStream();int b = 0;byte[] buf = new byte[1024];while ((b = readStream.read(buf)) != -1) {

    docxOs.write(buf,0, b);

    }

    docxResponseStream= newByteArrayInputStream(docxOs.toByteArray());//創建word 對象

    XWPFDocument document = newXWPFDocument(docxResponseStream);

    newOS= newByteArrayOutputStream();if (document != null && param != null) {//生成帶圖片的word(如需工具類請給我發郵件)

    XWPFDocument customXWPFDocument =WordUtil.getWord(param, document);//設置表格邊框樣式(另外一片文章會介紹)//List list = formatTableBorder(customXWPFDocument);//處理合並單元格(另外一片文章會介紹)//mergeCell(content, list);//寫入輸出流返回

    customXWPFDocument.write(newOS);

    document.close();

    customXWPFDocument.close();

    resultInpu= newByteArrayInputStream(newOS.toByteArray());

    }else{

    resultInpu=docxResponseStream;

    }

    以上內容即可完成Word中多圖片的動態展示。

    后續會寫處理表格邊框、單元格合並及段落都相關內容。

    更多相关内容
  • POI ,xdocreport框架是一个半成品,往往使用默认的解析结果无法满足业务需求,花了很长时间和心血研究了其源码,修复了以下问题 问题1: xdocreport能解析word转html,但解析出来的是基于word的整套html,往往我们的...
  • XDocReport XDocReport表示XML文档报告。 它是Java API,用于将使用MS Office(docx)或OpenOffice(odt),LibreOffice(odt)创建的XML文档与Java模型进行合并,以生成报告并将报告转换为其他格式(PDF,XHTML ......
  • fr.opensagres.xdocreport

    2022-05-16 22:05:11
    poi word转pdf
  • xdocreport-2.0.1.jar

    2018-06-18 18:41:30
    xdocreport-2.0.1.jar,生成word文件等,只有jar,自行需要下载
  • 纯javadocx转pdf,windows下jacob转pdf,openoffice转pdf,docx文书替换,插入表格,图片等
  • Java实现导出Word文档功能(XDocReport +FreeMarker) 前言 在日常的开发工作中,我们时常会遇到导出Word文档报表的需求,比如公司的财务报表、医院的患者统计报表、电商平台的销售报表等等。 导出Word方式多种多样...

    Java实现导出Word文档功能(XDocReport +FreeMarker)

    前言

    在日常的开发工作中,我们时常会遇到导出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 语言实现的,通过 XDocReport FreeMarker 模板引擎生成Word文档的方法。


    一、准备环境

    开发语言:

    Java7及以上的版本。

    开发工具:

    Eclipse/Idea。

    第三方依赖库:

    XDocReport、POI、Freemarker。

    模板语言:

    FreeMarker。

    Word编辑器:

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

    二、准备Word模板

    1.示例Word模板

    在这里插入图片描述

    2.制作模板

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

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

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

    2.FreeMarker模板下的变量表达式,比如用${title}替换Word示例模板中的报表

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

    步骤一:
    1.首先在Word模板中选中要替换的文本,在这儿拿标题中的标题的报表字样为例,全选标题然后键盘使用 Ctrl + F9 组合键将其设置为域,此时文本会被"{}"包围,接着鼠标右键选择【编辑域(E)...】
    在这里插入图片描述

    步骤二:
    2.在弹出的对话框中,类别选择“邮件合并”,在后侧域代码的 "MERGEFIELD "后面编写FreeMarker模板表达式${title},点击【确定】按钮:
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/9b96de8a63c5465296731b4238fd1379.png

    步骤三:
    3.编辑后的效果如下:
    在这里插入图片描述

    步骤四:
    4.掌握替换文本的方法后,我们可以把Word模板第文本部分需要替换的内容都替换成模板变量:
    在这里插入图片描述

    Word模板中表格数据的处理(重点)

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

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

    步骤一:
    1.选定表格中要替换的文本,然后键盘使用 Ctrl + F9 组合键将其设置为域,接着鼠标右键选择【编辑域( E)…】:
    步骤二:
    在弹出的对话框中,类别选择“邮件合并”,在后侧域代码的 "MERGEFIELD "后面编写FreeMarker模板表达式${student.id},点击【确定】按钮:
    在这里插入图片描述
    步骤三
    3.重复步骤2,替换表格中的其他文本内容:
    在这里插入图片描述

    步骤四
    四.将模板放到resources目录下:
    在这里插入图片描述

    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 word导出;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    
    import fr.opensagres.xdocreport.core.XDocReportException;
    import fr.opensagres.xdocreport.document.IXDocReport;
    import fr.opensagres.xdocreport.document.images.FileImageProvider;
    import fr.opensagres.xdocreport.document.images.IImageProvider;
    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;
    
    /**
     * Created by PRX on 2022/6/18 22:59
     */
    public class wordExport {
        public static void main(String[] args) throws IOException, XDocReportException {
            Test test = new Test();
            test.export();
    
        }
    }
    
    class Test{
        public void export() throws IOException, XDocReportException {
            //获取Word模板,模板存放路径在项目的resources目录下
            InputStream ins = this.getClass().getResourceAsStream("/word.docx");
            //注册xdocreport实例并加载FreeMarker模板引擎
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins,
                    TemplateEngineKind.Freemarker);
            
            //设置集合数组
            List<Student1> list = new ArrayList<Student1>();
            Student1 student = new Student1();
            student.setId(1);
            student.setName("小查");
            student.setAge(19);
            list.add(student);
    
            Student1 student2 = new Student1();
            student2.setId(2);
            student2.setName("小红");
            student2.setAge(19);
            list.add(student2);
    
            //创建xdocreport上下文对象
            IContext context = report.createContext();
            context.put("title","报表");
            context.put("name","彭先生");
            context.put("student",list);  //加入到上下文对象中
            context.put("nian","2022");
            context.put("yue","06");
            context.put("day","18");
    
            //创建字段元数据
            FieldsMetadata fm = report.createFieldsMetadata();
            //Word模板中的表格数据对应的集合类型
            fm.load("student", Student1.class, true);
            report.setFieldsMetadata(fm);
    
            //输出到本地目录
            FileOutputStream out = new FileOutputStream(new File("D://报表.docx"));
            report.process(context, out);
    
    
            System.out.println("导出成功");
    
    
    
        }
    }
    
    

    3.Word模板中生成序号

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

    语法如下:
    @before-row[#list list as item] //开头list集合数组
    ${item?index+1} //数据序号
    @after-row[/#list]//结尾

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

    注意

    语法的开头部分、中间数据部分、结尾部分分别都要设置单独的Word域并且在设置Word域的时候要使用" "包裹住FreeMarker语法 如图所示:
    在这里插入图片描述

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

    2.表格中除序号的列需要改成item.xxx而不是之前的student.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的书签功能,而且需要在元数据中加入图片类型的代码,以下为具体步骤:

    1.制作图片

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

    如果需要插入多个图片,就在需要插入图片的位置插入多个模板图片并插入书签设置对应的书签名称即可
    在这里插入图片描述

    2.编写后端代码

    package word导出;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.List;
    
    import fr.opensagres.xdocreport.core.XDocReportException;
    import fr.opensagres.xdocreport.document.IXDocReport;
    import fr.opensagres.xdocreport.document.images.FileImageProvider;
    import fr.opensagres.xdocreport.document.images.IImageProvider;
    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;
    
    /**
     * Created by PRX on 2022/6/18 22:59
     */
    public class wordExport {
        public static void main(String[] args) throws IOException, XDocReportException {
            Test test = new Test();
            test.export();
    
        }
    }
    
    class Test{
        public void export() throws IOException, XDocReportException {
            //获取Word模板,模板存放路径在项目的resources目录下
            InputStream ins = this.getClass().getResourceAsStream("/word.docx");
            //注册xdocreport实例并加载FreeMarker模板引擎
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins,
                    TemplateEngineKind.Freemarker);
    
            //设置集合数组
            List<Student1> list = new ArrayList<Student1>();
            Student1 student = new Student1();
            student.setId(1);
            student.setName("小查");
            student.setAge(19);
            list.add(student);
    
            Student1 student2 = new Student1();
            student2.setId(2);
            student2.setName("小红");
            student2.setAge(19);
            list.add(student2);
    
            //创建xdocreport上下文对象
            IContext context = report.createContext();
            context.put("title","报表");
            context.put("name","彭先生");
            context.put("student",list);  //加入到上下文对象中
            context.put("nian","2022");
            context.put("yue","06");
            context.put("day","18");
    
    //        context.put("img1",getImg("https://cdn.uviewui.com/uview/swiper/swiper1.png"));
    
    
            //创建字段元数据
            FieldsMetadata fm = report.createFieldsMetadata();
            //Word模板中的表格数据对应的集合类型
            fm.load("student", Student1.class, true);
    
    
            //替换word模板中的动态图⽚
    //        IImageProvider 图片 = new FileImageProvider(new File("C:\\Users\\xx\\Pictures\\Screenshots\\屏幕截图 2021-05-16 190200.png"),true); //绝对路径获取图片
            fm.addFieldAsImage("img1");
            context.put("img1",getImg("https://cdn.uviewui.com/uview/swiper/swiper1.png"));
            report.setFieldsMetadata(fm);
    
            //输出到本地目录
            FileOutputStream out = new FileOutputStream(new File("D://报表.docx"));
            report.process(context, out);
    
    
            System.out.println("输出成功");
    
    
    
        }
        //网络编程    处理网络图片
        public InputStream getImg(String urls) throws IOException {
            URL url = new URL(urls);   //解析路径链接  获取指定资源
            System.out.println("url====:"+url);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();  //得到网络对象  协议、请求头、请求体、响应信息等
            System.out.println("conn===="+conn);
            conn.setRequestMethod("GET");       //设置请求方式
            conn.setConnectTimeout(5 * 1000);   //设置过期时间
            InputStream inStream = conn.getInputStream();  //返回该对象的字节输入流
            return inStream;
        }
    }
    
    

    3. 导出效果如下

    在这里插入图片描述

    总结

    这就是用 Java 语言实现,结合 XDocReport 和 FreeMarker 模板引擎生成Word文档的方法

    展开全文
  • core org.jxls jxls-poi 1.2.0 fr.opensagres.xdocreport fr.opensagres.xdocreport.core 2.0.2 fr.opensagres.xdocreport fr.opensagres.xdocreport.document 2.0.2 fr.opensagres.xdocreport fr....

    最近要使用导出文档,网上找了资料,现在自己的总结如下
     

    一、文档模板的设置

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

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

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

     

    二、 代码引入依赖

     pom.xml

    <dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-freemarker</artifactId>
    		</dependency>
    		<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>commons-io</groupId>
    			<artifactId>commons-io</artifactId>
    			<version>2.5</version>
    		</dependency>

    controller方法

        /**
         * @param response
         */
        @RequestMapping("/exportWord")
        public void exportWord(HttpServletResponse response,TpfWholeEntity tpfWholeEntity){
            ExportWordUtil ewUtil = new ExportWordUtil();
            Map<String, Object> dataMap = tpfWholeService.getShowMap(tpfWholeEntity);
            //按月获取单个企业的能耗量
            List<TpfWholeEntity> energyList = tpfWholeService.findEnergysMonth(tpfWholeEntity);
            dataMap.put("energyList", energyList);
            //按月获取单个企业的碳排放量
            List<TpfWholeEntity> tpfMonthList = tpfWholeService.findTPFMonth(tpfWholeEntity);
            dataMap.put("tpfMonthList", tpfMonthList);
            ewUtil.exportWord(dataMap, "tpfWhole.ftl", response, "1111.doc");
        }

    其中showMap方法大致没用就是创建一个HashMap,然后设置属性,然后返回这个map,大致截图如下

    导出的exutil代码

    package com.cshl.modules.reports.utils;
    
    import freemarker.template.*;
    import lombok.extern.slf4j.Slf4j;
    
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.net.URLEncoder;
    import java.util.Map;
    
    import static freemarker.template.Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS;
    
    @Slf4j
    public class ExportWordUtil {
        private Configuration config;
    
        public ExportWordUtil() {
            config = new Configuration(DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            config.setDefaultEncoding("utf-8");
        }
    
        /**
         * FreeMarker生成Word
         * @param dataMap 数据
         * @param templateName 模板名
         * @param response HttpServletResponse
         * @param fileName 导出的word文件名
         */
        public void exportWord(Map<String, Object> dataMap, String templateName, HttpServletResponse response, String fileName) {
            //加载模板(路径)数据,也可使用setServletContextForTemplateLoading()方法放入到web文件夹下
            config.setClassForTemplateLoading(this.getClass(), "/report");
            //设置异常处理器 这样的话 即使没有属性也不会出错 如:${list.name}...不会报错
            config.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
            try {
                if(templateName.endsWith(".ftl")) {
                    templateName = templateName.substring(0, templateName.indexOf(".ftl"));
                }
                Template template = config.getTemplate(templateName + ".ftl");
                response.setContentType("application/msword");
                response.setHeader("Content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, "utf-8"));
                OutputStream outputStream = response.getOutputStream();
                Writer out = new BufferedWriter(new OutputStreamWriter(outputStream));
    
                //将模板中的预先的代码替换为数据
                template.process(dataMap, out);
                log.info("由模板文件:" + templateName + ".ftl" + " 生成Word文件 " + fileName + " 成功!!");
                out.flush();
            } catch (TemplateNotFoundException e) {
                log.info("模板文件未找到");
                e.printStackTrace();
            } catch (MalformedTemplateNameException e) {
                log.info("模板类型不正确");
                e.printStackTrace();
            } catch (TemplateException e) {
                log.info("填充模板时异常");
                e.printStackTrace();
            } catch (IOException e) {
                log.info("IO异常");
                e.printStackTrace();
            }
        }
    
    }

    代码大致如上,还有个问题,正常属性好像不能用对象,但是可以用列表list

    如果要使用list,需要另外设置,设置如下
    (我用的是笨方法,在修改为ftl之后手动添加list的,不知道其他方法行不行),截图如下

    大致格式如下,可复制修改

    <#list listTotol as notice>
    	例如时间:${notice.Day}
    	关于自增序号的是:${notice_index+1}
    </#list>
    

    三、 Word模板的转换方法

        设置好域的word文档另存问xml,选择2003的哪个,然后重命名为ftl,复制ftl里面内容,增加上面需要的list标签,不需要列表可不加。

    四、参考连接
    https://blog.csdn.net/plxddyxnmd/article/details/10912983ss
    本方法只是记录我遇到的问题以及解决,不是适合所有的方法

    展开全文
  • SSM框架集成导出Word文档功能 XDocReport +FreeMarker

             网上有很多关于使用XDocReport导出Word的文章,都差不多试用了一下,也看了一些评论,发现实现功能的过程当中大家还是会出现各种问题。现在我来把我自己实现的过程说一下,顺便总结一下会出现的问题怎么样解决。

    一、集成环境

            目前我用的SSM框架是maven工程创建的,只要在pom.xml文件当中配置,自动下载到本地maven仓库即可。

    <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>

             目前我的项目里面已经集成了io和poi,如果需要的话也需要加上,我这里就不做赘述。

    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.5</version>
    </dependency>

    二、制作模板

            这里注意wps和office有点不同:

             1、office编辑域的界面

            

            2、wps编辑域的界面

     三、编写代码

             

    package com.alibaba.controller;
     
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.fitech.jgbbvalidate.vo.Goods;
    
    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;
     
    @RestController
    public class ExportWordController {
    	
    	@GetMapping("jgbb/exportWord")
    	public void generateWord() throws IOException, XDocReportException {
    		//获取Word模板,模板存放路径在项目的resources目录下
    	    InputStream ins = new FileInputStream("D:\\123.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");
            goodsList.add(goods1);
            context.put("goods", goodsList);
            
            //创建字段元数据
            FieldsMetadata fm = report.createFieldsMetadata();
            //Word模板中的表格数据对应的集合类型
            fm.load("goods", Goods.class, true);
           
            //输出到本地目录
            FileOutputStream out = new FileOutputStream(new File("D://商品销售报表1.docx"));
            report.process(context, out);
    	}
     
    }

    代码上面我说两点我遇到的问题: 

    1、InputStream ins = this.getClass().getResourceAsStream("/模板.docx");有的博主会用到这个来获取word模板文档,模板存放路径在项目的resources目录下,这就会遇到找不到模板文档的情况,就会报错:

    fr.opensagres.xdocreport.core.XDocReportException: Impossible to create report for the input stream. The report loader supports only [docx] files type.

    所以我直接把模板文档放到了D盘,因为在实际项目部署也是在服务器上的。

    InputStream ins = new FileInputStream("D:\\123.docx");

    2、第二个问题就是:

    在生成表格的时候因为设置的模板原因,在创建Goods对象的时候有int类型的也会报错,得把属性变成String就可以了。

    public class Goods {
    	String num;
    	
    	String type;
    	
    	String sv;
    	
    	String sa;
    
    	public String getNum() {
    		return num;
    	}
    
    	public void setNum(String num) {
    		this.num = num;
    	}
    
    	public String getType() {
    		return type;
    	}
    
    	public void setType(String type) {
    		this.type = type;
    	}
    
    	public String getSv() {
    		return sv;
    	}
    
    	public void setSv(String sv) {
    		this.sv = sv;
    	}
    
    	public String getSa() {
    		return sa;
    	}
    
    	public void setSa(String sa) {
    		this.sa = sa;
    	}
    }
    

            以上就是我在实现导出word文档的时候遇到的问题 ,希望对你们有所帮助,如果有什么问题可以私聊我,想要代码和模板文档也可以问我要!

    展开全文
  • 具体的思路如图:Free Marker处理模版的方式Java的code就不贴在这里了,xdocreport中介绍的很详细。然而在word中添加freemarker的地方介绍的好像不是很清楚。笔者经过多次的尝试,总结如下:1.简单的...
  • 简单介绍 在项目中经常会遇到报表相关的需求,而大多数会以excel出现,今天咱们说说word导出的一些事 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助...2.xdocreport开源工具 freemarker+ftl 引
  • XDocReport的简单使用

    万次阅读 2018-12-02 16:42:37
    XDocReport介绍初步了解XDocReport适用范围源码地址模板引擎一个填充的简单例子需求设计设计填充模板最终效果图填充字段设置我对填充字段的理解图片填充设置代码编写maven依赖填充类模板加载设置域模拟填充数据开始...
  • 基于xdocreport导出复杂word文档,专业避坑指南

    千次阅读 热门讨论 2021-11-03 15:46:02
    在完成这个功能时花费了大量的时间查阅资料,发现能满足导出复杂word文档的工具只有xdocreport,如果有其他的工具欢迎分享。废话不多说,上菜! 一、导入包 <dependency> <groupId>fr.opensagres....
  • 本文采用XDocReport集合Freemaiker进行处理1. 引入Maven依赖:fr.opensagres.xdocreportxdocreport2.0.1org.apache.velocityvelocity-engine-core2.0org.freemarkerfreemarker2.3.232. 创建Word模版新建Word,在光标...
  • 要开始使用XDocReport,我想将ODT转换为PDF.我的所有应用程序都是OSGi.所以我安装了以下软件包:fr.opensagres.xdocreport.converter-1.0.5.jarfr.opensagres.xdocreport.core-1.0.5.jarfr.opensagres.xdocreport....
  • 关键字:java xdocreport centos7 PDF 中文 不显示 在我的项目中出现了问题 生产(Linux)上就是word转pdf没有汉字显示,只有字母和数字。 因为liunx系统上,没有安装有中文字体库; 解决方案: 问题确认命令: 1、...
  • XDocReport 示例
  • 注意:docx内容字体需要是宋体,我用的office是2013版本的,我在2007版本上也测试过,是可以生成的,其他会乱码,不过xdocreport支持扩展字体 github的issue(需翻**墙) 总结**: 通过freemarkder+xdocreport生成pdf...
  • 依赖的jar包 <dependency>...fr.opensagres.xdocreport</groupId> <artifactId>xdocreport</artifactId> <version>2.0.2</version> </dependenc...
  • 一、xdocReport支持的报告模板有三种:Docx格式,PPTX格式,ODT格式。 二、重点讲如何用FreeMaker语法设计docx的文档报告模板): 虽然可以采用word宏来定义变量设计文档报告模板,但我个人不建议,因为无法做一些...
  • Xdocreport和Freemaker生成docx

    千次阅读 2017-06-21 14:31:00
    FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据,并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用...通过Xdocreport和Freemaker可用来生成docx文件GitHub:http://code.google.com/...
  • MongoDB IDE 是用于管理数据库的 Eclipse 插件。 这些插件在几个上下文中工作: Eclipse集成开发环境Eclipse RCP(胖客户端) Eclipse RAP (WEB)。 你可以在看到在线演示 有关更多信息,请阅读 [MongoDB IDE wiki] ...
  • 一、我们在确定用xdocReport时要确定我们的需求,以下是我的需求: 1.采用docx作为文档模板,在里面定义freeMaker标签变量,最终和java模型结合生成docx文档。 2.采用freeMarker模板引擎(由于它的功能比...
  • (一)xdocreport能做什么? 1.xdocreport是一个java api,它能够根据ms office(docx或者ppt)以及open office的odt创建的xml文档模板,与java模型一起配合生成你想要的docx或者odt文档报告。 2.同时你可以把生成...
  • 【Exception】解决XDocReport生成word文件报错:numbering.xml错误   一、问题描述 1、使用 XDocReport根本模板生成word文件时,个别模板生成的word文档无法打开,报错信息: numbering.xml 错误 xx 行 。   ...
  • 首先创建一个maven工程 ... fr.opensagres.xdocreport fr.opensagres.xdocreport.converter.docx.xwpf 1.0.6 fr.opensagres.xdocreport org.apache.poi.xwpf.converter.pdf 1.0.6
  • 最近项目需要pdf打印,通过调研和网上搜索xdocreport,处理图片和word,pdf无论是生成速度和内存消耗,比doc4j都要速度快,内存消耗小。开发一直在window下面,生成pdf正常,中文不会乱码,部署到linux服务器就各种...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 890
精华内容 356
关键字:

xdocreport