springBoot+poi+aspose实现根据word模板生成文件并转换pdf

  1. Maven依赖

    <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>net.sf.jxls</groupId>
            <artifactId>jxls-core</artifactId>
            <version>1.0.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.poi.xwpf.converter.pdf-gae</artifactId>
            <version>2.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aspose.words</groupId>
            <artifactId>aspose-words</artifactId>
            <version>19.5</version>
        </dependency>
    
  2. aspose需要下载jar包(需要可以联系博主)

  3. license.xml(去除aspose的水印),放在resource目录下即可

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

    springBoot+poi+aspose实现根据word模板生成文件并转换pdf_第1张图片

  4. 部分关键代码
    调用生成word方法

    //data替换固定文本集合,2博主自用,int[]模板内有多少个表格
    generatePdf(data, 2, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8}, enPdfPath, LanguageTypeEnum.en_US.getType(), 0);
    

    获取模板并调用生成word方法

    private void generateZhCNPdf(PdfDTO pdfDTO) {
        Map<String, Object> data = pdfDTO.getData();
        File file;
        InputStream is;
        file = new File(this.getClass().getResource("/template/temp.docx").getPath());
        is = Thread.currentThread().getContextClassLoader().getResourceAsStream("template/temps.docx");
        List<List<String[]>> mapList = pdfDTO.getMapList();
        int[] placeList = pdfDTO.getPlaceList();
        String pdfPath = pdfDTO.getPdfPath();
        String str = pdfPath.substring(0, pdfPath.lastIndexOf("/"));
        //判断文件夹是否存在
        File file1 = new File(str);
        if (!file1.exists() && !file1.isDirectory()) {
            file1.mkdirs();
        }
        new Thread() {
            @SneakyThrows
            @Override
            public void run() {
                extractedZhCn(data,  file, is, mapList, placeList, pdfPath);
            }
        }.start();
    }
    

    生成word

     		//临时存储文件,本地运行,需要注释该行
            FileUtils.copyInputStreamToFile(is, file);
            Thread.sleep(1000);
            //data固定填充内容map集合,file.getPath()模板地址,mapList需要循环填充表格的内容 placelist创建多少个表格的int[]
            CustomXWPFDocument doc = WorderToNewWordUtils.changWord(file.getPath(), data, mapList, placeList);
            //生成临时word文档
            FileOutputStream fopts = new FileOutputStream(pdfPath + ".docx");
            doc.write(fopts);
            fopts.close();
    

    changWord方法(填充数据)

    	CustomXWPFDocument document = null;
        try {
            //获取docx解析对象
            document = new CustomXWPFDocument(POIXMLDocument.openPackage(inputUrl));
            //解析替换文本段落对象
            WorderToNewWordUtils.changeText(document, textMap);
            //解析替换表格对象
            WorderToNewWordUtils.changeTable(document, textMap, mapList,placeList);
    
    
        } catch (IOException e) {
            e.printStackTrace();
        }
        return document;
    

    changText()

     	public static void changeText(CustomXWPFDocument document, Map<String, Object> textMap){
        //获取段落集合
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        for (XWPFParagraph paragraph : paragraphs) {
            paragraph.setAlignment(ParagraphAlignment.LEFT);
            //判断此段落时候需要进行替换
            String text = paragraph.getText();
            if(checkText(text)){
    
                List<XWPFRun> runs = paragraph.getRuns();
                for (XWPFRun run : runs) {
                    // 替换模板原来位置
                    run.setText(changeValue(run.text(), textMap), 0);
                }
            }
        }
    }
    
    	 /**
         * 判断文本中时候包含$
         * @param text 文本
         * @return 包含返回true,不包含返回false
         */
        public static boolean checkText(String text){
            boolean check  =  false;
            if(text.indexOf("$")!= -1){
                check = true;
            }
            return check;
        }
        /**
         * 匹配传入信息集合与模板
         * @param value 模板需要替换的区域
         * @param textMap 传入信息集合
         * @return 模板需要替换区域信息集合对应值
         */
       	public static String changeValue(String value, Map<String, Object> textMap) {
            Set<Map.Entry<String, Object>> textSets = textMap.entrySet();
            for (Map.Entry<String, Object> textSet : textSets) {
                // 匹配模板与替换值 格式${key}
                String key = textSet.getKey() ;
                if (value.indexOf(key) != -1) {
                    if(textSet.getValue() != null){
                        value = textSet.getValue().toString();
                    }
    
                }
            }
            // 模板未匹配到区域替换为空
            if (checkText(value)) {
                value = "";
            }
            return value;
    }
    

    changeTable(填充循环数据)

     public static void changeTable(CustomXWPFDocument document, Map<String, Object> textMap, List<List<String[]>> mapList,int[] placeList){
        //获取表格对象集合
        List<XWPFTable> tables = document.getTables();
    
        //循环所有需要进行替换的文本,进行替换
        for (int i = 0; i < tables.size(); i++) {
            XWPFTable table = tables.get(i);
            if(checkText(table.getText())){
                List<XWPFTableRow> rows = table.getRows();
                System.out.println("简单表格替换:"+rows);
                //遍历表格,并替换模板
                eachTable(document,rows, textMap);
            }
        }
        int index=0;
        //操作word中的表格
        for (int i = 0; i < tables.size(); i++) {
            //只处理行数大于等于2的表格,且不循环表头
            XWPFTable table = tables.get(i);
            if(placeList != null){
                if(placeList[index]==i){
                    List<String[]> list = mapList.get(index);
                    //第二个表格使用daList,插入数据
                    if (null != list && 0 < list.size()){
                        insertTable(table, null,list,2);
                        List<Integer[]> indexList = startEnd(list);
                        for (int c=0;c<indexList.size();c++){
                            //合并行
                            mergeCellVertically(table,0,indexList.get(c)[0]+1,indexList.get(c)[1]+1);
                        }
                    }
                    if(placeList.length > (index+1)){
                        index++;
                    }
                }
            }
    
        }
    }
        /**
     * 合并行
     * @param table
     * @param col 需要合并的列
     * @param fromRow 开始行
     * @param toRow 结束行
     */
    public static void mergeCellVertically(XWPFTable table, int col, int fromRow, int toRow) {
        for(int rowIndex = fromRow; rowIndex <= toRow; rowIndex++){
            CTVMerge vmerge = CTVMerge.Factory.newInstance();
            vmerge.setVal(STMerge.RESTART);
            XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
            CTTcPr tcPr = cell.getCTTc().getTcPr();
            if (tcPr != null) {
                tcPr.setVMerge(vmerge);
            } else {
                tcPr = CTTcPr.Factory.newInstance();
                tcPr.setVMerge(vmerge);
                cell.getCTTc().setTcPr(tcPr);
            }
        }
    }
    /**
     * 遍历表格
     * @param rows 表格行对象
     * @param textMap 需要替换的信息集合
     */
    public static void eachTable(CustomXWPFDocument document, List<XWPFTableRow> rows , Map<String, Object> textMap){
        for (XWPFTableRow row : rows) {
            List<XWPFTableCell> cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {
                //判断单元格是否需要替换
                if(checkText(cell.getText())){
                    List<XWPFParagraph> paragraphs = cell.getParagraphs();
                    for (XWPFParagraph paragraph : paragraphs) {
                        paragraph.setAlignment(ParagraphAlignment.LEFT);
                        paragraph.setKeepNext(false);
                        List<XWPFRun> runs = paragraph.getRuns();
                        for (XWPFRun run : runs) {
                            Object ob = changeValue(run.toString(), textMap);
                            if (ob instanceof String){
                                run.setText((String)ob,0);
                            }else if (ob instanceof Map){
                                run.setText("",0);
                                Map pic = (Map)ob;
                                int width = Integer.parseInt(pic.get("width").toString());
                                int height = Integer.parseInt(pic.get("height").toString());
                                int picType = getPictureType(pic.get("type").toString());
                                byte[] byteArray = (byte[]) pic.get("content");
                                ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);
                                try {
                                    String blipId = document.addPictureData(byteInputStream,picType);
                                    document.addPictureToRun(run, blipId, document.getAllPictures().size() -1,width , height);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    /**
     * 为表格插入数据,行数不够添加新行
     * @param table 需要插入数据的表格
     * @param tableList 第四个表格的插入数据
     * @param daList 第二个表格的插入数据
     * @param type 表格类型:1-第一个表格 2-第二个表格 3-第三个表格 4-第四个表格
     */
    public static void insertTable(XWPFTable table, List<String> tableList,List<String[]> daList,Integer type){
        if (2 == type){
        	//设置表格边框样式
            table.setLeftBorder(XWPFTable.XWPFBorderType.NONE , 0 , 0 ,"FFFFFF");
            table.setRightBorder(XWPFTable.XWPFBorderType.NONE , 0 , 0 ,"FFFFFF");
            table.setTopBorder(XWPFTable.XWPFBorderType.NONE , 0 , 0 ,"FFFFFF");
            table.setInsideVBorder(XWPFTable.XWPFBorderType.NONE , 0 , 0 , "FFFFFF");
            table.setInsideHBorder(XWPFTable.XWPFBorderType.SINGLE,0,0,"BEBEBE");
            table.setBottomBorder(XWPFTable.XWPFBorderType.SINGLE,0,0,"BEBEBE");
             //创建行和创建需要的列
            for(int i = 1; i < daList.size(); i++){
                //添加一个新行
                XWPFTableRow row = table.insertNewTableRow(1);
                for(int k=0; k<daList.get(0).length;k++){
                    row.createCell();//根据String数组第一条数据的长度动态创建列
                    row.setCantSplitRow(true);
                }
    
            }
            //创建行,根据需要插入的数据添加新行,不处理表头
            for(int i = 0; i < daList.size(); i++){
                //合计行是否加粗
                boolean blods = false;
                List<XWPFTableCell> cells = table.getRow(i+1).getTableCells();
                for(int j = 0; j < cells.size(); j++){
                    //是否加粗合并
                    boolean blod = false;
                    //固定列是否合并
                    boolean mell = false;
                    XWPFTableCell cell02 = cells.get(j);
                    // 设置水平居中,需要ooxml-schemas包支持
                    CTTc cttc = cell02.getCTTc();
                    CTTcPr ctPr = cttc.addNewTcPr();
                    ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
                    // 修改字体大小
                    String s = daList.get(i)[j];
                    //获取 CTP
                    CTP ctP = (cttc.sizeOfPArray() == 0) ?
                            cttc.addNewP() : cttc.getPArray(0);
                    //getParagraph(ctP) 获取 XWPFParagraph
                    XWPFParagraph par = cell02.getParagraph(ctP);
                    CTP ctp = par.getCTP();
                    CTPPr ctpPr = ctp.isSetPPr() ? ctp.getPPr() : ctp.addNewPPr();
                    //设置行间距
                    CTSpacing spacing = ctpPr.isSetSpacing()? ctpPr.getSpacing() : ctpPr.addNewSpacing();
                    spacing.setAfter(BigInteger.valueOf(0));
                    spacing.setBefore(BigInteger.valueOf(0));
                    //注意设置行距类型为 EXACT
                    spacing.setLineRule(STLineSpacingRule.EXACT);
                    //1磅数是20
                    spacing.setLine(BigInteger.valueOf(360));
    
                    par.setAlignment(ParagraphAlignment.THAI_DISTRIBUTE);
                    par.setKeepNext(false);
                    Map<Object,Object> map = new HashMap<Object,Object>(1,0.70f);
                    Map<Object,Object> map1 = new HashMap<Object,Object>(map);
                    //par.setBorderTop();
                    //XWPFRun   设置格式
                    XWPFRun run = par.createRun();
                    //加粗
                    run.setBold(true);
                    run.setFontSize(10);
                    run.setText(s);
                    //设置字体
                    CTFonts font = run.getCTR().addNewRPr().addNewRFonts();
                    //中文
                    font.setEastAsia("思源");
                    // ASCII
                    font.setAscii("Poppins");
                    font.setCs("Poppins");
                    font.setHAnsi("Poppins");
                    if (run.getText(0) != null && run.getText(0).contains("\n")) {
                        String[] lines = run.getText(0).split("\n");
                        if (lines.length > 0) {
                            run.setText(lines[0], 0);
                            for (int n = 1; n < lines.length; n++) {
                                run.addBreak();
                                run.setText(lines[n]);
                            }
                        }
                    }
                  //合并列(合并的列内需要有值,会保留前一列的值)
                  mergeCellsHorizontal(table, i + 1, j + 2, j + 3);
                  //设置靠齐方向
                  par.setAlignment(ParagraphAlignment.RIGHT);
                   
                }
            }
        }else if (4 == type){
            //插入表头下面第一行的数据
            for(int i = 0; i < tableList.size(); i++){
                XWPFTableRow row = table.createRow();
                List<XWPFTableCell> cells = row.getTableCells();
                cells.get(0).setText(tableList.get(i));
            }
        }
    }
    //合并列方法
    public static void mergeCellsHorizontal(XWPFTable table, int row, int startCell, int endCell) {
        for (int i = startCell; i <= endCell; i++) {
            XWPFTableCell cell = table.getRow(row).getCell(i);
            if (i == startCell) {
                // The first merged cell is set with RESTART merge value
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
            }
            else {
                // Cells which join (merge) the first one, are set with CONTINUE
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
            }
        }
    }
    
  5. 转换pdf

    public static boolean zhCnWordToPDF(String sfileName, String toFileName) {
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return false;
        }
    
        FileOutputStream os = null;
        try {
            long old = System.currentTimeMillis();
            File file = new File(toFileName); // 新建一个空白pdf文档
            os = new FileOutputStream(file);
            Document document= new Document(sfileName); // Address是将要被转化的word文档
            Document document1 = new Document(toFileName);
            //设置pdf字体
            DocumentBuilder documentBuilder = new DocumentBuilder(document1);
            documentBuilder.getFont().setName("思源黑体 CN");
            documentBuilder.getFont().setNameAscii("Poppins");
            documentBuilder.getFont().setNameOther("Poppins");
            TableCollection tables = document.getFirstSection().getBody().getTables();
            for (Table table : tables) {
                RowCollection rows = table.getRows();
                table.setAllowAutoFit(false);
                for (Row row : rows) {
                    CellCollection cells = row.getCells();
                    for (Cell cell : cells) {
                        CellFormat cellFormat = cell.getCellFormat();
                        cellFormat.setFitText(false);
                        cellFormat.setWrapText(true);
                    }
                }
            }
            document.save(os, SaveFormat.PDF);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
            // EPUB, XPS, SWF 相互转换
            long now = System.currentTimeMillis();
            System.out.println("pdf转换成功,共耗时:" + ((now - old) / 1000.0) + "秒"); // 转化用时
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }finally {
            if (os != null) {
                try {
                    os.flush();
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }
    

    验证license

    public static boolean getLicense() {
            boolean result = false;
            InputStream is = null;
            try {
                Resource resource = new ClassPathResource("/license.xml");
                is = resource.getInputStream();
                License aposeLic = new License();
                aposeLic.setLicense(is);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return result;
        }
    

你可能感兴趣的:(模板生成,poi,spring,boot,java,后端)