POI填充word文字和图表

模板下载路径:https://download.csdn.net/download/junlong750/12805599

package com.mlogcn.wuhan.utils;

import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xwpf.usermodel.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

/**
 * @author longjun
 * @date 2020/8/21 - 16:37
 * @description: POI填充word文字和图表
 */
public class WordUtil {
    public static void main(String[] args) throws Exception {
//        String templatePath = "C:\\Users\\Administrator\\Desktop\\高影响天气模板2.docx";
//        InputStream is = new FileInputStream(new File(templatePath))
        InputStream is = WordUtil.class.getResourceAsStream("/template/高影响天气模板.docx");
        XWPFDocument doc = new XWPFDocument(is);

        //模拟统计图数据
        //系列
        String[] seriesTitles = {"风速(m/s)", "温度(℃)", "湿度(%)"};
        //x轴
        String[] categories = {"2020-02-20", "2020-02-21", "2020-02-22", "2020-02-23", "2020-02-24", "2020-02-25", "2020-02-26"};
        List<Number[]> values = new ArrayList<>();
        //风速
        Number[] value1 = {17, 15.8, 5, 8.9, 11, 25, 36};
        //温度
        Number[] value2 = {25.5, 35.5, 28.6, 25.2, 28.9, 38.9, 25.5};
        //湿度
        Number[] value3 = {100, 50, 80, 70, 80, 65, 80};

        values.add(value1);
        values.add(value2);
        values.add(value3);

        XWPFChart xChart = doc.getCharts().get(0);//获取第1个图表
        generateChart(xChart, seriesTitles, categories, values, "实况天气折线图");

        Map<String, String> data = new HashMap<>();
        data.put("${alarmSignal}", "大雾黄色预警信号");
        data.put("${alarmPublishTime}", "2020-07-29 03:09:00");
        data.put("${alarmPublishContent}", "如东县气象台2020年07月29日03时05分发布大雾黄色预警信号:预计今天早晨我县大部分地区将出现能见度不足500米的雾,能见度较低,请注意防范。");
        data.put("${alarmRelieveContent}", "如东县气象台2020年07月29日09时12分解除大雾黄色预警信号。");
        changeText(doc, data);

        OutputStream os = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\结果文件.docx");
        doc.write(os);
        close(os);
        close(is);
    }

    /**
     * 生成图表
     *
     * @param chart      从模板中获取到的图表
     * @param series     图例
     * @param categories X轴
     * @param values     数据
     * @param chartTitle 图标名称
     */
    public static void generateChart(XWPFChart chart, String[] series, String[] categories, List<Number[]> values, String chartTitle) {
        List<XDDFChartData> chartSeries = chart.getChartSeries();//不知道这个ChartSeries代表什么意思
        //final XDDFLineChartData line = (XDDFLineChartData) data.get(0);//这里一般获取第一个,我们这里是折线图就是XDDFLineChartData
        for (XDDFChartData chartData : chartSeries) {
            XDDFLineChartData line = (XDDFLineChartData) chartData;
            final int numOfPoints = categories.length;
            final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
            final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
            for (int i = 0; i < values.size(); i++) {
                final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, i + 1, i + 1));
                Number[] value = values.get(i);
                final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(value, valuesDataRange, i + 1);
                XDDFChartData.Series ser;//图表中的系列
                ser = line.getSeries().get(i);
                ser.replaceData(categoriesData, valuesData);
                CellReference cellReference = chart.setSheetTitle(series[i], 1);//修改系列标题
                ser.setTitle(series[i], cellReference);
            }
            chart.plot(line);
            chart.setTitleText(chartTitle);//折线图标题
            chart.setTitleOverlay(false);
        }

    }

    /**
     * 替换段落文本
     *
     * @param document docx解析对象
     * @param map      需要替换的信息集合
     */
    public static void changeText(XWPFDocument document, Map<String, String> map) {

        /**
         * 替换段落中的指定文字
         */
        Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();
        while (itPara.hasNext()) {
            XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
            Set<String> set = map.keySet();
            Iterator<String> iterator = set.iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                List<XWPFRun> runList = paragraph.getRuns();
                for (int i = 0; i < runList.size(); i++) {
                    XWPFRun xwpfRun = runList.get(i);
//                    int fontSize = xwpfRun.getFontSize();//获取原本的字体大小
//                    String color = xwpfRun.getColor();//获取原本的字体颜色
//                    String fontFamily = xwpfRun.getFontFamily();//获取原本的字体
                    String text = xwpfRun.getText(0);
                    for (Map.Entry<String, String> e : map.entrySet()) {
                        if (text != null && text.contains(e.getKey())) {
                            text = text.replace(e.getKey(), e.getValue());
                            //run.get(i).setText(text,0);
                            paragraph.removeRun(0);
                            XWPFRun xWPFRun = paragraph.createRun();
                            xWPFRun.setText(text, 0);
                        }
                    }
                }
            }
        }

        /**
         * 替换表格中的指定文字
         */
        Iterator<XWPFTable> itTable = document.getTablesIterator();
        while (itTable.hasNext()) {
            XWPFTable table = (XWPFTable) itTable.next();
            int count = table.getNumberOfRows();
            for (int i = 0; i < count; i++) {
                XWPFTableRow row = table.getRow(i);
                List<XWPFTableCell> cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    for (Map.Entry<String, String> e : map.entrySet()) {
                        if (cell.getText().equals(e.getKey())) {
                            cell.removeParagraph(0);
                            cell.setText(e.getValue());
                        }
                    }
                }
            }
        }
    }

    /**
     * 关闭输入流
     *
     * @param is
     */
    private static void close(InputStream is) {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭输出流
     *
     * @param os
     */
    public static void close(OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

最终效果

Poi Word 中插入图表,可以使用以下步骤: 1. 创建一个空白文档并打开它。 2. 创建一个 XWPFDocument 对象,用于在文档中插入图表。 ```java XWPFDocument document = new XWPFDocument(); ``` 3. 创建一个 XWPFChart 对象,并设置图表的类型、数据源和标题。 ```java XWPFChart chart = document.createChart(ChartTypes.LINE, new XDDFChartAxisPosition(), new XDDFChartAxisPosition(), 0, 0, 600, 400); XDDFDataSource<String> xs = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(0, 0, 0, data[0].length - 1)); XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, data[0].length - 1)); XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, data[0].length - 1)); chart.setTitleText("Line Chart"); chart.setTitleOverlay(false); XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis); XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1); XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs, ys2); series1.setTitle("Series 1", null); series2.setTitle("Series 2", null); chart.plot(data); ``` 4. 将图表插入到文档中指定的位置。 ```java XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); String blipId = document.addPictureData(new FileInputStream(chartFile), Document.PICTURE_TYPE_PNG); CTInline inline = run.getCTR().addNewDrawing().addNewInline(); CTGraphicalObject graphicalObject = inline.addNewGraphic(); CTGraphicData graphicData = graphicalObject.addNewGraphicData(); graphicData.setUri(GraphicData.URI_PICTURES + blipId); inline.setDistT(0); inline.setDistB(0); inline.setDistL(0); inline.setDistR(0); ``` 其中,chartFile 是保存图表的文件路径。 完整的代码示例: ```java import java.io.FileInputStream; import java.io.FileOutputStream; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xddf.usermodel.chart.*; import org.apache.poi.xddf.usermodel.chart.XDDFChartAxisPosition; import org.apache.poi.xwpf.usermodel.*; public class InsertChartExample { public static void main(String[] args) throws Exception { // 创建一个空白文档并打开它 XWPFDocument document = new XWPFDocument(); // 创建一个表格,并在其中填充数据 XWPFTable table = document.createTable(); String[][] data = new String[][]{{"Month", "Sales 1", "Sales 2"}, {"Jan", "10.0", "20.0"}, {"Feb", "20.0", "30.0"}, {"Mar", "30.0", "40.0"}}; for (int i = 0; i < data.length; i++) { XWPFTableRow row = table.getRow(i); for (int j = 0; j < data[i].length; j++) { XWPFTableCell cell = row.getCell(j); if (cell == null) { cell = row.createCell(); } cell.setText(data[i][j]); } } // 在表格下面插入一个段落,用于插入图表 XWPFParagraph paragraph = document.createParagraph(); // 创建一个图表,并设置图表的类型、数据源和标题 XWPFChart chart = document.createChart(ChartTypes.LINE, new XDDFChartAxisPosition(), new XDDFChartAxisPosition(), 0, 0, 600, 400); XSSFChart xssfChart = (XSSFChart) chart.getPackagePart().getPackage().createRelationship(XSSFRelation.CHART, XSSFRelation.NS_SPREADSHEETML, generateChartName(document)).getDocumentPart(); XSSFSheet sheet = xssfChart.getWorkbook().createSheet("Sheet1"); for (int i = 0; i < data.length; i++) { XSSFRow row = sheet.createRow(i); for (int j = 0; j < data[i].length; j++) { XSSFCell cell = row.createCell(j); if (i == 0) { cell.setCellValue(data[i][j]); } else { cell.setCellValue(Double.parseDouble(data[i][j])); } } } XDDFDataSource<String> xs = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(0, 0, 0, data[0].length - 1)); XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, data[0].length - 1)); XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, data[0].length - 1)); chart.setTitleText("Line Chart"); chart.setTitleOverlay(false); XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); bottomAxis.setTitle("Month"); XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); leftAxis.setTitle("Sales"); XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis); XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1); XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs, ys2); series1.setTitle("Series 1", null); series2.setTitle("Series 2", null); chart.plot(data); // 将图表插入到文档中指定的位置 XWPFRun run = paragraph.createRun(); String blipId = document.addPictureData(new FileInputStream("chart.png"), Document.PICTURE_TYPE_PNG); CTInline inline = run.getCTR().addNewDrawing().addNewInline(); CTGraphicalObject graphicalObject = inline.addNewGraphic(); CTGraphicData graphicData = graphicalObject.addNewGraphicData(); graphicData.setUri(GraphicData.URI_PICTURES + blipId); inline.setDistT(0); inline.setDistB(0); inline.setDistL(0); inline.setDistR(0); // 将文档保存到文件中 FileOutputStream out = new FileOutputStream("document.docx"); document.write(out); out.close(); document.close(); } private static String generateChartName(XWPFDocument document) { int i = 1; while (document.getPackagePart().getRelationshipsByType(XSSFRelation.CHART, XSSFRelation.NS_SPREADSHEETML).size() > 0) { String name = "Chart" + i; if (document.getPackagePart().getRelationshipsByType(XSSFRelation.CHART, XSSFRelation.NS_SPREADSHEETML).stream().anyMatch(r -> r.getTargetURI().toString().endsWith(name + ".xml"))) { i++; } else { return name; } } return "Chart1"; } } ``` 其中,chart.png 是保存图表的文件,需要先将图表保存为图片。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值