浏览代码

断纱分析专题

wukai 9 月之前
父节点
当前提交
fa97b39001

+ 8 - 200
ruoyi-admin/src/main/java/com/ruoyi/biz/controller/ApiController.java

@@ -3,6 +3,7 @@ package com.ruoyi.biz.controller;
 import com.ruoyi.biz.domain.*;
 import com.ruoyi.biz.service.*;
 import com.ruoyi.biz.service.impl.AsyncServiceImpl;
+import com.ruoyi.biz.service.impl.BrokenYarnExportServiceImpl;
 import com.ruoyi.biz.tools.Tools;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.controller.BaseController;
@@ -67,6 +68,8 @@ public class ApiController extends BaseController {
     private ITwinPanHeadInfoService panHeadInfoService;
     @Resource
     private ISysConfigService configService;
+    @Resource
+    private BrokenYarnExportServiceImpl exportService;
     @Value("${excel.total}")
     private String totalExcelTemplate;
     @Value("${excel.formula}")
@@ -489,208 +492,13 @@ public class ApiController extends BaseController {
     @CrossOrigin(origins = "*")
     public void brokenYarnExport(String date, HttpServletResponse response) throws ParseException {
         LocalDate localDate = LocalDate.parse(date);
-        LocalDate st = localDate.minusDays(7);
-        Date sd = Date.from(st.atStartOfDay(ZoneOffset.of("+8")).toInstant());
-        Date ed = Date.from(localDate.atStartOfDay(ZoneOffset.of("+8")).toInstant());
-        //7天数据
-        List<TwinCalcDay> dayList = twinCalcDayService.selectTwinCalcDayListByTime(sd, ed);
-        Map<Date, List<TwinCalcDay>> dayGroup = dayList.stream().collect(Collectors.groupingBy(TwinCalcDay::getTime, LinkedHashMap::new, Collectors.toList()));
-        List<TwinCalcDay> jdl = new ArrayList<>();
-        for (Map.Entry<Date, List<TwinCalcDay>> entry : dayGroup.entrySet()) {
-            TwinCalcDay day = new TwinCalcDay(entry.getKey());
-            List<TwinCalcDay> days = entry.getValue();
-            day.calcDays(days);
-            jdl.add(day);
-        }
-        //当天数据
-        List<TwinCalcDay> curr = dayList.stream().filter(day -> day.getTime().equals(ed)).collect(Collectors.toList());
-        LocalDateTime sdt = LocalDateTime.of(localDate, LocalTime.of(7, 0));
-        LocalDateTime edt = LocalDateTime.of(localDate.plusDays(1), LocalTime.of(6, 59, 59));
-        Date sTime = Date.from(sdt.atZone(ZoneId.systemDefault()).toInstant());
-        Date eTime = Date.from(edt.atZone(ZoneId.systemDefault()).toInstant());
-        List<TwinCalcStop> stopList = stopService.selectTwinCalcStopListByDate(sTime, eTime);
-        Map<Integer, List<TwinCalcStop>> stopDeviceGroup = stopList.stream().collect(Collectors.groupingBy(TwinCalcStop::getStopType, LinkedHashMap::new, Collectors.toList()));
-
-        List<TwinCalcStop> yarnStopList = stopList.stream().filter(stop -> stop.getStopType().equals(2)).collect(Collectors.toList());
-        Map<Long, TwinDevice> deviceMap = deviceService.deviceMap();
-        //1停经片停机,2-CCD停机(相机号+断纱/故障),3-人工停机,4-断电停机,5-设备故障停机,6-落布米数达到停机,7-盘头剩余圈数达到停机
-        String[] stopStr = {"停经片停机", "CCD停机(相机号+断纱/故障)", "人工停机", "断电停机", "设备故障停机", "落布米数达到停机", "盘头剩余圈数达到停机"};
-        //停机次数
-        Integer[] stopNum = new Integer[7];
-        Integer totalNum = 0;
-        //停机时间
-        Long[] stopTime = new Long[7];
-        Arrays.fill(stopTime, 0L);
-        AtomicReference<Long> totalTime = new AtomicReference<>(0L);
-        for (Map.Entry<Integer, List<TwinCalcStop>> entry : stopDeviceGroup.entrySet()) {
-            Integer stopType = entry.getKey();
-            int pos = stopType - 1;
-            List<TwinCalcStop> stops = entry.getValue();
-            stopNum[pos] = stops.size();
-            totalNum += stops.size();
-            stops.forEach(stop -> {
-                Date stopEndTime = stop.getEndTime();
-                // 调整停机时间
-                if (stop.getEndTime().compareTo(eTime) > 0) {
-                    stopEndTime = eTime;
-                }
-                Date stopStartTime = stop.getStartTime();
-                //调整开机时间
-                if (stop.getStartTime().compareTo(sTime) < 0) {
-                    stopStartTime = sTime;
-                }
-                long t = (stopEndTime.getTime() - stopStartTime.getTime()) / 1000;
-                stopTime[pos] += t;
-                totalTime.updateAndGet(v -> v + t);
-            });
-        }
-        try (FileInputStream inputStream = new FileInputStream(brokenYarnExcelTemplate); Workbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
-            CreationHelper creationHelper = wb.getCreationHelper();
-            CellStyle percentStyle = wb.createCellStyle();
-            percentStyle.setDataFormat(creationHelper.createDataFormat().getFormat("0.00%"));
-            CellStyle p2 = wb.createCellStyle();
-            p2.setDataFormat(wb.createDataFormat().getFormat("0.00"));
-            CellStyle dateStyle = wb.createCellStyle();
-            dateStyle.setDataFormat(creationHelper.createDataFormat().getFormat(DateUtils.YYYY_MM_DD));
-            CellStyle timeStyle = wb.createCellStyle();
-            timeStyle.setDataFormat(creationHelper.createDataFormat().getFormat(DateUtils.YYYY_MM_DD_HH_MM_SS));
-            CellStyle rightStyle = wb.createCellStyle();
-            rightStyle.setAlignment(HorizontalAlignment.RIGHT);
-            //1.基本信息
-            Sheet sheet = wb.getSheetAt(0);
-            Cell cell = sheet.getRow(1).getCell(1);
-            cell.setCellValue(localDate);
-
-            //计算开机设备数量,A班开机时间+B班开机时间大于0的。
-            //按设备分组
-            Map<Long, List<TwinCalcDay>> deviceGr = curr.stream().collect(Collectors.groupingBy(TwinCalcDay::getDeviceId, LinkedHashMap::new, Collectors.toList()));
-            int openDevices = 0;
-            BigDecimal totOpenTimes = BigDecimal.ZERO;
-            for (Map.Entry<Long, List<TwinCalcDay>> entry1 : deviceGr.entrySet()) {
-                TwinCalcDay tempDay = new TwinCalcDay(ed);
-                tempDay.calcDays(entry1.getValue());
-                BigDecimal tot = tempDay.getOpenTimeA().add(tempDay.getOpenTimeB());
-                if (tot.intValue() > 0) {
-                    openDevices++;
-                }
-                totOpenTimes = totOpenTimes.add(tot);
-            }
-
-            cell = sheet.getRow(2).getCell(1);
-            cell.setCellValue(openDevices);
-            BigDecimal avgOpenTimes = totOpenTimes.divide(BigDecimal.valueOf(openDevices), 0, RoundingMode.HALF_UP);
-
-            cell = sheet.getRow(3).getCell(1);
-            cell.setCellValue(Tools.convertHMS(totOpenTimes.longValue()));
-            cell = sheet.getRow(4).getCell(1);
-            cell.setCellValue(Tools.convertHMS(avgOpenTimes.longValue()));
-            cell = sheet.getRow(5).getCell(1);
-            cell.setCellValue(33);
+        try (FileInputStream inputStream = new FileInputStream(brokenYarnExcelTemplate); XSSFWorkbook wb = new XSSFWorkbook(inputStream); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
+            //1.基本信息表
+            exportService.base(wb, localDate);
             //2.停机原因分析
-            sheet = wb.getSheetAt(1);
-            for (int i = 0; i < stopStr.length; i++) {
-                Row row = sheet.createRow(i + 2);
-                Cell[] cells = new Cell[5];
-                for (int j = 0; j < cells.length; j++) {
-                    cells[j] = row.createCell(j);
-                }
-                cells[0].setCellValue(stopStr[i]);
-                cells[1].setCellValue(stopNum[i]);
-                cells[2].setCellValue(Tools.convertHMS(stopTime[i]));
-                cells[2].setCellStyle(rightStyle);
-                float percentNum = BigDecimal.valueOf(stopNum[i]).divide(BigDecimal.valueOf(totalNum), 4, RoundingMode.HALF_UP).floatValue();
-                float percentTimes = BigDecimal.valueOf(stopTime[i]).divide(BigDecimal.valueOf(totalTime.get()), 4, RoundingMode.HALF_UP).floatValue();
-                cells[3].setCellValue(percentNum);
-                cells[3].setCellStyle(percentStyle);
-                cells[4].setCellValue(percentTimes);
-                cells[4].setCellStyle(percentStyle);
-            }
-            //3.断纱分析
-            sheet = wb.getSheetAt(2);
-            int yst = yarnStopList.size();
-            cell = sheet.getRow(1).getCell(1);
-            cell.setCellValue(yst);
-            Map<Long, List<TwinCalcStop>> deviceGroup = yarnStopList.stream().collect(Collectors.groupingBy(TwinCalcStop::getDeviceId, LinkedHashMap::new, Collectors.toList()));
-            cell = sheet.getRow(2).getCell(1);
-            cell.setCellValue(deviceGroup.size());
-            float bl = 0f;
-            long aavg = 0;
-            if (yst > 0) {
-                bl = BigDecimal.valueOf(yst).divide(BigDecimal.valueOf(stopList.size()), 4, RoundingMode.HALF_UP).floatValue();
-                aavg = stopTime[1] / yst;
-            }
-            cell = sheet.getRow(3).getCell(1);
-            cell.setCellValue(bl);
-
-            cell = sheet.getRow(4).getCell(1);
-            cell.setCellValue(Tools.convertHMS(stopTime[1]));
-            cell = sheet.getRow(5).getCell(1);
-            cell.setCellValue(Tools.convertHMS(aavg));
+            exportService.stop(wb, localDate);
             //4.断纱停机TOP排名
-            sheet = wb.getSheetAt(3);
-            //5.并发断纱分析
-            sheet = wb.getSheetAt(4);
-            int rowNum = 1;
-            int rn = 2;
-            yarnStopList.sort(Comparator.comparing(TwinCalcStop::getDataDate).thenComparing(TwinCalcStop::getHour));
-            Map<Date, Map<Integer, List<TwinCalcStop>>> stopHourGroup = yarnStopList.stream().collect(
-                    Collectors.groupingBy(TwinCalcStop::getDataDate, LinkedHashMap::new,
-                            Collectors.groupingBy(TwinCalcStop::getHour, LinkedHashMap::new, Collectors.toList())));
-            for (Map.Entry<Date, Map<Integer, List<TwinCalcStop>>> entry : stopHourGroup.entrySet()) {
-                Map<Integer, List<TwinCalcStop>> map = entry.getValue();
-                for (Map.Entry<Integer, List<TwinCalcStop>> entry1 : map.entrySet()) {
-                    List<TwinCalcStop> stops = entry1.getValue();
-                    Row row = sheet.createRow(rowNum);
-                    Cell[] cells = new Cell[7];
-                    for (int j = 0; j < cells.length; j++) {
-                        cells[j] = row.createCell(j);
-                    }
-                    cells[0].setCellValue(entry.getKey());
-                    cells[0].setCellStyle(dateStyle);
-                    cells[1].setCellValue(entry1.getKey());
-                    Map<Long, List<TwinCalcStop>> yarnDeviceGroup = stops.stream().collect(Collectors.groupingBy(TwinCalcStop::getDeviceId, LinkedHashMap::new, Collectors.toList()));
-                    cells[2].setCellValue(yarnDeviceGroup.size());
-                    int num = stops.size();
-                    cells[3].setCellValue(num);
-                    //0.最小,1.最大,2.总时间
-                    final long[] time = {999999L, 0, 0};
-                    //6.设备断纱停机详情
-                    Sheet sheet6 = wb.getSheetAt(5);
-                    for (TwinCalcStop stop : stops) {
-                        long t = (stop.getEndTime().getTime() - stop.getStartTime().getTime()) / 1000;
-                        if (t < time[0]) {
-                            time[0] = t;
-                        }
-                        if (t > time[1]) {
-                            time[1] = t;
-                        }
-                        time[2] += t;
-
-                        Row r1 = sheet6.createRow(rn);
-                        Cell[] cs = new Cell[6];
-                        for (int j = 0; j < cs.length; j++) {
-                            cs[j] = r1.createCell(j);
-                        }
-                        cs[0].setCellValue(stop.getDataDate());
-                        cs[0].setCellStyle(dateStyle);
-                        cs[1].setCellValue(stop.getHour());
-                        cs[2].setCellValue(deviceMap.get(stop.getDeviceId()).getDeviceName());
-                        cs[3].setCellValue(stopStr[stop.getStopType() - 1]);
-                        cs[4].setCellValue(stop.getStartTime());
-                        cs[4].setCellStyle(timeStyle);
-                        cs[5].setCellValue(stop.getEndTime());
-                        cs[5].setCellStyle(timeStyle);
-                        rn++;
-                    }
-
-                    cells[4].setCellValue(time[1]);
-                    cells[5].setCellValue(time[0]);
-                    float avg = BigDecimal.valueOf(time[2]).divide(BigDecimal.valueOf(num), 2, RoundingMode.HALF_UP).floatValue();
-                    cells[6].setCellValue(avg);
-                    cells[6].setCellStyle(p2);
-                    rowNum++;
-                }
-            }
+            exportService.top(wb, localDate);
             // 清空response
             response.reset();
             // 设置response的Header

+ 33 - 0
ruoyi-admin/src/main/java/com/ruoyi/biz/tools/Tools.java

@@ -269,4 +269,37 @@ public class Tools {
         }
     }
 
+    /**
+     * 秒转换成 xxx分xx秒
+     *
+     * @param x x
+     * @return 结果
+     */
+    public static String convertMS(long x) {
+        long minutes = x / 60;
+        // 分钟差
+        long seconds = x % 60;
+        // 秒数差,不包括分钟的秒数
+        return minutes + "分" + (seconds > 10 ? seconds : "0" + seconds) + "秒";
+    }
+
+    /**
+     * 秒转换成 xxx分xx秒
+     *
+     * @param x x
+     * @return 结果
+     */
+    public static String convertHMS(long x) {
+        long hour = x / 60 / 60;
+        long minutes = x / 60 % 60;
+        // 分钟差
+        long seconds = x % 60;
+        // 秒数差,不包括分钟的秒数
+        String str = minutes + "分" + (seconds > 10 ? seconds : "0" + seconds) + "秒";
+        if (hour > 0) {
+            str = hour + "小时" + str;
+        }
+        return str;
+    }
+
 }

+ 1 - 0
ruoyi-admin/src/main/resources/application.yml

@@ -15,6 +15,7 @@ excel:
   stopsType: D:\SYSTEM\Desktop\temp\excel\stopsType.xlsx
   alarms: D:\SYSTEM\Desktop\temp\excel\alarms.xlsx
   yarn: D:\SYSTEM\Desktop\temp\excel\yarn.xlsx
+  brokenYarn: D:\SYSTEM\Desktop\temp\excel\brokenYarn.xlsx
 #数据补录
 data:
   bl: false

+ 193 - 0
ruoyi-admin/src/test/java/com/jjt/excel/ApachePoiBarChart5.java

@@ -0,0 +1,193 @@
+package com.jjt.excel;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xddf.usermodel.PresetColor;
+import org.apache.poi.xddf.usermodel.XDDFColor;
+import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
+import org.apache.poi.xddf.usermodel.chart.AxisCrossBetween;
+import org.apache.poi.xddf.usermodel.chart.AxisPosition;
+import org.apache.poi.xddf.usermodel.chart.BarDirection;
+import org.apache.poi.xddf.usermodel.chart.ChartTypes;
+import org.apache.poi.xddf.usermodel.chart.LegendPosition;
+import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
+import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
+import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
+import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
+import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
+import org.apache.poi.xssf.usermodel.XSSFChart;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * POI EXCEL 图表-柱状图
+ */
+public class ApachePoiBarChart5 {
+
+	public static void main(String[] args) throws IOException {
+		XSSFWorkbook wb = new XSSFWorkbook();
+		String sheetName = "Sheet1";
+		FileOutputStream fileOut = null;
+		try {
+			XSSFSheet sheet = wb.createSheet(sheetName);
+			// 第一行,国家名称
+			Row row = sheet.createRow(0);
+			Cell cell = row.createCell(0);
+			cell.setCellValue("俄罗斯");
+			cell = row.createCell(1);
+			cell.setCellValue("加拿大");
+			cell = row.createCell(2);
+			cell.setCellValue("美国");
+			cell = row.createCell(3);
+			cell.setCellValue("中国");
+			cell = row.createCell(4);
+			cell.setCellValue("巴西");
+			cell = row.createCell(5);
+			cell.setCellValue("澳大利亚");
+			cell = row.createCell(6);
+			cell.setCellValue("印度");
+			// 第二行,乡村地区
+			row = sheet.createRow(1);
+			cell = row.createCell(0);
+			cell.setCellValue(17098242);
+			cell = row.createCell(1);
+			cell.setCellValue(9984670);
+			cell = row.createCell(2);
+			cell.setCellValue(9826675);
+			cell = row.createCell(3);
+			cell.setCellValue(9596961);
+			cell = row.createCell(4);
+			cell.setCellValue(8514877);
+			cell = row.createCell(5);
+			cell.setCellValue(7741220);
+			cell = row.createCell(6);
+			cell.setCellValue(3287263);
+			// 第三行,农村人口
+			row = sheet.createRow(2);
+			cell = row.createCell(0);
+			cell.setCellValue(14590041);
+			cell = row.createCell(1);
+			cell.setCellValue(35151728);
+			cell = row.createCell(2);
+			cell.setCellValue(32993302);
+			cell = row.createCell(3);
+			cell.setCellValue(14362887);
+			cell = row.createCell(4);
+			cell.setCellValue(21172141);
+			cell = row.createCell(5);
+			cell.setCellValue(25335727);
+			cell = row.createCell(6);
+			cell.setCellValue(13724923);
+			// 第四行,面积平局
+			row = sheet.createRow(3);
+			cell = row.createCell(0);
+			cell.setCellValue(9435701.143);
+			cell = row.createCell(1);
+			cell.setCellValue(9435701.143);
+			cell = row.createCell(2);
+			cell.setCellValue(9435701.143);
+			cell = row.createCell(3);
+			cell.setCellValue(9435701.143);
+			cell = row.createCell(4);
+			cell.setCellValue(9435701.143);
+			cell = row.createCell(5);
+			cell.setCellValue(9435701.143);
+			cell = row.createCell(6);
+			cell.setCellValue(9435701.143);
+			// 第四行,人口平局
+			row = sheet.createRow(4);
+			cell = row.createCell(0);
+			cell.setCellValue(22475821.29);
+			cell = row.createCell(1);
+			cell.setCellValue(22475821.29);
+			cell = row.createCell(2);
+			cell.setCellValue(22475821.29);
+			cell = row.createCell(3);
+			cell.setCellValue(22475821.29);
+			cell = row.createCell(4);
+			cell.setCellValue(22475821.29);
+			cell = row.createCell(5);
+			cell.setCellValue(22475821.29);
+			cell = row.createCell(6);
+			cell.setCellValue(22475821.29);
+
+			// 创建一个画布
+			XSSFDrawing drawing = sheet.createDrawingPatriarch();
+			// 前四个默认0,[0,5]:从0列5行开始;[7,26]:到7列26行结束
+			// 默认宽度(14-8)*12
+			XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 7, 26);
+			// 创建一个chart对象
+			XSSFChart chart = drawing.createChart(anchor);
+			// 标题
+			chart.setTitleText("地区排名前七的国家");
+			// 标题覆盖
+			chart.setTitleOverlay(false);
+
+			// 图例位置
+			XDDFChartLegend legend = chart.getOrAddLegend();
+			legend.setPosition(LegendPosition.TOP);
+
+			// 分类轴标(X轴),标题位置
+			XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
+			bottomAxis.setTitle("国家");
+			// 值(Y轴)轴,标题位置
+			XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
+			leftAxis.setTitle("面积大小");
+
+			// CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)
+			// 分类轴标(X轴)数据,单元格范围位置[0, 0]到[0, 6]
+			XDDFDataSource<String> countries = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(0, 0, 0, 6));
+			// XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray(new String[] {"俄罗斯","加拿大","美国","中国","巴西","澳大利亚","印度"});
+			// 数据1,单元格范围位置[1, 0]到[1, 6]
+			XDDFNumericalDataSource<Double> area = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, 6));
+			// XDDFNumericalDataSource<Integer> area = XDDFDataSourcesFactory.fromArray(new Integer[] {17098242,9984670,9826675,9596961,8514877,7741220,3287263});
+
+			// bar:条形图,
+			XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
+
+			leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
+			// 设置为可变颜色
+			bar.setVaryColors(true);// 如果需要设置成自己想要的颜色,这里可变颜色要设置成false
+			// 条形图方向,纵向/横向:纵向
+			bar.setBarDirection(BarDirection.BAR);
+
+			// 图表加载数据,条形图1
+			XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(countries, area);
+			// 条形图例标题
+			series1.setTitle("面积图例", null);
+//			XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.RED));
+//			// 条形图,填充颜色
+//			series1.setFillProperties(fill);
+
+			// 绘制
+			chart.plot(bar);
+			// CTBarSer ser = chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(0);
+			// CTLegend legend2 = chart.getCTChartSpace().getChart().getLegend();//更详细的图例设置
+
+			// 打印图表的xml
+			System.out.println(chart.getCTChart());
+
+			// 将输出写入excel文件
+			String filename = "D:\\SYSTEM\\Desktop\\temp\\tmp\\排行榜前七的国家.xlsx";
+			fileOut = new FileOutputStream(filename);
+			wb.write(fileOut);
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			wb.close();
+			if (fileOut != null) {
+				fileOut.close();
+			}
+		}
+
+	}
+
+}

+ 99 - 0
ruoyi-admin/src/test/java/com/jjt/excel/Test.java

@@ -0,0 +1,99 @@
+package com.jjt.excel;
+
+import org.apache.poi.hssf.record.chart.NumberFormatIndexRecord;
+import org.apache.poi.xddf.usermodel.chart.*;
+import org.apache.poi.xssf.usermodel.*;
+
+import java.io.FileOutputStream;
+import java.text.NumberFormat;
+
+/**
+ * Test$
+ *
+ * @author wukai
+ * @date 2024/10/29 01:55
+ */
+public class Test {
+    public static void main(String[] args) throws Exception {
+        lineChart();
+    }
+    public static void lineChart() throws Exception {
+        try (XSSFWorkbook wb = new XSSFWorkbook()) {
+
+            String sheetName = "折线图";
+            XSSFSheet sheet = wb.createSheet(sheetName);
+            XSSFDrawing drawing = sheet.createDrawingPatriarch();
+            // 2 左侧距离单元格个数, 4 顶部距离单元格个数, 7 左侧距离单元格个数, 26 顶部距离单元格个数
+            XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 2, 4, 9, 26);
+            XSSFChart chart = drawing.createChart(anchor);
+            // 图表标题
+            chart.setTitleText("日总计里程");
+            // 图例是否覆盖标题
+            chart.setTitleOverlay(false);
+            XDDFChartLegend legend = chart.getOrAddLegend();
+            // 图例位置:上下左右
+            legend.setPosition(LegendPosition.TOP_RIGHT);
+            // 创建x轴
+            XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
+            // X轴标题
+            bottomAxis.setTitle("日期");
+            // 创建y轴
+            XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
+            leftAxis.setTitle("单位:%");
+//            leftAxis.setNumberFormat(new NumberFormat());
+            // x轴标题
+            String[] xTitleData = new String[] { "10.01", "10.02", "10.03", "10.04", "10.05", "10.06", "10.07" };
+            XDDFDataSource<String> date = XDDFDataSourcesFactory.fromArray(xTitleData);
+            // y轴数据
+            Integer[] xData1 = new Integer[] { 12020, 11464, 11604, 13154, 11654, 13689, 11235 };
+            Integer[] xData2 = new Integer[] { 11202, 12146, 13604, 13954, 16549, 16886, 16985 };
+            XDDFNumericalDataSource<Integer> oil = XDDFDataSourcesFactory.fromArray(xData1);
+            XDDFNumericalDataSource<Integer> newEnergy = XDDFDataSourcesFactory.fromArray(xData2);
+            // 创建y轴
+            XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
+            XDDFLineChartData.Series series = (XDDFLineChartData.Series) data.addSeries(date, oil);
+            // 图例标题
+            series.setTitle("燃油车", null);
+            // 线条样式:true平滑曲线,false折线
+            series.setSmooth(false);
+            // 点的样式
+            series.setMarkerStyle(MarkerStyle.CIRCLE);
+
+            XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(date, newEnergy);
+            series1.setTitle("新能源车", null);
+            series1.setSmooth(true);
+            series1.setMarkerStyle(MarkerStyle.CIRCLE);
+            chart.plot(data);
+
+            // 第二个折线图
+            XSSFDrawing drawing1 = sheet.createDrawingPatriarch();
+            XSSFClientAnchor anchor1 = drawing1.createAnchor(0, 0, 0, 0, 2, 27, 7, 53);
+            XSSFChart chart1 = drawing.createChart(anchor1);
+            chart1.setTitleText("月总计里程");
+            chart1.setTitleOverlay(false);
+            XDDFChartLegend legend1 = chart1.getOrAddLegend();
+            legend1.setPosition(LegendPosition.TOP);
+            XDDFCategoryAxis bottomAxis1 = chart1.createCategoryAxis(AxisPosition.BOTTOM);
+            bottomAxis1.setTitle("月总计里程");
+            XDDFValueAxis leftAxis1 = chart1.createValueAxis(AxisPosition.LEFT);
+            leftAxis1.setTitle("燃油车 & 新能源车");
+            XDDFDataSource<String> date1 = XDDFDataSourcesFactory.fromArray(new String[] { "2023-01", "2023-02", "2023-03" });
+            XDDFNumericalDataSource<Long> oil1 = XDDFDataSourcesFactory.fromArray(new Long[] { 232658L, 298751L, 254793L });
+            XDDFNumericalDataSource<Long> newEnergy1 = XDDFDataSourcesFactory.fromArray(new Long[] { 213691L, 198743L, 202146L });
+            XDDFLineChartData data1 = (XDDFLineChartData) chart1.createData(ChartTypes.LINE, bottomAxis, leftAxis);
+            XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data1.addSeries(date1, oil1);
+            series2.setTitle("燃油车", null);
+            series2.setSmooth(false);
+            series2.setMarkerStyle(MarkerStyle.CIRCLE);
+            XDDFLineChartData.Series series3 = (XDDFLineChartData.Series) data1.addSeries(date1, newEnergy1);
+            series3.setTitle("新能源车", null);
+            series3.setSmooth(true);
+            series3.setMarkerStyle(MarkerStyle.CIRCLE);
+            chart1.plot(data1);
+            String filename = "D:\\SYSTEM\\Desktop\\temp\\tmp\\折线图.xlsx";
+            try (FileOutputStream fileOut = new FileOutputStream(filename)) {
+                wb.write(fileOut);
+            }
+        }
+    }
+}