java通过模板生成docx,docx再转pdf

后面两篇对导出做出来改进以及详细操作:

 第二篇:  java通过模板生成docx(2)

第三篇:java 导出word 利用freemarker指令更改xml 导出word docx文档 (3)

本篇思路:通过模板导出word doc容易,网上资料很多,大概就是将doc后缀改成xml文本打开通过freemarker指令标记${} 通过java代码动态写入。

导出docx用以上方法不行,docx本质为压缩文件,通过解压取出document.xml(和doc用xml打开中间部分一样) ,取出后修改在写入,生成docx 最后通过工具将docx 转成pdf

流程: docx文档------取出docx中的document.xml ---------xml中的数据替换 freemarker指令标记${}----------通过freemarker和map填充数据到xml ----------生成docx文件 --------------docx转pdf

1. 新建一个docx文档,放在D盘命名test_template.docx

2.用winrar打开 test_template.docx,取出word/document.xml

3.代码:这个类是把内容填充到xml

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
 
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
 
public class XmlTplUtil {
 
    private static XmlTplUtil tplm = null;
    private Configuration cfg = null;
 
    private XmlTplUtil() {
        cfg = new Configuration();
        try {
            // 注册tmlplate的load路径
            // 这的路径是xml的路径
            cfg.setDirectoryForTemplateLoading(new File("d:/"));
        } catch (Exception e) {
 
        }
    }
 
    private static Template getTemplate(String name) throws IOException {
        if (tplm == null) {
            tplm = new XmlTplUtil();
        }
        return tplm.cfg.getTemplate(name);
    }
 
    /**
     *
     * @param templatefile 模板文件
     * @param param 需要填充的内容
     * @param out 填充完成输出的文件
     * @throws IOException
     * @throws TemplateException
     */
    public static void process(String templatefile, Map param, Writer out) throws IOException, TemplateException {
        // 获取模板
        Template template = XmlTplUtil.getTemplate(templatefile);
        template.setOutputEncoding("UTF-8");
        // 合并数据
        template.process(param, out);
        if (out != null) {
            out.close();
        }
    }
}

4.xml转成docx
import freemarker.template.TemplateException;
 
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
 
/**
 * 其实docx属于zip的一种,这里只需要操作word/document.xml中的数据,其他的数据不用动
 *
 * @author  
 *
 */
public class XmlToDocx {
 
    /**
     *
     * @param xmlTemplate xml的文件名
     * @param docxTemplate docx的路径和文件名
     * @param xmlTemp  填充完数据的临时xml
     * @param toFilePath  目标文件名
     * @param map  需要动态传入的数据
     * @throws IOException
     * @throws TemplateException
     */
    public static void toDocx(String xmlTemplate, String docxTemplate,String xmlTemp ,String  toFilePath,Map map)  {
        try {
            // 1.map是动态传入的数据
            Writer w = new FileWriter(new File(xmlTemp));
            // 2.把map中的数据动态由freemarker传给xml
            XmlTplUtil.process(xmlTemplate, map, w);
 
            // 3.把填充完成的xml写入到docx中
            XmlToDocx xtd = new XmlToDocx();
 
            xtd.outDocx(new File(xmlTemp), docxTemplate, toFilePath);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     *
     * @param documentFile 动态生成数据的docunment.xml文件
     * @param docxTemplate docx的模板
     * @param toFilePath  需要导出的文件路径
     * @throws ZipException
     * @throws IOException
     */
 
    public void outDocx(File documentFile, String docxTemplate, String toFilePath) throws ZipException, IOException {
 
        try {
            File docxFile = new File(docxTemplate);
            ZipFile zipFile = new ZipFile(docxFile);
            Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
            ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(toFilePath));
            int len = -1;
            byte[] buffer = new byte[1024];
            while (zipEntrys.hasMoreElements()) {
                ZipEntry next = zipEntrys.nextElement();
                InputStream is = zipFile.getInputStream(next);
                // 把输入流的文件传到输出流中 如果是word/document.xml由我们输入
                zipout.putNextEntry(new ZipEntry(next.toString()));
                if ("word/document.xml".equals(next.toString())) {
                    InputStream in = new FileInputStream(documentFile);
                    while ((len = in.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    in.close();
                } else {
                    while ((len = is.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    is.close();
                }
            }
            zipout.close();
 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
5.将docx 转pdf
import fr.opensagres.xdocreport.utils.StringUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.poi.xwpf.converter.pdf.PdfConverter;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
/**
 * Created by dengxy on 2018/1/4.
 */
public class DocxToPdf {
 
 protected static final Logger logger = LoggerFactory.getLogger(DocxToPdf.class);
 
    /**
     *
     * @param docxFilepath docx文件
     * @param outPdfpath  输出的PDF文件
     * @throws Exception
     */
    public static void toPdf(String docxFilepath,String outPdfpath) {
        try {
            InputStream source = new FileInputStream(docxFilepath);
            OutputStream target = new FileOutputStream(outPdfpath);
            Map<String, String> params = new HashMap<String, String>();
 
 
            PdfOptions options = PdfOptions.create();
 
            wordConverterToPdf(source, target, options, params);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
   /**
     * 将word文档, 转换成pdf, 中间替换掉变量
     * @param source 源为word文档, 必须为docx文档
     * @param target 目标输出
     * @param params 需要替换的变量
     * @throws Exception
     */
 public static void wordConverterToPdf(InputStream source,OutputStream target, Map<String, String> params) throws Exception {
        wordConverterToPdf(source, target, null, params);
    }

     /**
     * 将word文档, 转换成pdf, 中间替换掉变量
     * @param source 源为word文档, 必须为docx文档
     * @param target 目标输出
     * @param params 需要替换的变量
     * @param options PdfOptions.create().fontEncoding( "windows-1250" ) 或者其他
     * @throws Exception
     */
  public static void wordConverterToPdf(InputStream source, OutputStream target,PdfOptions options,Map<String, String> params) throws Exception {
        XWPFDocument doc = new XWPFDocument(source);
        paragraphReplace(doc.getParagraphs(), params);
        for (XWPFTable table : doc.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    paragraphReplace(cell.getParagraphs(), params);
                }
            }
        }
        PdfConverter.getInstance().convert(doc, target, options);
    }
 
     /** 替换段落中内容 */
    private static void paragraphReplace(List<XWPFParagraph> paragraphs, Map<String, String> params) {
        if (MapUtils.isNotEmpty(params)) {
            for (XWPFParagraph p : paragraphs){
                for (XWPFRun r : p.getRuns()){
                    String content = r.getText(r.getTextPosition());
                    logger.info(content);
                    if(StringUtils.isNotEmpty(content) && params.containsKey(content)) {
                        r.setText(params.get(content), 0);
                    }
                }
            }
        }
    }
 
}

6.main方法测试
 public static void main(String[] args) throws IOException, TemplateException {
        try {
         // xml的文件名  
         String xmlTemplate = "test.xml";  
        // docx的路径和文件名  
        String docxTemplate = "d:\\test_template.docx";  
        // 填充完数据的临时xml  
        String xmlTemp = "d:\\temp.xml";  
         // 目标文件名  
        String toFilePath = "d:\\test.docx";  
        // 1.map为需要动态传入的数据
        //转Docx
       XmlToDocx.toDocx(xmlTemplate, docxTemplate, xmlTemp, toFilePath, map);
        //pdf文件
        String  outPdfFilePath = "test.pdf";
        //docx 转pdf
        DocxToPdf.toPdf(toFilePath,outPdfFilePath);
        File file = new File(outPdfFilePath);
        //删除docx文件
        new File(toFilePath).delete();
        //删除临时xml文件
        new File(xmlTemp).delete();
        return file;//返回pdf文件
        } catch (Exception e) {
            e.printStackTrace();
        }
}
参考链接 ;http://blog.csdn.net/u010588262/article/details/53666644





  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
以下是一个通过Word模板生成DOCX文件并换为PDF,并提供浏览器下载的Java代码示例: ```java import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; import org.docx4j.Docx4J; import org.docx4j.convert.out.pdf.PdfConversion; import org.docx4j.convert.out.pdf.viaXSLFO.ConversionOptions; import org.docx4j.fonts.IdentityPlusMapper; import org.docx4j.fonts.Mapper; import org.docx4j.model.structure.PageSizePaper; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart; import org.docx4j.wml.CTBorder; import org.docx4j.wml.CTBorderPr; import org.docx4j.wml.CTTbl; import org.docx4j.wml.CTTblBorders; import org.docx4j.wml.CTTblGrid; import org.docx4j.wml.CTTblLayoutType; import org.docx4j.wml.CTTblPr; import org.docx4j.wml.CTTblWidth; import org.docx4j.wml.ObjectFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class WordToPdfController { @RequestMapping(value = "/word-to-pdf", method = RequestMethod.GET) public void generatePdf(HttpServletResponse response) throws Exception { // 获取Word模板文件 File templateFile = new File("template.docx"); FileInputStream in = new FileInputStream(templateFile); // 替换Word中的变量 Map<String, String> variables = new HashMap<>(); variables.put("name", "John Doe"); variables.put("age", "30"); variables.put("address", "123 Main Street"); byte[] docxBytes = replaceVariables(in, variables); // 将DOCX文件换为PDF byte[] pdfBytes = convertToPdf(docxBytes); // 设置响应头 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=output.pdf"); // 将PDF文件写入响应体 OutputStream out = response.getOutputStream(); out.write(pdfBytes); out.flush(); out.close(); } private byte[] replaceVariables(InputStream in, Map<String, String> variables) throws Exception { // 加载Word模板文件 WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(in); MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart(); // 获取文档中的所有段落和表格 java.util.List<Object> paragraphsAndTables = documentPart.getContent(); // 遍历文档中的所有段落和表格 for(Object paragraphOrTable : paragraphsAndTables) { if(paragraphOrTable instanceof XWPFParagraph) { // 如果是段落,则替换其中的变量 XWPFParagraph paragraph = (XWPFParagraph) paragraphOrTable; for(XWPFRun run : paragraph.getRuns()) { String text = run.getText(0); if(text != null) { for(Map.Entry<String, String> entry : variables.entrySet()) { if(text.contains(entry.getKey())) { text = text.replace(entry.getKey(), entry.getValue()); run.setText(text, 0); } } } } } else if(paragraphOrTable instanceof XWPFTable) { // 如果是表格,则遍历其中的单元格并替换其中的变量 XWPFTable table = (XWPFTable) paragraphOrTable; for(XWPFTableRow row : table.getRows()) { for(XWPFTableCell cell : row.getTableCells()) { for(XWPFParagraph paragraph : cell.getParagraphs()) { for(XWPFRun run : paragraph.getRuns()) { String text = run.getText(0); if(text != null) { for(Map.Entry<String, String> entry : variables.entrySet()) { if(text.contains(entry.getKey())) { text = text.replace(entry.getKey(), entry.getValue()); run.setText(text, 0); } } } } } } } } } // 将修改后的文档保存为字节数组 ByteArrayOutputStream out = new ByteArrayOutputStream(); Docx4J.save(wordMLPackage, out); return out.toByteArray(); } private byte[] convertToPdf(byte[] docxBytes) throws Exception { // 加载DOCX文件 ByteArrayInputStream in = new ByteArrayInputStream(docxBytes); WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(in); // 设置字体映射 Mapper fontMapper = new IdentityPlusMapper(); wordMLPackage.setFontMapper(fontMapper); // 设置页面大小和边距 PageSizePaper pageSizePaper = new PageSizePaper(); pageSizePaper.setCode("A4"); wordMLPackage.getDocumentModel().getSections().get(0).getPageDimensions().setPageSize(pageSizePaper); wordMLPackage.getDocumentModel().getSections().get(0).getPageDimensions().setMarginTop(1440); wordMLPackage.getDocumentModel().getSections().get(0).getPageDimensions().setMarginBottom(1440); wordMLPackage.getDocumentModel().getSections().get(0).getPageDimensions().setMarginLeft(1440); wordMLPackage.getDocumentModel().getSections().get(0).getPageDimensions().setMarginRight(1440); // 获取文档中的所有表格 java.util.List<Object> tables = wordMLPackage.getMainDocumentPart().getContent(); for (Object obj : tables) { if (obj instanceof javax.xml.bind.JAXBElement && ((javax.xml.bind.JAXBElement<?>) obj).getDeclaredType().getName().equals("org.docx4j.wml.Tbl")) { javax.xml.bind.JAXBElement<org.docx4j.wml.Tbl> element = (javax.xml.bind.JAXBElement<org.docx4j.wml.Tbl>) obj; org.docx4j.wml.Tbl table = element.getValue(); // 设置表格边框 CTTbl ctTbl = table.getCTTbl(); CTTblPr tblPr = ctTbl.getTblPr(); if (tblPr == null) { tblPr = new CTTblPr(); ctTbl.setTblPr(tblPr); } CTTblBorders borders = tblPr.getTblBorders(); if (borders == null) { borders = new CTTblBorders(); tblPr.setTblBorders(borders); } CTBorder border = new CTBorder(); border.setColor("#000000"); border.setSz(new BigInteger("2")); CTBorderPr borderPr = new CTBorderPr(); borderPr.setTop(border); borderPr.setBottom(border); borderPr.setLeft(border); borderPr.setRight(border); borders.setTop(borderPr); borders.setBottom(borderPr); borders.setLeft(borderPr); borders.setRight(borderPr); // 设置表格宽度 CTTblGrid tblGrid = ctTbl.getTblGrid(); if (tblGrid == null) { tblGrid = new CTTblGrid(); ctTbl.setTblGrid(tblGrid); } for (int i = 0; i < table.getContent().size(); i++) { Object row = table.getContent().get(i); if (row instanceof javax.xml.bind.JAXBElement && ((javax.xml.bind.JAXBElement<?>) row).getDeclaredType().getName().equals("org.docx4j.wml.Tr")) { javax.xml.bind.JAXBElement<org.docx4j.wml.Tr> rowElement = (javax.xml.bind.JAXBElement<org.docx4j.wml.Tr>) row; org.docx4j.wml.Tr tr = rowElement.getValue(); for (int j = 0; j < tr.getContent().size(); j++) { Object cell = tr.getContent().get(j); if (cell instanceof javax.xml.bind.JAXBElement && ((javax.xml.bind.JAXBElement<?>) cell).getDeclaredType().getName().equals("org.docx4j.wml.Tc")) { javax.xml.bind.JAXBElement<org.docx4j.wml.Tc> cellElement = (javax.xml.bind.JAXBElement<org.docx4j.wml.Tc>) cell; org.docx4j.wml.Tc tc = cellElement.getValue(); CTTblWidth tblWidth = new CTTblWidth(); tblWidth.setType("dxa"); tblWidth.setW(BigInteger.valueOf(1000)); tc.getTcPr().setTcW(tblWidth); } } } } } } // 将文档换为PDF ConversionOptions conversionOptions = new ConversionOptions(); conversionOptions.setQuality(PdfConversionQualityEnum.PDF_A_1_B); OutputStream out = new ByteArrayOutputStream(); PdfConversion converter = new org.docx4j.convert.out.pdf.viaXSLFO.Conversion(wordMLPackage); converter.output(out, conversionOptions); return ((ByteArrayOutputStream) out).toByteArray(); } } ``` 在上述代码中,我们首先通过`replaceVariables()`方法将Word模板中的变量替换为实际值,然后通过`convertToPdf()`方法将DOCX文件换为PDF。最后,我们将PDF文件写入响应体并设置响应头,使得浏览器可以下载该文件。注意,这里我们使用了`docx4j`和`poi`两个开源库来处理WordPDF文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值