java导出excle生成原生图表(包括折线图,柱状图,饼状图,面积图)


import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PoiExcelUtil {

    static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");

    private static String systemTime = df.format(System.currentTimeMillis());;
    private static SXSSFWorkbook wb = new SXSSFWorkbook();

    private SXSSFSheet sheet = null;

    public static void main(String[] args) {


        // 字段名
        List<String> fldNameArr = new ArrayList();

        // 标题
        List<String> titleArr = new ArrayList();

        // 模拟数据
        List<Map> dataList = new ArrayList();

        Map dataMap1 = new HashMap();

        dataMap1.put("value1", "货币基金");

        dataMap1.put("value2", Math.floor(Math.random() * 100) + "");

        dataMap1.put("value3", Math.floor(Math.random() * 100) + "");

        dataMap1.put("value4", Math.floor(Math.random() * 100) + "");

        Map dataMap2 = new HashMap();

        dataMap2.put("value1", "指数基金");

        dataMap2.put("value2", Math.floor(Math.random() * 100) + "");

        dataMap2.put("value3", Math.floor(Math.random() * 100) + "");

        dataMap2.put("value4", Math.floor(Math.random() * 100) + "");

        Map dataMap3 = new HashMap();

        dataMap3.put("value1", "偏股基金");

        dataMap3.put("value2", Math.floor(Math.random() * 100) + "");

        dataMap3.put("value3", Math.floor(Math.random() * 100) + "");

        dataMap3.put("value4", Math.floor(Math.random() * 100) + "");

        Map dataMap4 = new HashMap();

        dataMap4.put("value1", "债券基金");

        dataMap4.put("value2", Math.floor(Math.random() * 100) + "");

        dataMap4.put("value3", Math.floor(Math.random() * 100) + "");

        dataMap4.put("value4", Math.floor(Math.random() * 100) + "");



        fldNameArr.add("value1");

        fldNameArr.add("value2");

        fldNameArr.add("value3");

        fldNameArr.add("value4");

        titleArr.add("类型");

        titleArr.add("买入");

        titleArr.add("卖出");

        titleArr.add("分红");

        dataList.add(dataMap1);

        dataList.add(dataMap2);

        dataList.add(dataMap3);

        dataList.add(dataMap4);



        PoiExcelUtil ecu = new PoiExcelUtil();

        try {

            // 创建柱状图
            ecu.createBarChart(titleArr, fldNameArr, dataList);

            // 创建饼状图
            ecu.createPieChart(titleArr, fldNameArr, dataList);

            // 创建折线图
            ecu.createTimeXYChar(titleArr, fldNameArr, dataList);

            // 创建面积图
            ecu.createAreaChart(titleArr, fldNameArr, dataList);

            String title="测试数据";
            //导出到文件
            FileOutputStream out = new FileOutputStream(new File("D:/PoiExcel/"+systemTime+"_"+title+".xls"));

            wb.write(out);

            out.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    /**
     * 创建柱状图(堆积图,多组)
     *
     * @throws IOException
     */

    public void createBarChart(List<String> titleArr, List<String> fldNameArr, List<Map> dataList) {

        // 创建一个sheet页
        sheet = wb.createSheet("sheet0");
        // drawSheet0Table(sheet,titleArr,fldNameArr,dataList);
        // 堆积=STBarGrouping.STACKED 多组=STBarGrouping.CLUSTERED
        boolean result = drawSheet0Map(sheet, STBarGrouping.CLUSTERED, fldNameArr, dataList, titleArr);

        System.out.println("生成柱状图(堆积or多组)-->" + result);

    }


    /**
     * 生成柱状图
     *
     * @param sheet      页签
     * @param group      柱状图类型(堆积,多组)
     * @param fldNameArr 坐标名称
     * @param dataList   统计数据
     * @return
     */

    // private boolean drawSheet0Map(SXSSFSheet sheet, Enum group, List fldNameArr, List<Map> dataList, List titleArr) {
    private boolean drawSheet0Map(SXSSFSheet sheet, STBarGrouping.Enum group, List<String> fldNameArr, List<Map> dataList, List<String> titleArr) {

        boolean result = false;

        // 获取sheet名称
        String sheetName = sheet.getSheetName();

        result = drawSheet0Table(sheet, titleArr, fldNameArr, dataList);

        // 创建一个画布
        Drawing drawing = sheet.createDrawingPatriarch();

        // 画一个图区域
        // 前四个默认0,从第8行到第25行,从第0列到第6列的区域

        ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 8, 6, 25);

        // 创建一个chart对象
        Chart chart = drawing.createChart(anchor);

        CTChart ctChart = ((XSSFChart) chart).getCTChart();

        CTPlotArea ctPlotArea = ctChart.getPlotArea();

        // 创建柱状图模型
        CTBarChart ctBarChart = ctPlotArea.addNewBarChart();

        CTBoolean ctBoolean = ctBarChart.addNewVaryColors();

        ctBarChart.getVaryColors().setVal(true);

        // 设置图类型
        // STBarGrouping.Enum group = null;
        ctBarChart.addNewGrouping().setVal(group);

        ctBoolean.setVal(true);

        ctBarChart.addNewBarDir().setVal(STBarDir.COL);

        // 是否添加左侧坐标轴
        ctChart.addNewDispBlanksAs().setVal(STDispBlanksAs.ZERO);

        ctChart.addNewShowDLblsOverMax().setVal(true);

        // 设置这两个参数是为了在STACKED模式下生成堆积模式;(standard)标准模式时需要将这两行去掉
        if ("stacked".equals(group.toString()) || "percentStacked".equals(group.toString())) {

            ctBarChart.addNewGapWidth().setVal(150);

            ctBarChart.addNewOverlap().setVal((byte) 100);

        }

        // 创建序列,并且设置选中区域
        for (int i = 0; i < fldNameArr.size() - 1; i++) {

            CTBarSer ctBarSer = ctBarChart.addNewSer();

            CTSerTx ctSerTx = ctBarSer.addNewTx();

            // 图例区
            CTStrRef ctStrRef = ctSerTx.addNewStrRef();

            // 选定区域第0行,第1,2,3列标题作为图例 //1 2 3
            String legendDataRange = new CellRangeAddress(0, 0, i + 1, i + 1).formatAsString(sheetName, true);

            ctStrRef.setF(legendDataRange);

            ctBarSer.addNewIdx().setVal(i);

            // 横坐标区
            CTAxDataSource cttAxDataSource = ctBarSer.addNewCat();

            ctStrRef = cttAxDataSource.addNewStrRef();

            // 选第0列,第1-6行作为横坐标区域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0).formatAsString(sheetName, true);

            ctStrRef.setF(axisDataRange);

            // 数据区域
            CTNumDataSource ctNumDataSource = ctBarSer.addNewVal();

            CTNumRef ctNumRef = ctNumDataSource.addNewNumRef();

            // 选第1-6行,第1-3列作为数据区域 //1 2 3
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + 1, i + 1).formatAsString(sheetName,

                    true);

            System.out.println(numDataRange);

            ctNumRef.setF(numDataRange);

            // 添加柱状边框线
            ctBarSer.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{0, 0, 0});

            // 设置负轴颜色不是白色
            ctBarSer.addNewInvertIfNegative().setVal(false);

            // 设置标签格式
            ctBoolean.setVal(false);

            CTDLbls newDLbls = ctBarSer.addNewDLbls();

            newDLbls.setShowLegendKey(ctBoolean);

            ctBoolean.setVal(true);

            newDLbls.setShowVal(ctBoolean);

            ctBoolean.setVal(false);

            newDLbls.setShowCatName(ctBoolean);

            newDLbls.setShowSerName(ctBoolean);

            newDLbls.setShowPercent(ctBoolean);

            newDLbls.setShowBubbleSize(ctBoolean);

            newDLbls.setShowLeaderLines(ctBoolean);

        }

        // 告诉BarChart它有坐标轴,并给它们id
        ctBarChart.addNewAxId().setVal(123456);

        ctBarChart.addNewAxId().setVal(123457);

        // 横坐标
        CTCatAx ctCatAx = ctPlotArea.addNewCatAx();

        ctCatAx.addNewAxId().setVal(123456); // id of the cat axis

        CTScaling ctScaling = ctCatAx.addNewScaling();

        ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);

        ctCatAx.addNewAxPos().setVal(STAxPos.B);

        ctCatAx.addNewCrossAx().setVal(123457); // id of the val axis

        ctCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

        // 纵坐标
        CTValAx ctValAx = ctPlotArea.addNewValAx();

        ctValAx.addNewAxId().setVal(123457); // id of the val axis

        ctScaling = ctValAx.addNewScaling();

        ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);

        // 设置位置
        ctValAx.addNewAxPos().setVal(STAxPos.L);

        ctValAx.addNewCrossAx().setVal(123456); // id of the cat axis

        ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

        // 是否删除主左边轴
        ctValAx.addNewDelete().setVal(false);

        // 是否删除横坐标
        ctCatAx.addNewDelete().setVal(false);

        // legend图注


//        if (true) {
        CTLegend ctLegend = ctChart.addNewLegend();

        ctLegend.addNewLegendPos().setVal(STLegendPos.B);

        ctLegend.addNewOverlay().setVal(false);
//        }

        return result;

    }

    /**
     * 创建横向柱状图
     *
     * @throws IOException
     */

    public void createAreaChart(List<String> titleArr, List<String> fldNameArr, List<Map> dataList) {


        // 创建一个sheet页
        sheet = wb.createSheet("sheet3");

        boolean result = drawSheet1Map(sheet, "is3D", fldNameArr, dataList, titleArr);

        System.out.println("生成面积图-->" + result);

    }

    /**
     * 生成面积图
     *
     * @param sheet
     * @param type
     * @param fldNameArr
     * @param dataList
     * @param titleArr
     * @return
     */

    private boolean drawSheet1Map(SXSSFSheet sheet, String type, List<String> fldNameArr,

                                  List<Map> dataList, List<String> titleArr) {

        boolean result = false;

        // 获取sheet名称
        String sheetName = sheet.getSheetName();

        result = drawSheet0Table(sheet, titleArr, fldNameArr, dataList);

        // 创建一个画布
        Drawing drawing = sheet.createDrawingPatriarch();

        // 画一个图区域
        // 前四个默认0,从第8行到第25行,从第0列到第6列的区域

        ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 8, 6, 25);

        // 创建一个chart对象
        Chart chart = drawing.createChart(anchor);

        CTChart ctChart = ((XSSFChart) chart).getCTChart();

        CTPlotArea ctPlotArea = ctChart.getPlotArea();

        CTAreaChart ctAreaChart = ctPlotArea.addNewAreaChart();

        CTBoolean ctBoolean = ctAreaChart.addNewVaryColors();

        ctAreaChart.addNewGrouping().setVal(STGrouping.STANDARD);

        // 创建序列,并且设置选中区域
        for (int i = 2; i < fldNameArr.size() - 1; i++) {

            CTAreaSer ctAreaSer = ctAreaChart.addNewSer();

            CTSerTx ctSerTx = ctAreaSer.addNewTx();

            // 图例区
            CTStrRef ctStrRef = ctSerTx.addNewStrRef();

            // 选定区域第0行,第1,2,3列标题作为图例 //1 2 3
            String legendDataRange = new CellRangeAddress(0, 0, i + 1, i + 1).formatAsString(sheetName, true);

            ctStrRef.setF(legendDataRange);

            ctAreaSer.addNewIdx().setVal(i);

            // 横坐标区
            CTAxDataSource cttAxDataSource = ctAreaSer.addNewCat();

            ctStrRef = cttAxDataSource.addNewStrRef();

            // 选第0列,第1-6行作为横坐标区域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0).formatAsString(sheetName, true);

            ctStrRef.setF(axisDataRange);

            // 数据区域
            CTNumDataSource ctNumDataSource = ctAreaSer.addNewVal();

            CTNumRef ctNumRef = ctNumDataSource.addNewNumRef();

            // 选第1-6行,第1-3列作为数据区域 //1 2 3
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + 1, i + 1).formatAsString(sheetName,

                    true);

            System.out.println(numDataRange);

            ctNumRef.setF(numDataRange);

            // 设置标签格式
            ctBoolean.setVal(false);

            CTDLbls newDLbls = ctAreaSer.addNewDLbls();

            newDLbls.setShowLegendKey(ctBoolean);

            ctBoolean.setVal(true);

            newDLbls.setShowVal(ctBoolean);

            ctBoolean.setVal(false);

            newDLbls.setShowCatName(ctBoolean);

            newDLbls.setShowSerName(ctBoolean);

            newDLbls.setShowPercent(ctBoolean);

            newDLbls.setShowBubbleSize(ctBoolean);

            newDLbls.setShowLeaderLines(ctBoolean);

            /*

             * //是否是平滑曲线 CTBoolean addNewSmooth = ctAreaSer.addNewSmooth();

             * addNewSmooth.setVal(false); //是否是堆积曲线 CTMarker addNewMarker =

             * ctAreaSer.addNewMarker(); CTMarkerStyle addNewSymbol =

             * addNewMarker.addNewSymbol();

             * addNewSymbol.setVal(STMarkerStyle.NONE);

             */

        }

        // telling the BarChart that it has axes and giving them Ids
        ctAreaChart.addNewAxId().setVal(123456);

        ctAreaChart.addNewAxId().setVal(123457);

        // cat axis
        CTCatAx ctCatAx = ctPlotArea.addNewCatAx();

        ctCatAx.addNewAxId().setVal(123456); // id of the cat axis

        CTScaling ctScaling = ctCatAx.addNewScaling();

        ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);

        ctCatAx.addNewAxPos().setVal(STAxPos.B);

        ctCatAx.addNewCrossAx().setVal(123457); // id of the val axis

        ctCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

        // val axis
        CTValAx ctValAx = ctPlotArea.addNewValAx();

        ctValAx.addNewAxId().setVal(123457); // id of the val axis

        ctScaling = ctValAx.addNewScaling();

        ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);

        ctValAx.addNewAxPos().setVal(STAxPos.L);

        ctValAx.addNewCrossAx().setVal(123456); // id of the cat axis

        ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

        // 是否删除主左边轴
        ctValAx.addNewDelete().setVal(false);

        // 是否删除横坐标
        ctCatAx.addNewDelete().setVal(false);

        // legend图注
        CTLegend ctLegend = ctChart.addNewLegend();

        ctLegend.addNewLegendPos().setVal(STLegendPos.B);

        ctLegend.addNewOverlay().setVal(false);

        return result;

    }

    /**
     * 创建饼状图
     *
     * @throws IOException
     */

    public void createPieChart(List<String> titleArr, List<String> fldNameArr, List<Map> dataList) {

        // 创建一个sheet页
        sheet = wb.createSheet("sheet1");

        boolean result = drawSheet2Map(sheet, "is3D", fldNameArr, dataList, titleArr);

        System.out.println("生成饼状图(普通or3D)-->" + result);

    }

    /**
     * 创建饼状图
     *
     * @param sheet      页签
     * @param type       图类型(3D或者普通)
     * @param fldNameArr (类标题)
     * @param dataList   (填充数据)
     * @param titleArr   (标题)
     * @return
     */

    private boolean drawSheet2Map(SXSSFSheet sheet, String type, List<String> fldNameArr, List<Map> dataList, List<String> titleArr) {

        boolean result = false;

        // 获取sheet名称
        String sheetName = sheet.getSheetName();

        result = drawSheet0Table(sheet, titleArr, fldNameArr, dataList);

        // 创建一个画布
        Drawing drawing = sheet.createDrawingPatriarch();

        // 画一个图区域
        // 前四个默认0,从第8行到第25行,从第0列到第6列的区域
        ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 8, 6, 25);

        // 创建一个chart对象
        Chart chart = drawing.createChart(anchor);

        CTChart ctChart = ((XSSFChart) chart).getCTChart();

        CTPlotArea ctPlotArea = ctChart.getPlotArea();

        CTBoolean ctBoolean = null;

        CTPie3DChart ctPie3DChart = null;

        CTPieChart ctPieChart = null;

        // 创建饼状图模型
        if (type.equals("is3D")) {

            ctPie3DChart = ctPlotArea.addNewPie3DChart();

            ctBoolean = ctPie3DChart.addNewVaryColors();

        } else {

            ctPieChart = ctPlotArea.addNewPieChart();

            ctBoolean = ctPieChart.addNewVaryColors();

        }

        // 创建序列,并且设置选中区域
        for (int i = 0; i < fldNameArr.size() - 1; i++) {

            CTPieSer ctPieSer = null;

            if (type.equals("is3D")) {

                ctPieSer = ctPie3DChart.addNewSer();

            } else {

                ctPieSer = ctPieChart.addNewSer();

            }

            CTSerTx ctSerTx = ctPieSer.addNewTx();

            // 图例区
            CTStrRef ctStrRef = ctSerTx.addNewStrRef();

            // 选定区域第0行,第1,2,3列标题作为图例 //1 2 3
            String legendDataRange = new CellRangeAddress(0, 0, i + 1, i + 1).formatAsString(sheetName, true);

            ctStrRef.setF(legendDataRange);

            ctPieSer.addNewIdx().setVal(i);

            // 横坐标区
            CTAxDataSource cttAxDataSource = ctPieSer.addNewCat();

            ctStrRef = cttAxDataSource.addNewStrRef();

            // 选第0列,第1-6行作为横坐标区域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0).formatAsString(sheetName, true);

            ctStrRef.setF(axisDataRange);

            // 数据区域
            CTNumDataSource ctNumDataSource = ctPieSer.addNewVal();

            CTNumRef ctNumRef = ctNumDataSource.addNewNumRef();

            // 选第1-6行,第1-3列作为数据区域 //1 2 3
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + 1, i + 1).formatAsString(sheetName,

                    true);

            System.out.println(numDataRange);

            ctNumRef.setF(numDataRange);

            // 显示边框线
            ctPieSer.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{0, 0, 0});

            // 设置标签格式
            ctBoolean.setVal(true);

        }
        // legend图注
        CTLegend ctLegend = ctChart.addNewLegend();

        ctLegend.addNewLegendPos().setVal(STLegendPos.B);

        ctLegend.addNewOverlay().setVal(true);

        return result;

    }

    /**
     * 创建折线图
     *
     * @throws IOException
     */

    public void createTimeXYChar(List<String> titleArr, List<String> fldNameArr, List<Map> dataList) {

        // 创建一个sheet页
        sheet = wb.createSheet("sheet2");

        // 第二个参数折线图类型:line=普通折线图,line-bar=折线+柱状图
        boolean result = drawSheet3Map(sheet, "line", fldNameArr, dataList, titleArr);

        System.out.println("生成折线图(折线图or折线图-柱状图)-->" + result);

    }

    /**
     * 生成折线图
     *
     * @param sheet      页签
     * @param type       类型
     * @param fldNameArr X轴标题
     * @param dataList   填充数据
     * @param titleArr   图例标题
     * @return
     */

    private boolean drawSheet3Map(SXSSFSheet sheet, String type, List fldNameArr, List<Map> dataList, List titleArr) {

        boolean result = false;
        // 获取sheet名称
        String sheetName = sheet.getSheetName();

        result = drawSheet0Table(sheet, titleArr, fldNameArr, dataList);

        // 创建一个画布
        Drawing drawing = sheet.createDrawingPatriarch();

        // 画一个图区域
        // 前四个默认0,从第8行到第25行,从第0列到第6列的区域
        ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 8, 6, 25);

        // 创建一个chart对象
        Chart chart = drawing.createChart(anchor);

        CTChart ctChart = ((XSSFChart) chart).getCTChart();

        CTPlotArea ctPlotArea = ctChart.getPlotArea();

        if (type.equals("line-bar")) {

            CTBarChart ctBarChart = ctPlotArea.addNewBarChart();

            CTBoolean ctBoolean = ctBarChart.addNewVaryColors();

            ctBarChart.getVaryColors().setVal(true);

            // 设置类型
            ctBarChart.addNewGrouping().setVal(STBarGrouping.CLUSTERED);

            ctBoolean.setVal(true);

            ctBarChart.addNewBarDir().setVal(STBarDir.COL);

            // 是否添加左侧坐标轴
            ctChart.addNewDispBlanksAs().setVal(STDispBlanksAs.ZERO);

            ctChart.addNewShowDLblsOverMax().setVal(true);

            // 创建序列,并且设置选中区域
            for (int i = 0; i < fldNameArr.size() - 1; i++) {

                CTBarSer ctBarSer = ctBarChart.addNewSer();

                CTSerTx ctSerTx = ctBarSer.addNewTx();

                // 图例区
                CTStrRef ctStrRef = ctSerTx.addNewStrRef();

                // 选定区域第0行,第1,2,3列标题作为图例 //1 2 3
                String legendDataRange = new CellRangeAddress(0, 0, i + 1, i + 1).formatAsString(sheetName, true);

                ctStrRef.setF(legendDataRange);

                ctBarSer.addNewIdx().setVal(i);

                // 横坐标区
                CTAxDataSource cttAxDataSource = ctBarSer.addNewCat();

                ctStrRef = cttAxDataSource.addNewStrRef();

                // 选第0列,第1-6行作为横坐标区域
                String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0).formatAsString(sheetName, true);

                ctStrRef.setF(axisDataRange);

                // 数据区域
                CTNumDataSource ctNumDataSource = ctBarSer.addNewVal();

                CTNumRef ctNumRef = ctNumDataSource.addNewNumRef();

                // 选第1-6行,第1-3列作为数据区域 //1 2 3
                String numDataRange = new CellRangeAddress(1, dataList.size(), i + 1, i + 1).formatAsString(sheetName,

                        true);

                System.out.println(numDataRange);

                ctNumRef.setF(numDataRange);

                ctBarSer.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{0, 0, 0});

                // 设置负轴颜色不是白色
                ctBarSer.addNewInvertIfNegative().setVal(false);

                // 设置标签格式
                ctBoolean.setVal(false);

                CTDLbls newDLbls = ctBarSer.addNewDLbls();

                newDLbls.setShowLegendKey(ctBoolean);

                ctBoolean.setVal(true);

                newDLbls.setShowVal(ctBoolean);

                ctBoolean.setVal(false);

                newDLbls.setShowCatName(ctBoolean);

                newDLbls.setShowSerName(ctBoolean);

                newDLbls.setShowPercent(ctBoolean);

                newDLbls.setShowBubbleSize(ctBoolean);

                newDLbls.setShowLeaderLines(ctBoolean);

            }

            // telling the BarChart that it has axes and giving them Ids
            ctBarChart.addNewAxId().setVal(123456);

            ctBarChart.addNewAxId().setVal(123457);

            // cat axis
            CTCatAx ctCatAx = ctPlotArea.addNewCatAx();

            ctCatAx.addNewAxId().setVal(123456); // id of the cat axis

            CTScaling ctScaling = ctCatAx.addNewScaling();

            ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);

            ctCatAx.addNewAxPos().setVal(STAxPos.B);

            ctCatAx.addNewCrossAx().setVal(123457); // id of the val axis

            ctCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

            // val axis
            CTValAx ctValAx = ctPlotArea.addNewValAx();

            ctValAx.addNewAxId().setVal(123457); // id of the val axis

            ctScaling = ctValAx.addNewScaling();

            ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);

            ctValAx.addNewAxPos().setVal(STAxPos.L);

            ctValAx.addNewCrossAx().setVal(123456); // id of the cat axis

            ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

        }

        // 折线图
        CTLineChart ctLineChart = ctPlotArea.addNewLineChart();

        CTBoolean ctBoolean = ctLineChart.addNewVaryColors();

        ctLineChart.addNewGrouping().setVal(STGrouping.STANDARD);

        // 创建序列,并且设置选中区域
        for (int i = 0; i < fldNameArr.size() - 1; i++) {

            CTLineSer ctLineSer = ctLineChart.addNewSer();

            CTSerTx ctSerTx = ctLineSer.addNewTx();

            // 图例区
            CTStrRef ctStrRef = ctSerTx.addNewStrRef();

            // 选定区域第0行,第1,2,3列标题作为图例 //1 2 3
            String legendDataRange = new CellRangeAddress(0, 0, i + 1, i + 1).formatAsString(sheetName, true);

            ctStrRef.setF(legendDataRange);

            ctLineSer.addNewIdx().setVal(i);

            // 横坐标区
            CTAxDataSource cttAxDataSource = ctLineSer.addNewCat();

            ctStrRef = cttAxDataSource.addNewStrRef();

            // 选第0列,第1-6行作为横坐标区域
            String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0).formatAsString(sheetName, true);

            ctStrRef.setF(axisDataRange);

            // 数据区域
            CTNumDataSource ctNumDataSource = ctLineSer.addNewVal();

            CTNumRef ctNumRef = ctNumDataSource.addNewNumRef();

            // 选第1-6行,第1-3列作为数据区域 //1 2 3
            String numDataRange = new CellRangeAddress(1, dataList.size(), i + 1, i + 1).formatAsString(sheetName,

                    true);

            System.out.println(numDataRange);

            ctNumRef.setF(numDataRange);

            // 设置标签格式
            ctBoolean.setVal(false);

            CTDLbls newDLbls = ctLineSer.addNewDLbls();

            newDLbls.setShowLegendKey(ctBoolean);

            ctBoolean.setVal(true);

            newDLbls.setShowVal(ctBoolean);

            ctBoolean.setVal(false);

            newDLbls.setShowCatName(ctBoolean);

            newDLbls.setShowSerName(ctBoolean);

            newDLbls.setShowPercent(ctBoolean);

            newDLbls.setShowBubbleSize(ctBoolean);

            newDLbls.setShowLeaderLines(ctBoolean);

            // 是否是平滑曲线
            CTBoolean addNewSmooth = ctLineSer.addNewSmooth();

            addNewSmooth.setVal(false);

            // 是否是堆积曲线
            CTMarker addNewMarker = ctLineSer.addNewMarker();

            CTMarkerStyle addNewSymbol = addNewMarker.addNewSymbol();

            addNewSymbol.setVal(STMarkerStyle.NONE);

        }

        // telling the BarChart that it has axes and giving them Ids
        ctLineChart.addNewAxId().setVal(123456);

        ctLineChart.addNewAxId().setVal(123457);

        // cat axis
        CTCatAx ctCatAx = ctPlotArea.addNewCatAx();

        ctCatAx.addNewAxId().setVal(123456); // id of the cat axis

        CTScaling ctScaling = ctCatAx.addNewScaling();

        ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);

        ctCatAx.addNewAxPos().setVal(STAxPos.B);

        ctCatAx.addNewCrossAx().setVal(123457); // id of the val axis

        ctCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

        // val axis
        CTValAx ctValAx = ctPlotArea.addNewValAx();

        ctValAx.addNewAxId().setVal(123457); // id of the val axis

        ctScaling = ctValAx.addNewScaling();

        ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);

        ctValAx.addNewAxPos().setVal(STAxPos.L);

        ctValAx.addNewCrossAx().setVal(123456); // id of the cat axis

        ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

        // 是否删除主左边轴
        ctValAx.addNewDelete().setVal(false);

        // 是否删除横坐标
        if (type.equals("line-bar")) {

            ctCatAx.addNewDelete().setVal(true);

        }

        CTLegend ctLegend = ctChart.addNewLegend();

        ctLegend.addNewLegendPos().setVal(STLegendPos.B);

        ctLegend.addNewOverlay().setVal(false);

        return result;

    }

    /**
     * 生成数据表
     *
     * @param sheet      sheet页对象
     * @param titleArr   表头字段
     * @param fldNameArr 左边标题字段
     * @param dataList   数据
     * @return 是否生成成功
     */

    private boolean drawSheet0Table(SXSSFSheet sheet, List<String> titleArr, List<String> fldNameArr, List<Map> dataList) {

        // 测试时返回值
        boolean result = true;

        // 初始化表格样式
        List styleList = tableStyle();

        // 根据数据创建excel第一行标题行
        SXSSFRow row0 = sheet.createRow(0);

        for (int i = 0; i < titleArr.size(); i++) {

            // 设置标题
            row0.createCell(i).setCellValue(titleArr.get(i));

            // 设置标题行样式
            row0.getCell(i).setCellStyle((CellStyle) styleList.get(0));

        }

        // 填充数据
        for (int i = 0; i < dataList.size(); i++) {

            // 获取每一项的数据
            Map data = (Map) dataList.get(i);

            // 设置每一行的字段标题和数据
            SXSSFRow rowi = sheet.createRow(i + 1);

            for (int j = 0; j < data.size(); j++) {

                // 判断是否是标题字段列
                if (j == 0) {

                    rowi.createCell(j).setCellValue((String) data.get("value" + (j + 1)));

                    // 设置左边字段样式
                    sheet.getRow(i + 1).getCell(j).setCellStyle((CellStyle) styleList.get(0));

                } else {

                    rowi.createCell(j).setCellValue(Double.valueOf((String) data.get("value" + (j + 1))));

                    // 设置数据样式
                    sheet.getRow(i + 1).getCell(j).setCellStyle((CellStyle) styleList.get(2));

                }

            }

        }

        return result;

    }

    /**
     * 生成表格样式
     *
     * @return
     */

    private static List tableStyle() {

        List cellStyleList = new ArrayList();

        // 样式准备
        // 标题样式
        CellStyle style = wb.createCellStyle();

        style.setFillForegroundColor(IndexedColors.ROYAL_BLUE.getIndex());

        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        style.setBorderBottom(BorderStyle.THIN); // 下边框

        style.setBorderLeft(BorderStyle.THIN);// 左边框

        style.setBorderTop(BorderStyle.THIN);// 上边框

        style.setBorderRight(BorderStyle.THIN);// 右边框

        style.setAlignment(HorizontalAlignment.CENTER);

        cellStyleList.add(style);

        CellStyle style1 = wb.createCellStyle();

        style1.setBorderBottom(BorderStyle.THIN); // 下边框

        style1.setBorderLeft(BorderStyle.THIN);// 左边框

        style1.setBorderTop(BorderStyle.THIN);// 上边框

        style1.setBorderRight(BorderStyle.THIN);// 右边框

        style1.setAlignment(HorizontalAlignment.CENTER);

        cellStyleList.add(style1);

        CellStyle cellStyle = wb.createCellStyle();

        cellStyle.setBorderTop(BorderStyle.THIN);// 上边框

        cellStyle.setBorderBottom(BorderStyle.THIN); // 下边框

        cellStyle.setBorderLeft(BorderStyle.THIN);// 左边框

        cellStyle.setBorderRight(BorderStyle.THIN);// 右边框

        cellStyle.setAlignment(HorizontalAlignment.CENTER);// 水平对齐方式

        // cellStyle.setVerticalAlignment(VerticalAlignment.TOP);//垂直对齐方式
        cellStyleList.add(cellStyle);

        return cellStyleList;

    }
}

柱状图

折线图

<think>我们正在处理用户的问题:如何在Java导出带图片的订单到Excel,使用POI或EasyExcel库。根据引用内容,特别是引用[3]中的示例,我们注意到有一个字段`privatePictureDatapictureData;`并且被`@ExcelIgnore`注解忽略,这可能意味着在导出图片时需要特殊处理。由于用户提到了EasyExcel,而且引用中也有EasyExcel的相关信息,我们将重点放在EasyExcel上,因为它对POI做了封装,使用起来更简单,并且对内存更友好。在EasyExcel导出图片,我们可以使用`@ExcelProperty`注解配合自定义的转换器,或者使用EasyExcel提供的写操作中的方法直接写入图片。根据EasyExcel的文档,我们可以通过以下方式导出图片:1.在实体类中,对于图片字段,可以使用`@ExcelProperty`注解,并指定转换器为`ImageConverter`(EasyExcel提供的)或者自定义转换器。2.在写入Excel时,将图片数据转换为`byte[]`或者使用`File`对象。但是,在引用[3]中,我们看到有一个`PictureData`类型的字段,这可能是用户自定义的类型,所以我们需要将图片数据转换为EasyExcel能够处理的格式。下面是一个示例步骤:步骤1:添加依赖(如果使用EasyExcel)```xml<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version><!--请使用最新版本--></dependency>```步骤2:定义实体类,使用`@ExcelProperty`注解,并指定转换器为`ImageConverter`(注意:EasyExcel的ImageConverter要求图片数据为`byte[]`类型)例如:```javaimportcom.alibaba.excel.annotation.ExcelProperty;importcom.alibaba.excel.annotation.write.style.ColumnWidth;importcom.alibaba.excel.converters.bytearray.ByteArrayImageConverter;importlombok.Data;@DatapublicclassOrderWithImage{@ExcelProperty("订单号")privateStringorderId;//其他订单字段...//图片列,设置列宽以适应图片@ColumnWidth(30)@ExcelProperty(value="订单图片",converter=ByteArrayImageConverter.class)privatebyte[]image;}```步骤3:准备数据,将图片读取为字节数组。步骤4:使用EasyExcel的写功能将数据写入Excel。示例代码:```javaimportcom.alibaba.excel.EasyExcel;importjava.io.File;importjava.util.ArrayList;importjava.util.List;publicclassExportOrderWithImage{publicstaticvoidmain(String[]args){//准备数据List<OrderWithImage>orders=newArrayList<>();//假设有一个订单,读取图片文件为字节数组OrderWithImageorder1=newOrderWithImage();order1.setOrderId("ORD123");//读取图片文件到字节数组,这里使用一个方法(需要自己实现读取文件到字节数组)byte[]imageData=readImageData("path/to/image.jpg");order1.setImage(imageData);orders.add(order1);//写入Excel文件StringfileName="订单列表.xlsx";EasyExcel.write(fileName,OrderWithImage.class).sheet("订单").doWrite(orders);}privatestaticbyte[]readImageData(StringimagePath){//这里简化,实际需要读取文件为字节数组try{returnFiles.readAllBytes(Paths.get(imagePath));}catch(IOExceptione){e.printStackTrace();returnnull;}}}```注意:上面的`readImageData`方法需要处理IO异常,并正确读取图片文件。如果图片是网络图片,可以使用`URL`来读取。另外,如果使用POI库,则操作相对复杂,因为POI需要创建绘图patriarch,并在sheet中创建锚点和图片索引。但既然用户提到了EasyExcel,而且EasyExcel更简单,我们优先推荐EasyExcel。但是,如果用户需要更复杂的图片操作,比如调整图片位置和大小,可能需要使用POI的底层API。不过,在EasyExcel中,通过`ByteArrayImageConverter`导出的图片会适应单元格大小,所以通常够用。如果用户希望使用POI,我们也可以提供一个POI的示例,但根据问题,我们主要使用EasyExcel。因此,我们提供EasyExcel的解决方案。注意:在实体类中,我们使用了`@ColumnWidth`来设置列宽,这样图片可以更好地显示。另外,EasyExcel的图片转换器要求图片数据是字节数组。如果图片数据是多个,或者需要放在多个单元格,那么可能需要使用`@ExcelCollection`或`@ExcelEntity`等注解来处理复杂结构,但根据问题,订单图片通常是一对一的,所以一个订单对应一张图片即可。如果订单需要多张图片,我们可以考虑将图片拼接成一张,或者使用多个字段(多个列)来存储多张图片。综上所述,我们给出了使用EasyExcel导出带图片的订单的示例。下面生成相关问题:</think>### 在Java导出带图片的订单到Excel(使用EasyExcel) #### 解决方案(EasyExcel库) EasyExcel 是阿里巴巴开源的Excel操作库,支持图片导出且内存占用低,特别适合大数据量导出场景。以下是完整示例: ```java @Data @ExcelTarget("orderWithImage") // 标识实体类[^2] public class OrderExportDTO { @ExcelProperty("订单号") private String orderId; @ExcelProperty("商品名称") private String productName; // 关键:使用图片转换器 @ExcelProperty(value = "商品图片", converter = ImageConverter.class) private byte[] productImage; // 图片需转为字节数组 @ExcelProperty("金额") private BigDecimal amount; } ``` ```java // 导出服务类 public class OrderExporter { public static void exportOrders(List<OrderExportDTO> orders, String outputPath) { // 配置写入参数 WriteCellStyle imageCellStyle = new WriteCellStyle(); imageCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 执行导出 EasyExcel.write(outputPath, OrderExportDTO.class) .registerWriteHandler(new ImageWriteHandler() { // 图片处理器 @Override public void afterCellDispose(WriteSheetHolder sheetHolder) { // 自动调整图片行高(可选) sheetHolder.getSheet().setDefaultRowHeightInPoints(80); } }) .registerWriteHandler(new HorizontalCellStyleStrategy(null, imageCellStyle)) .sheet("订单数据") .doWrite(orders); } } ``` ```java // 使用示例 public static void main(String[] args) { List<OrderExportDTO> orders = new ArrayList<>(); // 读取图片为字节数组(本地文件示例) OrderExportDTO order1 = new OrderExportDTO(); order1.setOrderId("ORD2023001"); order1.setProductName("智能手机"); order1.setProductImage(Files.readAllBytes(Paths.get("phone.jpg"))); // 图片转字节数组 order1.setAmount(new BigDecimal("5999.00")); orders.add(order1); // 执行导出 OrderExporter.exportOrders(orders, "订单导出.xlsx"); } ``` #### 关键说明 1. **图片处理**: - 必须将图片转为 `byte[]` 格式 - 使用 `ImageConverter` 自动处理Excel图片嵌入[^3] - 通过 `ImageWriteHandler` 调整图片位置和单元格样式 2. **性能优化**: - 支持百万级数据分批次写入,避免OOM[^2] - 默认启用文件缓存模式(非内存模式) 3. **依赖配置(Maven)**: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.3.2</version> <!-- 使用最新版 --> </dependency> ``` #### 注意事项 1. 图片格式支持:`JPEG`, `PNG`, `BMP` 2. 单元格高度需手动调整以适应图片尺寸 3. 网络图片需先下载到本地再转为字节数组 4. 若使用POI库,需手动创建`XSSFDrawing`和`ClientAnchor`对象(代码更复杂) > 通过注解驱动的方式,EasyExcel 实现了实体与Excel的直观映射(model-row, filed-col),大幅简化了包含图片的复杂导出逻辑[^1]。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Da白兔萘糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值