java根据Freemarker模板渲染出Excel文件并在浏览器中下载

**java根据Freemarker模板渲染出Excel文件并在浏览器中下载**

  • 准备工作
    • 1.导入的依赖
    • 2.创建模板
    • Freemrker语法大全: [Freemarker语法使用请点击该链接跳转学习](http://t.csdn.cn/TGGwU)
  • 3.渲染Excel模板文件方法
  • 4.浏览器进行下载方法
  • 5.生成效果展示
  • **注意**:如果需要像上面红框框里面的展示、自动换行效果需要在Excel文件中设置成自动换行,然后再需要换行的文字后面加上xml文件的特殊换行符,如下所示!
    • 创作不易,都是根据自己使用后确实有用才进行记录,如有其他更好的方法,欢迎评论区留言讨论,点个赞再走!

准备工作

1.导入的依赖

这边用到的依赖是FreeMarker、hutool工具类

        <!--FreeMarker依赖-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>
        <!--Hutool工具类-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.17</version>
        </dependency>

2.创建模板

2.1 : 将需要动态替换的内容转换成占位符名称并用${占位符}包裹起来.
java根据Freemarker模板渲染出Excel文件并在浏览器中下载_第1张图片
2.2 : 将文件保存为xml文件。
java根据Freemarker模板渲染出Excel文件并在浏览器中下载_第2张图片
2.3 : 将文件复制到编译器idea下并修改后缀名称为 模板文件.ftl

Freemrker语法大全: Freemarker语法使用请点击该链接跳转学习

注意 : 转换后的Excel文件中的单元格都为String类型,如果为数字最好将String转换成Number类型,这样才能进行Excel导出的动态公式计算。
java根据Freemarker模板渲染出Excel文件并在浏览器中下载_第3张图片
2.4 : 如果需要遍历多个单元格,可以根据Freemarker语法在单元格中进行遍历添加(先找到要遍历的Table(表格)标签,行遍历找Row标签,单元格遍历找Cell标签)

 <#list PjCenterPlans as data>
            <Table ss:ExpandedColumnCount="24" ss:ExpandedRowCount="27" x:FullColumns="1" x:FullRows="1"
                   ss:DefaultColumnWidth="54" ss:DefaultRowHeight="13.5">
                <Row ss:Height="20.25">
                    <Cell ss:StyleID="s166" ss:MergeAcross="23">
                             <#--取值根据遍历后的对象来取值 data.数据-->
                        <Data ss:Type="String">${data.projectPage!}Data>
                    Cell>
                Row>
            Table>
  #list>

#本项目的代码,仅参考具体的操作,具体的核心方法为

//本项目的代码,方法仅供参考。
public void print() throws IOException, TemplateException{
Map<String, Object> map = new HashMap<>();
        List<ExportCentrePlanVo> vos = new ArrayList<>();
        map.put("PjCenterPlans", vos);
        ModelTemplateUtil templateUtil = new ModelTemplateUtil();
        //渲染Excel模板文件(方法在下面展示)
        File file = templateUtil.createExcel(map, "模板名称", "输出路径");
        //在浏览器进行下载
        FileUtil.downFile(IdWorker.get32UUID() + ".xlsx", file, true);
  }

3.渲染Excel模板文件方法


//临时文件夹 (user.dir:当前项目相对路径  当前项目路径/temporary/)
    public static final String temporary = System.getProperty("user.dir").concat(File.separator + "temporary" + File.separator);

    //freeMark模板文件夹路径  当前项目路径/modelTemplate/
    private static final String modelTemplate = System.getProperty("user.dir").concat(File.separator + "modelTemplate");

/**
     * FreeMarker生成Excel方法
     *
     * @param dataMap      数据
     * @param templateName 目标名
     * @param saveFilePath 保存文件路径的全路径名(路径+文件名)
     */
    public File createExcel(Map<String, Object> dataMap, String templateName, String saveFilePath) throws IOException, TemplateException {
        //临时下载文件路径
        saveFilePath = saveFilePath.concat(RandomUtil.randomInt(0, Integer.MAX_VALUE) + ".xls");
        // 设置模板文件的父目录
        FileTemplateLoader templateLoader = new FileTemplateLoader(new File(modelTemplate));
        //加载模板(路径)数据
        config.setTemplateLoader(templateLoader);
        //设置异常处理器 这样的话 即使没有属性也不会出错 如:${list.name}...不会报错
        config.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
        Template template = null;
        // 数据准备,可以是从数据库中查询,这里为了方便演示,手动 new 了
        // 生成 excel 文件
        try {
            if (templateName.contains("."))
                template = config.getTemplate(templateName);
            else
                template = config.getTemplate(templateName + ".ftl");
        } catch (TemplateNotFoundException e) {
            log.error("模板文件未找到", e);
            e.printStackTrace();
        } catch (MalformedTemplateNameException e) {
            log.error("模板类型不正确", e);
            e.printStackTrace();
        } catch (ParseException e) {
            log.error("解析模板出错,请检查模板格式", e);
            e.printStackTrace();
        } catch (IOException e) {
            log.error("IO读取失败", e);
            e.printStackTrace();
        }
        File outFile = new File(saveFilePath);
        if (!outFile.getParentFile().exists()) {
            outFile.getParentFile().mkdirs();
        }
        Writer out;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(outFile);
        } catch (FileNotFoundException e) {
            log.error("输出文件时未找到文件", e);
            e.printStackTrace();
        }
        out = new BufferedWriter(new OutputStreamWriter(fos));
        //将模板中的预先的代码替换为数据
        try {
            template.process(dataMap, out);
        } catch (TemplateException e) {
            log.error("填充模板时异常", e);
            e.printStackTrace();
        } catch (IOException e) {
            log.error("IO读取时异常", e);
            e.printStackTrace();
        }
        log.info("由模板文件:" + templateName + ".ftl" + " 生成文件 :" + saveFilePath + " 成功!!");
        try {
            out.close();//web项目不可关闭
        } catch (IOException e) {
            log.error("关闭Write对象出错", e);
            e.printStackTrace();
        }
        return outFile;
    }

4.浏览器进行下载方法

/**
     * 下载文件到浏览器
     *
     * @param fileName 要下载的文件名
     * @param file     需要下载的文件对象
     * @param remove   是否删除文件
     * @throws IOException
     */
    public static void downFile(String fileName, File file, Boolean remove) throws IOException {
        //获取上下文的request和response
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (ObjectUtil.isNull(attributes)) {
            return;
        }
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        //  文件存在才下载
        if (file.exists()) {
            OutputStream out = null;
            FileInputStream in = null;
            try {
                // 1.读取要下载的内容
                in = new FileInputStream(file);
                // 2. 告诉浏览器下载的方式以及一些设置
                // 解决文件名乱码问题,获取浏览器类型,转换对应文件名编码格式,IE要求文件名必须是utf-8, firefo要求是iso-8859-1编码
                setHttpHeader(request, response, fileName);

                // 将要下载的文件内容通过输出流写到浏览器
                assert response != null;
                out = response.getOutputStream();
                int len;
                byte[] buffer = new byte[1024];
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
                if (remove && file.isFile() && file.exists()) {
                    file.delete();
                    System.out.println(String.format("%s文件删除成功", file.getName()));
                }
            }
        }

5.生成效果展示

![在这里插入图片描述](https://img-blog.csdnimg.cn/49fca25640ed4036838415e652d118b9.png
java根据Freemarker模板渲染出Excel文件并在浏览器中下载_第4张图片

注意:如果需要像上面红框框里面的展示、自动换行效果需要在Excel文件中设置成自动换行,然后再需要换行的文字后面加上xml文件的特殊换行符,如下所示!

/**
     * xml回车符(特殊符号),在每一个需要换行的文字后面拼接上该字符即可完成换行操作
     */
    private final String chr = "
";
    

创作不易,都是根据自己使用后确实有用才进行记录,如有其他更好的方法,欢迎评论区留言讨论,点个赞再走!

你可能感兴趣的:(excel,java,开发语言)