maven依赖引入
<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>
代码示例
public class ExportChart {
public static void main(String[] args) throws Exception {
testCreateChart();
}
public static void testCreateChart() throws Exception {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
String sheetName = "温度折线图";
XSSFSheet sheet = wb.createSheet(sheetName);
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 2, 4, 30, 50);
XSSFChart chart = drawing.createChart(anchor);
chart.setTitleText("单据: ****运输过程温度数据 车牌:豫P12345");
chart.setTitleOverlay(false);
setChartTitleFontSize(chart, 16);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
xAxis.setTitle("采集时间");
setAxisTitleFontSize(xAxis, 16);
XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.TOP);
yAxis.setTitle("温度");
yAxis.setMajorUnit(5);
setAxisTitleFontSize(yAxis, 16);
List<TemperatureModel> list = getResult();
List<String> xTitleData = new ArrayList<>(list.size());
List<Double> yData1 = new ArrayList<>(list.size());
List<Double> yData2 = new ArrayList<>(list.size());
List<Double> yData3 = new ArrayList<>(list.size());
for (TemperatureModel layer : list) {
xTitleData.add(layer.getGatherTime());
yData1.add(layer.getTemperature() == null ? 0D : layer.getTemperature());
yData2.add(layer.getTemperature2() == null ? 0D : layer.getTemperature2());
yData3.add(layer.getTemperature3() == null ? 0D : layer.getTemperature3());
}
XDDFDataSource<String> date = XDDFDataSourcesFactory.fromArray(xTitleData.toArray(new String[0]));
XDDFNumericalDataSource<Double> one = XDDFDataSourcesFactory.fromArray(yData1.toArray(new Double[0]));
XDDFNumericalDataSource<Double> two = XDDFDataSourcesFactory.fromArray(yData2.toArray(new Double[0]));
XDDFNumericalDataSource<Double> three = XDDFDataSourcesFactory.fromArray(yData3.toArray(new Double[0]));
XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, xAxis, yAxis);
XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(date, one);
series1.setTitle("温度1(℃)", null);
series1.setSmooth(true);
series1.setMarkerStyle(MarkerStyle.CIRCLE);
XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(date, two);
series2.setTitle("温度2(℃)", null);
series2.setSmooth(true);
series2.setMarkerStyle(MarkerStyle.CIRCLE);
chart.plot(data);
XDDFLineChartData.Series series3 = (XDDFLineChartData.Series) data.addSeries(date, three);
series3.setTitle("温度3(℃)", null);
series3.setSmooth(true);
series3.setMarkerStyle(MarkerStyle.CIRCLE);
chart.plot(data);
try (FileOutputStream fileOut = new FileOutputStream("d:/豫P12345运输温度折线图.xlsx")) {
wb.write(fileOut);
wb.close();
}
}
}
public static List<TemperatureModel> getResult() {
List<TemperatureModel> list = new ArrayList<>();
for (int i = 0; i < 30; i++) {
ExportChart.TemperatureModel temperatureModel = new ExportChart.TemperatureModel();
temperatureModel.setGatherTime("2024-06-03 10:" + String.format("%02d", i * 2) + ":00");
temperatureModel.setTemperature(i % 2 == 0 ? -RandomUtils.nextDouble(0, 30) : RandomUtils.nextDouble(0, 30));
temperatureModel.setTemperature2(RandomUtils.nextDouble(0, 30));
temperatureModel.setTemperature3(i % 2 == 0 ? -RandomUtils.nextDouble(0, 30) : RandomUtils.nextDouble(0, 30));
list.add(temperatureModel);
}
return list;
}
private static void setChartTitleFontSize(XSSFChart chart, double fontSize) {
CTChart ctChart = chart.getCTChart();
if (ctChart.isSetTitle()) {
CTTitle title = ctChart.getTitle();
if (title.isSetTx()) {
CTTextBody rich = title.getTx().getRich();
CTTextParagraph para = rich.getPArray(0);
CTTextCharacterProperties rPr = para.getRArray(0).getRPr();
rPr.setSz((int) (fontSize * 100));
}
}
}
private static void setAxisTitleFontSize(XDDFCategoryAxis axis, double fontSize) {
try {
Field ctCatAx1 = XDDFCategoryAxis.class.getDeclaredField("ctCatAx");
ctCatAx1.setAccessible(true);
CTCatAx ctCatAx = (CTCatAx) ctCatAx1.get(axis);
if (ctCatAx.isSetTitle()) {
CTTitle title = ctCatAx.getTitle();
if (title.isSetTx()) {
CTTextBody rich = title.getTx().getRich();
if (rich != null && rich.sizeOfPArray() > 0) {
CTTextParagraph para = rich.getPArray(0);
if (para.sizeOfRArray() > 0) {
CTTextCharacterProperties rPr = para.getRArray(0).getRPr();
if (rPr == null) {
rPr = para.getRArray(0).addNewRPr();
}
rPr.setSz((int) (fontSize * 100));
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void setAxisTitleFontSize(XDDFValueAxis axis, double fontSize) {
try {
Field ctValAx1 = XDDFValueAxis.class.getDeclaredField("ctValAx");
ctValAx1.setAccessible(true);
CTValAx ctValAx = (CTValAx) ctValAx1.get(axis);
if (ctValAx.isSetTitle()) {
CTTitle title = ctValAx.getTitle();
if (title.isSetTx()) {
CTTextBody rich = title.getTx().getRich();
if (rich != null && rich.sizeOfPArray() > 0) {
CTTextParagraph para = rich.getPArray(0);
if (para.sizeOfRArray() > 0) {
CTTextCharacterProperties rPr = para.getRArray(0).getRPr();
if (rPr == null) {
rPr = para.getRArray(0).addNewRPr();
}
rPr.setSz((int) (fontSize * 100));
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Data
public static class TemperatureModel {
private String gatherTime;
private Double temperature;
private Double temperature2;
private Double temperature3;
}
}
导出效果图

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)