java根据所需格式生成word文档

准备工作

准备好空白的word模板
在需要的字段中填写字段名称
如果需要插入图片的地方需要优先插入备用图片
在这里插入图片描述
将word文档另存存为xml格式
在这里插入图片描述
这里说明一下,使用office和使用wps是有错位编码的,根据应用习惯去进行word的格式化
将生成的xml文件复制一份,并更改后缀名为ftl文件
在这里插入图片描述

java

正常的pom文件以外还要引入以下库

<!-- freeMarker begin-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

        <dependency>
            <groupId>com.documents4j</groupId>
            <artifactId>documents4j-local</artifactId>
            <version>1.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.documents4j</groupId>
            <artifactId>documents4j-transformer-msoffice-word</artifactId>
            <version>1.0.3</version>
        </dependency>

util文件

  1. FreemarkerParseUtils
package cc.vace.cloud.str.util;

import cc.vace.cloud.str.util.SpringUtil;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.IOUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import java.io.*;
import java.util.Map;

public final class FreemarkerParseUtils {

	/**
	 * a不可实例化
	 */
	private FreemarkerParseUtils() {

	}

	/**
	 * a把ftl文件解析成html字符串内容
	 *
	 * @param templatePath ftl文件路径
	 * @param model        模型数据(插值)
	 * @return 解析后的html文件内容
	 */
	public static String parse(String templatePath, Map<String, Object> model) {
		StringWriter stringWriter = null;
		BufferedWriter writer = null;
		File f = new File(templatePath);
		if (!f.getParentFile().exists()) {
			f.getParentFile().mkdirs();
		}
		try {
			//获取模板
			Template template = SpringUtil
					.getBean("freeMarkerConfigurer", FreeMarkerConfigurer.class)
					.getConfiguration()
					.getTemplate(templatePath);
			stringWriter = new StringWriter();
			writer = new BufferedWriter(stringWriter);
			//将模板与数据模型合并
			template.process(model, writer);
			writer.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(writer);
			IOUtils.closeQuietly(stringWriter);
		}
		return stringWriter.toString();
	}

	/**
	 * a解析ftl文件内容
	 *
	 * @param content 原ftl模板文件内容
	 * @param model   模板文件数据
	 * @return 解析后的html文件内容
	 */
	public static String parseFtlContent(String content, Map<String, Object> model) {
		// 获取配置
		StringWriter out = new StringWriter();
		try {
			Template template = new Template("template", new StringReader(content),
					SpringUtil.getBean("freeMarkerConfigurer", FreeMarkerConfigurer.class).getConfiguration());
			template.process(model, out);
		} catch (TemplateException | IOException e) {
			return "";
		}
		String htmlContent = out.toString();

		if (out != null) {
			try {
				out.close();
			} catch (IOException e) {
				return "";
			}
		}
		return htmlContent;
	}
}

2.SpringUtil

package cc.vace.cloud.str.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringUtil.applicationContext == null) {
            SpringUtil.applicationContext = applicationContext;
        }
        System.out.println("========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext=" + SpringUtil.applicationContext + "========");

        System.out.println("---------------------------------------------------------------------");
    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

}
  1. ImageUtil
package cc.vace.cloud.str.util;

import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Encoder;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 图片工具类
 */
@Component
public class ImageUtil {

    /**
     * 将图片内容转换成Base64编码的字符串
     * @param imageFile 图片文件的全路径名称
     * @return 转换成Base64编码的图片内容字符串
     */
    public static String getImageBase64String(String imageFile) {
        if (StringUtils.isEmpty(imageFile)) {
            return "";
        }
        File file = new File(imageFile);
        if (!file.exists()) {
            return "";
        }
        InputStream is = null;
        byte[] data = null;
        try {
            is = new FileInputStream(file);
            data = new byte[is.available()];
            is.read(data);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return Base64.encodeBase64String(data);
    }

}
  1. TemplateUtil
package cc.vace.cloud.str.util;

import com.documents4j.api.DocumentType;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import freemarker.core.ParseException;
import freemarker.template.*;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class TemplateUtil {

    /**
     * a生成word文件
     *
     * @param dataMap      模板中需要展示的动态数据,用map集合来保存
     * @param templateName 模板名称
     * @param fileCompletePath 输出文件完整路径,例如:D:/wordFile/
     * @throws IOException
     * @throws ParseException
     * @throws MalformedTemplateNameException
     * @throws TemplateNotFoundException
     * @throws TemplateException
     */
    public static void createFile(Map dataMap, String templateName, String fileCompletePath) throws Exception {
        File file = new File(fileCompletePath);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        // 创建配置实例
        Configuration configuration = new Configuration();
        // 设置编码
        configuration.setDefaultEncoding("UTF-8");
        // ftl模板文件
        configuration.setClassForTemplateLoading(TemplateUtil.class, "/");
        // 获取模板
        Template template = configuration.getTemplate(templateName);
        // 输出文件
        File outFile = new File(fileCompletePath);
        // 如果输出目标文件夹不存在,则创建
        if (!outFile.getParentFile().exists()) {
            outFile.getParentFile().mkdirs();
        }
        // 将模板和数据模型合并生成文件
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
        // 生成文件
        template.process(dataMap, out);
        // 关闭流
        out.flush();
        out.close();
    }

    public static void createTemplateAndConverter(Map dataMap, String templateName, String fileCompletePath) throws Exception {
        // 创建配置实例
        Configuration configuration = new Configuration();
        // 设置编码
        configuration.setDefaultEncoding("UTF-8");
        // ftl模板文件
        configuration.setClassForTemplateLoading(TemplateUtil.class, "/");
        // 获取模板
        Template template = configuration.getTemplate(templateName);

        // 将模板和数据模型合并生成文件
//		Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Writer writer = new BufferedWriter(new OutputStreamWriter(byteArrayOutputStream, "UTF-8"));
        // 生成文件
        template.process(dataMap, writer);
        File file = new File(fileCompletePath);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        OutputStream outputStream = new FileOutputStream(file);
        IConverter converter = LocalConverter.builder().baseFolder(new File(file.getParentFile().getPath())).build();
        converter.convert(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute();
    }

    public static void main(String[] args) throws Exception {
        Map map = new HashMap();
        // map数据,模板,
        createFile(map,"templates/csdn.ftl","D:/csdn_generate.doc");

    }

}

将生成的csdn.ftl文件放入程序的resources/templates下

这时我们的文件时这个样子的
在这里插入图片描述
格式化一下代码
在ftl文件中,有可能会需要更改里边我们设置的参数
在这里插入图片描述

将多余的标签删除,直到参数为实际参数为止
最终效果(如果本来就是${参数}可以不用修改)
在这里插入图片描述
找到图片base64编码区域,将编码删除,设置成我们的图片参数
在这里插入图片描述

<pkg:part pkg:name="/word/media/image1.png" pkg:contentType="image/png" pkg:compression="store">
       <pkg:binaryData>${img1}</pkg:binaryData>
</pkg:part>

在这里插入图片描述
这里需要注意,如果你是多张图片位置,但是在设置模板的时候为同一个图片,则只会有一个图片包出现,需要自己添加新的图片包
在这里插入图片描述
找到Relationships中的image1.png,在文件中有多个Relationships,一定要找到image1.png的Relationship
在后面追加
在这里插入图片描述
根据image1.png的id:rtd4搜索找到应用的地方
在这里插入图片描述
或者
在这里插入图片描述
修改其中一个改成我们自己写的ID就可以啦

使用

@Autowired
TemplateUtil templateUtil;
 @Override
    public void test(BaseQuery query) {
 		Map map = new HashMap();
        map.put("name","张三");
        map.put("id","202145154545");
        map.put("sex","男的");
        map.put("nation","汉族");
        map.put("img1",ImageUtil.getImageBase64String("C:/Users/king/Desktop/hh.png"));
        //图片路径,并由ImageUtil生成base64编码格式
        map.put("img2",ImageUtil.getImageBase64String("C:/Users/king/Desktop/mz.png"));
		//"template/blog.ftl":指向模板
		//"D:/blog1.doc":生成的文件路径以及文件名
       templateUtil.createFile(map,"template/blog.ftl","D:/blog1.doc");
    }

运行之后我们就可以在d盘找到blog.doc文件啦
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vace cc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值