使用FreeMarker导出word文档(支持循环导出实时多张图片)

news2025/1/15 16:35:44

续上一期的更新内容  ,导出的是单张图片,直接在路径的src  里面填写对应的占位符,就可以了,随着需求的变化,那么今天我们继续往下写一个循环导出多张图片到word里面。

使用FreeMarker导出word文档(支持导出单张图片)

首先我们需要进行在word 里面把对应的模版设置好。

设置好点击另存为,目前我用的html 格式的,网上也有很多xml  形式的,每种写法还不一样

接着我们用记事本进行打开,第一步一定要先修改编码格式为utf-8的

然后我们将html 中head中的标签全部,如果编码不修改,head标签不删除,将来导出的时候就是乱码,这个坑是很深的,排查了好长时间才解决。

这些都修改好后,我们点击另存为将这个模版改成后缀为ftl形式的

接下来我们就开始编写代码

	@Override
	public void exporttdYsdWord(HttpServletRequest request,
			HttpServletResponse response, String objId, String gllx) {
		List<Map<String, String>> list = null;
		List<Map<String, String>> list3 = null;
		List<Map<String, String>> list5 = null;
		String ysdName = "";
		String ysdSql = "";
		String zpSql = "";
		String sdsgfa = "";
		String ysgjjd = "";
		String sdsgfaEname = "";
		if ("0".equals(gllx)) {
			sdsgfa = "sdsgfa";
			ysgjjd = "ysgjjd";
			sdsgfaEname = "sczbjys_sczbjys_sdsgfa";
			ysdName = "中间环节验收报告";
			ysdSql = "select t.gcmc,t.jgdw,t.jgdwfzr,t.jgdwfzrdh,"
						+ "t.tdsgdw,t.tdsgdwlxr,t.tdsgdwlxrdh,to_char(t.sqyssj,'yyyy-MM-dd') sqyssj,"
						+ "t.czwt,  (select a.username from gw_yhgl_user a where a.id = t.yxbzrm) yxbzrm, (select h.value  from gw_limit_enums h  where h.enumName like '%sczbjys_sczbjys_yxbz%' and h.key = t.yxbz) yxbz,(select t.value from   gw_limit_enums t   where   t.enumName like '%sczbjys_sczbjys_ysgjjd%'  and t.key=ysgjjd)  ysgjjd from GW_SCZBJYS_ZLC t where t.OBJ_ID = ?";
		}
		list = this.hibernateDao
				.queryForListWithSql(ysdSql,new String[]{objId});

		Map<String, String> map0 = new HashMap<String, String>();
		Map<String, Object> map = new HashMap<String, Object>();
        StringBuilder sb = new StringBuilder();
        String aa="";
		zpSql="select   t.ipath ,t.dpt from   gw_pig_address_rw t   where  t.taskid=?   and t.ipath is not   null  and t.dpt='问题照片'  and t.dpt  is not null   and t.ipath   not  like '%dat%'" ;
				list3 = this.hibernateDao
				.queryForListWithSql(zpSql,new String[]{objId});
				
			String 	zpSqla="select   t.ipath ,t.dpt from   gw_pig_address_rw t   where  t.taskid=?   and t.ipath is not   null   and t.dpt  is not null   and t.ipath   not  like '%dat%'" ;
				list5 = this.hibernateDao
				.queryForListWithSql(zpSqla,new String[]{objId});
				if(list3.size()>0){
					
		            for (Map<String, String> stringObjectMap : list3) {
		                if (stringObjectMap.get("DPT").equals("问题照片")) {
//		                	map.put("PSZP", "" + PlatformConfigUtil.getString("TASK_PIC_ADDRESS") + stringObjectMap.get("IPATH"));
//		                     aa= String.valueOf(sb.append(PlatformConfigUtil.getString("TASK_PIC_ADDRESS")+ stringObjectMap.get("IPATH")).append(","));
//		                	 aa= String.valueOf(sb.append("  <img width=249  height=273\"  src=\""+PlatformConfigUtil.getString("TASK_PIC_ADDRESS") + stringObjectMap.get("IPATH")).append(">").append(","));

		                    aa= String.valueOf(sb.append("<img width=\"249\"  height=\"273\" src=\""+PlatformConfigUtil.getString("TASK_PIC_ADDRESS") + stringObjectMap.get("IPATH")+"\">").append(","));

		                	

		                }
		            }
				}else{
					
		            for (Map<String, String> stringObjectMap : list5) {
		                if (!stringObjectMap.get("DPT").equals("问题照片")) {
//		                	map.put("PSZP", "" + PlatformConfigUtil.getString("TASK_PIC_ADDRESS") + stringObjectMap.get("IPATH"));
//		                     aa= String.valueOf(sb.append(PlatformConfigUtil.getString("TASK_PIC_ADDRESS")+ stringObjectMap.get("IPATH")).append(","));
		        			String   hh="<img width=\"249\"  height=\"273\"  src=\"http://192.168.200.86:18080/XSGL/2023-07-27/20230802155008.jpg\",<img width=\"249\"  height=\"273\"  src=\"http://192.168.200.86:18080/XSGL/2023-07-27/20230802154952.jpg\"";

		                    aa= String.valueOf(sb.append("<img width=\"249\"  height=\"273\" src=\""+PlatformConfigUtil.getString("TASK_PIC_ADDRESS") + stringObjectMap.get("IPATH")+"\">").append(","));


		                }
		            }
					
				}
				
				if(aa.length()>0){
				      String a1 = aa.substring(0, aa.length() - 1);
				      map.put("PSZP", a1);
				}else{

					if(aa.length()>0){
						  String a1 = aa.substring(0, aa.length() - 1);
					      map.put("PSZP", a1);
					}else{
					      map.put("PSZP", "");
					}
				  
				}


		if (!Tool.isEmptyList(list)) {
			map0 = list.get(0);
			if (Tool.isEmptyStr(map0.get("gcmc"))) {
				map.put("GCMC", "");
			} else {
				map.put("GCMC", map0.get("gcmc"));
			}
			if (Tool.isEmptyStr(map0.get("jgdw"))) {
				map.put("JGDW", "");
			} else {
				map.put("JGDW",
						getEnumsValueFromEnumDB("sczbjys_sczbjys_jgdw",map0.get("jgdw")));
			}

			if (Tool.isEmptyStr(map0.get("tdsgdw"))) {
				map.put("TDSGDW", "");
			} else {
				map.put("TDSGDW", map0.get("tdsgdw"));
			}
			if (Tool.isEmptyStr(map0.get("tdsgdwlxr"))) {
				map.put("TDSGDWLXR", "");
			} else {
				map.put("TDSGDWLXR", map0.get("tdsgdwlxr"));
			}
			if (Tool.isEmptyStr(map0.get("tdsgdwlxrdh"))) {
				map.put("TDSGDWLXRDH", "");
			} else {
				map.put("TDSGDWLXRDH", map0.get("tdsgdwlxrdh"));
			}
			if (Tool.isEmptyStr(map0.get("yxbz"))) {
				map.put("YXBZ", "");
			} else {
				map.put("YXBZ", map0.get("yxbz"));
			}
			if (Tool.isEmptyStr(map0.get("yxbzrm"))) {
				map.put("YXBZRM", "");
			} else {
				map.put("YXBZRM", map0.get("yxbzrm"));
			}
			
			if (Tool.isEmptyStr(map0.get("ysgjjd"))) {
				map.put("YSGJJD", "");
			} else {
				map.put("YSGJJD", map0.get("ysgjjd"));
			}
			if (Tool.isEmptyStr(map0.get("sqyssj"))) {
				map.put("SQYSSJ", "");
			} else {
				SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
				String string = map0.get("sqyssj"); 
				Date parse = null;
				try {
					parse = simpleDateFormat.parse(string);
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			String format = simpleDateFormat.format(parse);
	        StringBuilder myName = new StringBuilder(format);
	        myName.setCharAt(4, '年');
	        myName.setCharAt(7, '月');
	        myName.append("日");

	        System.out.println(myName);
//  时间变成 年月日形式
				map.put("SQYSSJ", myName.toString());
			}
			if (Tool.isEmptyStr(map0.get("czwt"))) {
				map.put("CZWT", "");
			} else {
				map.put("CZWT", map0.get("czwt"));
			}
			map.put("SJDW", "设计单位");
			map.put("JLDW", "监理");
			map.put("BD", "121");
			map.put("SDJG", "结构好");
			map.put("CD", "长度1");
			map.put("JCJ", "井口1");
			
			String   hh="<img width=\"249\"  height=\"273\"  src=\"http://192.168.200.86:18080/XSGL/2023-07-27/20230802155008.jpg\",<img width=\"249\"  height=\"273\"  src=\"http://192.168.200.86:18080/XSGL/2023-07-27/20230802154952.jpg\"";
			map.put("TFT", "");
//			map.put("PSZP", hh);
//			map.put("YSGJJD", "飒飒");
			
			
		} else {

			map.put("SJDW", "");
			map.put("JLDW", "");
			map.put("BD", "");
			map.put("SDJG", "");
			map.put("CD", "");
			map.put("JCJ", "");
			map.put("TFT", "");
		}
		try {
			WordUtils.exportWorde(request, response, map, "scbzjystd.ftl",
					ysdName);
		} catch (IOException e) {
			// TODO Auto-generated catch block
//			e.printStackTrace();
		}
	}
}

 

图片的格式高宽度提前在代码里面设置好,然后我们在模版里面用一个占位符来进行替代就可以了。

 设置下载格式

	public static void exportWorde(HttpServletRequest request,
			HttpServletResponse response, Map<String, Object> map,
			String templateName, String fileName)  throws IOException {
		String pathString = request.getSession().getServletContext().getRealPath("/WEB-INF/templete/");
    	logger.info("获取到的模板路径是:templetePath------->" + pathString);
    	configuration.setDirectoryForTemplateLoading(new File(pathString));
    	
    	Template freemarkerTemplate = configuration.getTemplate(templateName);
        File file = null;
        InputStream fin = null;
        ServletOutputStream out = null;
        try {
            // 调用工具类的createDoc方法生成Word文档
            file = createDoce(map,freemarkerTemplate);
            fin = new FileInputStream(file);
 
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            // 设置浏览器以下载的方式处理该文件名
            fileName = fileName + DateUtil.currentDateToString() + ".doc";
            response.setHeader("Content-Disposition", "attachment;filename="
                    .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
 
            out = response.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(); // 删除临时文件
        }
		
	}

设置编码:

    private static File createDoce(Map<String, Object> dataMap, Template template) {
        String name =  ".doc";
        File f = new File(name);
        Template t = template;
        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;
    }

 导出效果

若本文对你有所帮助,请一键三连,说不定后期工作中就用到了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1104792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何评估大语言模型是否可信?这里总结了七大维度

源自&#xff1a;机器之心发布 作者&#xff1a;刘扬&#xff0c;Kevin Yao 实际部署中&#xff0c;如何 “对齐”&#xff08;alignment&#xff09;大型语言模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;&#xff0c;即让模型行为与人类意图相一致…

荣耀推送服务业务介绍

概述 荣耀推送服务&#xff08;HONOR Push&#xff09;是荣耀公司向开发者提供的消息推送服务&#xff0c;通过服务端与客户端建立一条稳定、可靠的长连接通道&#xff0c;向荣耀手机系统上的APP应用客户端实时推送消息的服务。无论应用进程是否存在&#xff0c;均可正常收到消…

【AIFEM案例教程】水轮机活动导叶强度分析

AIFEM是由天洑自主研发的一款通用的智能结构仿真软件&#xff0c;助力用户解决固体结构相关的静力学、动力学、振动、热力学等实际工程问题&#xff0c;软件提供高效的前后处理工具和高精度的有限元求解器&#xff0c;帮助用户快速、深入地评估结构的力学性能&#xff0c;加速产…

LAS Spark+云原生:数据分析全新解决方案

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 随着数据规模的迅速增长和数据处理需求的不断演进&#xff0c;云原生架构和湖仓分析成为了现代数据处理的重要趋势。在这个数字化时代&#xff0c;企业面临着海量数…

leetcode:101.对称二叉树

借用二叉树是否相同的代码改动左右孩子相等对应关系&#xff0c;即为是否对称。 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/bool isSameTree(struct TreeNode* p, struct Tr…

纳米软件科普|什么是运放芯片?运放芯片测试方法是什么?

运放芯片是一种电路元件&#xff0c;它可以用于信号放大、滤波、积分、微分等电路中。在多媒体音箱领域&#xff0c;运放芯片主要负责音量、音调和周边效果调节的运算功能。例如&#xff0c;音响中的前级和耳机放大器(耳放)中都会使用集成运算放大器。常见的运放芯片有OPA1612和…

nvm 安装 node 安装不上 npm

遇到一个问题 nvm install 18.18.2 node -v 安装上了 npm -v 发现没有安装上 解决办法 nvm -v 查看到自己的 nvm 版本号是 1.1.7 NVM下载 - NVM中文网 下载最新版本的 nvm .exe 文件 nvm list 查看手里 node 的所有版本 nvm uninstall 各个版本只保留一个最低版本 点…

中文编程开发语言工具编程案例:计时计费管理系统软件连接灯控器编程案例

中文编程开发语言工具编程案例&#xff1a;计时计费管理系统软件连接灯控器编程案例 中文编程开发语言工具编程案例&#xff1a;计时计费管理系统软件连接灯控器编程案例 中文编程系统化教程&#xff0c;不需英语基础。学习链接 https://edu.csdn.net/course/detail/39036

Messari发布Moonbeam简报,每日交易量稳步增长,首次公布利润数据

区块链数据公司Messari首次发布Moonbeam项目分析简报&#xff0c;从项目市值、链上数据表现、质押以及Moonbeam的技术优势XCM使用量等角度全面分析。这个再熊市初期上线的项目一直在默默开发&#xff0c;并在跨链互操作领域拥有了相当的实操成绩。我们翻译了Messari简报中的部分…

分类预测 | Matlab实现WOA-BiLSTM鲸鱼算法优化双向长短期记忆神经网络的数据多输入分类预测

分类预测 | Matlab实现WOA-BiLSTM鲸鱼算法优化双向长短期记忆神经网络的数据多输入分类预测 目录 分类预测 | Matlab实现WOA-BiLSTM鲸鱼算法优化双向长短期记忆神经网络的数据多输入分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现WOA-BiLSTM鲸鱼算法…

AirPods Max奇特的关机模式!如何关闭AirPods Max

对于一家专注于让事情变得更简单的公司来说&#xff0c;苹果已经把关闭最高端耳机这样的基本问题过于复杂了。耳机没有电源按钮。别担心&#xff1b;如果你想弄清楚情况&#xff0c;你并不孤单。今天&#xff0c;我们将教你如何关闭AirPods Max。 如何关闭AirPods Max AirPods…

万界星空科技离散型制造企业MES解决方案

MES即制造企业生产过程执行系统,面向制造企业车间执行层的生产信息化管理系统。是精益生产、数字化工厂、智慧工厂的支撑平台。帮助企业对生产全流程进行管控并进行信息追溯,实现柔性化生产、精细化管理。 一、企业生产场景总览: 二、MES系统架构图: 帮助企业实现制造执行自动…

QT的QStringList的使用

初始 化 默认构造函数创建一个空列表。可以使用初始值设定项列表构造函数创建包含元素的列表&#xff1a; QStringList fonts { "Arial", "Helvetica", "Times" }; 添加字符串 可以使用insert 、append&#xff08;&#xff09; 和 operator…

CH7-任务管理

7.1 任务管理概述&#xff08;TASK MANAGEMENT OVERVIEW&#xff09; 什么是任务&#xff1f; 任务是操作系统中的一个基本执行单位&#xff0c;可以是一个进程或者一个线程&#xff0c;代表了系统中的一个活动。 80x86 提供了哪些硬件支持&#xff1f; 80x86 提供了任务状态段…

解决IDEA中SpringBoot项目创建多个子模块时配置文件小绿叶图标异常问题

在新建子模块下创建配置文件&#xff1a; 在子模块gateway中新建的配置文件,正常情况下配置文件左侧是小树叶标识&#xff0c;而这次新建application-dev.yml是个小树叶标识&#xff0c;bootstrap.yml是个方框。 看其他方案都是在project structure中设置&#xff0c;但未显示…

HTML 表单笔记/练习

表单 概述 表单用于收集用户信息&#xff0c;用户填写表单提交到服务器 一般传参方式&#xff1a; GETPOSTCookie 传参要素 传参方式 GETPOST 参数的名字目标页面内容的数据类型&#xff08;只有在上传文件的时候&#xff09; 提示信息 一个表单中通常还包含一些说明性的文…

如何从一门编程语言过渡到另一门编程语言?

在数字时代&#xff0c;软件开发领域不断进化&#xff0c;不同编程语言层出不穷。作为一位富有经验的开发者&#xff0c;你可能曾面临过一个重要的问题&#xff1a;如何顺利过渡到一门全新的编程语言&#xff1f; 这个问题不仅是对技术领域的学习&#xff0c;更是对职业生涯的…

哨兵1号后向散射系数土壤水分反演

哨兵1号后向散射系数土壤水分反演 数据导入 打开之前预处理之后的VH和VV极化的后向散射系数转存的tiff文件 导入实测点 选择KML转图层 kml文件是由奥维地图导出的.ovkml格式改后缀名得到的 提取采样点的后向散射系数 选择多值提取至点 右键打开点图层的属性表,发现…

2000年至2017年LandScan全球人口分布数据(1KM分辨率)

简介&#xff1a; LandScan全球人口分布数据来自于East View Cartographic&#xff0c;由美国能源部橡树岭国家实验室(ORNL)开发。LandScan运用GIS和遥感等创新方法&#xff0c;是全球人口数据发布的社会标准&#xff0c;是全球最为准确、可靠&#xff0c;基于地理位置的&…

音频处理到雷达系统:滤波组的多领域应用 | 百能云芯

在电子元器件和电路设计领域&#xff0c;滤波组&#xff08;Filter Bank&#xff09;是一个关键概念&#xff0c;它用于处理和过滤信号&#xff0c;以满足各种应用的需求。云芯将带您深入研究滤波组在元器件中的应用&#xff0c;包括其工作原理、不同类型以及在通信、音频处理和…