java如何根据模板填充数据生成word文档

2023-11-13

这篇文章干什么?

  使用代码将word模板内容进行替换,并输出替换后的word。

思路总览

1、准备一个word模板,将里面需要替换的值改为${变量名}
2、将word导出为xml,复制一份xml,将复制的这份xml文件改为.ftl结尾的文件。
3、引包,编写(复制)代码。

1、准备word模板

  ${test1}就是要通过代码替换的内容
在这里插入图片描述

2、转换文件格式

  xml文件可以通过word导出,然后修改后缀为.ftl的文件,我们需要的就是.ftl文件。并将该文件放入到指定文件夹。
在这里插入图片描述

3、编写代码

引包:

		<dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.30</version>
        </dependency>

代码:

	import freemarker.template.Configuration;
	import freemarker.template.Template;
	import java.io.*;
	// 相关工具
	@Autowired
    private ExportFile exportFile;
    
	// 常量
	private Configuration configuration = null;
    /**
     * 输出word
     */
    public void commonExportWord() {

        // 获取map数据
        Map<String,Object> map = getColumnMapById();
        // 配置configuration
        Template template = setConfiguration();

        try{
            // 输出文档路径及名称
            Writer out = null;
            String fileName = exportFile.encodingFilenameWord("filename");
            // 文件的输出位置(输出到本地绝对路径里)
             File outFile = new File("/Users/relycf/Desktop/test");
            // 文件的输出位置(输出到项目相对路径里)
            // File outFile = new File(exportFile.getAbsoluteFile(fileName));
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8));
            template.process(map, out);
            out.close();
            // 如果你只是输出到本地,就可以不要下面这句,这句主要是为了返回流下载word。
            // exportFile.fileDownload(fileName);
        }catch (Exception e){
            log.error("导出word 输出流异常");
        }
    }


	/**
     * 构建填充word的数据
     * @return
     */
    public Map<String,Object> getColumnMapById(){
        Map<String,Object> map = new HashMap<>();
        map.put("test1","一百");
        return map;
    }
	/**
     * 填充 configuration
     */
    public Template setConfiguration(){
    	// 这是三种不同的文件加载方式,我们本地读取用第二种
        // public void setClassForTemplateLoading(Class clazz, String pathPrefix);
        // public void setDirectoryForTemplateLoading(File dir) throws IOException;
        // public void setServletContextForTemplateLoading(Object servletContext, String path);
        Template template = null;
        try{
            configuration = new Configuration();
            configuration.setDefaultEncoding("utf-8");
            // 输入文档路径及名称
            // 从本地路径读取存放ftl的文件夹
            configuration.setDirectoryForTemplateLoading(new File("/Users/relycf/Desktop/test"));
            // 从项目里的相对路径读取存放ftl的文件夹
            // configuration.setDirectoryForTemplateLoading(new File("./template"));
            // 被读取的文件
            template = configuration.getTemplate("two2.ftl");
            template.setEncoding("utf-8");
            return template;
        }catch (Exception e){
            log.error("configuration配置失败");
        }
        return template;
    }

相关方法中的封装代码:

@Component
@Slf4j
public class ExportFile {

	/**
     * 获取相对位置的下载路径
     *
     * @param filename 文件名称
     */
    public String getAbsoluteFile(String filename) {
        String downloadPath = "./download/" + filename;
        File desc = new File(downloadPath);
        if (!desc.getParentFile().exists()) {
            desc.getParentFile().mkdirs();
        }
        return downloadPath;
    }
    
    
	/**
     * 编码文件名word
     */
    public String encodingFilenameWord(String filename) {
        filename = UUID.randomUUID() + "_" + filename + ".docx";
        return filename;
    }
   
}

  到这里,执行commonExportWord方法,就可以在输出的本地文件夹找到输出的.docx文件了,打开后发现已经成功了(如下图)
在这里插入图片描述

补充–下载流

  截止到这里,如果不需要下载文件流,只是输出到本地,已经结束了。如果需要输出流,还有一段代码:(需要将上面那个输出文件路径的位置改为相对的,让下载流能够获取到位置)


	@Resource
    private HttpServletResponse response;

	/**
     * 下载文件 如果需要下载才需要到这个方法
     * @param fileName
     * @param delete
     */
    public void fileDownload(String fileName) {
        try {
            response.setContentType("application/json;charset=utf-8");
            String filePath = getAbsoluteFile(fileName);
            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
            FileUtils.deleteFile(filePath);
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }

    }

FileUtils:


import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
 * 文件处理工具类
 * 
 */
public class FileUtils extends org.apache.commons.io.FileUtils{

	/**
     * 输出指定文件的byte数组
     * 
     * @param filePath 文件路径
     * @param os 输出流
     * @return
     */
    public static void writeBytes(String filePath, OutputStream os) throws IOException
    {
        FileInputStream fis = null;
        try
        {
            File file = new File(filePath);
            if (!file.exists())
            {
                throw new FileNotFoundException(filePath);
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int length;
            while ((length = fis.read(b)) > 0)
            {
                os.write(b, 0, length);
            }
        }
        catch (IOException e)
        {
            throw e;
        }
        finally
        {
            if (os != null)
            {
                try
                {
                    os.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
            if (fis != null)
            {
                try
                {
                    fis.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        }
    }


	/**
     * 删除文件
     * 
     * @param filePath 文件
     * @return
     */
    public static boolean deleteFile(String filePath)
    {
        boolean flag = false;
        File file = new File(filePath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists())
        {
            file.delete();
            flag = true;
        }
        return flag;
    }

	/**
     * 下载文件名重新编码
     *
     * @param response 响应对象
     * @param realFileName 真实文件名
     * @return
     */
    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
    {
        String percentEncodedFileName = percentEncode(realFileName);

        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=")
                .append(percentEncodedFileName)
                .append(";")
                .append("filename*=")
                .append("utf-8''")
                .append(percentEncodedFileName);

        response.setHeader("Content-disposition", contentDispositionValue.toString());
    }

    /**
     * 百分号编码工具方法
     *
     * @param s 需要百分号编码的字符串
     * @return 百分号编码后的字符串
     */
    public static String percentEncode(String s) throws UnsupportedEncodingException
    {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
        return encode.replaceAll("\\+", "%20");
    }
}

请求方式(需要自己写个controller):
在这里插入图片描述

结束。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java如何根据模板填充数据生成word文档 的相关文章

  • 无法在 Android 10 中创建目录

    我无法在 android 10 中创建目录 它可以在 android Oreo 之前的设备上运行 我尝试了两种创建文件夹的方法 Using File mkdir File f new File Environment getExternal
  • 具有更高可见性的重写方法是良好的实践吗?

    回答这个问题 如何使用 GUI 使用 PaintComponent 初始化 GUI 然后添加基于鼠标的 GUI https stackoverflow com questions 21336141 how to gui using pain
  • Java Try Catch Final 没有 Catch 的情况下会阻塞

    我正在审查一些新代码 该程序只有一个 try 和一个 finally 块 既然排除了 catch 块 那么如果 try 块遇到异常或任何可抛出的内容 它如何工作 它直接进入finally块吗 如果 try 块中的任何代码可以引发已检查异常
  • 将 jar 作为 Linux 服务运行 - init.d 脚本在启动应用程序时卡住

    我目前正在致力于在 Linux VM 上实现一个可运行的 jar 作为后台服务 我已经使用了找到的例子here https gist github com shirish4you 5089019作为工作的基础 并将 start 方法修改为
  • 无法使用maven编译java项目

    我正在尝试在 java 16 0 1 上使用 maven 构建 IntelliJ 项目 但它无法编译我的项目 尽管 IntelliJ 能够成功完成 在此之前 我使用maven编译了一个java 15项目 但我决定将所有内容更新到16 0 1
  • Spring安全“记住我”cookie在第一个请求中不可用

    我无法在登录请求后检索 Spring 记住我 cookie 但它在对受保护页面的下一个请求中工作正常 谁能告诉我怎样才能立即得到它 我在登录请求中设置了记住我的 cookie 但在 Spring 重定向回原始 受保护的 url 后无法检索它
  • Java:使用 HttpURLConnection 的 HTTP PUT

    如何执行 HTTP PUT 我正在使用的类似乎认为它正在执行 PUT 但端点将其视为我执行了 GET 我做错了什么吗 URL url new URL https HttpURLConnection conn HttpURLConnectio
  • 如何在 JSP 中导入类?

    我是一个完全的JSP初学者 我正在尝试使用java util List在 JSP 页面中 我需要做什么才能使用除以下类之外的类java lang 使用以下导入语句进行导入java util List 顺便说一句 要导入多个类 请使用以下格式
  • 使用 RecyclerView 适配器在运行时更改布局屏幕

    我有两个布局文件 如下所示 如果列表中存在数据 则我显示此布局 当列表为空时 我会显示此布局 现在我想在运行时更改布局 当用户从列表中删除最后一项时 我想将布局更改为第二张图片中显示的 空购物车布局 In getItemCount Recy
  • 主线程如何在该线程之前运行?

    我有以下代码 public class Derived implements Runnable private int num public synchronized void setA int num try Thread sleep 1
  • 如何让spring为JdbcMetadataStore创建相应的schema?

    我想使用此处描述的 jdbc 元数据存储 https docs spring io spring integration docs 5 2 0 BUILD SNAPSHOT reference html jdbc html jdbc met
  • 在java中实现你自己的阻塞队列

    我知道这个问题之前已经被问过并回答过很多次了 但我只是无法根据互联网上找到的示例找出窍门 例如this http tutorials jenkov com java concurrency blocking queues html or t
  • Java:正则表达式排除空值

    在问题中here https stackoverflow com questions 51359056 java regexp for a separated group of digits 我得到了正则表达式来匹配 1 到 99 之间的一
  • Java 服务器-客户端 readLine() 方法

    我有一个客户端类和一个服务器类 如果客户端向服务器发送消息 服务器会将响应发送回客户端 然后客户端将打印它收到的所有消息 例如 如果客户端向服务器发送 A 则服务器将向客户端发送响应 1111 所以我在客户端类中使用 readLine 从服
  • 尝试使用等于“是”或“否”的字符串变量重新启动 do-while 循环

    计算行程距离的非常简单的程序 一周前刚刚开始 我有这个循环用于解决真或假问题 但我希望它适用于简单的 是 或 否 我为此分配的字符串是答案 public class Main public static void main String a
  • 解决错误javax.mail.AuthenticationFailedException

    我不熟悉java中发送邮件的这个功能 我在发送电子邮件重置密码时遇到错误 希望你能给我一个解决方案 下面是我的代码 public synchronized static boolean sendMailAdvance String emai
  • 挂钩 Eclipse 构建过程吗?

    我希望在 Eclipse 中按下构建按钮时能够运行一个简单的 Java 程序 目前 当我单击 构建 时 它会运行一些 JRebel 日志记录代码 我有一个程序可以解析 JRebel 日志文件并将统计信息存储在数据库中 是否可以编写一个插件或
  • Android - 9 补丁

    我正在尝试使用 9 块图片创建一个新的微调器背景 我尝试了很多方法来获得完美的图像 但都失败了 s Here is my 9 patch 当我用Draw 9 patch模拟时 内容看起来不错 但是带有箭头的部分没有显示 或者当它显示时 这部
  • 嵌入式 Jetty - 以编程方式添加基于表单的身份验证

    有没有一种方法可以按如下方式以编程方式添加基于表单的身份验证 我用的是我自己的LdapLoginModule 最初我使用基本身份验证并且工作正常 但现在我想在登录页面上进行更多控制 例如显示徽标等 有没有好的样品 我正在使用嵌入式 jett
  • JAXB - 列表<可序列化>?

    我使用 xjc 制作了一些课程 public class MyType XmlElementRefs XmlElementRef name MyInnerType type JAXBElement class required false

随机推荐