使用freemaker 导出word 包含分页,表格循环java

2023-11-01

在平时项 目开发中,相信或多或少的都遇到过word导出的需求,这里整理一个比较全面的java word导出方法,希望可以跟大家一起交流学习。

  • 创建word模板

  • 1.1 新建一个word模板,并修改字段

    在这里插入图片描述

    1. 2 将word文件另存为xml 格式,打开xml 格式文件,你会发现你刚刚编写的会变成这样。

      这里推荐一个比较好用的编辑器 sublime 具体教程可以参考这一篇sublime

      安装好之后,修改刚刚的xml文件。
      在这里插入图片描述
      把需要更改的变量都替换成${xxx}.改完后,把xml文档重命名成后缀为.ftl 的freemaker文件。

      1.3 列表和分页
      分页标签为 <w:p><w:r><w:br w:type="page"/></w:r></w:p>
      在word xml 格式中,<w:body></w:body> 表示的就是整个文本内容。我这里的业务需求是不同的类型的内容分页打印,既然<w:body></w:body> 表示整个文本内容,那么就可以在模板中写多个<w:body></w:body> ,不同的分类显示不同的word模板内容。我这里分了三类,就有三个不同的分页。
      在这里插入图片描述
      列表循环
      如果你的模板中包含表格, 找到 <w:tbl></w:tbl> 标签,使用<#list></#list>指令 循环你的list<对象> 数据,然后使用 ${} 取到相应的值。
      在这里插入图片描述
      自此,ftl 模板部分全部写完,将ftl 文件放入你电脑的某个位置,接下来可以开开心心的写java代码部分。

2.java后台编写

思路 :1.编写读取ftl 模板以及参数的方法
2.查询你需要填入word的数据,放入map。注意map的key一定要跟你在ftl文件中填写的字段对应。
话不多说,直接上代码。


package cn.ys.common.utils;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.POIXMLTextExtractor;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import sun.misc.BASE64Encoder;
import cn.ys.common.web.HtmlMessage;

import com.google.common.collect.Maps;

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

public class WordUtils {

	private WordUtils() {
		throw new AssertionError();
	}
	/**
	 *
	 * @param templateFolder 你的ftl文件位置
	 * @param ftlFile  你的ftl 文件名
	 * @param map  需要渲染 数据
	 * @param localPath  生成word文档的位置    
	 * @param title  word文档名
	 * @return
	 * @throws IOException
	 */
	public static String exportWord(String templateFolder, String ftlFile, Map map, String localPath, String title) throws IOException {
		Configuration configuration = new Configuration();
		configuration.setDefaultEncoding("utf-8");
		configuration.setClassicCompatible(true);
		configuration.setDirectoryForTemplateLoading(new File(templateFolder)); //读取ftl 模板位置

		try {
			String datePath = DateUtils.getNowTime("yyyy/MM/dd");
			//使用时间为文件夹生成word生成的位置
			String path = localPath + "/word/" + datePath; 
			//定义word文档名称
			String fileName = title + ".doc";  
			//创建文件夹
			File outFile = new File(path + "/" + fileName);
			if (!outFile.getParentFile().exists()) {
				outFile.getParentFile().mkdirs();
			}
			//读取 模板内容
			Template template = configuration.getTemplate(ftlFile, "utf-8");

			Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));

			template.process(map, out);

			out.flush();
			out.close();
			
			return path + "/" + fileName;
		} catch (TemplateException e) {
			e.printStackTrace();
		}
		return "";
	}


}

自此,你的doc文件实际上已经生成在你指定的文件夹了。 接下来如果让他能够使用文浏览器下载,只需要去读取你本地的这个文件就行。

 @SuppressWarnings("unchecked")
    @RequestMapping(value = "/word/download/{id}")
    public void exportSupplier(@PathVariable("id") Integer gysbaId, HttpServletResponse response, HttpServletRequest request) {
        try {
 				//  注意这里的参数,根据你自己业务出入,参数说明上面已经注明!
                String downLoadPath = WordUtils.exportWord(templateFolder,ftlName,map,root,title);
                String fileName = map.get("message").toString();

                File file = new File(downLoadPath);
                InputStream inputStream;
                inputStream = new BufferedInputStream(new FileInputStream(file));
                byte[] buffer = new byte[inputStream.available()];
                inputStream.read(buffer);
                inputStream.close();

                response.reset();

                String userAgent = request.getHeader("user-agent").toLowerCase();
                if (userAgent.contains("msie") || userAgent.contains("like gecko")) {
                    fileName = URLEncoder.encode(fileName, "UTF-8");
                } else {
                    fileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
                }

                response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName));

                response.addHeader("Content-Length", "" + file.length());

                response.setContentType("application/x-download");
                os.write(buffer);// 输出文件
                os.flush();
                os.close();
         
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

好的,大功告成!如果发现有什么问题,希望各位大佬指出,共同学习。

love & peace

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用freemaker 导出word 包含分页,表格循环java 的相关文章

随机推荐

  • BAPI_ACC_DOCUMENT_POST 简单理解过账BAPI使用

    业务场景 甲方是一家从事房屋租赁的公司 它的主营业务就是从各大租户手里收租子 月底了 小明发了工资美滋滋 钱到手没多久房东就催租子了 房租每月100 水电100 税费22 合计222 小明如约在手机APP上向房东支付了当月的房租 这边钱到账
  • HTML中为什么有一些标签有结束标签,一些没有结束标签

    HTML中为什么有一些标签有结束标签 一些没有结束标签 button 有结束标签 但是
  • ue4文档接口类学习

    看了看Ue4文档中的接口类 摸索着进行了下 在编辑器 先从Unreal interface派生个接口类ReceiveHttpInterface 废话不多说 上代码 接口类文件 Fill out your copyright notice i
  • Netty服务端口的绑定

    调用netty的bootstrap的bind 方法会开始netty对本地端口的绑定与监听 在serverBootstrap的超类abstractBootstrap的bind 方法开始绑定的全过程 public ChannelFuture b
  • Redis多机实现

    Background 为啥要有多机 1 容错 2 从服务器分担读压力 主从结构一大难题 如何保障一致性 对这个一致性要求不是很高 因为redis是用来做缓存的 同时我们要自动化进行故障转移 哨兵机制 同时哨兵也可能crash 所以我们要引入
  • 手把手教你制作AR增强实现项目

    都快一年时间没写技术文章了马上要开始职业生涯新篇章借此机会发布最近研究的一些成果 AR name Card 项目制作教程 需要准备的工具及软件 1 unity3d 4 0以上版本并且需要破解为pro版本 2 Metaio sdk最新版 下载
  • 维纳滤波器、卡尔曼系列滤波器以及自适应LMS、RLS滤波器matlab代码实现

    warning off clear clc x normrnd 5 2 1 2000 index 5 if index 1 自适应滤波LMS N 50 W zeros N 1 d 5 miu 0 1 29 N 0 5 x hat set z
  • httpclient请求403

    问题 httpclient请求对方服务器报403 用postman是可以的 原因 HttpPost request new HttpPost uri request setHeader User Agent Mozilla 5 0 Wind
  • Android开发

    1 Android简介 Android一词的本义指 机器人 同时也是Google于2007年11月5日宣布的基子 Linx平台的开源手机操作系统的名称 该平台由操作系统 中间件 用户界面和应用软组成 Android系统具有如下5个特点 开放
  • CSS深入剖析border和box-shadow(附漂亮样式)

    剖析border 一 border radius 二 border image 三 box shadow 四 利用这些属性渲染出漂亮图形 在CSS3中赋予了border更过的功能 但是其知识结构也更加复杂 在本文中博主对border进行深入
  • 线性空间与线性变换

    1 1线性空间 广义的概念 如何证明一个向量集合是线性空间 1 首先问下什么是线性空间 2 如何表示该集合中的全部向量 知识点1 首先我们需要知道什么是空间 空间其实就是向量的集合 而什么是线性空间呢 定义了线性运算的非空集合 线性运算指的
  • Photoshop出现无法完成,因为内存不够(RAM),如何解决?

    Photoshop出现无法完成 因为内存不够 RAM 时 你所需要如下步骤进行系统的适用 1 在你点击 编辑 首选项 性能 系统提示中如果出现了 要求在96和8之间的整数 已插入最接近的数 这个就需要你在注册表中进行操作 操作如下 1 wi
  • 加拿大安省欢ajax,加拿大安省省考OSSLT介绍

    原标题 加拿大安省省考OSSLT介绍 加拿大省考相当于中国的会考 必须通过才可以取得加拿大高中毕业证 不同省份的省考 BC省除外 目前已取消省考 对申请大学的影响不同 安大略省的省考只有一门课 即由安大略省教育质量和问责办公室 EQAO 举
  • Sqoop简介、原理、安装、简单使用案例、一些常用命令及参数

    问题导读1 Sqoop原理是怎样的 2 如何利用Sqoop导入数据 3 如何利用Sqoop导出数据 4 Sqoop常用的命令及对应参数有哪些 第1章 Sqoop 简介 Sqoop 是一款开源的工具 主要用于在 Hadoop Hive 与传统
  • vector 的作用

    c 中 vector作为容器 它的作用是 一个动态数组模板类 你可以把它当做一个普通数组用 但是他的功能远比一般数组强大 数组最大的不好就是数组长度的限制和删除其中一个时候的后续移位问题 这些在vector中都得到了完美的解决 而且可以存储
  • 教你一步步创建属于自己的Python爬虫代理IP池(含代码示例)

    前言 在进行网络数据采集时 遇到反爬虫限制是常见的问题 使用代理IP可以帮助我们绕过这些限制 保护自己的爬虫程序 本文将教您如何使用Python创建属于自己的代理IP池 以便获取可用的代理IP并应用于 Python爬虫程序 同时 我们将提供
  • 关于Qt调用多/两次setupUi导致信号与槽自动连接失败问题

    代码场景 函数内部调用两次 setupUi okBtn自动连接槽函数失效 问题分析 在 setupUi 函数内部调用了这么一个函数 connectSlotsByName 从函数名来看就是通过名字 部件名 连接信号与槽 官方文档的解释 所以流
  • Spring@Autowired注解与自动装配

    今天在预发布环境配置一个manager的时候 应用启动失败 报错 Caused by org springframework beans factory BeanCreationException Could not autowire fi
  • ELK日志采集平台(四)---轻量级采集工具metricbeat

    目录 一 安装metricbeat 二 与kibana数据可视化联用 logstash是负责采集数据的 是入口 流向为logstash gt ES gt kibana 但是它的资源消耗很大 有时候没那么多内存给他占用 同时有些定制的采集指标
  • 使用freemaker 导出word 包含分页,表格循环java

    在平时项 目开发中 相信或多或少的都遇到过word导出的需求 这里整理一个比较全面的java word导出方法 希望可以跟大家一起交流学习 创建word模板 1 1 新建一个word模板 并修改字段 2 将word文件另存为xml 格式 打