Java使用freemarker导出word模板

Java使用freemarker导出word模板
1, 新建一个word文档, 输入如下类容: 

 2, 将该word文件另存为xml格式(注意是另存为,不是直接改扩展名)
 3,图片处理
    搜索w:binData 或者 png可以快速定位图片的位置,图片             已经是0-F的字符串了, 如下: 

将上述0-F的字符串全部删掉,写上${open.pic}(变量名随便写)后保存
4,表格循环处理
搜索  w:tr 可以找到行的起点与结束点(注意第一对w:tr 是表头,应找第二对 w:tr), 
 4, 用<#list openlist as open> </#list>标签将第二对 w:tr 标签包围起来(userList是集合的key, user是集合中的每个元素

java代码
public void downOpenWord() throws IOException {
		String imgPath = ServletActionContext.getServletContext().getRealPath("/uploads/");
		Map<String, Object> dataMap = new HashMap<String, Object>();
		List<Map<String, Object>> list4 = new ArrayList<Map<String, Object>>();
		List<ImccOpen> imccOpenList = imccOpenService.ExprMessList();
		ImccOpen imccOpen=new ImccOpen();
		if(!imccOpenList.isEmpty()){
		for(int i=0;i<imccOpenList.size();i++){
			imccOpen=imccOpenList.get(i);
			imccOpen.setFlag(1);
			imccOpenDao.saveOrUpdatePo(imccOpen);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("text", imccOpen.getOpencontent());
			map.put("tel", imccOpen.getOpentel());
			map.put("name", imccOpen.getOpenname());
			map.put("pic", DocUtil.getImageStr(imgPath+"/"+imccOpen.getOpenpicture()+".jpg"));
			map.put("adr",imccOpen.getOpenadress());
			map.put("num", imccOpen.getOpennum());
			list4.add(map);
		}
		dataMap.put("openlist", list4);
		File file = null;  
        InputStream fin = null;  
        ServletOutputStream out = null;  
        try {  
            // 调用工具类WordGenerator的createDoc方法生成Word文档  
            file = WordGenerator.createDoc(dataMap, "resume");  
            fin = new FileInputStream(file);  
              
            HttpServletResponse resp= (HttpServletResponse)  
            		ActionContext.getContext().get(org.apache.struts2.StrutsStatics.HTTP_RESPONSE);
			resp.setCharacterEncoding("utf-8");  
            resp.setContentType("application/msword");  
            // 设置浏览器以下载的方式处理该文件默认名为resume.doc  
            resp.addHeader("Content-Disposition", "attachment;filename=resume.doc");  
              
            out = resp.getOutputStream();  
            byte[] buffer = new byte[512];  // 缓冲区  
            int bytesToRead = -1;  
            // 通过循环将读入的Word文件的内容输出到浏览器中  
            while((bytesToRead = fin.read(buffer)) != -1) {  
                out.write(buffer, 0, bytesToRead);  
            }  
        } finally {  
            if(fin != null) fin.close();  
            if(out != null) out.close();  
            if(file != null) file.delete(); // 删除临时文件  
        }  
		}
	}

util
public static String getImageStr(String imgFile) {
       
        InputStream in = null;
        byte[] data = null;
        try {
            in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }
wordCreat
package com.szhtp.faq.actityTest.util;

import java.io.File;



import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

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

public class WordGenerator {
	private static Configuration configuration = null;
	private static Map<String, Template> allTemplates = null;
	
	static {
		configuration = new Configuration();
		configuration.setDefaultEncoding("utf-8");
		configuration.setClassForTemplateLoading(WordGenerator.class, "/com/szhtp/faq/actityTest/util");
		allTemplates = new HashMap<String, Template>();	// Java 7 钻石语法
		try {
			allTemplates.put("resume", configuration.getTemplate("open.ftl"));
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	private WordGenerator() {
		throw new AssertionError();
	}

	public static File createDoc(Map<?, ?> dataMap, String type) {
		String name = "temp" + (int) (Math.random() * 100000) + ".doc";
		File f = new File(name);
		Template t = allTemplates.get(type);
		try {
			// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
			Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
			t.process(dataMap, w);
			w.close();
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}
		return f;
	}

}





注意:
多张图片显示时,当list循环的时候,如果你不改变图片两个属性 w:name和 imagedata  src的值,那么它永远也是调用第一张图片的地址,显示的都是第一张图片。
更改两个属性w:name和imagedata src的方法:

用变量个体的索引来改变两个属性的名字,变量个体的索引格式为“变量名字_index”例如:open_index,见下面红色加粗字体部分。

   < w:binData  w:name="${" wordml://0200000"+open_index+1+".jpg"}"  xml:space = "preserve" >${im}</ w:binData >
       < v:shape  id = "图片"  o:spid = "_x0000_i1025"  type = "#_x0000_t75"  style = "width:414.75pt;height:207.75pt;visibility:visible;mso-wrap-style:square" >
        <v:imagedata src="${" wordml://0200000"+open_index+1+".jpg"}"  o:title = "菜单" />

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot_Freemarker生成Word_多个表格+两层嵌套循环; 步骤说明: 1.用Microsoft Office Word打开word原件;将文档中需要动态生成的内容,替换为属性名 ${name} 2.另存为,选择保存类型Word 2003 XML 文档(*.xml) 3.用Firstobject free XML editor打开文件,选择Tools下的Indent【或者按快捷键F8】格式化文件内容。左边是文档结构,右边是文档内容; 4. 文档生成后有时需要手动修改,查找第一步中设置的属性名,可能会产生类似${n.....ame}类似的样子,我们将将名字中间的标签删掉,恢复为${name} 5. word模板中有表格,需要循环的位置, 用 标签将第二对 标签(即除表头的w:tr标签后的一对)包围起来 同时表格内的属性例如${name},在这里需要修改为${user.name} (userList是集合在dataMap中的key, user是集合中的每个元素, 类似), 如图: PLUS:若表格之外还有嵌套的循环,也需要用,注意这里的标签不要和某对其他标签交叉,不可以出现这种 6. 标识替换完之后,另存为.ftl后缀文件即可。 代码里是相对有一丢丢复杂的,两层嵌套循环; 总(dataMap) deptName 部门名 list(Table)表的集合 table1(map) table-名字 ${map.table} tableName-中文名 ${map.tableName} columnCount-字段数 ${map.columnCount} recordCount-记录数 ${map.recordCount} listA-List--表格1 map.listA column Model属性——字段名 ${model.column} columnName Model属性——字段中文名 ${model.column} rate Model属性——字段占比 ${model.rate} nullValueCount Model属性——字段空值数 ${model.nullValueCount} listB-List--表格2 map.listB …… listC-List--表格3 map.listC …… table2 table-名字 ${map.table} tableName-中文名 ${map.tableName} columnCount-字段数 ${map.columnCount} recordCount-记录数 ${map.recordCount} listA-List--表格1 map.listA column Model属性——字段名 ${model.column} columnName Model属性——字段中文名 ${model.column} rate Model属性——字段占比 ${model.rate} nullValueCount Model属性——字段空值数 ${model.nullValueCount} listB-List--表格2 map.listB …… listC-List--表格3 map.listC …… table3 ……
您可以使用XDocReport和FreeMarker模板来生成带页数的Word文档。以下是一个示例代码: 1. 添加以下依赖项到您的项目中: ```xml <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>xdocreport</artifactId> <version>1.0.6</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>xdocreport-template-freemarker</artifactId> <version>1.0.6</version> </dependency> ``` 2. 创建一个FreeMarker模板,包含一个名为“page”的变量,用于显示当前页数。例如,以下是一个简单的模板: ``` <html> <head> <title>My Document</title> </head> <body> <p>Page ${page} of ${nbPages}</p> <p>This is the content of my document.</p> </body> </html> ``` 3. 在Java代码中使用XDocReport和FreeMarker模板来填充Word文档。以下是一个示例代码: ```java import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import org.apache.poi.xwpf.usermodel.XWPFDocument; import fr.opensagres.xdocreport.core.XDocReportException; import fr.opensagres.xdocreport.core.io.XOutputStream; import fr.opensagres.xdocreport.document.registry.XDocReportRegistry; import fr.opensagres.xdocreport.template.TemplateEngineKind; import fr.opensagres.xdocreport.template.formatter.FieldsMetadata; public class GenerateWordDoc { public static void main(String[] args) { try { // Load the template InputStream in = GenerateWordDoc.class.getResourceAsStream("template.docx"); XWPFDocument document = new XWPFDocument(in); FieldsMetadata metadata = new FieldsMetadata(); metadata.addFieldAsTextStyling("page"); XDocReportRegistry.getRegistry().register(document, metadata, TemplateEngineKind.Freemarker); // Populate the template Map<String, Object> context = new HashMap<>(); context.put("page", "${page}"); context.put("nbPages", "${nbPages}"); OutputStream out = new FileOutputStream("output.docx"); XDocReportRegistry.getRegistry().getReport(document, null).process(context, new XOutputStream(out)); // Close the streams in.close(); out.close(); } catch (Exception e) { e.printStackTrace(); } } } ``` 此代码将使用名为“template.docx”的模板创建一个新的Word文档,并将“page”变量替换为当前页数。请注意,您需要使用FieldsMetadata对象来标识文档中的字段,并将其注册到XDocReportRegistry中。最后,代码将输出生成的Word文档到名为“output.docx”的文件中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值