word docx 文件替换变量 并 转换为 pdf

package com.zhj.zw.backend.service;

import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import com.zkj.zw.backend.util.WordUtils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

/**
 * docx 直接生成 pdf
 *
 * @author: hzq
 * @date: 2022/5/19
 */
public class DocxTemplateToPdfTest {

    public static void main(String[] args) {
        try {
            // 加载word文档
            XWPFDocument xwpfDocument = new XWPFDocument(OPCPackage.open("E:\\msxf\\2022\\doc\\test\\doc_template.docx"));
            // 替换word变量
            WordUtils.replaceInPara(xwpfDocument, new HashMap<String,Object>());
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            xwpfDocument.write(byteArrayOutputStream);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            // 去除水印
            if (!WordUtils.getLicense())
                return;
            // 转换并保存为pdf
            Document document = new Document(byteArrayInputStream);
            document.save("E:/msxf/2022/doc/test/new_doc_template.pdf", SaveFormat.PDF);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 WordUtils.java

package com.zkj.zw.backend.util;

import com.aspose.words.License;
import lombok.experimental.UtilityClass;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDLbls;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: hzq
 * @date: 2022/5/18
 */
@UtilityClass
public class WordUtils {

    /**
     * 替换文档中的内容
     *
     * @param doc    Word的文档
     * @param params 待填充的数据
     *               params.put("key",value) 文档中对应为 ${key}
     */
    public void replaceInPara(XWPFDocument doc, Map<String, Object> params) {
        Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
        while (iterator.hasNext()) {
            replaceInPara(iterator.next(), params);
        }
    }


    /**
     * 遍历所有表格,替换表格里面的变量
     *
     * @param doc    要替换的文档
     * @param params 参数
     */
    public void replaceInAllTable(XWPFDocument doc, Map<String, Object> params) {
        Iterator<XWPFTable> iterator = doc.getTablesIterator();
        while (iterator.hasNext()) {
            replaceInTable(iterator.next(), params);
        }
    }

    /**
     * 替换指定表格中的变量
     *
     * @param doc
     * @param tabIndex 表格下标
     * @param params   替换参数
     */
    public void replaceInTable(XWPFDocument doc, int[] tabIndex, Map<String, Object> params) {
        List<XWPFTable> tables = doc.getTables();
        for (int index : tabIndex) {
            replaceInTable(tables.get(index), params);
        }
    }

    /**
     * 替换表格中的变量
     *
     * @param table
     * @param params
     */
    public void replaceInTable(XWPFTable table, Map<String, Object> params) {
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        List<XWPFParagraph> paras;
        //判断表格中是否有 ${} 有就表示需要替换值
        if (matcher(table.getText()).find()) {
            rows = table.getRows();
            for (XWPFTableRow row : rows) {
                cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    paras = cell.getParagraphs();
                    for (XWPFParagraph para : paras) {
                        replaceInPara(para, params);
                    }
                }
            }
        }
    }

    /**
     * 在表格中新增行数并填充数据
     *
     * @param table    需要插入数据的表格
     * @param rowDatas 插入数据集合(注:填充的数据要与单元格的数量保持一致)
     */
    public void insertTableRow(XWPFTable table, List<String[]> rowDatas) {
        for (String[] cellDatas : rowDatas) {
            XWPFTableRow row = table.createRow();
            List<XWPFTableCell> cells = row.getTableCells();
            for (int j = 0; j < cells.size(); j++) {
                cells.get(j).setText(cellDatas[j]);
            }
        }
    }

    /**
     * 替换段落里面的变量
     *
     * @param para   要替换的段落
     * @param params 参数
     */
    private void replaceInPara(XWPFParagraph para, Map<String, Object> params) {
        List<XWPFRun> runs;
        StringBuilder runText = new StringBuilder();
        if (matcher(para.getParagraphText()).find()) {
            runs = para.getRuns();
            int j = runs.size();
            for (int i = 0; i < j; i++) {
                runText.append(runs.get(0).toString());
                //保留最后一个段落,在这段落中替换值,保留原有段落样式
                if (!((j - 1) == i)) {
                    para.removeRun(0);
                }
            }
            String text = runText.toString();
            Matcher matcher;
            while ((matcher = matcher(text)).find()) {
                text = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1))));
            }
            runs.get(0).setText(text, 0);
        }
    }

    /**
     * 创建标题
     *
     * @param paragraph
     * @param data
     */
    public void createTitle(XWPFParagraph paragraph, String data) {
        XWPFRun createRun = paragraph.insertNewRun(0);
        createRun.setText(data);
        createRun.setFontFamily("宋体");
        createRun.setFontSize(14);
        createRun.setBold(true);
        paragraph.setSpacingAfter(10);
        paragraph.setSpacingBefore(10);
        //对齐方式
        paragraph.setAlignment(ParagraphAlignment.LEFT);
    }

    /**
     * 创建段落
     *
     * @param paragraph
     * @param data
     */
    public void createParagraph(XWPFParagraph paragraph, String data) {
        XWPFRun createRun = paragraph.createRun();
        createRun.setText(data);
        createRun.setFontFamily("宋体");
        createRun.setFontSize(12);

        paragraph.setFirstLineIndent(20);
        paragraph.setAlignment(ParagraphAlignment.BOTH);
        paragraph.setIndentationFirstLine(600);
        paragraph.setSpacingAfter(10);
        paragraph.setSpacingBefore(10);
    }

    /**
     * 创建表格
     *
     * @param document
     * @param tableList
     */
    public void createTable(XWPFDocument document, List<String[]> tableList) {
        XWPFTable table = document.createTable(tableList.size(), tableList.get(0).length);
        //设置表格的宽度
        CTTblWidth comTableWidth = table.getCTTbl().addNewTblPr().addNewTblW();
        comTableWidth.setType(STTblWidth.PCT);
        comTableWidth.setW(BigInteger.valueOf(5000));

        // 填充数据
        int length = tableList.size();
        for (int i = 0; i < length; i++) {
            XWPFTableRow row = table.getRow(i);
            List<XWPFTableCell> cells = row.getTableCells();
            for (int j = 0; j < cells.size(); j++) {
                cells.get(j).setText(tableList.get(i)[j]);
            }
        }

    }


    /**
     * 饼图
     *
     * @param document
     * @param title      图的标题
     * @param valueTitle 图种类名称
     * @param values     图种类的值
     */
    public void createPieChart(XWPFDocument document, String title, String[] valueTitle, Double[] values) throws IOException, InvalidFormatException {

        XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);
        // 标题
        chart.setTitleText(title);
        // 标题是否覆盖图表
        chart.setTitleOverlay(false);

        // 图例位置
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.TOP_RIGHT);

        XDDFCategoryDataSource categorys = XDDFDataSourcesFactory.fromArray(valueTitle);

        XDDFNumericalDataSource<Double> numerical = XDDFDataSourcesFactory.fromArray(values);

        XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);
        // 设置为可变颜色
        data.setVaryColors(true);
        // 图表加载数据
        data.addSeries(categorys, numerical);
        // 绘制
        chart.plot(data);

        CTDLbls dLbls = chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).addNewDLbls();
        dLbls.addNewShowVal().setVal(false);//不显示值
        dLbls.addNewShowLegendKey().setVal(false);
        dLbls.addNewShowCatName().setVal(true);//类别名称
        dLbls.addNewShowSerName().setVal(false);//不显示系列名称
        dLbls.addNewShowPercent().setVal(true);//显示百分比
        dLbls.addNewShowLeaderLines().setVal(true); //显示引导线

    }

    /**
     * 柱状图
     *
     * @param document
     * @param title      标题
     * @param xAxisTitle X轴标题
     * @param yAxisTitle Y轴标题
     * @param categorys  种类
     * @param values     值
     * @throws IOException
     * @throws InvalidFormatException
     */
    public void createBarChart(XWPFDocument document, String title, String xAxisTitle, String yAxisTitle, String[] categorys, Map<String, Number[]> values) throws IOException, InvalidFormatException {

        XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);
        // 标题
        chart.setTitleText(title);
        // 标题覆盖
        chart.setTitleOverlay(false);
        // 图例位置
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.TOP);
        legend.setOverlay(true);

        //X轴属性
        XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        xAxis.setTitle(xAxisTitle);

        // Y轴属性
        XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT);
        yAxis.setTitle(yAxisTitle);
        yAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        yAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

        XDDFChartData data = chart.createData(ChartTypes.BAR, xAxis, yAxis);
        data.setVaryColors(true);
        ((XDDFBarChartData) data).setBarDirection(BarDirection.COL); // 设置方向为竖状

        XDDFDataSource<String> categoriesData = XDDFDataSourcesFactory.fromArray(categorys);
        values.forEach((k, v) -> {
            XDDFChartData.Series series = data.addSeries(categoriesData, XDDFDataSourcesFactory.fromArray(v));
            series.setTitle(k, null);
        });
        chart.plot(data);


    }


    /**
     * 柱状图
     *
     * @param document
     * @param title      标题
     * @param xAxisTitle X轴标题
     * @param yAxisTitle Y轴标题
     * @param categorys  种类
     * @param values     值
     * @throws IOException
     * @throws InvalidFormatException
     */
    public void createLineChart(XWPFDocument document, String title, String xAxisTitle, String yAxisTitle, String[] categorys, Map<String, Number[]> values) throws IOException, InvalidFormatException {
        XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);

        // 标题
        chart.setTitleText(title);
        // 标题覆盖
        chart.setTitleOverlay(false);
        // 图例位置
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.TOP);
        legend.setOverlay(true);

        //X轴属性
        XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        xAxis.setTitle(xAxisTitle);

        //Y轴属性
        XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT);
        yAxis.setTitle(yAxisTitle);

        // 折线图,
        XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, xAxis, yAxis);

        XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray(categorys);
        // 加载数据
        values.forEach((k, v) -> {
            XDDFLineChartData.Series series = (XDDFLineChartData.Series) data.addSeries(countries, XDDFDataSourcesFactory.fromArray(v));
            series.setTitle(k, null); // 折线图例标题
            series.setMarkerStyle(MarkerStyle.CIRCLE); // 设置标记样式
        });
        // 绘制
        chart.plot(data);
    }

    /**
     * 柱状图
     *
     * @param document
     * @param title      标题
     * @param xAxisTitle X轴标题
     * @param yAxisTitle Y轴标题
     * @param categorys  种类
     * @param values     值
     * @throws IOException
     * @throws InvalidFormatException
     */
    public void createBarLineChart(XWPFDocument document, String title, String xAxisTitle, String yAxisTitle, String[] categorys, Map<String, Number[]> values) throws IOException, InvalidFormatException {
        XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);

        // 标题
        chart.setTitleText(title);
        // 标题覆盖
        chart.setTitleOverlay(false);
        // 图例位置
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.TOP);
        legend.setOverlay(true);

        //X轴属性
        XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        xAxis.setTitle(xAxisTitle);

        //Y轴属性
        XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT);
        yAxis.setTitle(yAxisTitle);
        yAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        yAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

        // 折线图,
        XDDFLineChartData lineData = (XDDFLineChartData) chart.createData(ChartTypes.LINE, xAxis, yAxis);
        // 柱状图
        XDDFChartData barData = chart.createData(ChartTypes.BAR, xAxis, yAxis);
        barData.setVaryColors(true);
        ((XDDFBarChartData) barData).setBarDirection(BarDirection.COL); // 设置方向为竖状

        XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray(categorys);
        // 加载数据
        values.forEach((k, v) -> {
            XDDFChartData.Series barSeries = barData.addSeries(countries, XDDFDataSourcesFactory.fromArray(v));
            barSeries.setTitle(k, null);
            XDDFLineChartData.Series lineSeries = (XDDFLineChartData.Series) lineData.addSeries(countries, XDDFDataSourcesFactory.fromArray(v));
            lineSeries.setTitle(k, null); // 折线图例标题
            lineSeries.setMarkerStyle(MarkerStyle.CIRCLE); // 设置标记样式
        });
        // 绘制
        chart.plot(lineData);
        chart.plot(barData);
    }

    /**
     * 正则匹配字符串
     *
     * @param str
     * @return
     */
    private Matcher matcher(String str) {
        Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(str);
        return matcher;
    }

    /**
     * 获取license 去除水印
     */
    public boolean getLicense() {
        boolean result = false;
        try (InputStream is = WordUtils.class.getClassLoader().getResourceAsStream("license.xml")) {
            License license = new License();
            license.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}


 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>

            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>4.1.2</version>
            </dependency>

            
            <!-- pdf工具 -->
            <dependency>
                <groupId>com.aspose</groupId>
                <artifactId>aspose-words</artifactId>
                <version>15.8.0</version>
            </dependency>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值