当前位置: 首页 > news >正文

Xdocreport实现根据模板导出word

只使用freemaker生成简单的word文档很容易,但是当word文档需要插入动态图片,带循环数据,且含有富文本时解决起来相对比较复杂,但是使用Xdocreport可以轻易解决。
Xdocreport既可以实现文档填充也可以实现文档转换,此处只介绍其文档填充功能。

步骤:
1.制作模板


以以下文档为例

 会议内容为一段富文本
我们需要在变量替换的位置通过快捷键Ctrl+F9 或 工具栏“插入”->“文档部件或文本”->“域”

遇到需要循环的位置
在第一列的里

1.在第一个单元格设置域 "@before-row[#list userList as user]"
2.紧接着后面继续设置域 @after-row[/#list]
3.在1和2两个域之间设置普通的list里的元素的域

注意:

1.创建一个普通域值后,可以直接复制,但是需要右键编辑域修改域的名字.

2.word里有的域值,但是我代码里直接没传,代码运行就会报错,代码给这个域值传null,运行也会报错.

3.word里没有的域值,我代码里传了,word仅仅是不会显示这个值,并不会报错.

4.测试得知:如果想要在List里一个单元格里填两个变量,那么你在单元格里创建完一个变量域后,这个单元格的第二个变量域来源必须是复制第一个变量域, 不能自己再新建一个域, 会报错的.

5.在List里创建完一个单元格里的变量域,再创建第二个单元格里的变量域时,你复制第一个单元格的变量域也好,还是自己再新建一个变量域也好,都可以,都不会报错.


遇到图片,先插入一张图片,再为图片添加书签

 这样模板就制作完成,不需要保存为xml,ftl。直接使用doc或者docx后缀即可


2.代码实现
引入依赖

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

上代码

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String xh;
    private String bumen;
    private String name;
    private String age;
    private ByteArrayImageProvider touxiang;

}
@RestController
@RequestMapping("order/")
@Slf4j
public class OneController {
    
    @GetMapping("/bb")
    public void createXdocreport(HttpServletResponse response) throws IOException {

        InputStream inputStream = null;
        ServletOutputStream outputStream = response.getOutputStream();
        try {
            //读取模板       
            inputStream = new FileInputStream("F:\\Desktop\\aa.docx");
            //注册xdocreport实例并加载FreeMarker模版引擎
            IXDocReport report = XDocReportRegistry
                    .getRegistry()
                    .loadReport(inputStream, TemplateEngineKind.Freemarker);
            // 设置特殊字段
            FieldsMetadata metadata = report.createFieldsMetadata();
            metadata.addFieldAsTextStyling("content", SyntaxKind.Html);//富文本
            metadata.addFieldAsImage("touxiang", "user.touxiang", NullImageBehaviour.RemoveImageTemplate);//图片
            metadata.addFieldAsImage("xiangzheng","xiangzheng", NullImageBehaviour.RemoveImageTemplate);//图片
            report.setFieldsMetadata(metadata);
            // 创建内容-text为模版中对应都变量名称
            String content = "&#x3c;p&#x3e;我在这里放了一段富文本&#x3c;/p&#x3e;" +
                    "&#x3c;p&#x3e;我准备测试富文本的处理&#x3c;/p&#x3e;";
            content = HtmlUtils.htmlUnescape(content);
            IContext context = report.createContext();
            //放普通字段
            context.put("name", "年终总结大会");
            context.put("time", "2021年3月26日");
            //放富文本
            context.put("content", content);
            //放list内容,其中包括放入图片流
            InputStream p1 = new FileInputStream(new File("F:\\Desktop\\风灵月影.png"));
            InputStream p2 = new FileInputStream(new File("F:\\Desktop\\孤岛5.png"));
            List<User> users = Arrays.asList(
                    new User("1", "市场部", "张三", "33", new ByteArrayImageProvider(p1)),
                    new User("2", "设计部", "李四", "40", new ByteArrayImageProvider(p2)));
            context.put("userList", users);
            //放入单独的图片
            File file = new File("F:\\Desktop\\孤岛6.png");
            FileImageProvider xiangzheng = new FileImageProvider(file);
            context.put("xiangzheng",xiangzheng);

            // 生成文件,浏览器访问可以直接下载.
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            String fileName = "warning_task.docx";
            response.setHeader("Content-Disposition", "attachment;filename="
                    .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
            report.process(context, outputStream);
        } catch (Exception e) {
            log.info("生成纪要文件发生异常:<{}>", e.getMessage());
        }finally {
            if(inputStream != null){
                inputStream.close();
            }
        }
    }


}

 最后浏览器下载的结果

完成

相关文章:

  • 图论整理复习
  • 国标GB28181视频平台EasyCVR如何搭建汽车修理厂远程视频网络监控方案
  • std::string` 类
  • 数据库数据恢复——sql server数据库被加密怎么恢复数据?
  • Dify+DeepSeek能做出什么来?快速构建可扩展的 AI 应用
  • 程序化广告行业(76/89):行业融资全景剖析与代码应用拓展
  • 电力交易中长期市场基础知识
  • 高并发的业务场景下,如何防止数据库事务死锁
  • image tokenizer 原理和代码
  • C++ 知识笔记
  • 项目整合管理_项目管理计划和项目文件
  • 用css画一条弧线
  • 数据库分表分库
  • 为什么AI系统习惯性“画大饼”?:深度解析算法逻辑与技术瓶颈
  • docker部署postgresql
  • Notepad++安装Markdown实时预览插件
  • 国产Linux统信安装mysql8教程步骤
  • 工厂模式(简单工厂,工厂方法,抽象工厂)
  • 【14】Strongswan watcher详解1
  • P8682 [蓝桥杯 2019 省 B] 等差数列
  • 菏泽做网站建设找哪家好/html静态网页制作
  • 门户网站和社交网络的区别/seo服务外包
  • 做泥网站/百度知道网页入口
  • 网站建设公司有哪些重要职务/营销型网站建设价格
  • 东莞智通人才网官网登录/seo排名赚钱
  • 户外网站 整站下载/打开网站搜索