1、导出大量数据到excel

  1. package com.sgcc.hpc.dc.util;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.apache.poi.ss.usermodel.*;
  4. import org.apache.poi.ss.util.CellRangeAddress;
  5. import org.apache.poi.xssf.streaming.SXSSFSheet;
  6. import org.apache.poi.xssf.streaming.SXSSFWorkbook;
  7. import java.io.FileOutputStream;
  8. import java.time.LocalDateTime;
  9. import java.time.format.DateTimeFormatter;
  10. import java.util.HashMap;
  11. import java.util.Map;
  12. import java.util.concurrent.*;
  13. import java.util.concurrent.atomic.AtomicInteger;
  14. /**
  15. * @Author: 李孟帅
  16. * @CreateTime: 2021/5/11$ 10:35$
  17. * @Description: TODO
  18. */
  19. @Slf4j
  20. public class Poi {
  21. private final static DateTimeFormatter PATTERN = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
  22. private final SXSSFWorkbook workbook;
  23. private SXSSFSheet sheet;
  24. private final String fileName;
  25. private final AtomicInteger size = new AtomicInteger(0);
  26. public Poi(String fileName) {
  27. this.fileName = fileName;
  28. // 1.创建工作簿
  29. // 阈值,内存中的对象数量最大值,超过这个值会生成一个临时文件存放到硬盘中
  30. workbook = new SXSSFWorkbook(1000);
  31. }
  32. public AtomicInteger getSize() {
  33. return size;
  34. }
  35. public void createSheet() {
  36. createSheet("sheet" + workbook.getNumberOfSheets());
  37. }
  38. public void createSheet(String sheetName) {
  39. //2.在Workbook中添加一个sheet,对应Excel文件中的sheet
  40. sheet = workbook.createSheet(sheetName);
  41. //3.设置样式以及字体样式
  42. CellStyle titleCellStyle = createTitleCellStyle();
  43. CellStyle headCellStyle = createHeadCellStyle();
  44. //4.创建标题、表头,内容和合并单元格等操作
  45. int rowNum = 0;// 行号
  46. // 创建第一行,索引从0开始
  47. Row row0 = this.sheet.createRow(rowNum++);
  48. row0.setHeight((short) 800);// 设置行高
  49. String title = "这里是标题标题标题";
  50. Cell c00 = row0.createCell(0);
  51. c00.setCellValue(title);
  52. c00.setCellStyle(titleCellStyle);
  53. // 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
  54. this.sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 2));
  55. // 第二行
  56. Row row1 = this.sheet.createRow(rowNum++);
  57. row1.setHeight((short) 500);
  58. String[] row_first = {"采集点的标识", "采集点的值", "采集时间"};
  59. for (int i = 0; i < row_first.length; i++) {
  60. Cell tempCell = row1.createCell(i);
  61. tempCell.setCellValue(row_first[i]);
  62. tempCell.setCellStyle(headCellStyle);
  63. }
  64. }
  65. private CellStyle createTitleCellStyle() {
  66. CellStyle cellStyle = createCellStyle();
  67. cellStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.index);
  68. cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
  69. return cellStyle;
  70. }
  71. private CellStyle createHeadCellStyle() {
  72. CellStyle cellStyle = createCellStyle();
  73. cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);
  74. cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
  75. return cellStyle;
  76. }
  77. private CellStyle createCellStyle() {
  78. CellStyle cellStyle = workbook.createCellStyle();
  79. cellStyle.setAlignment(HorizontalAlignment.CENTER);
  80. cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
  81. cellStyle.setBorderBottom(BorderStyle.THIN);
  82. cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);
  83. cellStyle.setBorderLeft(BorderStyle.THIN);
  84. cellStyle.setLeftBorderColor(IndexedColors.BLACK.index);
  85. cellStyle.setBorderRight(BorderStyle.THIN);
  86. cellStyle.setRightBorderColor(IndexedColors.BLACK.index);
  87. cellStyle.setBorderTop(BorderStyle.THIN);
  88. cellStyle.setTopBorderColor(IndexedColors.BLACK.index);
  89. return cellStyle;
  90. }
  91. public void write(BlockingQueue<Map<String, String>> queue) {
  92. try {
  93. // int rowNum = this.sheet.getLastRowNum() + 1;
  94. while (true) {
  95. Map<String, String> take = queue.take();
  96. String code = take.get("code");
  97. SXSSFSheet sheet = workbook.getSheet(code);
  98. if (sheet == null) {
  99. createSheet(code);
  100. }
  101. sheet = workbook.getSheet(code);
  102. int rowNum = sheet.getLastRowNum() + 1;
  103. Row tempRow = sheet.createRow(rowNum);
  104. tempRow.setHeight((short) 500);
  105. // 循环单元格填入数据
  106. for (int j = 0; j < 3; j++) {
  107. Cell tempCell = tempRow.createCell(j);
  108. tempCell.setCellStyle(createCellStyle());
  109. String tempValue;
  110. if (j == 0) {
  111. tempValue = take.get("code");
  112. } else if (j == 1) {
  113. tempValue = take.get("value");
  114. } else {
  115. tempValue = take.get("time");
  116. }
  117. tempCell.setCellValue(tempValue);
  118. //设置列宽,必须在单元格设值以后进行
  119. sheet.setColumnWidth(0, 4000);
  120. sheet.setColumnWidth(1, 3000);
  121. sheet.setColumnWidth(2, 3000);
  122. }
  123. int num = this.size.incrementAndGet();
  124. if (num == 10000) {
  125. break;
  126. }
  127. }
  128. } catch (InterruptedException e) {
  129. log.warn(e.getMessage());
  130. }
  131. }
  132. public void flush() {
  133. //导出
  134. try {
  135. FileOutputStream outputStream = new FileOutputStream(fileName);
  136. workbook.write(outputStream);
  137. workbook.close();
  138. outputStream.close();
  139. } catch (Exception e) {
  140. e.printStackTrace();
  141. }
  142. }
  143. public static void main(String[] args) throws InterruptedException {
  144. LocalDateTime now = LocalDateTime.now();
  145. ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 30, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
  146. // ArrayBlockingQueue<Map<String, String>> queue = new ArrayBlockingQueue<>(1024);
  147. LinkedBlockingQueue<Map<String, String>> queue = new LinkedBlockingQueue<>(10240);
  148. ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
  149. AtomicInteger index = new AtomicInteger(0);
  150. String basePath = "C:\\Users\\lms\\Desktop\\";
  151. scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
  152. // 当文件个数超过10个时,会覆盖旧的文件
  153. if (index.get()==10){
  154. index.set(0);
  155. }
  156. String fileName = basePath + "报表文件名称-" + index.incrementAndGet() + ".xlsx";
  157. Poi poi = new Poi(fileName);
  158. long start = System.currentTimeMillis();
  159. poi.write(queue);
  160. log.warn("数据10000条了,开始写入磁盘!");
  161. poi.flush();
  162. log.warn("写入excel时间:{}ms,队列中还有元素个数:{}", System.currentTimeMillis() - start, queue.size());
  163. }, 10, 1000, TimeUnit.MILLISECONDS);
  164. while (true) {
  165. int count = 1;
  166. for (int i = 0; i < 10; i++) {
  167. HashMap<String, String> map = new HashMap<>();
  168. String format = now.plusSeconds(count++).format(PATTERN);
  169. map.put("code", "inputRegister-1");
  170. map.put("value", String.valueOf(i * 10 + 0.23));
  171. map.put("time", format);
  172. queue.put(map);
  173. }
  174. for (int i = 8; i >= 0; i--) {
  175. HashMap<String, String> map = new HashMap<>();
  176. String format = now.plusSeconds(count++).format(PATTERN);
  177. map.put("code", "inputRegister-2");
  178. map.put("value", String.valueOf(i * 10 + 0.23));
  179. map.put("time", format);
  180. queue.put(map);
  181. }
  182. Thread.sleep(10);
  183. // break;
  184. }
  185. }
  186. }

2、绘制xy散点图

  1. package com.sgcc.lms.easypoi.util;
  2. import org.apache.poi.openxml4j.util.ZipSecureFile;
  3. import org.apache.poi.ss.usermodel.ClientAnchor;
  4. import org.apache.poi.ss.util.CellRangeAddress;
  5. import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
  6. import org.apache.poi.xddf.usermodel.chart.*;
  7. import org.apache.poi.xssf.usermodel.XSSFChart;
  8. import org.apache.poi.xssf.usermodel.XSSFDrawing;
  9. import org.apache.poi.xssf.usermodel.XSSFSheet;
  10. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  11. import java.io.File;
  12. import java.io.FileInputStream;
  13. import java.io.FileOutputStream;
  14. import java.io.InputStream;
  15. public class XSSFUtils {
  16. public static void main(String[] args) throws Exception {
  17. String tmpFileName = "C:\\Users\\lms\\Desktop\\RTU采集数据_ankong_5.xlsx";
  18. File file = new File(tmpFileName);
  19. System.out.println(file.exists());
  20. InputStream fis = new FileInputStream(file);
  21. ZipSecureFile.setMinInflateRatio(-1.0d);
  22. XSSFWorkbook wb = new XSSFWorkbook(fis);
  23. // SXSSFWorkbook workbook = new SXSSFWorkbook(wb);
  24. XSSFSheet sheet = wb.getSheetAt(0);
  25. //创建一个画布
  26. XSSFDrawing drawing = sheet.createDrawingPatriarch();
  27. //前四个默认0,[5,20]:从5列0行开始;[0,15]:宽度15个单元格,15向下扩展到第15行 左上角[0,5] -> 右下角[15,20]
  28. ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 5, 1, 20, 15);
  29. //创建一个chart对象
  30. XSSFChart chart = drawing.createChart(anchor);
  31. //标题
  32. chart.setTitleText("code");
  33. //标题覆盖
  34. chart.setTitleOverlay(false);
  35. //图例位置
  36. XDDFChartLegend legend = chart.getOrAddLegend();
  37. legend.setPosition(LegendPosition.TOP);
  38. //分类轴标(X轴),标题位置
  39. //****** 如果是多条线,且X轴时数值类型的,切记::::要用XDDFValueAxis
  40. XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.TOP);
  41. bottomAxis.setTitle("time");
  42. XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.BOTTOM);
  43. leftAxis.setTitle("value");
  44. //CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)
  45. //分类轴标(X轴)数据,单元格范围位置[0, 0]到[0, 6]
  46. XDDFNumericalDataSource<Double> x = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 1600, 2, 2));
  47. XDDFNumericalDataSource<Double> y = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 1600, 1, 1));
  48. //scatter:XY散点图
  49. XDDFScatterChartData scatter = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis);
  50. // 设置y轴刻度的样式
  51. leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
  52. leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
  53. XDDFScatterChartData.Series series1 = (XDDFScatterChartData.Series) scatter.addSeries(x, y);
  54. //条形图例标题
  55. series1.setTitle("code", null);
  56. XDDFSolidFillProperties fill = new XDDFSolidFillProperties();
  57. //条形图,填充颜色
  58. series1.setFillProperties(fill);
  59. //绘制
  60. chart.plot(scatter);
  61. FileOutputStream fileOut = new FileOutputStream(tmpFileName);
  62. wb.write(fileOut);
  63. wb.close();
  64. }
  65. }