-
2021-03-04 11:43:34
核心代码如下
/** * 导出word * <p>第一步生成替换后的word文件,只支持docx</p> * <p>第二步下载生成的文件</p> * <p>第三步删除生成的临时文件</p> * 模版变量中变量格式:{{foo}} * @param orderNo 根据自己的情况传入参数 即文件名字 * @param templatePath word模板地址 默认在resource下面 * @param fileName 文件名 文件名字和orderNoY一直 后缀多个(.docx) * @param params 替换的参数 word文档模板中替换的参数 * @param response HttpServletResponse */ public static void exportWord(String orderNo,String templatePath, String fileName, Map<String, Object> params, HttpServletResponse response) { Assert.notNull(templatePath,"模板路径不能为空"); Assert.notNull(fileName,"导出文件名不能为空"); Assert.isTrue(fileName.endsWith(".docx"),"word导出请使用docx格式"); try { XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params); FileOutputStream fos = new FileOutputStream(fileName); doc.write(fos); // 设置强制下载不打开 response.setContentType("application/force-download"); // 设置文件名 response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(orderNo + ".doc", "UTF-8")); OutputStream out = response.getOutputStream(); doc.write(out); out.close(); } catch (Exception e) { e.printStackTrace(); } }
word模板
{{insuredName}}: 我司对借款人{{cusName}}(统一信用代码:{{identifiyNumber}})提出投保{{riskName}}业务申请已经受理,对该客户的承保意见为:
word模板只是简单一段话,里面所需要的参数和map里面的Key一致。
以上为java导出word模板,如需转载请注明处处。
更多相关内容 -
java 导出word文档
2022-01-26 11:30:18java 导出word文档 1、设置模板 设置方法: 1、选中需要动态生成数据的部分,按 Ctrl+F9 -> 选择编辑域。 2.1、选择邮件合并,并在域代码部分后面加上相应参数,例如 :${videoNum} 'videoNum’是对应的参数名...java 导出word文档
1、设置模板
设置方法:
1、选中需要动态生成数据的部分,按 Ctrl+F9 -> 选择编辑域。
2.1、选择邮件合并,并在域代码部分后面加上相应参数,例如 :${videoNum} 'videoNum’是对应的参数名,后面代码编辑的时候会用到。
2.2、如果是表格类型的动态数据,按照2.1的方式设置参数,但参数以 ${video.name} 方式设置,用以后续动态数据的生成。
2、代码编写
2.1 pom导入
<!-- word生成--> <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>
2.2、代码编写
2.2.1、编写控制层
import com.fongtech.cli.report.service.ReportService; import com.fongtech.cli.report.util.ResUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; /** * @Author: lin * @Date: 2022/1/10 14:25 * @Version 1.0 */ @Slf4j @RestController @RequestMapping("/report") @Api(tags = "报表相关接口") public class ReportController { @Autowired private ReportService reportService; @GetMapping("/exportReportExcel") @ApiOperation("导出数据分析报告") public Object exportReportExcel(HttpServletRequest request, @RequestParam(value = "startDate", required = false) String startDate, @RequestParam(value = "endDate", required = false) String endDate, @RequestParam(value = "type", required = true) String type) { log.info("数据分析报告导出 开始时间:" + startDate + " 结束时间:" + endDate + " 类型:" + type); byte[] data = reportService.getWordByte(startDate, endDate, type); return ResUtil.getStreamData(request, data, "wordReportExport-" + type, "docx"); } }
2.2.2、编写service层
/** * @Author: linbo * @Date: 2022/1/10 14:25 * @Version 1.0 */ public interface ReportService { /** * 报告导出 * @param startDate * @param endDate * @return */ byte[] getWordByte(String startDate,String endDate, String type); }
import com.fongtech.cli.report.util.ExportData; import com.fongtech.cli.report.service.ReportService; import com.fongtech.cli.report.util.SoMap; import com.fongtech.cli.report.util.WordUtil; import com.fongtech.cli.report.vo.ReportVo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.*; /** * @Author: lin * @Date: 2022/1/7 10:13 * @Version 1.0 */ @Service public class ReportServiceImpl implements ReportService { /** * 模板文件的地址 */ @Value("${report.model-path-day}") private String MODEL_PATH_DAY; @Override public byte[] getWordByte(String startDate, String endDate, String type) { //准备数据 ExportData evaluation = WordUtil.createExportData(MODEL_PATH_DAY); //时间设置 String[] date = getDate(startDate); evaluation.setData("beginYear", date[0]); evaluation.setData("beginMonth", date[1]); evaluation.setData("beginDay", date[2]); String[] dateEnd = getDate(endDate); evaluation.setData("endYear", dateEnd[0]); evaluation.setData("endMonth", dateEnd[1]); evaluation.setData("endDay", dateEnd[2]); evaluation.setData("videoNum", "10"); //设置视频监控状态 List<SoMap> videoList = new ArrayList<SoMap>(); for (int i = 0; i < 5; i++) { ReportVo reportVo = new ReportVo(); reportVo.setName("园区名称" + i); reportVo.setPark("园区" + i); reportVo.setCondition("设备状态" + i); videoList.add(new SoMap(reportVo)); } evaluation.setTable("video", videoList); // 获取新生成的文件流 byte[] data = evaluation.getByteArr(); return data; } private String[] getDate(String date) { if (date.contains(" ")) { return date.split("-| "); } else { return date.split("-"); } } }
application.yml文件:
report: model-path-day: "E://modelDay.docx" #根据模板文件位置设定
2.2.3、Utile类设置
ExportData:
import fr.opensagres.xdocreport.document.IXDocReport; import fr.opensagres.xdocreport.document.images.ByteArrayImageProvider; import fr.opensagres.xdocreport.document.images.IImageProvider; import fr.opensagres.xdocreport.template.IContext; import fr.opensagres.xdocreport.template.formatter.FieldsMetadata; import org.springframework.core.io.ClassPathResource; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; public class ExportData { private IXDocReport report; private IContext context; /** * 构造方法 * @param report * @param context */ public ExportData(IXDocReport report, IContext context) { this.report = report; this.context = context; } /** * 设置普通数据,包括基础数据类型,数组,试题对象 * 使用时,直接 ${key.k} 或者 [#list d as key] * @param key 健 * @param value 值 */ public void setData(String key, Object value) { context.put(key, value); } /** * 设置表格数据,用来循环生成表格的 List 数据 * 使用时,直接 ${key.k} * @param key 健 * @param maps List 集合 */ public void setTable(String key, List<SoMap> maps) { FieldsMetadata metadata = report.getFieldsMetadata(); metadata = metadata == null ? new FieldsMetadata() : metadata; SoMap map = maps.get(0); for (String kk : map.keySet()) { metadata.addFieldAsList(key + "." + kk); } report.setFieldsMetadata(metadata); context.put(key, maps); } /** * 设置图片数据 * 使用时 直接在书签出 key * @param key 健 * @param url 图片地址 */ public void setImg(String key, String url) { FieldsMetadata metadata = report.getFieldsMetadata(); metadata = metadata == null ? new FieldsMetadata() : metadata; metadata.addFieldAsImage(key); report.setFieldsMetadata(metadata); try ( InputStream in = new ClassPathResource(url).getInputStream(); ) { IImageProvider img = new ByteArrayImageProvider(in); context.put(key, img); } catch (IOException ex) { throw new RuntimeException(ex.getMessage()); } } /** * 获取文件流数据 * @return 文件流数组 */ public byte[] getByteArr() { try ( ByteArrayOutputStream out = new ByteArrayOutputStream(); ) { report.process(context, out); return out.toByteArray(); } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex.getMessage()); } } }
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; import java.io.UnsupportedEncodingException; public class ResUtil { /** * 生成下载文件,浏览器直接访问为下载文件 * @param request 请求对象 * @param data 数据流数组 * @param prefix 下载的文件名 * @param suffix 文件后缀 * @return 浏览器可以直接下载的文件流 */ public static ResponseEntity<byte[]> getStreamData( HttpServletRequest request, byte[] data, String prefix, String suffix ) { HttpHeaders headers = new HttpHeaders(); prefix = StringUtils.isEmpty(prefix) ? "未命名" : prefix; suffix = suffix == null ? "" : suffix; try { String agent = request.getHeader("USER-AGENT"); boolean isIE = null != agent, isMC = null != agent; isIE = isIE && (agent.indexOf("MSIE") != -1 || agent.indexOf("Trident") != -1); isMC = isMC && (agent.indexOf("Mozilla") != -1); prefix = isMC ? new String(prefix.getBytes("UTF-8"), "iso-8859-1") : (isIE ? java.net.URLEncoder.encode(prefix, "UTF8") : prefix); headers.setContentDispositionFormData("attachment", prefix + "." + suffix); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); return new ResponseEntity<byte[]>(data, headers, HttpStatus.OK); } catch (UnsupportedEncodingException ex) { ex.printStackTrace(); throw new RuntimeException(ex.getMessage()); } } }
package com.fongtech.cli.report.util; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.HashMap; /** * @Author: linbo * @Date: 2022/1/4 11:38 * @Version 1.0 */ public class SoMap extends HashMap<String, Object> { public SoMap() { } /** * 构造方法,将任意实体类转化为 Map * @param obj */ public SoMap(Object obj) { Class clazz = obj.getClass(); Field[] fields = clazz.getDeclaredFields(); try { for (Field field : fields) { field.setAccessible(true); this.put(field.getName(), field.get(obj)); } } catch (IllegalAccessException ex) { throw new RuntimeException(ex.getMessage()); } } /** * 将 Map 转化为 任意实体类 * @param clazz 反射获取类字节码对象 * @return */ public <T> T toEntity(Class<T> clazz) { Field[] fields = clazz.getDeclaredFields(); try { Constructor constructor = clazz.getDeclaredConstructor(); T t = (T) constructor.newInstance(); for (Field field : fields) { field.setAccessible(true); field.set(t, this.get(field)); } return t; } catch (Exception ex) { throw new RuntimeException(ex.getMessage()); } } /** * 从集合中获取一个字段的方法,如果字段不存在返回空 * @param key 字段的唯一标识 * @param <T> 字段的类型,运行时自动识别,使用时无需声明和强转 * @return 对应字段的值 */ public <T> T get(String key) { return (T) super.get(key); } }
package com.fongtech.cli.report.util; 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 java.io.FileInputStream; import java.io.InputStream; public class WordUtil { /** * 获取 Word 模板的两个操作对象 IXDocReport 和 IContext * @param path 模板绝对地址 * @return 模板数据对象 */ public static ExportData createExportData(String path) { try { IXDocReport report = createReport(path); IContext context = report.createContext(); return new ExportData(report, context); } catch (XDocReportException ex) { throw new RuntimeException(ex.getMessage()); } } /** * 加载模板的方法,主要是指定模板的路径和选择渲染数据的模板 * @param url 模板相对于类路径的地址 * @return word 文档操作类 */ private static IXDocReport createReport(String url) { try ( InputStream in = new FileInputStream(url); ) { IXDocReport ix = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker); return ix; } catch (Exception ex) { throw new RuntimeException(ex.getMessage()); } } }
Vo类:
package com.fongtech.cli.report.vo; import com.fongtech.cli.framework.model.BaseModel; import java.io.Serializable; /** * @Author: linbo * @Date: 2022/1/4 13:47 * @Version 1.0 */ public class ReportVo extends BaseModel implements Serializable { private static final long serialVersionUID = 1L; private String name; private String transmissibility; private String condition; private String park; public String getPark() { return park; } public void setPark(String park) { this.park = park; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getTransmissibility() { return transmissibility; } public void setTransmissibility(String transmissibility) { this.transmissibility = transmissibility; } public String getCondition() { return condition; } public void setCondition(String condition) { this.condition = condition; } }
3、数据导出
-
java导出word文档的jar包
2017-09-09 19:40:31这是java里面进行导出为word的jar包,包括两个,一个是:poi-3.8-beta5-20111217.jar,另一个是:poi-scratchpad-3.5-beta1.jar,分别可以导出为*.doc和*.docx -
java导出word
2019-04-19 01:16:25NULL 博文链接:https://zhanghongliang-cyj.iteye.com/blog/1864421 -
java生成word的实例 java导出Word文档的实例
2012-03-02 11:48:10java生成word的实例 java导出Word文档的实例 项目说明 -
Java导出Word文档的实现
2022-01-07 15:11:24在日常的开发工作中,我们时常会遇到导出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 语言实现的,通过 XDocReport 和 FreeMarker 模板引擎生成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(); //把图片添加到上下文对象 context.put("img1", getImg("http://192.168.0.105:8081/profile/upload/2022/01/06/95ec1617-a1ee-4e29-9af5-a6e5ebaca605.png")); context.put("img2", getImg("http://192.168.0.105:8081/profile/upload/2022/01/06/95ec1617-a1ee-4e29-9af5-a6e5ebaca605.png")); //输出到本地目录 FileOutputStream out = new FileOutputStream(new File("D://图片报表.docx")); report.process(context, out); } public InputStream getImg(String urls) throws IOException { URL url = new URL(urls); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5 * 1000); InputStream inStream = conn.getInputStream(); return inStream; } }
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 语言实现,结合 XDocReport 和 FreeMarker 模板引擎生成Word文档的方法。希望能给致力于开发的小伙伴带来一丝丝帮助。
-
Java使用POI导出Word文档
2018-07-12 10:30:21最近项目中需要用到数据的导出到Word,本在项目中使用POI将数据导入到Word,代码示例非常简洁,代码包含pom依赖文件,下载解压即可到本地调试运行。 -
java导出word并插入图片
2017-07-04 17:22:50WORD导出,并插入图片 -
基于Freemarker和xml实现Java导出word
2020-08-19 07:45:25主要介绍了基于Freemarker和xml实现Java导出word,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 -
java poi导出word文档DEMO
2017-08-24 17:18:55java poi导出word文档DEMO -
java根据word模板导出Word文件,插入图片表格都可以
2020-06-12 16:57:03网络上的根据模板填充Word我都看过一些, 它们的功能在数据换行的时候用的是run对象的.addCarriageReturn()方法,或者是直接用\n实现换行。这些都不符合我的需求, 因为我要的是分段,而不是换行。换行的word导致另一... -
Java 导出word文档,遍历表格数据,导出图片
2022-01-19 17:51:16引用:... ... import cn.afterturn.easypoi.word.WordExportUtil; import org.apache.poi.xwpf.usermodel.XWPFDocument; import java.io.ByteArrayOutputStream; import java.io.File; import java.引用:https://www.cnblogs.com/pxblog/p/13072711.html
1.引入maven依赖:
<dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>3.3.0</version> </dependency> <!--注意:word中要使用循环等标签必须单独导入以下依赖--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>ooxml-schemas</artifactId> <version>1.1</version> </dependency>
2.word模板内容
3.参数说明:$fe:jobs(jobs:java代码中集合名称),t.属性名(t表示集合中单个对象)EasyPoi 模板 表达式支持
空格分割
三目运算 {{test ? obj:obj2}}
n: 表示 这个cell是数值类型 {{n:}}
le: 代表长度{{le:()}} 在if/else 运用{{le:() > 8 ? obj1 : obj2}}
fd: 格式化时间 {{fd:(obj;yyyy-MM-dd)}}
fn: 格式化数字 {{fn:(obj;###.00)}}
fe: 遍历数据,创建row
!fe: 遍历数据不创建row
$fe: 下移插入,把当前行,下面的行全部下移.size()行,然后插入
!if: 删除当前列 {{!if:(test)}}
单引号表示常量值 ‘’ 比如’1’ 那么输出的就是 1
&NULL& 控制
]] 换行符4.工具类
package com.example.demo.utils; import cn.afterturn.easypoi.word.WordExportUtil; import org.apache.poi.xwpf.usermodel.XWPFDocument; import java.io.ByteArrayOutputStream; import java.io.File; import java.util.Map; public class WordUtil { /** * 导出word(2007版本docx) * * @param templateWordPath * @param dataMap * @return * @throws Exception */ public static byte[] exportWord(String templateWordPath, Map<String, Object> dataMap) throws Exception { File tf = new File(templateWordPath); if (!tf.exists() || !tf.isFile()) { throw new RuntimeException("File [" + templateWordPath + "] Not Found Or Not File."); } XWPFDocument document = WordExportUtil.exportWord07(templateWordPath, dataMap); ByteArrayOutputStream bos = new ByteArrayOutputStream(); document.write(bos); return bos.toByteArray(); } }
5.控制层
package com.example.demo.controller; import cn.afterturn.easypoi.word.entity.WordImageEntity; import com.example.demo.utils.WordUtil; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletResponse; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Controller public class TestController { @RequestMapping(value = "/export") public void export(HttpServletResponse response){ try { // Map<String, Object> dataMap = new HashMap<>(); //导出单个数据 dataMap.put("title","我是导出文档的标题");//导出对象 Map<String, String> user = new HashMap<>(); user.put("name", "姓名"); user.put("age", "443"); user.put("address", "地址"); user.put("other", "我不知道"); dataMap.put("user", user); //导出图片 WordImageEntity image = new WordImageEntity(); //设置图片尺寸 image.setHeight(500); image.setWidth(500); //图片地址,需要是本地项目中图片,如果是第三方的需要把图片先下载下来 image.setUrl("C:\\Users\\Fr\\Pictures\\11163144hqk4.JPG"); image.setType(WordImageEntity.URL); dataMap.put("images", image); List<Map<String, Object>> jobs = new ArrayList<>(); //导出列表 Map<String, Object> job; for (int i = 0; i < 5; i++) { job = new HashMap<>(); job.put("id", "ID-" + i); job.put("name", "姓名:" + i); jobs.add(job); } dataMap.put("jobs", jobs); // “D:/word-template-test.docx”是word模板所在位置 byte[] doc = WordUtil.exportWord("D:/word-template-test.docx", dataMap); response.setContentType("application/vnd.ms-word;charset=utf-8"); response.setHeader("Content-Disposition", "attachment;filename=\"" + new String("word文档导出".getBytes("gb2312"), "ISO8859-1")+".docx"); //文件名中文需进行格式转换,不然可能出现乱码 OutputStream out = response.getOutputStream(); out.write(doc); out.flush(); } catch (Exception e) { e.printStackTrace(); } } }
5.导出效果
-
JAVA 导出WORD
2011-12-14 17:02:28完整的JAVA导出WORD源代码,解压即可运行 -
【day22】java导出word文档(包含导出图片)
2021-04-22 18:54:011、【Java】使用freemarker模板技术导出word main方法测试 package com.havenliu.document; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; public class ... -
java导出word文档,固定模板
2014-01-02 15:52:41使用freemarker技术,首先将word模板另存为xml文档,方便填充数据。然后将后缀名改为ftl,简单方便. -
【Java用法】使用Java导出word文档的解决方案(适用于Windows电脑)
2020-11-21 16:51:10最近在做一个word导出功能,需求非常简单,只需要将内容导出到word文件里即可,对于word的格式并没有要求。功能不复杂,想快速实现这个功能,但是使用POI的话,比较麻烦。本文记录一下通过一个工具类即可实现简单的... -
【Java用法】使用Java导出word文档的解决方案(适用于从服务器上下载到本地电脑)
2020-11-24 13:07:43本文目录 一、Controller ...本文记录一下通过一个工具类即可实现简单的word导出的功能,上一篇文章讲的是通过这个工具类实现服用在本地,word文档下载到本地的功能。本文将会实现项目部署到服务 -
JAVA导出word文档,在循环的时候只写出第一次是为什么?
2021-02-26 13:13:48/**word模板*/FontfontChinese=newFont(bfChinese,12,Font.NORMAL,Color.BLACK);for(inti=0;i/**word模板*/Font fontChinese = new Font(bfChinese, 12, Font.NORMAL, Color.BLACK);for (int i = 0; i < list.... -
java生成word的实例 java导出Word文档的实例.rar
2020-01-06 00:47:28java生成word的实例 java导出Word文档的实例.rar -
Java导出Word文档案例
2021-03-09 04:27:27import java.io.File;import java.io.FileInputStream;import java.io.FileWriter;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.util.Itera... -
java导出word文档
2017-10-26 20:05:38包括freemarker.jar以及使用freemarker导出work文档的方法 -
Java用freemarker导出word例子
2020-09-02 17:30:22Java用freemarker导出word例子详见我的博客 Java用freemarker导出word例子详见我的博客 -
java导出word模板
2015-05-08 14:10:23以道路案卷为例,把后缀改为ftl就可以了 -
Java导出word文档(POI&Spire.Doc)
2021-03-11 12:05:20导出文件* @param condition* @return*/@PostMapping(value = "/exportInfoToWord")public void exportInfoToWord(@RequestBody HashMap condition, HttpServletResponse response) throws IOException {//创建Word... -
Java导出Word问题
2021-03-13 14:34:56//使用的是Apache POIpublic static String readWord(InputStream ins)throws Exception{StringBuffer sRet=new StringBuffer();byte[] bContent = null;ByteArrayOutputStream outs = null;byte[] head = new byte... -
关于Java导出Word文件
2021-02-12 23:07:24做个很多个项目里基本上都涉及了word、Excel导入导出,虽然其中的要求有些小差异,不过总的方向上变化不大,所以做一些总结:一)、利用freemarker,制作xml模版导出wordXml模版部分:打开word另存为xml格式(注:这里... -
Java导出word模板
2020-12-01 23:05:13Java导出word模板 最近项目中有生成word报文需求, 需求中使用到word模板导出功能, 记录下, 以便复用; 之前有相似需求, 当时做法稍显复杂,区分了doc和docx两种后缀形式的word,本文基于docx模板导出。 1. 编写word模板... -
java 导出word并插入图片
2021-04-17 06:29:41import java.awt.Color;import java.io.FileOutputStream;import java.util.Date;import com.lowagie.text.Cell;import com.lowagie.text.Document;import com.lowagie.text.Element;import com.lowagi...