java 按模版生成word,docx格式、ftl,并以zip格式下载

按照word模版生成文件,此处为高版本docx,采用ftl的方式

一、前期准备word模版

首先准备好word模版,将docx直接改为zip,双击打开zip,在word文件夹下将document.xml和document.xml.rels两个文件剪切出,将剩余部分最好放置项目中,我为了方便放在了jsp同目录下,将document.xml和document.xml.rels这两个文件直接加后缀‘.ftl’。

用idea打开document.xml.ftl文件,如果格式比较乱,可通过Ctrl+Alt+L格式化,然后添加你需要的参数

 

这里需要注意如果模版中涵盖图片,如统计图,两个文件需注意参数一致

 

 二、代码生成

import org.apache.commons.io.FileUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
public ActionForward exportRec(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                  HttpServletResponse response) throws Exception {
        response.setCharacterEncoding("GBK");
        PrintWriter pw = response.getWriter();
        String basepath = request.getSession().getServletContext().getRealPath("/");
        String realpath = basepath + "\\tmp\\";
        String directory = GeneratorUUID.generateUUID();
        String filepath = realpath + directory + "\\";
        JSONObject jsonObject = new JSONObject();
        File fsub = new File(filepath);
        if (!fsub.getParentFile().exists()) {
            fsub.getParentFile().mkdir();
        }
        if (!fsub.exists()) {
            fsub.mkdir();
        }
        try {
            String param = request.getParameter("param");
            param = URLDecoder.decode(param, "UTF-8");
            JSONObject object = Common.getInstance().jsonFormatObject(param);
            String beginDate = object.get("beginDate") == null ? "" : (String)object.get("beginDate");
            String endDate = object.get("endDate") == null ? "" : (String)object.get("endDate");
            String templatedoc = basepath + "\\文件路径\\wordrec.zip";
            ZipUtil.decompress(templatedoc, filepath + "tmp\\");
            Map<String, Object> dataset = WordUtils.getInstance().getWordDataset(beginDate,endDate,filepath);
            WordUtils.getInstance().createWord(dataset, "document.xml.ftl", filepath + "\\tmp\\word\\", "document.xml");
            WordUtils.getInstance().createWord(dataset, "document.xml.rels.ftl", filepath + "\\tmp\\word\\_rels\\", "document.xml.rels");
            ZipUtil.compress(filepath + "tmp\\", filepath + filename);
            try {
                FileUtils.deleteDirectory(new File(filepath + "tmp\\"));
            } catch (Exception e) {

            }
            File outZipFile = new File(
                    filepath + "\\" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".zip");
            InputStream in = null;
            ZipOutputStream zipOutputStream = new ZipOutputStream(outZipFile);
            String filesStr[] = fsub.list();

            for (String ffn : filesStr) {
                if (!ffn.endsWith("zip")) {
                    File zpfile = new File(filepath + ffn);
                    in = new FileInputStream(zpfile);
                    zipOutputStream.putNextEntry(new ZipEntry(ffn));
                    int len = 0;
                    byte b[] = new byte[1024];
                    while ((len = in.read(b)) > -1) {
                        zipOutputStream.write(b, 0, len);
                    }
                    zpfile.delete();
                    in.close();
                    zipOutputStream.closeEntry();
                }
            }
            zipOutputStream.close();

            if (outZipFile.exists()) {
                jsonObject.put("code", "0");
                jsonObject.put("id", GeneratorUUID.generateUUID().toLowerCase().replace("-", ""));
                jsonObject.put("name", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
                jsonObject.put("url", "\\tmp\\" + directory + "\\" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".zip");
            }

        } catch (Exception e) {
            e.printStackTrace();
            jsonObject.put("code", "1");
            jsonObject.put("msg", e.getMessage());
            throw e;
        } finally {
            try {
                File[] filesubs = fsub.listFiles();
                for (File fa : filesubs) {
                    if (!fa.getName().endsWith(".zip")) {
                        boolean flag = fa.delete();
                        if (!flag) {
                            System.gc();
                            fa.delete();
                        }
                    }
                }
            } catch (Exception e) {
            }
        }
        pw.write(jsonObject.toJSONString());
        pw.flush(); pw.close();
        return (mapping.findForward(null));
    }

生成word工具类

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.jfree.chart.*;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.BarRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.CategoryDataset;
import org.jfree.data.DefaultCategoryDataset;
import org.jfree.data.DefaultPieDataset;
import org.jfree.ui.TextAnchor;
public class WordUtils {
    private static final class InstanceHolder {
        static final WordUtils instance = new WordUtils();
    }

    public static WordUtils getInstance() {
        return WordUtils.InstanceHolder.instance;
    }

    private String getDateStr(String day,int num){
        String str = "";
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Date dd = format.parse(day);
            Calendar calendar1 = Calendar.getInstance();
            calendar1.setTime(dd);
            calendar1.add(Calendar.DATE, num);
            str = format.format(calendar1.getTime());
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return str;
    }

    public Map<String,Object> getWordDataset(String orgid,String exptype
            ,String orgname,String title,String beginDate,String endDate
            ,String filepath){
        String docimgpath = filepath + "\\tmp\\word\\media\\";
        Map<String, Object> dataMap = new HashMap<String, Object>();
        /**
         *  word模板操作流程:①在word文档中编写变量(${}) ②将docx改为zip
         *  ③双击zip,找到word文件夹下拿到document.xml,加后缀.ftl
         *  ④找到word\_rels文件夹下document.xml.rels,加后缀.ftl
         *  ⑤调整document.xml.ftl、document.xml.rels.ftl
         */



        // 0.标题、日期
        dataMap.put("title", title);
        dataMap.put("riqi",sjd);

        

        String jbtbid = "tb"+GeneratorUUID.generateUUID().toLowerCase();
        dataMap.put("jbtbid",jbtbid);
        if(total > 0){
            // 图表标题
            String tbtitle = ttitle + "XX统计分析";
            DefaultCategoryDataset bardataset = new DefaultCategoryDataset();
            bardataset.addValue(10,"昨日","湿度");
            bardataset.addValue(5,"今日","湿度");

            bardataset.addValue(2,"昨日","温度");
            bardataset.addValue(5,"今日","温度");

            createBarChart(tbtitle, "", ytitle, bardataset, false, docimgpath + jbtbid + ".jpg");

        }

        
        
        dataMap.put("list",数据list);

        return dataMap;
    }


    /**
     * 生成word文档
     *
     * @param dataMap
     * @param templateName
     * @param filePath
     * @param fileName
     */
    public void createWord(Map<String, Object> dataMap, String templateName, String filePath, String fileName) {

        Writer out = null;
        try {
            Configuration configuration = new Configuration();
            configuration.setDefaultEncoding("UTF-8");
            configuration.setClassForTemplateLoading(WordUtils.class, "xml.ftl地址");
            Template template = configuration.getTemplate(templateName);
            File outFile = new File(filePath + File.separator + fileName);
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdir();
            }
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
            template.process(dataMap, out);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void createBarChart(String title, String xtitle, String ytitle, CategoryDataset dataset, boolean islegend, String path) {
        String str = "";
        JFreeChart chart = createBarChart(title, xtitle, ytitle, dataset, islegend);
        copyJFreeChartFile(chart, path);
    }

    private void createPieChart(String title, DefaultPieDataset dataset, boolean islegend, String path) {
        String str = "";
        JFreeChart chart = createPieChart(title, dataset, islegend);
        copyJFreeChartFile(chart, path);
    }
    /**
     * 创建柱状图
     *
     * @param title
     * @param xtitle
     * @param ytitle
     * @param dataset
     * @param islegend
     * @return
     */
    private JFreeChart createBarChart(String title, String xtitle, String ytitle, CategoryDataset dataset, boolean islegend) {
        JFreeChart chart = ChartFactory.createBarChart(title, xtitle, ytitle, dataset, PlotOrientation.VERTICAL, islegend, false, false);
        chart.setTitle(new TextTitle(title,new Font("黑体",Font.BOLD,28)));
        chart.setBackgroundPaint(Color.white);
        chart.setAntiAlias(true);

        //图例
        StandardLegend legend = (StandardLegend) chart.getLegend();
        if (legend != null) {
            legend.setDisplaySeriesShapes(true);
            legend.setShapeScaleX(1.5);
            legend.setShapeScaleY(1.5);
            legend.setDisplaySeriesLines(true);
            legend.setAnchor(Legend.NORTH_NORTHEAST);
            legend.setItemFont(new Font("宋体", Font.PLAIN, 16));
        }

        CategoryPlot plot = chart.getCategoryPlot();
        plot.setBackgroundPaint(Color.white);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);
        plot.setBackgroundAlpha(0.5f);
        plot.setForegroundAlpha(0.7f);
        plot.setRangeGridlinePaint(Color.BLACK);
        plot.setOutlinePaint(Color.BLACK);
        // 设置是否显示水平方向背景线,默认值为true
        plot.setRangeGridlinesVisible(true);
        // 设置垂直方向背景线颜色
        plot.setDomainGridlinePaint(Color.BLACK);
        // 设置是否显示垂直方向背景线,默认值为false
        plot.setDomainGridlinesVisible(false);

        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        rangeAxis.setUpperMargin(0.1D);
        rangeAxis.setAutoRange(true);
        //rangeAxis.setRange(0.0D, 100.0D);
        rangeAxis.setLabelFont(new Font("宋体", Font.BOLD, 16));
        rangeAxis.setTickLabelFont(new Font("宋体", Font.BOLD, 16));

        BarRenderer renderer = (BarRenderer) plot.getRenderer();
        renderer.setSeriesItemLabelsVisible(0, Boolean.TRUE);
        //renderer.setSeriesItemLabelFont(0, new Font("宋体", Font.BOLD, 16));
        //renderer.setSeriesItemLabelFont(1, new Font("宋体", Font.BOLD, 16));
        renderer.setItemLabelFont(new Font("宋体", Font.BOLD, 16));
        renderer.setDrawBarOutline(false); // Bar的外轮廓线不画
        GradientPaint gradientpaint = new GradientPaint(0.0F, 0.0F, Color.blue, 0.0F, 0.0F, new Color(0, 0, 64)); //设定特定颜色
        renderer.setSeriesPaint(0, gradientpaint);
        renderer.setLabelGenerator(new StandardCategoryLabelGenerator());
        renderer.setItemLabelsVisible(true);
        renderer.setItemMargin(0.05);
        renderer.setMaxBarWidth(0.05);
        renderer.setSeriesItemLabelFont(0, new Font("宋体", Font.BOLD, 16));
        ItemLabelPosition p = new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_CENTER, TextAnchor.CENTER, 0);
        renderer.setPositiveItemLabelPosition(p);
        //renderer.setNegativeItemLabelPosition(p);

        CategoryAxis domainAxis = plot.getDomainAxis();
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.STANDARD);
        domainAxis.setTickLabelFont(new Font("宋体", Font.BOLD, 16));
        return chart;
    }

    /**
     * 生成jfreechart图片
     *
     * @param chart
     * @param path
     */
    private void copyJFreeChartFile(JFreeChart chart, String path) {
        File newFile = new File(path);
        try {
            ChartUtilities.saveChartAsJPEG(newFile, 100, chart, 1000, 800, null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public JFreeChart createPieChart(String title,DefaultPieDataset pds, boolean islegend) {
        // 分别是:显示图表的标题、需要提供对应图表的DateSet对象、是否显示图例、是否生成贴士以及是否生成URL链接
        JFreeChart chart = ChartFactory.createPieChart(title, pds, islegend, false, false);
        chart.setBackgroundPaint(Color.white);
        // 如果不使用Font,中文将显示不出来
        Font font = new Font("宋体", Font.BOLD, 28);
        // 设置图片标题的字体
        chart.getTitle().setFont(font);
        // 得到图块,准备设置标签的字体
        PiePlot plot = (PiePlot) chart.getPlot();
        // 设置标签字体
        plot.setLabelFont(font);
        plot.setStartAngle(new Float(3.14f / 2f));

        // 设置plot的前景色透明度
        plot.setForegroundAlpha(0.7f);
        // 设置plot的背景色透明度
        plot.setBackgroundAlpha(0.5f);

        plot.setLabelBackgroundPaint(Color.white);

        // 饼图连接线
        plot.setLabelLinkStroke(new BasicStroke(5.0f));
        return chart;
    }
}

ZipUtil工具类


import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.*;

/**
 * java.util.zip压缩/解压文件
 */
public class ZipUtil {

    /**
     * 缓冲器大小
     */
    private static final int BUFFER = 512;

    /**
     * 得到源文件路径的所有文件
     *
     * @param dirFile 压缩源文件路径
     */
    public static List<File> getAllFile(File dirFile) {

        List<File> fileList = new ArrayList<File>();

        File[] files = dirFile.listFiles();
        for (File file : files) {//文件
            if (file.isFile()) {
                fileList.add(file);
                System.out.println("add file:" + file.getName());
            } else {//目录
                if (file.listFiles().length != 0) {//非空目录
                    fileList.addAll(getAllFile(file));//把递归文件加到fileList中
                } else {//空目录
                    fileList.add(file);
                    System.out.println("add empty dir:" + file.getName());
                }
            }
        }
        return fileList;
    }

    /**
     * 获取相对路径
     *
     * @param dirPath 源文件路径
     * @param file    准备压缩的单个文件
     */
    public static String getRelativePath(String dirPath, File file) {
        File dirFile = new File(dirPath);
        String relativePath = file.getName();

        while (true) {
            file = file.getParentFile();
            if (file == null) {
                break;
            }
            if (file.equals(dirFile)) {
                break;
            } else {
                relativePath = file.getName() + "/" + relativePath;
            }
        }
        return relativePath;
    }


    /**
     * @param destPath 解压目标路径
     * @param fileName 解压文件的相对路径
     */
    public static File createFile(String destPath, String fileName) {

        String[] dirs = fileName.split("/");//将文件名的各级目录分解
        File file = new File(destPath);

        if (dirs.length > 1) {//文件有上级目录
            for (int i = 0; i < dirs.length - 1; i++) {
                file = new File(file, dirs[i]);//依次创建文件对象知道文件的上一级目录
            }

            if (!file.exists()) {
                file.mkdirs();//文件对应目录若不存在,则创建
                try {
                    System.out.println("mkdirs: " + file.getCanonicalPath());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            file = new File(file, dirs[dirs.length - 1]);//创建文件

            return file;
        } else {
            if (!file.exists()) {//若目标路径的目录不存在,则创建
                file.mkdirs();
                try {
                    System.out.println("mkdirs: " + file.getCanonicalPath());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            file = new File(file, dirs[0]);//创建文件

            return file;
        }

    }

    /**
     * 没有指定压缩目标路径进行压缩,用默认的路径进行压缩
     *
     * @param dirPath 压缩源文件路径
     */
    public static void compress(String dirPath) {

        int firstIndex = dirPath.indexOf("/");
        int lastIndex = dirPath.lastIndexOf("/");
        String zipFileName = dirPath.substring(0, firstIndex + 1) + dirPath.substring(lastIndex + 1);
        compress(dirPath, zipFileName);
    }

    /**
     * 压缩文件
     *
     * @param dirPath     压缩源文件路径
     * @param zipFileName 压缩目标文件路径
     */
    public static void compress(String dirPath, String zipFileName) {

        File dirFile = new File(dirPath);
        List<File> fileList = getAllFile(dirFile);

        byte[] buffer = new byte[BUFFER];
        ZipEntry zipEntry = null;
        int readLength = 0;     //每次读取出来的长度

        try {
            // 对输出文件做CRC32校验
            CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(
                    zipFileName), new CRC32());
            ZipOutputStream zos = new ZipOutputStream(cos);

            for (File file : fileList) {

                if (file.isFile()) {   //若是文件,则压缩文件

                    zipEntry = new ZipEntry(getRelativePath(dirPath, file));  //
                    zipEntry.setSize(file.length());
                    zipEntry.setTime(file.lastModified());
                    zos.putNextEntry(zipEntry);

                    InputStream is = new BufferedInputStream(new FileInputStream(file));

                    while ((readLength = is.read(buffer, 0, BUFFER)) != -1) {
                        zos.write(buffer, 0, readLength);
                    }
                    is.close();
                    System.out.println("file compress:" + file.getCanonicalPath());
                } else {     //若是空目录,则写入zip条目中
                    zipEntry = new ZipEntry(getRelativePath(dirPath, file) + "/");
                    zos.putNextEntry(zipEntry);
                    System.out.println("dir compress: " + file.getCanonicalPath() + "/");
                }
            }
            zos.close();  //最后得关闭流,不然压缩最后一个文件会出错
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压
     */
    public static void decompress(String zipFileName, String destPath) {

        try {
            ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName));
            ZipEntry zipEntry = null;
            byte[] buffer = new byte[BUFFER];//缓冲器
            int readLength = 0;//每次读出来的长度
            while ((zipEntry = zis.getNextEntry()) != null) {
                if (zipEntry.isDirectory()) {//若是目录
                    File file = new File(destPath + "/" + zipEntry.getName());
                    if (!file.exists()) {
                        file.mkdirs();
                        System.out.println("mkdirs:" + file.getCanonicalPath());
                        continue;
                    }
                }//若是文件
                File file = createFile(destPath, zipEntry.getName());
                System.out.println("file created: " + file.getCanonicalPath());
                OutputStream os = new FileOutputStream(file);
                while ((readLength = zis.read(buffer, 0, BUFFER)) != -1) {
                    os.write(buffer, 0, readLength);
                }
                os.close();
                System.out.println("file uncompressed: " + file.getCanonicalPath());
            }


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值