JAVA poi生成折线图

JAVA poi生成折线图(数据有负数比较麻烦,暂时代码还没解决,打开文档的图表工具设置成“样式1”可解决)

导入依赖

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

一、不使用模板,直接生成word图表(可能会导致wps和office打开的格式不一样,甚至打不开,跟数据有一点的关系)

    @Test
    void test1() throws Exception {
        XWPFDocument document = new XWPFDocument();
        int charNum = 3; // 折线图数量
        for (int num = 0; num < charNum; num++) {
            // 设置标题
            setDocumentTitle(document, DocumentTitleEnum.H1.getCode(), "一级标题");
            setDocumentTitle(document, DocumentTitleEnum.H2.getCode(), "二级标题");
            setDocumentTitle(document, DocumentTitleEnum.H3.getCode(), "三级标题");
            setDocumentTitle(document, DocumentTitleEnum.P.getCode(), "正文标题");
            // 创建折线图
            XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);
            chart.setTitleText("多维度折线图" + (num + 1));
            chart.setTitleOverlay(false);
            XDDFChartLegend legend = chart.getOrAddLegend();
            legend.setPosition(LegendPosition.TOP);
            XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
            xAxis.setTitle("日期(年月)"); // X轴标题
            String[] xAxisData = new String[]{
                    "2021-01", "2021-02", "2021-03", "2021-04", "2021-05", "2021-06",
                    "2021-07", "2021-08", "2021-09", "2021-10", "2021-11", "2021-12"
            };
            XDDFCategoryDataSource xAxisSource = XDDFDataSourcesFactory.fromArray(xAxisData);

            XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT);
            yAxis.setTitle("粉丝数(个)"); // Y轴标题

            XDDFLineChartData lineChart = (XDDFLineChartData) chart.createData(ChartTypes.LINE, xAxis, yAxis);

            Integer[][] yAxisData = new Integer[][]{
                    {10, 35, -21, 46, 79, 88, 39, 102, 71, null, 99, 57},
                    {20, 25, 31, 56, null, null, 49, 92, 61, -18, 79, 67}
            };

            for (int i = 0; i < yAxisData.length; i++) {
                Integer[] data = yAxisData[i];
                XDDFNumericalDataSource<Integer> yAxisSource = XDDFDataSourcesFactory.fromArray(data);
                XDDFLineChartData.Series lineSeries1 = (XDDFLineChartData.Series) lineChart.addSeries(xAxisSource, yAxisSource);
                lineSeries1.setTitle("折线" + (i + 1), null);
                lineSeries1.setSmooth(true); // 设置线为圆弧
                lineSeries1.setMarkerStyle(MarkerStyle.NONE); // 折线点样式
            }
            // 设置空点跨越(不设置这个,空内容会自动设置为0)
            CTDispBlanksAs disp = CTDispBlanksAs.Factory.newInstance();
            disp.setVal(STDispBlanksAs.GAP);
            chart.getCTChart().setDispBlanksAs(disp);
            chart.plot(lineChart);
        }
        String date = DateUtil.now().replace("-","").replace(":", "").replace(" ", "");
        FileOutputStream fos = new FileOutputStream("C:\\Users\\admin\\Desktop\\LineChart" + date + ".docx");
        document.write(fos);
        fos.close();
        document.close();
    }

二、使用模板导出(模板里面有多少个图表,就只能导出多少个图标,不够灵活,好处是兼容wps和office)

public static void main(String[] args) throws Exception {

    final String returnurl = "C:\\Users\\admin\\Desktop\\新建文件夹\\barchartresult.docx";  // 结果文件
    final String templateurl = "E:\\poi-demo-master\\poi-demo\\src\\main\\resources\\barchart.docx";  // 模板文件

    InputStream is = new FileInputStream(new File(templateurl1));
    XWPFDocument doc = new XWPFDocument(is);

    // 替换word模板数据
    doCharts(doc);

    // 保存结果文件
    try {
        FileOutputStream fos = new FileOutputStream(templateurl1);
        doc.write(fos);
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * 处理图表
 *
 * @param doc
 * @throws FileNotFoundException
 */
public static void doCharts(XWPFDocument doc) throws Exception {
    /**----------------------------处理图表------------------------------------**/
    // 获取word模板中的所有图表元素,用map存放
    // 为什么不用list保存:查看doc.getRelations()的源码可知,源码中使用了hashMap读取文档图表元素,
    // 对relations变量进行打印后发现,图表顺序和文档中的顺序不一致,也就是说relations的图表顺序不是文档中从上到下的顺序
    List<String> keys = new ArrayList<>();
    Map<String, POIXMLDocumentPart> chartsMap = new HashMap<String, POIXMLDocumentPart>();
    //动态刷新图表
    List<POIXMLDocumentPart> relations = doc.getRelations();
    for (POIXMLDocumentPart poixmlDocumentPart : relations) {
        if (poixmlDocumentPart instanceof XWPFChart) {  // 如果是图表元素
            // 获取图表对应的表格数据里面的第一行第一列数据,可以拿来当作key值
            // String key = new PoiWordTools().getZeroData(poixmlDocumentPart);
            String str = poixmlDocumentPart.toString();
            String key = str.replaceAll("Name: ", "")
                    .replaceAll(" - Content Type: application/vnd\\.openxmlformats-officedocument\\.drawingml\\.chart\\+xml", "").trim();
            chartsMap.put(key, poixmlDocumentPart);
            keys.add(key);
        }
    }
    Collections.sort(keys);
    for (int i = 0; i < 3; i++) {
        doCharts(chartsMap.get(keys.get(i)));
    }
}

public static void doCharts(POIXMLDocumentPart poixmlDocumentPart) {
    // 数据准备
    List<String> titleArr = new ArrayList<String>();// 标题
    titleArr.add("");
    titleArr.add("折线1");
    titleArr.add("折线2");
    titleArr.add("折线3");

    List<String> fldNameArr = new ArrayList<String>();// 字段名(数据有多少列,就多少个)
    fldNameArr.add("item1");
    fldNameArr.add("item2");
    fldNameArr.add("item3");
    fldNameArr.add("item4");

    // 数据集合
    List<Map<String, String>> listItemsByType = new ArrayList<Map<String, String>>();

    // 数据的话随便整都行
    for (int i = 0; i < 9; i++) {
        // 第一行数据
        Map<String, String> base1 = new HashMap<String, String>();
        String[] array = {null, "1", "2", "3", "4", "5", "-6", "7", "8", "-9"};
        base1.put("item1", "2020-0"+(i+1));
        base1.put("item2", array[(int)(Math.random() * array.length)]);
        base1.put("item3", array[(int)(Math.random() * array.length)]);
        base1.put("item4", array[(int)(Math.random() * array.length)]);
        listItemsByType.add(base1);
    }
    new PoiWordTools().replaceLineCharts(poixmlDocumentPart, titleArr, fldNameArr, listItemsByType);
}

三、使用直接导出+模板(结合了两者的好处,导出的格式还会有一点问题,不过问题不大)

@Test
void test3() throws Exception {
    XWPFDocument document = new XWPFDocument();
    // 设置标题
    setDocumentTitle(document, DocumentTitleEnum.H1.getCode(), "一级标题");
    setDocumentTitle(document, DocumentTitleEnum.H2.getCode(), "二级标题");
    setDocumentTitle(document, DocumentTitleEnum.H3.getCode(), "三级标题");
    setDocumentTitle(document, DocumentTitleEnum.P.getCode(), "正文标题");
    for (int num = 0; num < chartList.size(); num++) {
        ChartData chartData = chartList.get(num);
        // 创建图表
        XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);

        // 设置折线图标题
        chart.setTitleText(chartData.getChartTitle());
        chart.setTitleOverlay(false);
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.TOP);

        // 设置X轴
        XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        xAxis.setPosition(AxisPosition.BOTTOM);
        xAxis.setTickLabelPosition(AxisTickLabelPosition.LOW); // 设置x轴文字在最下方
        xAxis.setMajorTickMark(AxisTickMark.NONE); // 设置主要刻度线样式
        String[] xAxisData = new String[]{};
        XDDFCategoryDataSource xAxisSource = XDDFDataSourcesFactory.fromArray(xAxisData);

        // 设置Y轴
        XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT);
        yAxis.setTitle(chartData.getYTitle()); // Y轴标题
        yAxis.setMajorTickMark(AxisTickMark.OUT); // 不显示刻度标签
        // 设置X轴在刻度线之间
        yAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        yAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

        // 设置图表为折线图
        XDDFLineChartData lineChart = (XDDFLineChartData) chart.createData(ChartTypes.LINE, xAxis, yAxis);
        lineChart.setVaryColors(true);

        // 生成图表
        chart.plot(lineChart);
    }
    // 生成一个临时的模板docx文件
    String templateUrl = "src/data/wordLineChartTemp.docx";
    FileOutputStream fos = new FileOutputStream(templateUrl);
    document.write(fos);
    fos.close();
    document.close();
    String date = DateUtil.now().replace("-","").replace(":", "").replace(" ", "");
    String resultUrl = "C:\\Users\\admin\\Desktop\\LineChart" + date + ".docx";
    updateTempFile(templateUrl, resultUrl);
}

/**
 * 处理并替换文档
 * @param templateUrl 模板文档路径
 * @param resultUrl 结果文档路径
 * @throws Exception
 */
private void updateTempFile(String templateUrl, String resultUrl) throws Exception{
    File file = new File(templateUrl);
    InputStream is = new FileInputStream(new File(templateUrl));
    XWPFDocument doc = new XWPFDocument(is);

    // 替换word模板数据
    repalceTempFile(doc);
    // 保存结果文件
    try {
        FileOutputStream fos = new FileOutputStream(resultUrl);
        doc.write(fos);
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // 删除模板文档
        is.close();
        file.delete();
    }
}

private void repalceTempFile(XWPFDocument doc) throws Exception {
    /**----------------------------处理图表------------------------------------**/
    // 获取word模板中的所有图表元素,用map存放
    // 为什么不用list保存:查看doc.getRelations()的源码可知,源码中使用了hashMap读取文档图表元素,
    // 对relations变量进行打印后发现,图表顺序和文档中的顺序不一致,也就是说relations的图表顺序不是文档中从上到下的顺序
    List<String> keys = new ArrayList<>();
    Map<String, POIXMLDocumentPart> chartsMap = new HashMap<String, POIXMLDocumentPart>();
    //动态刷新图表
    List<POIXMLDocumentPart> relations = doc.getRelations();
    for (POIXMLDocumentPart poixmlDocumentPart : relations) {
        if (poixmlDocumentPart instanceof XWPFChart) {  // 如果是图表元素
            // 获取图表对应的表格数据里面的第一行第一列数据,可以拿来当作key值
            // String key = new PoiWordTools().getZeroData(poixmlDocumentPart);
            String str = poixmlDocumentPart.toString();
            String key = str.replaceAll("Name: ", "")
                    .replaceAll(" - Content Type: application/vnd\\.openxmlformats-officedocument\\.drawingml\\.chart\\+xml", "").trim();
            chartsMap.put(key, poixmlDocumentPart);
            keys.add(key);
        }
    }
    Collections.sort(keys);
    for (int i = 0; i < keys.size(); i++) {
        doChart(chartsMap.get(keys.get(i)));
    }
}

private void doChart(POIXMLDocumentPart poixmlDocumentPart) {
    // 数据准备
    List<String> titleArr = new ArrayList<String>();// 标题
    titleArr.add("");
    titleArr.add("折线1");
    titleArr.add("折线2");
    titleArr.add("折线3");

    List<String> fldNameArr = new ArrayList<String>();// 字段名(数据有多少列,就多少个)
    fldNameArr.add("item1");
    fldNameArr.add("item2");
    fldNameArr.add("item3");
    fldNameArr.add("item4");

    // 数据集合
    List<Map<String, String>> listItemsByType = new ArrayList<Map<String, String>>();

    // 数据的话随便整都行
    for (int i = 0; i < 9; i++) {
        // 第一行数据
        Map<String, String> base1 = new HashMap<String, String>();
        String[] array = {"0", null, "2", "3", "4", "5", "-6", "7", "8", "-9"};
        base1.put("item1", "2020-0"+(i+1));
        base1.put("item2", array[(int)(Math.random() * array.length)]);
        base1.put("item3", array[(int)(Math.random() * array.length)]);
        base1.put("item4", array[(int)(Math.random() * array.length)]);
        listItemsByType.add(base1);
    }
    new PoiWordTools().replaceLineCharts(poixmlDocumentPart, titleArr, fldNameArr, listItemsByType);
}

四、需要的类

4、1 PoiWordTitle

/**
 * 更新图表的标题
 */
public class PoiWordTitle {

    public void setBarTitle(CTChart ctChart, String title) {
        CTTitle ctTitle = ctChart.getTitle();
        CTTx ctTx = ctTitle.getTx();
        if (null != ctTx) {
            CTTextBody ctTextBody = ctTx.getRich();
            List<CTTextParagraph> ctTextParagraphslist = ctTextBody.getPList();
            CTTextParagraph ctTextParagraph1 = ctTextParagraphslist.get(0);
            List<CTRegularTextRun> ctRegularTextRunslist = ctTextParagraph1.getRList();
            ctRegularTextRunslist.get(0).setT(title);  // 设置标题
        }
    }
}

4、2 PoiWordTools

/**
 * poi生成word的工具类
 * 针对于模板中的图表是静态的,也就是模板中的图表长什么样子不会根据数据而改变
 */
public class PoiWordTools {

    private static final BigDecimal bd2 = new BigDecimal("2");


    /**
     * 调用替换雷达图数据
     */
    public static void replaceRadarCharts(POIXMLDocumentPart poixmlDocumentPart,
                                          List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
        XWPFChart chart = (XWPFChart) poixmlDocumentPart;
        chart.getCTChart();

        //根据属性第一列名称切换数据类型
        CTChart ctChart = chart.getCTChart();
        CTPlotArea plotArea = ctChart.getPlotArea();

        // 设置标题
        // new PoiWordTitle().setBarTitle(ctChart, "我是雷达图标题");

        CTRadarChart radarChart = plotArea.getRadarChartArray(0);
        List<CTRadarSer> radarList = radarChart.getSerList();  // 获取雷达图单位

        //刷新内置excel数据
        new PoiWordTools().refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新页面显示数据
        refreshRadarStrGraphContent(radarChart, radarList, listItemsByType, fldNameArr, 1);


    }


    /**
     * 调用替换柱状图数据
     */
    public static void replaceBarCharts(POIXMLDocumentPart poixmlDocumentPart,
                                        List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
        XWPFChart chart = (XWPFChart) poixmlDocumentPart;
        chart.getCTChart();

        //根据属性第一列名称切换数据类型
        CTChart ctChart = chart.getCTChart();
        CTPlotArea plotArea = ctChart.getPlotArea();

        // 设置标题
        new PoiWordTitle().setBarTitle(ctChart, "我是修改后的标题");

        CTBarChart barChart = plotArea.getBarChartArray(0);
        List<CTBarSer> BarSerList = barChart.getSerList();  // 获取柱状图单位

        //刷新内置excel数据
        new PoiWordTools().refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新页面显示数据
        refreshBarStrGraphContent(barChart, BarSerList, listItemsByType, fldNameArr, 1);


    }


    /**
     * 调用替换折线图数据
     */
    public static void replaceLineCharts(POIXMLDocumentPart poixmlDocumentPart,
                                         List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
        XWPFChart chart = (XWPFChart) poixmlDocumentPart;
        chart.getCTChart();
        // chart.setTitleText(""); // 设置折线图标题
        // 设置空点跨越(不设置这个,空内容会自动设置为0)
        CTDispBlanksAs disp = CTDispBlanksAs.Factory.newInstance();
        disp.setVal(STDispBlanksAs.GAP);
        chart.getCTChart().setDispBlanksAs(disp);
        //根据属性第一列名称切换数据类型
        CTChart ctChart = chart.getCTChart();
        CTPlotArea plotArea = ctChart.getPlotArea();

        CTLineChart lineChart = plotArea.getLineChartArray(0);
        List<CTLineSer> lineSerList = lineChart.getSerList();   // 获取折线图单位
        //刷新内置excel数据
        new PoiWordTools().refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新页面显示数据
        new PoiWordTools().refreshLineStrGraphContent(titleArr, lineChart, lineSerList, listItemsByType, fldNameArr, 1);

    }


    /**
     * 调用替换饼图数据
     */
    public static void replacePieCharts(POIXMLDocumentPart poixmlDocumentPart,
                                        List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
        XWPFChart chart = (XWPFChart) poixmlDocumentPart;
        chart.getCTChart();

        //根据属性第一列名称切换数据类型
        CTChart ctChart = chart.getCTChart();
        CTPlotArea plotArea = ctChart.getPlotArea();

        CTPieChart pieChart = plotArea.getPieChartArray(0);
        List<CTPieSer> pieSerList = pieChart.getSerList();  // 获取饼图单位

        //刷新内置excel数据
        new PoiWordTools().refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新页面显示数据
        new PoiWordTools().refreshPieStrGraphContent(pieChart, pieSerList, listItemsByType, fldNameArr, 1);

    }


    /**
     * 调用替换柱状图、折线图组合数据
     */
    public static void replaceCombinationCharts(POIXMLDocumentPart poixmlDocumentPart,
                                                List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
        XWPFChart chart = (XWPFChart) poixmlDocumentPart;
        chart.getCTChart();

        //根据属性第一列名称切换数据类型
        CTChart ctChart = chart.getCTChart();
        CTPlotArea plotArea = ctChart.getPlotArea();


        CTBarChart barChart = plotArea.getBarChartArray(0);
        List<CTBarSer> barSerList = barChart.getSerList();  // 获取柱状图单位
        //刷新内置excel数据
        new PoiWordTools().refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新页面显示数据   数据中下标1开始的是柱状图数据,所以这个是1
        refreshBarStrGraphContent(barChart, barSerList, listItemsByType, fldNameArr, 1);


        CTLineChart lineChart = plotArea.getLineChartArray(0);
        List<CTLineSer> lineSerList = lineChart.getSerList();   // 获取折线图单位
        //刷新内置excel数据   有一个就可以了    有一个就可以了    有一个就可以了
        //new PoiWordTools().refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
        //刷新页面显示数据   数据中下标3开始的是折线图的数据,所以这个是3
        new PoiWordTools().refreshLineStrGraphContent(titleArr, lineChart, lineSerList, listItemsByType, fldNameArr, 3);

    }


    /**
     * 刷新折线图数据方法
     *
     * @param typeChart
     * @param serList
     * @param dataList
     * @param fldNameArr
     * @param position
     * @return
     */
    public static boolean refreshLineStrGraphContent(List<String> titleArr, Object typeChart,
                                                     List<?> serList, List<Map<String, String>> dataList, List<String> fldNameArr, int position) {

        boolean result = true;
        //更新数据区域
        for (int i = 0; i < titleArr.size() - 1; i++) {
            CTAxDataSource cat = null;
            CTNumDataSource val = null;
            CTLineSer ser = null;
            try {
                ser = ((CTLineChart) typeChart).getSerArray(i);
            } catch (Exception e) {
                ser = ((CTLineChart) typeChart).addNewSer();
            }
            // 设置标题
            CTSerTx tx = ser.getTx();
            if (tx == null){
                CTStrData ctStrData = ser.addNewTx().addNewStrRef().addNewStrCache();
                ctStrData.addNewPt();
                ctStrData.addNewPtCount().setVal(1L);
                ser.addNewCat().addNewStrRef().addNewStrCache().addNewPtCount();
                ser.addNewVal().addNewNumRef().addNewNumCache().addNewPtCount();
                ser.addNewIdx().setVal(i);
                ser.addNewOrder().setVal(i);
                ser.addNewSpPr().addNewLn().setW(28575);
                ser.addNewMarker().addNewSymbol().setVal(STMarkerStyle.NONE); // 设置折线点的样式
                ser.addNewSmooth().setVal(true); // 设置折线:true圆弧、false折线
                ser.addNewExtLst();
                tx = ser.getTx();
            }
            tx.getStrRef().getStrCache().getPtList().get(0).setV(titleArr.get(i + 1)); // 设置折线名称
            tx.getStrRef().getStrCache().getPtList().get(0).setIdx(0L); // 设置折线idx
            String StrRefF = "Sheet1!$" + getExcelCol(i + 2) + "$1";
            tx.getStrRef().setF(StrRefF); // 设置折线与图表绑定
            // 设置折线为圆弧
            ser.getSmooth().setVal(true);
            // Category Axis Data
            cat = ser.getCat();
            // 获取图表的值
            val = ser.getVal();
            // strData.set
            CTStrData strData = cat.getStrRef().getStrCache();
            CTNumData numData = val.getNumRef().getNumCache();
            strData.setPtArray((CTStrVal[]) null); // unset old axis text
            numData.setPtArray((CTNumVal[]) null); // unset old values

            // set model
            long idx = 0;
            for (int j = 0; j < dataList.size(); j++) {
                //判断获取的值是否为空
                String value = "0";
                String s = dataList.get(j).get(fldNameArr.get(i + position));
                if (!"".equals(s) && s != null){
                    if (new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))) != null) {
                        value = new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))).toString();
                    }
                } else {
                    value = null;
                }
                CTNumVal numVal = numData.addNewPt();//序列值
                numVal.setIdx(idx);
                numVal.setV(value);
                CTStrVal sVal = strData.addNewPt();//序列名称
                sVal.setIdx(idx);
                sVal.setV(dataList.get(j).get(fldNameArr.get(0)));
                idx++;
            }
            numData.getPtCount().setVal(idx);
            strData.getPtCount().setVal(idx);


            //赋值横坐标数据区域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0)
                    .formatAsString("Sheet1", false);
            cat.getStrRef().setF(axisDataRange);

            //数据区域
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + position, i + position)
                    .formatAsString("Sheet1", false);
            val.getNumRef().setF(numDataRange);

            // 设置系列生成方向


        }
        return result;
    }


    /**
     * 刷新柱状图数据方法
     *
     * @param typeChart
     * @param serList
     * @param dataList
     * @param fldNameArr
     * @param position
     * @return
     */
    public static boolean refreshBarStrGraphContent(Object typeChart,
                                                    List<?> serList, List<Map<String, String>> dataList, List<String> fldNameArr, int position) {
        boolean result = true;
        //更新数据区域
        for (int i = 0; i < serList.size(); i++) {
            CTAxDataSource cat = null;
            CTNumDataSource val = null;
            CTBarSer ser = ((CTBarChart) typeChart).getSerArray(i);

            // 设置标题 用以下这个方式,可以兼容office和wps
            CTSerTx tx = ser.getTx();
            // tx.getStrRef().getStrCache().getPtList().get(0).setV("嘿嘿嘿");

            // Category Axis Data
            cat = ser.getCat();
            // 获取图表的值
            val = ser.getVal();
            // strData.set
            CTStrData strData = cat.getStrRef().getStrCache();
            CTNumData numData = val.getNumRef().getNumCache();
            strData.setPtArray((CTStrVal[]) null); // unset old axis text
            numData.setPtArray((CTNumVal[]) null); // unset old values

            // set model
            long idx = 0;
            for (int j = 0; j < dataList.size(); j++) {
                //判断获取的值是否为空
                String value = "0";
                if (new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))) != null) {
                    value = new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))).toString();
                }
                if (!"0".equals(value)) {
                    CTNumVal numVal = numData.addNewPt();//序列值
                    numVal.setIdx(idx);
                    numVal.setV(value);
                }
                CTStrVal sVal = strData.addNewPt();//序列名称
                sVal.setIdx(idx);
                sVal.setV(dataList.get(j).get(fldNameArr.get(0)));
                idx++;
            }
            numData.getPtCount().setVal(idx);
            strData.getPtCount().setVal(idx);


            //赋值横坐标数据区域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0)
                    .formatAsString("Sheet1", true);
            cat.getStrRef().setF(axisDataRange);

            //数据区域
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + position, i + position)
                    .formatAsString("Sheet1", true);
            val.getNumRef().setF(numDataRange);


        }
        return result;
    }


    /**
     * 刷新饼图数据方法
     *
     * @param typeChart
     * @param serList
     * @param dataList
     * @param fldNameArr
     * @param position
     * @return
     */
    public static boolean refreshPieStrGraphContent(Object typeChart,
                                                    List<?> serList, List<Map<String, String>> dataList, List<String> fldNameArr, int position) {

        boolean result = true;
        //更新数据区域
        for (int i = 0; i < serList.size(); i++) {
            //CTSerTx tx=null;
            CTAxDataSource cat = null;
            CTNumDataSource val = null;
            CTPieSer ser = ((CTPieChart) typeChart).getSerArray(i);

            //tx.getStrRef().getStrCache().getPtList().get(0).setV("阿里嘎痛");
            // Category Axis Data
            cat = ser.getCat();
            // 获取图表的值
            val = ser.getVal();
            // strData.set
            CTStrData strData = cat.getStrRef().getStrCache();
            CTNumData numData = val.getNumRef().getNumCache();
            strData.setPtArray((CTStrVal[]) null); // unset old axis text
            numData.setPtArray((CTNumVal[]) null); // unset old values

            // set model
            long idx = 0;
            for (int j = 0; j < dataList.size(); j++) {
                //判断获取的值是否为空
                String value = "0";
                if (new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))) != null) {
                    value = new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))).toString();
                }
                if (!"0".equals(value)) {
                    CTNumVal numVal = numData.addNewPt();//序列值
                    numVal.setIdx(idx);
                    numVal.setV(value);
                }
                CTStrVal sVal = strData.addNewPt();//序列名称
                sVal.setIdx(idx);
                sVal.setV(dataList.get(j).get(fldNameArr.get(0)));
                idx++;
            }
            numData.getPtCount().setVal(idx);
            strData.getPtCount().setVal(idx);


            //赋值横坐标数据区域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0)
                    .formatAsString("Sheet1", true);
            cat.getStrRef().setF(axisDataRange);

            //数据区域
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + position, i + position)
                    .formatAsString("Sheet1", true);
            val.getNumRef().setF(numDataRange);
        }
        return result;
    }


    /**
     * 刷新内置excel数据
     *
     * @param chart
     * @param dataList
     * @param fldNameArr
     * @param titleArr
     * @return
     */
    public static boolean refreshExcel(XWPFChart chart,
                                       List<Map<String, String>> dataList, List<String> fldNameArr, List<String> titleArr) {
        boolean result = true;
        Workbook wb = new XSSFWorkbook();
        Sheet sheet = wb.createSheet("Sheet1");
        //根据数据创建excel第一行标题行
        for (int i = 0; i < titleArr.size(); i++) {
            if (sheet.getRow(0) == null) {
                sheet.createRow(0).createCell(i).setCellValue(titleArr.get(i) == null ? "" : titleArr.get(i));
            } else {
                sheet.getRow(0).createCell(i).setCellValue(titleArr.get(i) == null ? "" : titleArr.get(i));
            }
        }

        //遍历数据行
        for (int i = 0; i < dataList.size(); i++) {
            Map<String, String> baseFormMap = dataList.get(i);//数据行
            //fldNameArr字段属性
            for (int j = 0; j < fldNameArr.size(); j++) {
                if (sheet.getRow(i + 1) == null) {
                    if (j == 0) {
                        try {
                            sheet.createRow(i + 1).createCell(j).setCellValue(baseFormMap.get(fldNameArr.get(j)) == null ? "" : baseFormMap.get(fldNameArr.get(j)));
                        } catch (Exception e) {
                            if (baseFormMap.get(fldNameArr.get(j)) == null) {
                                sheet.createRow(i + 1).createCell(j).setCellValue("");
                            } else {
                                sheet.createRow(i + 1).createCell(j).setCellValue(baseFormMap.get(fldNameArr.get(j)));
                            }
                        }
                    }
                } else {
                    BigDecimal b = null;
                    String s = baseFormMap.get(fldNameArr.get(j));
                    if (!"".equals(s) && s != null){
                        b = new BigDecimal(baseFormMap.get(fldNameArr.get(j)));
                    } else {
                        System.out.println();
                    }
                    double value = 0d;
                    if (b != null) {
                        value = b.doubleValue();
                    }
                    if (value == 0) {
                        sheet.getRow(i + 1).createCell(j);
                    } else {
                        sheet.getRow(i + 1).createCell(j).setCellValue(b.doubleValue());
                    }
                }
            }

        }
        // 更新嵌入的workbook
        POIXMLDocumentPart xlsPart = chart.getRelations().get(0);
        OutputStream xlsOut = xlsPart.getPackagePart().getOutputStream();

        try {
            wb.write(xlsOut);
            xlsOut.close();
        } catch (IOException e) {
            e.printStackTrace();
            result = false;
        } finally {
            if (wb != null) {
                try {
                    wb.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    result = false;
                }
            }
        }
        return result;
    }


    /**
     * 设置表格样式
     *
     * @param cell
     * @param fontName
     * @param fontSize
     * @param fontBlod
     * @param alignment
     * @param vertical
     * @param fontColor
     * @param bgColor
     * @param cellWidth
     * @param content
     */
    public static void setWordCellSelfStyle(XWPFTableCell cell, String fontName, String fontSize, int fontBlod,
                                            String alignment, String vertical, String fontColor,
                                            String bgColor, String cellWidth, String content) {

        //poi对字体大小设置特殊,不支持小数,但对原word字体大小做了乘2处理
        BigInteger bFontSize = new BigInteger("24");
        if (fontSize != null && !fontSize.equals("")) {
            //poi对字体大小设置特殊,不支持小数,但对原word字体大小做了乘2处理
            BigDecimal fontSizeBD = new BigDecimal(fontSize);
            fontSizeBD = bd2.multiply(fontSizeBD);
            fontSizeBD = fontSizeBD.setScale(0, BigDecimal.ROUND_HALF_UP);//这里取整
            bFontSize = new BigInteger(fontSizeBD.toString());// 字体大小
        }

        // 设置单元格宽度
        cell.setWidth(cellWidth);

        //=====获取单元格
        CTTc tc = cell.getCTTc();
        //====tcPr开始====》》》》
        CTTcPr tcPr = tc.getTcPr();//获取单元格里的<w:tcPr>
        if (tcPr == null) {//没有<w:tcPr>,创建
            tcPr = tc.addNewTcPr();
        }

        //  --vjc开始-->>
        CTVerticalJc vjc = tcPr.getVAlign();//获取<w:tcPr>  的<w:vAlign w:val="center"/>
        if (vjc == null) {//没有<w:w:vAlign/>,创建
            vjc = tcPr.addNewVAlign();
        }
        //设置单元格对齐方式
        vjc.setVal(vertical.equals("top") ? STVerticalJc.TOP : vertical.equals("bottom") ? STVerticalJc.BOTTOM : STVerticalJc.CENTER); //垂直对齐

        CTShd shd = tcPr.getShd();//获取<w:tcPr>里的<w:shd w:val="clear" w:color="auto" w:fill="C00000"/>
        if (shd == null) {//没有<w:shd>,创建
            shd = tcPr.addNewShd();
        }
        // 设置背景颜色
        shd.setFill(bgColor.substring(1));
        //《《《《====tcPr结束====

        //====p开始====》》》》
        CTP p = tc.getPList().get(0);//获取单元格里的<w:p w:rsidR="00C36068" w:rsidRPr="00B705A0" w:rsidRDefault="00C36068" w:rsidP="00C36068">

        //---ppr开始--->>>
        CTPPr ppr = p.getPPr();//获取<w:p>里的<w:pPr>
        if (ppr == null) {//没有<w:pPr>,创建
            ppr = p.addNewPPr();
        }
        //  --jc开始-->>
        CTJc jc = ppr.getJc();//获取<w:pPr>里的<w:jc w:val="left"/>
        if (jc == null) {//没有<w:jc/>,创建
            jc = ppr.addNewJc();
        }
        //设置单元格对齐方式
        jc.setVal(alignment.equals("left") ? STJc.LEFT : alignment.equals("right") ? STJc.RIGHT : STJc.CENTER); //水平对齐
        //  <<--jc结束--
        //  --pRpr开始-->>
        CTParaRPr pRpr = ppr.getRPr(); //获取<w:pPr>里的<w:rPr>
        if (pRpr == null) {//没有<w:rPr>,创建
            pRpr = ppr.addNewRPr();
        }
        CTFonts pfont = pRpr.getRFonts();//获取<w:rPr>里的<w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体"/>
        if (pfont == null) {//没有<w:rPr>,创建
            pfont = pRpr.addNewRFonts();
        }
        //设置字体
        pfont.setAscii(fontName);
        pfont.setEastAsia(fontName);
        pfont.setHAnsi(fontName);

        CTOnOff pb = pRpr.getB();//获取<w:rPr>里的<w:b/>
        if (pb == null) {//没有<w:b/>,创建
            pb = pRpr.addNewB();
        }
        //设置字体是否加粗
        pb.setVal(fontBlod == 1 ? STOnOff.ON : STOnOff.OFF);

        CTHpsMeasure psz = pRpr.getSz();//获取<w:rPr>里的<w:sz w:val="32"/>
        if (psz == null) {//没有<w:sz w:val="32"/>,创建
            psz = pRpr.addNewSz();
        }
        // 设置单元格字体大小
        psz.setVal(bFontSize);
        CTHpsMeasure pszCs = pRpr.getSzCs();//获取<w:rPr>里的<w:szCs w:val="32"/>
        if (pszCs == null) {//没有<w:szCs w:val="32"/>,创建
            pszCs = pRpr.addNewSzCs();
        }
        // 设置单元格字体大小
        pszCs.setVal(bFontSize);
        //  <<--pRpr结束--
        //<<<---ppr结束---

        //---r开始--->>>
        List<CTR> rlist = p.getRList(); //获取<w:p>里的<w:r w:rsidRPr="00B705A0">
        CTR r = null;
        if (rlist != null && rlist.size() > 0) {//获取第一个<w:r>
            r = rlist.get(0);
        } else {//没有<w:r>,创建
            r = p.addNewR();
        }
        //--rpr开始-->>
        CTRPr rpr = r.getRPr();//获取<w:r w:rsidRPr="00B705A0">里的<w:rPr>
        if (rpr == null) {//没有<w:rPr>,创建
            rpr = r.addNewRPr();
        }
        //->-
        CTFonts font = rpr.getRFonts();//获取<w:rPr>里的<w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体" w:hint="eastAsia"/>
        if (font == null) {//没有<w:rFonts>,创建
            font = rpr.addNewRFonts();
        }
        //设置字体
        font.setAscii(fontName);
        font.setEastAsia(fontName);
        font.setHAnsi(fontName);

        CTOnOff b = rpr.getB();//获取<w:rPr>里的<w:b/>
        if (b == null) {//没有<w:b/>,创建
            b = rpr.addNewB();
        }
        //设置字体是否加粗
        b.setVal(fontBlod == 1 ? STOnOff.ON : STOnOff.OFF);
        CTColor color = rpr.getColor();//获取<w:rPr>里的<w:color w:val="FFFFFF" w:themeColor="background1"/>
        if (color == null) {//没有<w:color>,创建
            color = rpr.addNewColor();
        }
        // 设置字体颜色
        if (content.contains("↓")) {
            color.setVal("43CD80");
        } else if (content.contains("↑")) {
            color.setVal("943634");
        } else {
            color.setVal(fontColor.substring(1));
        }
        CTHpsMeasure sz = rpr.getSz();
        if (sz == null) {
            sz = rpr.addNewSz();
        }
        sz.setVal(bFontSize);
        CTHpsMeasure szCs = rpr.getSzCs();
        if (szCs == null) {
            szCs = rpr.addNewSz();
        }
        szCs.setVal(bFontSize);
        //-<-
        //<<--rpr结束--
        List<CTText> tlist = r.getTList();
        CTText t = null;
        if (tlist != null && tlist.size() > 0) {//获取第一个<w:r>
            t = tlist.get(0);
        } else {//没有<w:r>,创建
            t = r.addNewT();
        }
        t.setStringValue(content);
        //<<<---r结束---
    }


    /**
     * 获取内置表格数据,拿到第一行第一列格子数据
     * 有时候模板设计太复杂,对于图表不能精准定位,可以通过设置图表表格数据的第一行第一列格子数据来区分,这个数据不影响图表显示,所以用来区分每个图表
     */
    public static String getZeroData(POIXMLDocumentPart poixmlDocumentPart) {
        String text = "";
        try {
            XWPFChart chart = (XWPFChart) poixmlDocumentPart;
            chart.getCTChart();

            POIXMLDocumentPart xlsPart = chart.getRelations().get(0);
            InputStream xlsin = xlsPart.getPackagePart().getInputStream();

            Workbook workbook = new XSSFWorkbook(xlsin);
            // 获取第一个sheet
            Sheet sheet = workbook.getSheetAt(0);
            // 第一行
            Row row = sheet.getRow(0);
            // 第一列
            Cell cell = row.getCell(0);

            cell.setCellType(CellType.STRING);  // 设置一下格子类型为字符串,不然如果是数字或者时间的话,获取很麻烦
            text = cell.getStringCellValue();   // 获取格子内容

            System.out.println("(0,0)格子值:" + text);

            // 关闭流
            xlsin.close();

        } catch (Exception e) {
            e.printStackTrace();
        }


        return text;
    }


    /**
     * 刷新雷达图数据方法
     *
     * @param typeChart
     * @param serList
     * @param dataList
     * @param fldNameArr
     * @param position
     * @return
     */
    public static boolean refreshRadarStrGraphContent(Object typeChart,
                                                      List<?> serList, List<Map<String, String>> dataList, List<String> fldNameArr, int position) {
        boolean result = true;
        //更新数据区域
        for (int i = 0; i < serList.size(); i++) {
            CTAxDataSource cat = null;
            CTNumDataSource val = null;
            CTRadarSer ser = ((CTRadarChart) typeChart).getSerArray(i);


            // 设置标题 用以下这个方式,可以兼容office和wps
            CTSerTx tx = ser.getTx();
            // tx.getStrRef().getStrCache().getPtList().get(0).setV("嘿嘿嘿");

            // Category Axis Data
            cat = ser.getCat();
            // 获取图表的值
            val = ser.getVal();

            // strData.set
            if (null != cat.getNumRef()) {
                cat.unsetNumRef();
            }
            if (null != cat.getStrRef()) {
                cat.unsetStrRef();
            }
            cat.addNewStrRef().addNewStrCache();

            CTStrData strData = cat.getStrRef().getStrCache();
            CTNumData numData = val.getNumRef().getNumCache();
            strData.setPtArray((CTStrVal[]) null); // unset old axis text
            numData.setPtArray((CTNumVal[]) null); // unset old values

            // set model
            long idx = 0;
            for (int j = 0; j < dataList.size(); j++) {
                //判断获取的值是否为空
                String value = "0";
                if (new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))) != null) {
                    value = new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))).toString();
                }
                if (!"0".equals(value)) {
                    CTNumVal numVal = numData.addNewPt();//序列值
                    numVal.setIdx(idx);
                    numVal.setV(value);
                }
                CTStrVal sVal = strData.addNewPt();//序列名称
                sVal.setIdx(idx);
                sVal.setV(dataList.get(j).get(fldNameArr.get(0)));
                idx++;
            }
            strData.addNewPtCount().setVal(idx);
            numData.getPtCount().setVal(idx);


            //赋值横坐标数据区域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0)
                    .formatAsString("Sheet1", true);
            cat.getStrRef().setF(axisDataRange);

            //数据区域
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + position, i + position)
                    .formatAsString("Sheet1", true);
            val.getNumRef().setF(numDataRange);


        }
        return result;
    }

    /**
     * 传参列数,返回excel的列
     * 例如:3返回C 27返回AA
     * @param columnNumber
     * @return
     */
    private static String getExcelCol(int columnNumber) {
        StringBuilder columnName = new StringBuilder();
        while (columnNumber > 0) {
            int remainder = (columnNumber - 1) % 26;
            columnName.insert(0, (char) (remainder + 'A'));
            columnNumber = (columnNumber - 1) / 26;
        }
        return columnName.toString();
    }
}

4、3 DocumentTitleEnum

@Getter
public enum DocumentTitleEnum {

    /**
     * h1格式
     */
    H1("2", "h1格式"),

    /**
     * h2格式
     */
    H2("3", "h2格式"),

    /**
     * h3格式
     */
    H3("4", "h3格式"),

    /**
     * P格式
     */
    P("5", "正文格式");

    private final String code;

    private final String message;

    DocumentTitleEnum(String code, String message) {
        this.code = code;
        this.message = message;
    }

}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值