Make writing a habit together! This is the 16th day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

Word template data is filled and converted to PDF

Problem Background Description

When we are working on a project, we may encounter the need to generate a PDF file based on business data and then provide it for users to download and view.

To generate a PDF file, there are several possible ways to do this:

  • 1. According toHTML templateFill the data into the HTML template to generate a PDF file
  • 2. According toPDF template, fill the data into the PDF template to generate a PDF file
  • 3. According towordTemplate, fill the data into the Word template to generate a PDF file

The three implementations are compared:

The first implementation, the HTML code, will cause some style to be lost and will not work well. (Not recommended)

The second implementation is cumbersome, requires a lot of code, and the result is not very friendly. (Difficult, not recommended)

The third kind of realization, this kind of realization, is a kind of way that the individual feels better at present, the style, the realization also can accept!!

Above, represent personal viewpoint only, there may be wrong place, do not spray, or light spray!!

That today we focus on the discussion of the first 3 ways to achieve!! ^_^

Word to PDF instructions

At present, word to PDF, we can use OpenOffice to help us achieve this function.

If there is a but, after all, you have to use OpenOffice, which is a tool, then we will have to deploy and run the program, so that will not aggravate our server deployment and operation.

So here, we still have to think about, is there another easy way to do this? 😅

Ha ha, that is certainly some, we can through the pure code way, realize word to PDF function!!

Below see elder brother operation!! ^_^

Word to PDF implementation

  • Word template data filling utility class
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文档");
        XWPFDocument 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="http://schemas.openxmlformats.org/drawingml/2006/main">"
                + "   <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">"
                + "      <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">"
                + "         <pic:nvPicPr>" + "            <pic:cNvPr id=""
                + id
                + "" name="Generated"/>"
                + "            <pic:cNvPicPr/>"
                + "         </pic:nvPicPr>"
                + "         <pic:blipFill>"
                + "            <a:blip r:embed=""
                + blipId
                + "" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"/>"
                + "            <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:\word\file", ""D:\word\file\" + fileName, 
            "D:\word\template\template.docx", contentMap);
    }
}
Copy the code

A Word template can look like this:

The resulting effect looks like this:

  • Word to PDF tool class
Jar */ public class PdfUtil {/** * public class PdfUtil {/** * public class PdfUtil {/** * public class PdfUtil { private static boolean getLicense() { boolean result = false; Try {// license.xml should be placed in.. / WebRoot/WEB - INF \ classes directory path 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 pdfPath */ @param pdfPath */ public static void doc2pdf(String wordPath, String pdfPath) { if (! GetLicense ()) {// Verify the License. If the License is not verified, the converted PDF document will have a watermark and return; } try { long old = System.currentTimeMillis(); File file = new File(pdfPath); FileOutputStream OS = new FileOutputStream(file); Document doc = new Document(wordPath); / / Address is going to be transmuted word document doc. Save (OS, com. Aspose. Words. SaveFormat. PDF); Long now = system.currentTimemillis (); currentTimeMillis(); os.close(); System. The out. Println (" took: "+ (1000.0) (now - old) / +" seconds "); } catch (Exception e) {e.printStackTrace(); }} /** * @param excelPath Excel full path file name * @param pdfPath CONVERTED PDF full path file name */ public static void excel2pdf(String) excelPath, String pdfPath) { if (! GetLicense ()) {// Verify the License. If the License is not verified, the converted PDF document will have a watermark and return; } try { long old = System.currentTimeMillis(); Workbook wb = new Workbook(excelPath); FileOutputStream fileOS = new FileOutputStream(new File(pdfPath)); wb.save(fileOS, com.aspose.cells.SaveFormat.PDF); fileOS.close(); long now = System.currentTimeMillis(); System. The out. Println (" took: "+ (1000.0) (now - old) / +" seconds "); } catch (Exception e) {e.printStackTrace(); }} public static void main(String[] args) {//word and excel to PDF String fileName = "D: word file\demo.docx"; String pdfPath = "D:\word\pdf\demo.. pdf"; doc2pdf(filePaths, pdfPath); }}Copy the code

Here’s the License. XML file

<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/2IRfqwnPf8itN8aFZlV3TJPYeD3 yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature> </License>Copy the code

Here are the required JAR files

Download address

Ok, this is the example of word to PDF, is relatively simple!!

Ok, word to PDF, probably realized, that’s it!! ^_^

Then we can have fun writing code!! ^_^