使用poi生成word文档(最全例子)

1.说明

平时的项目中,我们可能需要做大量的报告。而这些报告中,有些是固定的格式,有些是需要自定义模板来生成。如果是固定的形式的,那么相对而言是比较好做的,但要是根据模板来生成报告,比如:word、Excel或PDF。这样的话,可能需要我们花点时间去解决了。这篇博客主要是带领大家学习一下,如何用poi技术来实现生成word报告。

2.设计

我们知道,poi的技术可以做出word、Excel、PDF等文件。在网上也有大量的博客是关于如何使用poi的ftl的模板来生成word、Excel、PDF。主要是思路是将某个模板(自己定义的,可以是word或Excel)上传至服务器,然后解析成对应的ftl文件,之后服务在做报告时,就可以直接拿取对应的ftl文件来生成报告。这种方式会比较灵活,现在用的也比较多。但是对于一份简单的,不需要ftl的文件来作为中间生成文件时,那么可能会比较难了。比如,接下来我们要学习的,使用word的模板作为报告模板,然后直接生成需要的报告。但是word中的所的之间的设置,如字体大小、颜色等都不能改变。这个思路大概是:用户直接设计一个word模板,然后上传至服务器,服务器将其直接保存到对应的文件夹下;在要生成报告时,直接拿word的模板来填充数据。这样,好像也不是很难,但是想想细节上的地方,可能很多东西就不好做了。接下来,我们来说说问题所在。

3.问题

我们在使用word作为一份模板时,首先要解决的时,如何向模板中定义的字段替换数据,如:{name}要换成真实的改名;其次我们如果要做表格的话,如何向word上直接画出表格;再次,表格的行列要怎么合并,多张表应该怎么复制等;最后,我们应该怎么将一比我图片插入到word中。带着这些问题,我们来一一解决。

4.开发

4.1普通文本替换

在word的文件中,我们同一个使用“{**}”来标志需要替换的文件,如{name}就是要将name的字段替换成真实的姓名。所以我们需要用正则表达式来寻找到广本的内容是否包含了“{}”。正则表达式是:\\{.+?\\}。同时,我们需要用poi提供的XWPFRun的接口来替换文本。为了使用替换后的文本可以的换行的操作。比如,我们自己定义的一行文本需要换行,笔者用“@”符号作为标签,也就是如果遇到内容含有“@”,就要实现换行。而换行是调用XWPFRun的addBreak()的方法。部分代码如下:

public void replaceParagraph(XWPFParagraph xWPFParagraph, Map<String, Object> parametersMap) {
		List<XWPFRun> runs = xWPFParagraph.getRuns();
		String xWPFParagraphText = xWPFParagraph.getText();
		String regEx = "\\{.+?\\}";
	    Pattern pattern = Pattern.compile(regEx);
	    Matcher matcher = pattern.matcher(xWPFParagraphText);//正则匹配字符串{****}

		if (matcher.find()) {
			// 查找到有标签才执行替换
			int beginRunIndex = xWPFParagraph.searchText("{", new PositionInParagraph()).getBeginRun();// 标签开始run位置
			int endRunIndex = xWPFParagraph.searchText("}", new PositionInParagraph()).getEndRun();// 结束标签
			StringBuffer key = new StringBuffer();

			if (beginRunIndex == endRunIndex) {
				// {**}在一个run标签内
				XWPFRun beginRun = runs.get(beginRunIndex);
				String beginRunText = beginRun.text();

				int beginIndex = beginRunText.indexOf("{");
				int endIndex = beginRunText.indexOf("}");
				int length = beginRunText.length();

				if (beginIndex == 0 && endIndex == length - 1) {
					// 该run标签只有{**}
					XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
					insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
					// 设置文本
					key.append(beginRunText.substring(1, endIndex));
					insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
					xWPFParagraph.removeRun(beginRunIndex + 1);
				} else {
					// 该run标签为**{**}** 或者 **{**} 或者{**}**,替换key后,还需要加上原始key前后的文本
					XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
					insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
					// 设置文本
					key.append(beginRunText.substring(beginRunText.indexOf("{")+1, beginRunText.indexOf("}")));
					String textString=beginRunText.substring(0, beginIndex) + getValueBykey(key.toString(),parametersMap)
							+ beginRunText.substring(endIndex + 1);
					
					insertNewRun.setText(textString);
					xWPFParagraph.removeRun(beginRunIndex + 1);
				}

			}else {
				// {**}被分成多个run

				//先处理起始run标签,取得第一个{key}值
				XWPFRun beginRun = runs.get(beginRunIndex);
				String beginRunText = beginRun.text();
				int beginIndex = beginRunText.indexOf("{");
				if (beginRunText.length()>1  ) {
					key.append(beginRunText.substring(beginIndex+1));
				}
				ArrayList<Integer>
  • 22
    点赞
  • 226
    收藏
    觉得还不错? 一键收藏
  • 21
    评论
部分代码.................. . .. .. /** * 处理动态表格 * 默认取第二行第一列的标识 * @param table * @param ctRow * @param values 需要添加的数据 */ public static void processDynamicTable(XWPFTable table, CTRow ctRow, List values) { if(values==null || values.size()==0) return; for (Iterator iterator = values.iterator(); iterator.hasNext();) { String[] value = iterator.next(); XWPFTableRow newRow = new XWPFTableRow(ctRow,table); List cells = newRow.getTableCells(); if(cells==null || cells.size()==0) return; for (int j = 0; j < cells.size(); j++) { XWPFTableCell cell = cells.get(j); cell.removeParagraph(0); if(j<=value.length) cell.setText(value[j]); } table.addRow(newRow); } } /** * 处理表格 * @param doc * @param dataMap */ public static void processTable(XWPFDocument doc, Map dataMap) { Iterator iter = doc.getTablesIterator(); while(iter.hasNext()) { XWPFTable table = iter.next(); List rows = table.getRows(); if(rows==null || rows.size()==0) continue; CTRow ctRow = null; for (int i = 0; i < rows.size(); i++) { XWPFTableRow row = rows.get(i); ctRow = (CTRow)row.getCtRow().copy(); List cells = row.getTableCells(); if(cells==null || cells.size()==0) continue; //处理标致 boolean sign = false; for (int j = 0; j < cells.size(); j++) { XWPFTableCell cell = cells.get(j); if(cell.getText()==null) continue; if(i==1 && j==0) { //取第二行第一列的值,再添加table.关键字之后与dataMap匹配,有则当动态表格处理 String key = "table."+ cell.getText(); if(dataMap.containsKey(key)) { List values = (List)dataMap.get(key); table.removeRow(1); processDynamicTable(table, ctRow, values); //更新处理标致 sign = true; break; } } if(!cell.getText().startsWith("\\$") && cell.getText().endsWith("\\$")) continue; String key = cell.getText().replaceAll("\\$", ""); if(dataMap.containsKey(key)) {
您好!对于Spring Boot使用Freemarker模板生成Word文档并加密的例子,可以按照以下步骤进行操作: 1. 首先,您需要在pom.xml文件中添加Freemarker和Apache POI的依赖项。在 `<dependencies>` 标签内添加以下代码: ```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.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> ``` 2. 创建一个Freemarker模板文件,例如 `template.ftl`,并在其中编Word文档的内容,可以使用Freemarker语法进行动态内容替换。 3. 创建一个Controller类,并添加以下代码: ```java import freemarker.template.Configuration; import freemarker.template.Template; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFEncryptor; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import javax.servlet.http.HttpServletResponse; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; @Controller public class WordController { @Autowired private Configuration freemarkerConfiguration; @GetMapping("/generate-word") public void generateWord(HttpServletResponse response) throws Exception { // 加载Freemarker模板 Template template = freemarkerConfiguration.getTemplate("template.ftl"); // 创建Word文档对象 XWPFDocument document = new XWPFDocument(); // 创建段落对象 XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); // 填充模板内容 Map<String, Object> data = new HashMap<>(); // 添加模板中需要的数据,可以根据实际需求自行修改 // 渲染模板 run.setText(templateToString(template, data)); // 加密Word文档 XWPFEncryptor encryptor = new XWPFEncryptor(document); encryptor.encrypt("password"); // 替换为您自己的密码 // 设置响应头 response.setHeader("Content-disposition", "attachment; filename=encrypted_word.docx"); response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); // 导出Word文档 OutputStream outputStream = response.getOutputStream(); document.write(outputStream); outputStream.close(); } private String templateToString(Template template, Map<String, Object> data) throws Exception { StringWriter stringWriter = new StringWriter(); template.process(data, stringWriter); return stringWriter.toString(); } } ``` 4. 在Spring Boot的配置文件(例如 `application.properties`)中添加以下配置: ```properties spring.freemarker.template-loader-path=classpath:/templates/ ``` 5. 运行Spring Boot应用程序,并访问 `/generate-word` 路径,即可生成并下载加密的Word文档。 请注意,上述代码仅为示例,您可以根据实际需求进行修改和扩展。同时,为了确保文档的安全性,请根据您的需求修改加密密码和文件名。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值