1、导出大量数据到excel
package com.sgcc.hpc.dc.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.FileOutputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Author: 李孟帅
* @CreateTime: 2021/5/11$ 10:35$
* @Description: TODO
*/
@Slf4j
public class Poi {
private final static DateTimeFormatter PATTERN = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
private final SXSSFWorkbook workbook;
private SXSSFSheet sheet;
private final String fileName;
private final AtomicInteger size = new AtomicInteger(0);
public Poi(String fileName) {
this.fileName = fileName;
// 1.创建工作簿
// 阈值,内存中的对象数量最大值,超过这个值会生成一个临时文件存放到硬盘中
workbook = new SXSSFWorkbook(1000);
}
public AtomicInteger getSize() {
return size;
}
public void createSheet() {
createSheet("sheet" + workbook.getNumberOfSheets());
}
public void createSheet(String sheetName) {
//2.在Workbook中添加一个sheet,对应Excel文件中的sheet
sheet = workbook.createSheet(sheetName);
//3.设置样式以及字体样式
CellStyle titleCellStyle = createTitleCellStyle();
CellStyle headCellStyle = createHeadCellStyle();
//4.创建标题、表头,内容和合并单元格等操作
int rowNum = 0;// 行号
// 创建第一行,索引从0开始
Row row0 = this.sheet.createRow(rowNum++);
row0.setHeight((short) 800);// 设置行高
String title = "这里是标题标题标题";
Cell c00 = row0.createCell(0);
c00.setCellValue(title);
c00.setCellStyle(titleCellStyle);
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
this.sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 2));
// 第二行
Row row1 = this.sheet.createRow(rowNum++);
row1.setHeight((short) 500);
String[] row_first = {"采集点的标识", "采集点的值", "采集时间"};
for (int i = 0; i < row_first.length; i++) {
Cell tempCell = row1.createCell(i);
tempCell.setCellValue(row_first[i]);
tempCell.setCellStyle(headCellStyle);
}
}
private CellStyle createTitleCellStyle() {
CellStyle cellStyle = createCellStyle();
cellStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.index);
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
return cellStyle;
}
private CellStyle createHeadCellStyle() {
CellStyle cellStyle = createCellStyle();
cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
return cellStyle;
}
private CellStyle createCellStyle() {
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
cellStyle.setBorderBottom(BorderStyle.THIN);
cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);
cellStyle.setBorderLeft(BorderStyle.THIN);
cellStyle.setLeftBorderColor(IndexedColors.BLACK.index);
cellStyle.setBorderRight(BorderStyle.THIN);
cellStyle.setRightBorderColor(IndexedColors.BLACK.index);
cellStyle.setBorderTop(BorderStyle.THIN);
cellStyle.setTopBorderColor(IndexedColors.BLACK.index);
return cellStyle;
}
public void write(BlockingQueue<Map<String, String>> queue) {
try {
// int rowNum = this.sheet.getLastRowNum() + 1;
while (true) {
Map<String, String> take = queue.take();
String code = take.get("code");
SXSSFSheet sheet = workbook.getSheet(code);
if (sheet == null) {
createSheet(code);
}
sheet = workbook.getSheet(code);
int rowNum = sheet.getLastRowNum() + 1;
Row tempRow = sheet.createRow(rowNum);
tempRow.setHeight((short) 500);
// 循环单元格填入数据
for (int j = 0; j < 3; j++) {
Cell tempCell = tempRow.createCell(j);
tempCell.setCellStyle(createCellStyle());
String tempValue;
if (j == 0) {
tempValue = take.get("code");
} else if (j == 1) {
tempValue = take.get("value");
} else {
tempValue = take.get("time");
}
tempCell.setCellValue(tempValue);
//设置列宽,必须在单元格设值以后进行
sheet.setColumnWidth(0, 4000);
sheet.setColumnWidth(1, 3000);
sheet.setColumnWidth(2, 3000);
}
int num = this.size.incrementAndGet();
if (num == 10000) {
break;
}
}
} catch (InterruptedException e) {
log.warn(e.getMessage());
}
}
public void flush() {
//导出
try {
FileOutputStream outputStream = new FileOutputStream(fileName);
workbook.write(outputStream);
workbook.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
LocalDateTime now = LocalDateTime.now();
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 30, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
// ArrayBlockingQueue<Map<String, String>> queue = new ArrayBlockingQueue<>(1024);
LinkedBlockingQueue<Map<String, String>> queue = new LinkedBlockingQueue<>(10240);
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
AtomicInteger index = new AtomicInteger(0);
String basePath = "C:\\Users\\lms\\Desktop\\";
scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
// 当文件个数超过10个时,会覆盖旧的文件
if (index.get()==10){
index.set(0);
}
String fileName = basePath + "报表文件名称-" + index.incrementAndGet() + ".xlsx";
Poi poi = new Poi(fileName);
long start = System.currentTimeMillis();
poi.write(queue);
log.warn("数据10000条了,开始写入磁盘!");
poi.flush();
log.warn("写入excel时间:{}ms,队列中还有元素个数:{}", System.currentTimeMillis() - start, queue.size());
}, 10, 1000, TimeUnit.MILLISECONDS);
while (true) {
int count = 1;
for (int i = 0; i < 10; i++) {
HashMap<String, String> map = new HashMap<>();
String format = now.plusSeconds(count++).format(PATTERN);
map.put("code", "inputRegister-1");
map.put("value", String.valueOf(i * 10 + 0.23));
map.put("time", format);
queue.put(map);
}
for (int i = 8; i >= 0; i--) {
HashMap<String, String> map = new HashMap<>();
String format = now.plusSeconds(count++).format(PATTERN);
map.put("code", "inputRegister-2");
map.put("value", String.valueOf(i * 10 + 0.23));
map.put("time", format);
queue.put(map);
}
Thread.sleep(10);
// break;
}
}
}
2、绘制xy散点图
package com.sgcc.lms.easypoi.util;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
public class XSSFUtils {
public static void main(String[] args) throws Exception {
String tmpFileName = "C:\\Users\\lms\\Desktop\\RTU采集数据_ankong_5.xlsx";
File file = new File(tmpFileName);
System.out.println(file.exists());
InputStream fis = new FileInputStream(file);
ZipSecureFile.setMinInflateRatio(-1.0d);
XSSFWorkbook wb = new XSSFWorkbook(fis);
// SXSSFWorkbook workbook = new SXSSFWorkbook(wb);
XSSFSheet sheet = wb.getSheetAt(0);
//创建一个画布
XSSFDrawing drawing = sheet.createDrawingPatriarch();
//前四个默认0,[5,20]:从5列0行开始;[0,15]:宽度15个单元格,15向下扩展到第15行 左上角[0,5] -> 右下角[15,20]
ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 5, 1, 20, 15);
//创建一个chart对象
XSSFChart chart = drawing.createChart(anchor);
//标题
chart.setTitleText("code");
//标题覆盖
chart.setTitleOverlay(false);
//图例位置
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP);
//分类轴标(X轴),标题位置
//****** 如果是多条线,且X轴时数值类型的,切记::::要用XDDFValueAxis
XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.TOP);
bottomAxis.setTitle("time");
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.BOTTOM);
leftAxis.setTitle("value");
//CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)
//分类轴标(X轴)数据,单元格范围位置[0, 0]到[0, 6]
XDDFNumericalDataSource<Double> x = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 1600, 2, 2));
XDDFNumericalDataSource<Double> y = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 1600, 1, 1));
//scatter:XY散点图
XDDFScatterChartData scatter = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis);
// 设置y轴刻度的样式
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
XDDFScatterChartData.Series series1 = (XDDFScatterChartData.Series) scatter.addSeries(x, y);
//条形图例标题
series1.setTitle("code", null);
XDDFSolidFillProperties fill = new XDDFSolidFillProperties();
//条形图,填充颜色
series1.setFillProperties(fill);
//绘制
chart.plot(scatter);
FileOutputStream fileOut = new FileOutputStream(tmpFileName);
wb.write(fileOut);
wb.close();
}
}