实现效果
测试类 public class ChartTest {// 开始行public static int chartRowStart = 3;// 结束行public static int chartRowEnd = 20;public static ChartPosition chartPosition;public static void main(String[] args) throws IOException {// 填充数据XSSFWorkbook workbook = createExcel();FileOutputStream fileOut = null;try {// 将输出写入excel文件String filename = UUID.randomUUID() + ".xlsx";fileOut = new FileOutputStream(filename);workbook.write(fileOut);DesktopHelpers.openFile(filename);} catch (Exception e) {e.printStackTrace();} finally {workbook.close();if (fileOut != null) {fileOut.close();}}}public static XSSFWorkbook createExcel() {XSSFWorkbook workbook = new XSSFWorkbook();XSSFSheet sheet = workbook.createSheet();//-------------------------折线图--------------------------List lineCharts = initLineChart();for (LineChart lineChart : lineCharts) {// 图表位置(左上角坐标,右下角坐标) 左上角坐标的(列,行),(右下角坐标)列,行,偏移量均为0chartPosition = new ChartPosition().setRow1(chartRowStart).setCol1(0).setRow2(chartRowEnd).setCol2(lineChart.getXAxisList().size() + 3);ChartUtils.createLine(sheet, chartPosition, lineChart);}chartRowStart = chartRowEnd + 2;chartRowEnd = chartRowStart + 20;//-------------------------柱状图--------------------------XSSFRow row = sheet.createRow(chartRowStart);row.setHeight((short) 500);XSSFCell cell0 = row.createCell(0);cell0.setCellValue("测试柱状图");cell0.setCellStyle(ChartUtils.tableNameCellStyle(workbook));sheet.addMergedRegion(new CellRangeAddress(chartRowStart, chartRowStart, 0, 2));// 获取数据List pieCharts = initPieChart();for (PieChart pieChart : pieCharts) {// 图表位置(左上角坐标,右下角坐标) 左上角坐标的(列,行),(右下角坐标)列,行,偏移量均为0chartPosition = new ChartPosition().setRow1(chartRowStart + 1).setCol1(0).setRow2(chartRowEnd).setCol2(8);ChartUtils.createBar(sheet, chartPosition, pieChart);}chartRowStart = chartRowEnd + 2;chartRowEnd = chartRowStart + 15;//-------------------------饼图--------------------------XSSFRow row1 = sheet.createRow(chartRowStart);row1.setHeight((short) 500);XSSFCell cell1 = row1.createCell(0);cell1.setCellValue("测试饼图");cell1.setCellStyle(ChartUtils.tableNameCellStyle(workbook));sheet.addMergedRegion(new CellRangeAddress(chartRowStart, chartRowStart, 0, 2));// 获取数据for (PieChart pieChart : pieCharts) {// 图表位置(左上角坐标,右下角坐标) 左上角坐标的(列,行),(右下角坐标)列,行,偏移量均为0chartPosition = new ChartPosition().setRow1(chartRowStart + 1).setCol1(0).setRow2(chartRowEnd).setCol2(8);ChartUtils.createPie(sheet, chartPosition, pieChart);}chartRowStart = chartRowEnd + 2;chartRowEnd = chartRowStart + 15;//-------------------------Excel--------------------------// 获取列表数据ChartUtils.createTable(chartRowStart, workbook, sheet);// 去除网格线// sheet.setDisplayGridlines(false);return workbook;}/** * 折线图 * @return */public static List initLineChart() {List lineCharts = new ArrayList();lineCharts.add(new LineChart().setChartTitle("折线图").setTitleList(Arrays.asList("2020年", "2021年")).setDataList(Arrays.asList(Arrays.asList(1, 2, 3, 3, 1, 6, 3, 7, 12, 11, null, null), Arrays.asList(5, 4, 0, null, 12, 3, 8, 9, 11, 9, 2, 1))).setXAxisList(Arrays.asList("1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月")));return lineCharts;}/** * 饼图 * @return */public static List initPieChart() {List pieCharts = new ArrayList();String[] name = {"北京", "上海", "广东", "深圳"};String[] title = {"城市占比"};Integer[] data1 = {15, 3, 5, 9};for (int i = 0; i < title.length; i++) {PieChart pieChart = new PieChart();pieChart.setTitleList(Arrays.asList(name));pieChart.setTitleName(title[i]);pieChart.setDataList(Arrays.asList(data1));pieCharts.add(pieChart);}return pieCharts;}}
实体类 @Accessors(chain = true)@Datapublic class ChartPosition {/** * 图表的左上角坐标列 */private int col1;/** * 图表的左上角坐标行 */private int row1;/** * 图表的右下角坐标列 */private int col2;/** * 图表的右下角坐标行t */private int row2;/** * 下面的为偏移量均设置为0 */private int dx1 = 0;private int dy1 = 0;private int dx2 = 0;private int dy2 = 0;}
@Data@Accessors(chain = true)public class LineChart {/** * 图表的名称 */private String chartTitle;/** * 每条折线的名称 */private List titleList;/** * 每条折线对应的数据 这里的类型根据自己的实际情况给 */private List<List> dataList;/** * x轴 这里的类型根据自己的实际情况给 */private List xAxisList;}
@Data@Accessors(chain = true)public class PieChart {/** * 饼图每块的名称 */private List titleList;/** * 饼图每块的数据 这里的类型根据自己的实际情况给 */private List dataList;/** * 饼图标题名称 */private String titleName;}
工具类 public class ChartUtils {private static XSSFChart createDrawingPatriarch(XSSFSheet sheet, ChartPosition chartPosition, String chartTitle) {//创建一个画布XSSFDrawing drawing = sheet.createDrawingPatriarch();//前偏移量四个默认0XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, chartPosition.getCol1(), chartPosition.getRow1(), chartPosition.getCol2(), chartPosition.getRow2());//创建一个chart对象XSSFChart chart = drawing.createChart(anchor);//标题chart.setTitleText(chartTitle);//标题是否覆盖图表chart.setTitleOverlay(false);return chart;}/** * 柱状图 * @param sheet * @param chartPosition * @param pieChart */public static void createBar(XSSFSheet sheet,ChartPosition chartPosition, PieChart pieChart){String titleName = pieChart.getTitleName();List titleList = pieChart.getTitleList();List dataList = pieChart.getDataList();XSSFChart chart = createDrawingPatriarch(sheet, chartPosition, titleName);//分类轴标(X轴),标题位置XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);//值(Y轴)轴,标题位置XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);//分类轴标数据XDDFDataSource xData = XDDFDataSourcesFactory.fromArray(titleList.toArray(new String[]{}));XDDFNumericalDataSource values = XDDFDataSourcesFactory.fromArray(dataList.toArray(new Integer[]{}));//bar:条形图XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);//设置为可变颜色bar.setVaryColors(true);//条形图方向,纵向/横向:纵向bar.setBarDirection(BarDirection.COL);//图表加载数据,条形图1XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(xData, values);//条形图例标题XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.BLUE_VIOLET));//条形图,填充颜色series1.setFillProperties(fill);//绘制chart.plot(bar);}/** * 创建饼图 * * @param sheet 图表 * @see com.gideon.entity.PieChart饼图数据的封装 * @see com.gideon.entity.ChartPosition 饼图的坐标位置 */public static void createPie(XSSFSheet sheet, ChartPosition chartPosition, PieChart pieChart) {String titleName = pieChart.getTitleName();List titleList = pieChart.getTitleList();List dataList = pieChart.getDataList();XSSFChart chart = createDrawingPatriarch(sheet, chartPosition, titleName);//图例位置XDDFChartLegend legend = chart.getOrAddLegend();legend.setPosition(LegendPosition.BOTTOM);//分类轴标数据XDDFDataSource countries = XDDFDataSourcesFactory.fromArray(titleList.toArray(new String[]{}));XDDFNumericalDataSource values = XDDFDataSourcesFactory.fromArray(dataList.toArray(new Integer[]{}));XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);//设置为可变颜色data.setVaryColors(true);//图表加载数据data.addSeries(countries, values);//绘制chart.plot(data);CTDLbls ctdLbls = chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).addNewDLbls();ctdLbls.addNewShowVal().setVal(false);ctdLbls.addNewShowLegendKey().setVal(false);//类别名称ctdLbls.addNewShowCatName().setVal(false);//百分比ctdLbls.addNewShowSerName().setVal(false);ctdLbls.addNewShowPercent().setVal(true);//引导线ctdLbls.addNewShowLeaderLines().setVal(false);//分隔符为分行符ctdLbls.setSeparator("\n");//数据标签内ctdLbls.addNewDLblPos().setVal(STDLblPos.Enum.forString("inEnd"));}/** * 创建折线图 * * @param sheet 图表 * @see com.gideon.entity.PieChart饼图数据的封装 * @see com.gideon.entity.ChartPosition 饼图的坐标位置 */public static void createLine(XSSFSheet sheet, ChartPosition chartPosition, LineChart lineChart) {List xAxisList = lineChart.getXAxisList();List chartTitleList = lineChart.getTitleList();List<List> chartDataList = lineChart.getDataList();String chartTitle = lineChart.getChartTitle();XSSFChart chart = createDrawingPatriarch(sheet, chartPosition, chartTitle);//图例位置XDDFChartLegend legend = chart.getOrAddLegend();legend.setPosition(LegendPosition.TOP);//分类轴标(X轴),标题位置XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);//值(Y轴)轴,标题位置XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);//LINE:折线图XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray(Arrays.copyOf(xAxisList.toArray(), xAxisList.toArray().length, String[].class));for (int i = 0; i < chartDataList.size(); i++) {List floats = chartDataList.get(i);XDDFNumericalDataSource dataSource = XDDFDataSourcesFactory.fromArray(floats.toArray(new Integer[]{}));//图表加载数据,折线XDDFLineChartData.Series series = (XDDFLineChartData.Series) data.addSeries(countries, dataSource);series.setTitle(chartTitleList.get(i), null);//直线series.setSmooth(false);//设置标记大小series.setMarkerSize((short) 2);//添加标签数据,折线图中拐点值展示series.setShowLeaderLines(true);chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(i).getDLbls().addNewDLblPos().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STDLblPos.CTR);chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(i).getDLbls().addNewShowVal().setVal(true);chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(i).getDLbls().addNewShowLegendKey().setVal(false);chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(i).getDLbls().addNewShowCatName().setVal(false);chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(i).getDLbls().addNewShowSerName().setVal(false);}//绘制chart.plot(data);if (chartDataList.size() == 1) {chart.getCTChart().getPlotArea().getLineChartArray(0).addNewVaryColors().setVal(false);}}/** * 创建列表 */public static void createTable(int rowNum, XSSFWorkbook wb, XSSFSheet sheet) {// 样式XSSFCellStyle titleStyle = createTitleCellStyle(wb);XSSFCellStyle contentStyle = createContentCellStyle(wb);// 创建第一页的第一行,索引从0开始XSSFRow row = sheet.createRow(rowNum);row.setHeight((short) 500);XSSFCell cell0 = row.createCell(0);cell0.setCellValue("动态列表");cell0.setCellStyle(tableNameCellStyle(wb));// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum, 0, 2));XSSFRow row1 = sheet.createRow(rowNum + 1);XSSFRow row2 = sheet.createRow(rowNum + 2);row1.setHeight((short) 600);row2.setHeight((short) 600);String title0 = "序号";XSSFCell cell = row1.createCell(0);cell.setCellValue(title0);// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)CellRangeAddress region = new CellRangeAddress(rowNum + 1, rowNum + 2, 0, 0);sheet.addMergedRegion(region);// 合并之后为合并的单元格设置样式setRegionStyle(sheet, region, titleStyle);String title = "城市";XSSFCell c00 = row1.createCell(1);c00.setCellValue(title);// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)CellRangeAddress cellRangeAddress = new CellRangeAddress(rowNum + 1, rowNum + 2, 1, 1);sheet.addMergedRegion(cellRangeAddress);setRegionStyle(sheet, cellRangeAddress, titleStyle);String[] years = {"21年", "22年", "23年"};int startCellIndex = 2;int endCellIndex = 4;// 动态年份for (int i = 0; i < years.length; i++) {XSSFCell cell1 = row1.createCell(startCellIndex);cell1.setCellValue(years[i]);CellRangeAddress cellAddresses = new CellRangeAddress(rowNum + 1, rowNum + 1, startCellIndex, endCellIndex);sheet.addMergedRegion(cellAddresses);setRegionStyle(sheet, cellAddresses, titleStyle);XSSFCell cell11 = row2.createCell(startCellIndex++);cell11.setCellValue("动态列1");cell11.setCellStyle(titleStyle);XSSFCell cell2 = row2.createCell(startCellIndex++);cell2.setCellValue("动态列2");cell2.setCellStyle(titleStyle);XSSFCell cell3 = row2.createCell(startCellIndex++);cell3.setCellValue("动态列3");cell3.setCellStyle(titleStyle);endCellIndex += 3;}rowNum += 3;for (int j = 0; j < 10; j++) {int k = j + 1;XSSFRow tempRow = sheet.createRow(rowNum);rowNum++;// 序号XSSFCell cell11 = tempRow.createCell(0);cell11.setCellValue(k);cell11.setCellStyle(contentStyle);// 城市XSSFCell cell2 = tempRow.createCell(1);cell2.setCellValue("城市" + k);cell2.setCellStyle(contentStyle);int columnIndex = 2;int k1 = 1;for (int i = 0; i < years.length; i++) {XSSFCell cell3 = tempRow.createCell(columnIndex++);cell3.setCellValue("测试" + k1++);cell3.setCellStyle(contentStyle);XSSFCell cell4 = tempRow.createCell(columnIndex++);cell4.setCellValue("测试" + k1++);cell4.setCellStyle(contentStyle);XSSFCell cell5 = tempRow.createCell(columnIndex++);cell5.setCellValue("测试" + k1++);cell5.setCellStyle(contentStyle);}}}/** * 为合并的单元格设置样式(可根据需要自行调整) */@SuppressWarnings("deprecation")public static void setRegionStyle(XSSFSheet sheet, CellRangeAddress region, XSSFCellStyle cs) {for (int i = region.getFirstRow(); i <= region.getLastRow(); i++) {XSSFRow row = sheet.getRow(i);if (null == row) row = sheet.createRow(i);for (int j = region.getFirstColumn(); j <= region.getLastColumn(); j++) {XSSFCell cell = row.getCell(j);if (null == cell) cell = row.createCell(j);cell.setCellStyle(cs);}}}/** * 列表名称样式 * * @param wb * @return */public static XSSFCellStyle tableNameCellStyle(XSSFWorkbook wb) {XSSFCellStyle cellStyle = wb.createCellStyle();cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直对齐XSSFFont headerFont1 = wb.createFont(); // 创建字体样式headerFont1.setBold(true); //字体加粗headerFont1.setFontName("黑体"); // 设置字体类型headerFont1.setFontHeightInPoints((short) 12); // 设置字体大小cellStyle.setFont(headerFont1); // 为标题样式设置字体样式return cellStyle;}/** * 创建标题样式 * * @param wb * @return */private static XSSFCellStyle createTitleCellStyle(XSSFWorkbook wb) {XSSFCellStyle cellStyle = wb.createCellStyle();cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直对齐cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());//背景颜色cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);cellStyle.setBorderBottom(BorderStyle.THIN); //下边框cellStyle.setBorderLeft(BorderStyle.THIN); //左边框cellStyle.setBorderRight(BorderStyle.THIN); //右边框cellStyle.setBorderTop(BorderStyle.THIN); //上边框XSSFFont headerFont1 = wb.createFont(); // 创建字体样式//headerFont1.setBold(true); //字体加粗headerFont1.setFontName("黑体"); // 设置字体类型headerFont1.setFontHeightInPoints((short) 12); // 设置字体大小cellStyle.setFont(headerFont1); // 为标题样式设置字体样式return cellStyle;}/** * 创建内容样式 * * @param wb * @return */private static XSSFCellStyle createContentCellStyle(XSSFWorkbook wb) {XSSFCellStyle cellStyle = wb.createCellStyle();cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中cellStyle.setAlignment(HorizontalAlignment.CENTER);// 水平居中cellStyle.setWrapText(true);// 设置自动换行cellStyle.setBorderBottom(BorderStyle.THIN); //下边框cellStyle.setBorderLeft(BorderStyle.THIN); //左边框cellStyle.setBorderRight(BorderStyle.THIN); //右边框cellStyle.setBorderTop(BorderStyle.THIN); //上边框// 生成12号字体XSSFFont font = wb.createFont();font.setColor((short) 8);font.setFontHeightInPoints((short) 12);cellStyle.setFont(font);return cellStyle;}}
完整代码地址:https://gitee.com/Szw99/create-excel.git