您的位置 首页 java

word模板数据填充并转pdf

问题背景描述

我们在做项目的时候,可能会遇到这样的一个需求,根据业务数据,生成一份 Pdf 文件,然后提供给用户下载查看。

生成pdf文件,可能会有很多种方式实现:

  • 1.根据 html 模板,把数据填充到html模板,生成一份pdf文件
  • 2.根据pdf模板,把数据填充到pdf模板,生成一份pdf文件
  • 3.根据word模板,把数据填充到word模板,生成一份pdf文件

对比了这3种实现方式:

以上,仅代表个人观点,可能有不对的地方,别喷,或轻点喷!!!

那今天咋们着重的讨论一下第3种实现方式!!!^_^

word转pdf说明

目前,word转pdf,我们可以借助 openoffice 帮我们实现这个功能。

但凡,有个但是啦,毕竟你要借助openoffice,这毕竟是一个工具,那咋们就不得不部署运行这个程序,那这样得话,不得加重咋们后期服务器的部署和运维了嘛?

所以这里,咋们还是得想想看,有无其他简单的实现方式?

哈哈,那肯定是有的啦,我们可以通过纯代码的方式,实现word转pdf的功能!!!

下面看哥们操作喽!!!^_^

word转pdf实现

  • word模板数据填充工具类
 public class WordTemplateUtils {
     private   static  Logger logger = LoggerFactory.getLogger(WordTemplateUtils.class);
    /*
     * 根据Word模板生成word文档
     * @param uploadPath    文件夹路径
     * @param writePath     生成word文件路径
     * @param templatePath  word模板路径
     * @param contentMap    填充数据
     */
    public static boolean writeWordByTemplate(String uploadPath, String writePath,  String  templatePath, Map<String, Object> contentMap) throws  Exception  {
        //如果文件夹不存在,新建文件夹
         File  file = new File(uploadPath);
        //如果路径不存在,新建
         if  (!file. exists () && !file.isDirectory()) {
            file.mkdirs();
        }
         boolean  result = false;
        logger.info("---根据模板生成word文档");
        XWPF Document  document = new XWPFDocument(new FileInputStream(templatePath));
        if (document == null) {
            logger.error("---模板文件不存在,tempPath:{}", templatePath);
            return result;
        }
         InputStream  is = null;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(writePath);
            WordTemplateUtils.changeText(document, contentMap);
            //生成新的word文档
            document.write(fos);
            result = true;
        } catch (IOException e) {
            logger.error("---输出word文档失败,原因:{}", e.getMessage());
            result = false;
        } finally {
            if (is != null) {
                is.close();
            }
            if (fos != null) {
                fos.close();
            }
        }
        return result;
    }

    /**
     * 替换段落文本
     *
     * @param document docx解析对象
     * @param textMap  需要替换的信息集合
     */
    private static  void  changeText(XWPFDocument document, Map<String, Object> textMap) {
        //获取段落集合
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        for (XWPFParagraph paragraph : paragraphs) {
            //判断此段落时候需要进行替换
            String text = paragraph.getText();
            System.out.println(text);
            if (!text.equals("")) {
                List<XWPFRun> runs = paragraph.getRuns();
                for (XWPFRun run : runs) {
                    String textR = run.getText(0);//读取的模板段落
                    if (StringUtils.isEmpty(textR)) {
                        continue;
                    }
                    String newTxetR = "";
                    //判断文本是否需要进行替换
                    // System.out.print(textR + ",");
                    for (Map.Entry<String, Object> entry : textMap.entrySet()) {
                        //匹配模板与替换值 格式${key}
                        String key = entry.getKey();
                        Object value = entry.getValue();

                        if (textR.contains(key)) {//
                            if (value instanceof String) { //文字替换
                                String inputText = value.toString();
                                if (inputText.contains("n")) {//包含换行符
                                    String[] lines = inputText.split("n");
                                    //newTxetR = textR.replace(key, lines[0]);
                                    run.setText(lines[0].trim(), 0); // set first line into XWPFRun
                                    for (int i = 1; i < lines.length; i++) {
                                        // add break and insert new text
                                        run.addBreak();//换行
                                        run.addTab();//缩进
                                        run.setText(lines[i].trim());
                                    }
                                } else {
                                    newTxetR = textR.replace(key, (String) value);
                                    //替换模板原来位置
                                    if (!newTxetR.equals("")) {
                                        run.setText(newTxetR, 0);
                                    }
                                }
                            } else if (value instanceof Map) { //图片替换
                                newTxetR = textR.replace(key, "");
                                //替换模板原来位置
                                if (!newTxetR.equals("")) {
                                    run.setText(newTxetR, 0);
                                }
                                Map picMap = (Map) value;
                                int width = Integer.parseInt(picMap.get("width").toString());
                                int height = Integer.parseInt(picMap.get("height").toString());
                                int picType = getPictureType(picMap.get("type").toString());
                                 FileInputStream  fis = (FileInputStream) picMap.get("content");
                                try {
                                    String blipId = document.addPictureData(fis, picType);
                                    int id = document.getNextPicNameNumber(picType);
                                    createPicture(id, blipId, width, height, run);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * @param id
     * @param blipId
     * @param width  宽
     * @param height 高
     *               //* @param paragraph  段落
     */
    private static void createPicture(int id, String blipId, int width, int height, XWPFRun xwpfRun) {
        final int EMU = 9525;
        width *= EMU;
        height *= EMU;
        CTInline inline = xwpfRun.getCTR().addNewDrawing().addNewInline();
        //CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline(); //在遍历run列表的时候,创建新的run有可能会导致报错
        String picXml = ""
                + "<a:graphic xmlns:a="#34;>"
                + "   <a:graphicData uri="#34;>"
                + "      <pic:pic xmlns:pic="#34;>"
                + "         <pic:nvPicPr>" + "            <pic:cNvPr id=""
                + id
                + "" name="Generated"/>"
                + "            <pic:cNvPicPr/>"
                + "         </pic:nvPicPr>"
                + "         <pic:blipFill>"
                + "            <a:blip r:embed=""
                + blipId
                + "" xmlns:r="#34;/>"
                + "            <a:stretch>"
                + "               <a:fillRect/>"
                + "            </a:stretch>"
                + "         </pic:blipFill>"
                + "         <pic:spPr>"
                + "            <a:xfrm>"
                + "               <a:off x="0" y="0"/>"
                + "               <a:ext cx=""
                + width
                + "" cy=""
                + height
                + ""/>"
                + "            </a:xfrm>"
                + "            <a:prstGeom prst="rect">"
                + "               <a:avLst/>"
                + "            </a:prstGeom>"
                + "         </pic:spPr>"
                + "      </pic:pic>"
                + "   </a:graphicData>" + "</a:graphic>";

        inline.addNewGraphic().addNewGraphicData();
        XmlToken xmlToken = null;
        try {
            xmlToken = XmlToken.Factory.parse(picXml);
        } catch (XmlException xe) {
            xe.printStackTrace();
        }
        inline.set(xmlToken);

        inline.setDistT(0);
        inline.setDistB(0);
        inline.setDistL(0);
        inline.setDistR(0);

        CTPositiveSize2D extent = inline.addNewExtent();
        extent.setCx(width);
        extent.setCy(height);

        CTNonVisualDrawingProps docPr = inline.addNewDocPr();
        docPr.setId(id);
        docPr.setName("docx_img_ " + id);
        docPr.setDescr("docx Picture");
    }

    /**
     * 根据图片类型,取得对应的图片类型代码
     *
     * @param picType
     * @return int
     */
    private static int getPictureType(String picType) {
        int res = XWPFDocument.PICTURE_TYPE_PICT;
        if (picType != null) {
            if (picType.equalsIgnoreCase("png")) {
                res = XWPFDocument.PICTURE_TYPE_PNG;
            } else if (picType.equalsIgnoreCase("dib")) {
                res = XWPFDocument.PICTURE_TYPE_DIB;
            } else if (picType.equalsIgnoreCase("emf")) {
                res = XWPFDocument.PICTURE_TYPE_EMF;
            } else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) {
                res = XWPFDocument.PICTURE_TYPE_JPEG;
            } else if (picType.equalsIgnoreCase("wmf")) {
                res = XWPFDocument.PICTURE_TYPE_WMF;
            }
        }
        return res;
    }


    public static void main(String[] args) throws Exception {
        Map<String, Object> contentMap = new HashMap<String, Object>();

        //组装文本参数
        contentMap.put("demo1", "示例1");
        contentMap.put("demo2", "示例2");
       
        String fileName = "demo.docx";
        WordTemplateUtils.writeWordByTemplate("D:wordfile", ""D:wordfile" + fileName, 
            "D:wordtemplatetemplate.docx", contentMap);
    }
}
复制代码  

word模板,可以是这样:

word模板数据填充并转pdf

最终生成的效果如下:

  • word转pdf工具类
 /**
 * Word或Excel 转Pdf 工具类
 *
 * 备注:需要引入 aspose-words-15.8.0-jdk16.jar / aspose-cells-8.5.2.jar
 */
public class PdfUtil {

    private static boolean getLicense() {
        boolean result = false;
        try {
            // license.xml应放在..WebRootWEB-INFclasses路径下
            InputStream is = PdfUtil.class.getClassLoader().getResourceAsStream("License.xml");
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * @param wordPath 需要被转换的word文件名
     * @param pdfPath  转换之后pdf的文件
     */
    public static void doc2pdf(String wordPath, String pdfPath) {
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try {
            long old = System.currentTimeMillis();
            File file = new File(pdfPath); //新建一个pdf文档
            FileOutputStream os = new FileOutputStream(file);
            Document doc = new Document(wordPath); //Address是将要被转化的word文档
            doc.save(os, com.aspose.words.SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            long now = System.currentTimeMillis();
            os.close();
            System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); //转化用时
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param excelPath 需要被转换的excel全路径带文件名
     * @param pdfPath   转换之后pdf的全路径带文件名
     */
    public static void excel2pdf(String excelPath, String pdfPath) {
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try {
            long old = System.currentTimeMillis();
            Workbook wb = new Workbook(excelPath);// 原始excel路径
            FileOutputStream fileOS = new FileOutputStream(new File(pdfPath));
            wb.save(fileOS, com.aspose.cells.SaveFormat.PDF);
            fileOS.close();
            long now = System.currentTimeMillis();
            System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); //转化用时
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

   

    public static void main(String[] args) {
        //word 和excel 转为pdf
        String fileName = "D:wordfiledemo.docx";
        String pdfPath = "D:wordpdfdemo..pdf";
        doc2pdf(filePaths, pdfPath);
    }
}
复制代码  

这里提供一下:License.xml文件

 <License>
    <Data>
        <Products>
            <Product>Aspose.Total for Java</Product>
            <Product>Aspose.Words for Java</Product>
        </Products>
        <EditionType>Enterprise</EditionType>
        <SubscriptionExpiry>20991231</SubscriptionExpiry>
        <LicenseExpiry>20991231</LicenseExpiry>
        <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
    </Data>
    <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>  

好了,这个就是word转pdf的 示例 ,也是比较 简单 啦!!!

好了,word转pdf,大概的实现,就是这样了!!!^_^

那我们就可以愉快的编写代码了!!!^_^

作者:llsydn
链接:

文章来源:智云一二三科技

文章标题:word模板数据填充并转pdf

文章地址:https://www.zhihuclub.com/189563.shtml

关于作者: 智云科技

热门文章

网站地图