Java学习笔记-EXCEL文件的读写操作

一、基于POI操作EXCEL文件

<!-- POI依赖包 -->
<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>

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml-schemas</artifactId>
	<version>4.1.2</version>
</dependency>

<dependency>
	<groupId>xerces</groupId>
	<artifactId>xercesImpl</artifactId>
	<version>2.12.0</version>
</dependency>

EXCEL文件读操作示例如下:

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.platform.utils.date.DateFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

import java.io.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;

public class PoiExcelFileReader {

	private Logger LOG = LoggerFactory.getLogger(PoiExcelFileReader.class);

	enum XssfDataType {
		BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, NULL
	}

	public static final SimpleDateFormat SDF = DateFormatter.TIME.get();

	public static final DecimalFormat DF = new DecimalFormat("0");

	public static final int ERROR = 0;
	public static final int BOOLEAN = 1;
	public static final int NUMBER = 2;
	public static final int STRING = 3;
	public static final int DATE = 4;
	public static final String DATE_FORMAT_STR1 = "yyyy-MM-dd HH:mm:ss";
	public static final String DATE_FORMAT_STR2 = "yyyy/MM/dd HH:mm:ss";

	private boolean isExcel2007 = true;
	private InputStream inputStream = null;
	private InputStream sheetInputStream = null;
	private InputSource sheetInputSource = null;
	private XMLReader xmlReader = null;

	private List<PoiExcelRow> rowDataList = new ArrayList<PoiExcelRow>();
	// 批量处理
	private Consumer<List<PoiExcelRow>> consumer = null;
	// 批量处理的阀值
	private Integer threshold = null;
	// 跳过表头的行数
	private Integer skipHeadLineCount = 0;

	public PoiExcelFileReader(InputStream in, String suffix, Consumer<List<PoiExcelRow>> consumer, int threshold) {
		this(in, suffix, consumer, threshold, 0);
	}

	public PoiExcelFileReader(InputStream in, String suffix, Consumer<List<PoiExcelRow>> consumer, int threshold,
                              int skipHeadLineCount) {
		this.inputStream = in;
		this.isExcel2007 = "xls".equals(suffix.toLowerCase()) ? false : true;
		this.consumer = consumer;
		this.threshold = threshold;
		this.skipHeadLineCount = skipHeadLineCount;
	}

	public void parse() {
		if (isExcel2007) {
			try {
				init(OPCPackage.open(inputStream));
			} catch (Exception e) {
				LOG.error(e.getMessage(), e);
			}
			parseExcel2007();
		} else {
			parseExcel2003(inputStream);
		}
	}

	public List<PoiExcelRow> getRowDataList() {
		return this.rowDataList;
	}
	
	/** 初始化将Excel转换为XML */
	private void init(OPCPackage pkg) throws IOException, OpenXML4JException, SAXException{
		XSSFReader xssfReader = new XSSFReader(pkg);
		SharedStringsTable sharedStringsTable = xssfReader.getSharedStringsTable();
		StylesTable stylesTable = xssfReader.getStylesTable();
		sheetInputStream = xssfReader.getSheet(getSheetId(xssfReader.getWorkbookData()));
		sheetInputSource = new InputSource(sheetInputStream);
		xmlReader = getXmlReader(sharedStringsTable, stylesTable);
	}
	
	private XMLReader getXmlReader(SharedStringsTable sharedStringsTable, StylesTable stylesTable) throws SAXException {
		XMLReader xmlReader = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
		ContentHandler contentHandler = new CustomHandler(sharedStringsTable, stylesTable);
		xmlReader.setContentHandler(contentHandler);
		return xmlReader;
	}

	private void parseExcel2007(){
		try {
			xmlReader.parse(sheetInputSource);
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		} finally{
			if(sheetInputStream != null){
				try {
					sheetInputStream.close();
				} catch (IOException e) {
					LOG.error(e.getMessage(), e);
				}
			}
		}
	}

	private String getSheetId(InputStream workbookDataInputStream) {
		String sheetId = "rId1";
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(workbookDataInputStream));
			String line = null;
			loop:
			while (null != (line = br.readLine())) {
				if (line.startsWith("<workbook")) {
					InputStream in = null;
					try {
						in = new ByteArrayInputStream(line.getBytes("UTF-8"));
						Document document = new SAXBuilder().build(in);
						Element rootElement = document.getRootElement();
						Iterator<Element> iterator = rootElement.getChildren().iterator();
						while (iterator.hasNext()) {
							Element element = iterator.next();
							if (!"sheets".equals(element.getName())) continue;
							List<Element> children = element.getChildren();
							for (int i = 0, iLen = children.size(); i < iLen; i++) {
								Element subElement = children.get(i);
								for (Attribute attribute : subElement.getAttributes()) {
									if ("id".equals(attribute.getName())) {
										sheetId = attribute.getValue();
										break loop;
									}
								}
							}
						}
					} catch (JDOMException e) {
						LOG.error(e.getMessage(), e);
					} finally {
						try {
							if (null != in) in.close();
						} catch (Exception e) {
							LOG.error(e.getMessage(), e);
						}
					}
				}
			}
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
		} finally {
			try {
				if (null != workbookDataInputStream) workbookDataInputStream.close();
				if (null != br) br.close();
			} catch (Exception e) {
				LOG.error(e.getMessage(), e);
			}
		}
		return sheetId;
	}
	
	private class CustomHandler extends DefaultHandler {
		
		// 映射字符串
		private SharedStringsTable sharedStringsTable = null;
		// 单元格样式
		private StylesTable stylesTable = null;
		// 读取值
		private String readValue = null;
		// 单元格类型
		private XssfDataType dataType = null;
		// 一行中数据文本
		private String[] rowStrings = null;
		// 一行中数据类型
		private int[] rowTypes = null;
		// 当前行索引
		private int rowIndex = 0;
		// 当前列索引
		private int columnIndex;
		
		private short formatIndex = -1;
		
		private CustomHandler(SharedStringsTable sharedStringsTable,StylesTable stylesTable) {
			this.sharedStringsTable = sharedStringsTable;
			this.stylesTable = stylesTable;
		}
		
		@Override
		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
			// 单元格
			if (qName.equals("c")) {
				this.columnIndex = getColumnIndex(attributes);
				String cellType = attributes.getValue("t");
				String cellStyle = attributes.getValue("s");
				this.dataType = XssfDataType.NUMBER;
				if ("b".equals(cellType)) {
					this.dataType = XssfDataType.BOOL;
				} else if ("e".equals(cellType)) {
		        	this.dataType = XssfDataType.ERROR;
		        } else if ("inlineStr".equals(cellType)) {
		        	this.dataType = XssfDataType.INLINESTR;
		        } else if ("s".equals(cellType)) {
		        	this.dataType = XssfDataType.SSTINDEX;
		        } else if ("str".equals(cellType)) {
		        	this.dataType = XssfDataType.FORMULA;
		        } else if (cellStyle != null) {
		        	int styleIndex = Integer.parseInt(cellStyle);  
		            XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);  
		            this.formatIndex = style.getDataFormat();  
		        }
			} else if (qName.equals("row")) {
				rowIndex++;
				// 获取该行的单元格数 初始化数组
				int columnNumber = getColumnNumber(attributes);
				this.rowStrings = new String[columnNumber];
				this.rowTypes = new int[columnNumber];
			}
			readValue = "";
		}
		
		@Override
		public void endElement(String uri, String localName, String qName) throws SAXException {
			// 单元格的值
			if (qName.equals("v")) {
				switch (this.dataType) {
					case BOOL: {
						rowStrings[columnIndex] = readValue.charAt(0) == '0' ? "FALSE" : "TRUE";
						rowTypes[columnIndex] = BOOLEAN;
						break;
					}
					case ERROR: {
						rowStrings[columnIndex] = "ERROR:" + readValue.toString();
						rowTypes[columnIndex] = ERROR;
						break;
					}
					case INLINESTR: {
						rowStrings[columnIndex] = new XSSFRichTextString(readValue).getString();
						rowTypes[columnIndex] = STRING;
						break;
					}
					case SSTINDEX: {
						rowStrings[columnIndex] = sharedStringsTable.getItemAt(Integer.parseInt(readValue)).getString();
			            rowTypes[columnIndex] = STRING;
			            break;
					}
					case FORMULA: {
						rowStrings[columnIndex] = readValue;
						rowTypes[columnIndex] = STRING;
						break;
					}
					case NUMBER: {
						// 判断是否是日期格式  
			            if (formatIndex != -1 && DateUtil.isADateFormat(formatIndex, readValue)) {  
			                Date date = DateUtil.getJavaDate(Double.parseDouble(readValue));
			                if (null != date) {
								rowStrings[columnIndex] = DateFormatUtils.format(date, DATE_FORMAT_STR1);
							} else {
								rowStrings[columnIndex] = readValue;
							}
							rowTypes[columnIndex] = DATE;
							formatIndex = -1;
						} else {
			            	rowStrings[columnIndex] = readValue;
			            	rowTypes[columnIndex] = NUMBER;
			            }
			            break;
					}
					default : break;
				}
			} else if (qName.equals("row")) {
				// 当解析的一行的末尾时输出数组中的数据
				if (rowIndex > skipHeadLineCount) {
					// 过滤空行
					boolean isValid = false;
					for (int i = 0, len = rowStrings.length; i < len; i++) {
						if (StringUtils.isNotBlank(rowStrings[i])) {
							isValid = true;
							break;
						}
					}
					if (isValid) {
						rowDataList.add(new PoiExcelRow(rowIndex, rowTypes, rowStrings));
						if (null != threshold && rowDataList.size() > threshold) {
							consumer.accept(rowDataList);
							rowDataList.clear();
						}
					}
				}
			}
		}

		/**
		 * 如果单元格类型是字符串、INLINESTR、数字、日期,readValue则是索引值
		 * 如果单元格类型是布尔值、错误、公式,readValue则是内容值
		 */
		@Override
		public void characters(char[] ch, int start, int length) throws SAXException {
			readValue += new String(ch, start, length);
		}
		
		@Override
		public void endDocument() throws SAXException {
			super.endDocument();
			if (rowDataList.size() > 0) {
				consumer.accept(rowDataList);
				rowDataList.clear();
			}
		}
		
		private int getColumnIndex(Attributes attributes) {
			String attributeValue = attributes.getValue("r");
	        int columnIndex = -1;
	        for (int i = 0, len = attributeValue.length(); i < len; ++i) {
	        	if (Character.isDigit(attributeValue.charAt(i))) break;
	            columnIndex = (columnIndex + 1) * 26 + attributeValue.charAt(i) - 'A';
	        }  
	        return columnIndex;
	    }
		
		private int getColumnNumber(Attributes attrubuts){
			String spans = attrubuts.getValue("spans");
			return StringUtils.isBlank(spans) ? -1 : Integer.parseInt(spans.substring(spans.indexOf(":") + 1));
		}
		
	}
	
	private void parseExcel2003(InputStream in) {
		Workbook workbook = null;
		try {
			workbook = WorkbookFactory.create(in);
	    	Sheet sheet = workbook.getSheetAt(0);
	    	int lastCellNum = sheet.getRow(0).getPhysicalNumberOfCells();
	    	for (int i = skipHeadLineCount, iLen = sheet.getLastRowNum(); i <= iLen; i++) {
	    		Row row = sheet.getRow(i);
	    		String[] rowStrings = new String[lastCellNum];
	    		for (int j = 0, jLen = lastCellNum; j < jLen; j++) {
	    			Cell cell = row.getCell(j);
	    			if (null == cell) continue;
	    			Object cellValue = null;
	    			switch (cell.getCellType()) {
	    				case BOOLEAN: cellValue = cell.getBooleanCellValue(); break;
	    				case ERROR: cellValue = cell.getErrorCellValue(); break;
	    				case FORMULA: cellValue = cell.getCellFormula(); break;
	    				case NUMERIC: cellValue = DF.format(cell.getNumericCellValue()); break;
	    				default: cellValue = cell.getStringCellValue(); break;
	    			}
	    			rowStrings[j] = String.valueOf(cellValue);
	    		}
	    		rowDataList.add(new PoiExcelRow(i, null, rowStrings));
				if (null != threshold && rowDataList.size() > threshold) {
					consumer.accept(rowDataList);
					rowDataList.clear();
				}
	    	}
	    	if (rowDataList.size() > 0) {
				consumer.accept(rowDataList);
				rowDataList.clear();
			}
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		} finally {
			try {
				if (null != in) in.close();
				if (null != workbook) workbook.close();
			} catch (IOException e) {
				LOG.error(e.getMessage(), e);
			}
		}
	}
	
}

EXCEL文件写操作示例如下:

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.List;

public class PoiExcelFileWriter {

    private static Logger LOG = LoggerFactory.getLogger(PoiExcelFileWriter.class);

    /**
     * 操作Excel2003以前(包括2003)的版本,扩展名是.xls。导出的行数至多为65535行
     * */
    public static void writeHSSFWorkbook(List<String> headerList, List<List<Object>> resultList, OutputStream outputStream) {
        HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
        HSSFSheet hssfSheet = hssfWorkbook.createSheet("sheet1");
        HSSFRow hssfRow = null;
        boolean isBlankHeader = null == headerList || headerList.isEmpty();
        if (!isBlankHeader) {
            hssfRow = hssfSheet.createRow(0);
            for (int i = 0, len = headerList.size(); i < len; i++) {
                HSSFCell hssfCell = hssfRow.createCell(i);
                hssfCell.setCellValue(headerList.get(i));
            }
        }
        for (int i = 0, iLen = resultList.size(); i < iLen; i++) {
            hssfRow = hssfSheet.createRow(isBlankHeader ? i : i + 1);
            List<Object> result = resultList.get(i);
            for (int j = 0, jLen = result.size(); j < jLen; j++) {
                HSSFCell hssfCell = hssfRow.createCell(j);
                Object valueObj = result.get(j);
                if (valueObj instanceof String) {
                    hssfCell.setCellValue(null == valueObj ? "" : valueObj.toString());
                } else if (valueObj instanceof BigDecimal) {
                    BigDecimal vDecimal = (BigDecimal) valueObj;
                    hssfCell.setCellValue(vDecimal.doubleValue());
                } else if (valueObj instanceof Integer) {
                    hssfCell.setCellValue((Integer) valueObj);
                } else if (valueObj instanceof Double) {
                    hssfCell.setCellValue((Double) valueObj);
                } else {
                    hssfCell.setCellValue(null == valueObj ? "" : valueObj.toString());
                }
            }
        }
        try {
            hssfWorkbook.write(outputStream);
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        } finally {
            try {
                if (null != hssfWorkbook) hssfWorkbook.close();
            } catch (IOException e) {
                LOG.error(e.getMessage(), e);
            }
        }
    }

    /**
     * 操作Excel2007后的版本,扩展名是.xlsx。导出的数据至多为1048576行,16384列。存在OOM内存溢出
     * */
    public static void writeXSSFWorkbook(List<String> headerList, List<List<Object>> resultList, OutputStream outputStream) {
        XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
        XSSFSheet xssfSheet = xssfWorkbook.createSheet("sheet1");
        XSSFRow xssfRow = null;
        boolean isBlankHeader = null == headerList || headerList.isEmpty();
        if (!isBlankHeader) {
            xssfRow = xssfSheet.createRow(0);
            for (int i = 0, len = headerList.size(); i < len; i++) {
                XSSFCell xssfCell = xssfRow.createCell(i);
                xssfCell.setCellValue(headerList.get(i));
            }
        }
        for (int i = 0, iLen = resultList.size(); i < iLen; i++) {
            xssfRow = xssfSheet.createRow(isBlankHeader ? i : i + 1);
            List<Object> result = resultList.get(i);
            for (int j = 0, jLen = result.size(); j < jLen; j++) {
                XSSFCell xssfCell = xssfRow.createCell(j);
                Object valueObj = result.get(j);
                if (valueObj instanceof String) {
                    xssfCell.setCellValue(null == valueObj ? "" : valueObj.toString());
                } else if (valueObj instanceof BigDecimal) {
                    BigDecimal vDecimal = (BigDecimal) valueObj;
                    xssfCell.setCellValue(vDecimal.doubleValue());
                } else if (valueObj instanceof Integer) {
                    xssfCell.setCellValue((Integer) valueObj);
                } else if (valueObj instanceof Double) {
                    xssfCell.setCellValue((Double) valueObj);
                } else {
                	xssfCell.setCellValue(null == valueObj ? "" : valueObj.toString());
                }
            }
        }
        try {
            xssfWorkbook.write(outputStream);
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        } finally {
            try {
                if (null != xssfWorkbook) xssfWorkbook.close();
            } catch (IOException e) {
                LOG.error(e.getMessage(), e);
            }
        }
    }

    /**
     * 操作Excel2007后的版本,扩展名是.xlsx。导出的数据至多为1048576行,16384列。硬盘空间换内存,避免OOM内存溢出。
     * */
    public static void writeSXSSFWorkbook(List<String> headerList, List<List<Object>> resultList, OutputStream outputStream) {
        SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook();
        SXSSFSheet sxssfSheet = sxssfWorkbook.createSheet("sheet1");
        SXSSFRow sxssfRow = null;
        boolean isBlankHeader = null == headerList || headerList.isEmpty();
        if (!isBlankHeader) {
            sxssfSheet.createRow(0);
            for (int i = 0, len = headerList.size(); i < len; i++) {
                SXSSFCell sxssfCell = sxssfRow.createCell(i);
                sxssfCell.setCellValue(headerList.get(i));
            }
        }
        for (int i = 0, len = resultList.size(); i < len; i++) {
            sxssfRow = sxssfSheet.createRow(isBlankHeader ? i : i + 1);
            List<Object> result = resultList.get(i);
            for(int j = 0, jLen = result.size(); j < jLen; j++){
                SXSSFCell sxssfCell = sxssfRow.createCell(j);
                Object valueObj = result.get(j);
                if (valueObj instanceof String) {
                	sxssfCell.setCellValue(null == valueObj ? "" : valueObj.toString());
                } else if (valueObj instanceof BigDecimal) {
                    BigDecimal vDecimal = (BigDecimal) valueObj;
                    sxssfCell.setCellValue(vDecimal.doubleValue());
                } else if (valueObj instanceof Integer) {
                    sxssfCell.setCellValue((Integer) valueObj);
                } else if (valueObj instanceof Double) {
                    sxssfCell.setCellValue((Double) valueObj);
                } else {
                	sxssfCell.setCellValue(null == valueObj ? "" : valueObj.toString());
                }
            }
        }
        try {
            sxssfWorkbook.write(outputStream);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        } finally {
            sxssfWorkbook.dispose();
            try {
                if (null != sxssfWorkbook) sxssfWorkbook.close();
            } catch (IOException e) {
                LOG.error(e.getMessage(), e);
            }
        }
    }


}

二、基于EASYEXCEL操作EXCEL文件

<!-- EASYEXCEL依赖包 -->
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>easyexcel</artifactId>
	<version>2.2.3</version>
</dependency>

EXCEL文件读写操作示例如下:

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EasyExcelFileUtils {

    private static Logger LOG = LoggerFactory.getLogger(EasyExcelFileUtils.class);

    public static void read(InputStream in, int threshold, List<String> headerFieldList, List<Map<String, Object>> dataList) {
        Map<Integer, String> indexFieldMap = new HashMap<Integer, String>();
        EasyExcelFactory.read(in, EventListenerUtils.getListener(
            head -> {
                Map<Integer, Object> header = (Map<Integer, Object>) head;
                for (Map.Entry<Integer, Object> entry : header.entrySet()) {
                    String entryValue = String.valueOf(entry.getValue());
                    headerFieldList.add(entryValue);
                    indexFieldMap.put(entry.getKey(), entryValue);
                }
            },
            results -> {
                List<Object> resultList = (List<Object>) results;
                for (int i = 0, len = resultList.size(); i < len; i++) {
                    Map<String, Object> data = new HashMap<String, Object>();
                    Map<Integer, Object> result = (Map<Integer, Object>) resultList.get(i);
                    for (Map.Entry<Integer, Object> entry : result.entrySet()) {
                        data.put(indexFieldMap.get(entry.getKey()), entry.getValue());
                    }
                    dataList.add(data);
                }
            }, threshold)).sheet(0).headRowNumber(0).autoTrim(true).doRead();
        try {
            if (null != in) in.close();
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }

    public static void write(List<List<String>> headerList, List<List<Object>> resultList, OutputStream outputStream) {
        ExcelWriter excelWriter = EasyExcelFactory.write(outputStream).excelType(ExcelTypeEnum.XLSX).useDefaultStyle(true)
            .needHead(true).head(headerList).autoTrim(true).build();
        WriteSheet writeSheet = new WriteSheet();
        writeSheet.setSheetNo(1);
        excelWriter.write(resultList, writeSheet);
        excelWriter.finish();
    }

}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;

public class EventListenerUtils {

	/**
	 * 批量监听
	 * @param <T>
	 * @param consumer 批量消费
	 * @param threshold 批量阀值
	 * @return
	 */
	public static <T> AnalysisEventListener<T> getListener(Consumer<List<T>> consumer, int threshold) {
		return new AnalysisEventListener<T>() {
			
			private List<T> ts = new ArrayList<T>();
			
			@Override
			public void invoke(T t, AnalysisContext context) {
				ts.add(t);
				if (ts.size() == threshold) {
					consumer.accept(ts);
					ts.clear();
				}
			}
			
			@Override
			public void doAfterAllAnalysed(AnalysisContext context) {
				if (ts.size() > 0) {
					consumer.accept(ts);
					ts.clear();
				}
			}
			
		};
	}
	
	/**
	 * 批量监听
	 * @param <T>
	 * @param headConsumer 表头消费
	 * @param consumer 批量消费
	 * @param threshold 批量阀值
	 * @return
	 */
	public static <T> AnalysisEventListener<T> getListener(Consumer<T> headConsumer, Consumer<List<T>> consumer, int threshold) {
		return new AnalysisEventListener<T>() {
			
			private List<T> ts = new ArrayList<T>();
			
			@Override
			public void invoke(T t, AnalysisContext context) {
				if (context.readRowHolder().getRowIndex() == 0) {
					headConsumer.accept(t);
				} else {
					ts.add(t);
					if (ts.size() == threshold) {
						consumer.accept(ts);
						ts.clear();
					}
				}
			}
			
			@Override
			public void doAfterAllAnalysed(AnalysisContext context) {
				if (ts.size() > 0) {
					consumer.accept(ts);
					ts.clear();
				}
			}
			
		};
	}
	
	/**
	 * 限制数量的监听
	 * @param <T>
	 * @param headConsumer 表头消费
	 * @param consumer 消费
	 * @param threshold 限制阀值
	 * @return
	 */
	public static <T> AnalysisEventListener<T> getLimitListener(Consumer<T> headConsumer, Consumer<List<T>> consumer, int threshold) {
		return new AnalysisEventListener<T>() {
			
			private List<T> ts = new ArrayList<T>();
			
			@Override
			public void invoke(T t, AnalysisContext context) {
				if (context.readRowHolder().getRowIndex() == 0) {
					headConsumer.accept(t);
				} else {
					if (ts.size() < threshold) {
						ts.add(t);
					}
				}
			}
			
			@Override
			public void doAfterAllAnalysed(AnalysisContext context) {
				if (ts.size() > 0) {
					consumer.accept(ts);
					ts.clear();
				}
			}
			
		};
	}
	
}

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
STM32是一款非常流行的嵌入式微控制器系列,它具有强大的性能和丰富的外设资源。在学习STM32时,掌握如何进行Flash是非常重要的。 Flash是一种非易失性存储器,可以用来存储程序代码和数据。在STM32中,Flash存储器通常用来存储应用程序代码。下面是一个简单的Flash程序的示例: 1.首先,我们需要包含适用于所使用的STM32型号的头文件。例如,对于STM32F4系列,我们需要包含"stm32f4xx.h"。 2.然后,我们需要定义一个指向Flash存储器的指针变量。例如,可以使用如下代码:`uint32_t* flash_address = (uint32_t*)0x08000000;`其中0x08000000是Flash存储器的起始地址。 3.要取Flash存储器中的数据,我们可以通过以下代码实现:`data = *flash_address;`其中data是一个变量,用于存储取到的数据。 4.要入数据到Flash存储器中,我们可以通过以下代码实现:`*flash_address = data;`其中data是要入的数据。 需要注意的是,STM32的Flash存储器是有保护机制的,因此在入数据之前,我们需要禁用保护。可以使用以下代码禁用保护:`FLASH->KEYR = 0x45670123; FLASH->KEYR = 0xCDEF89AB;`然后才能进行数据入。 另外,为了确保数据的完整性,我们可以使用CRC校验来验证Flash存储器中的程序代码的正确性。可以使用库函数来计算校验和,然后将其与预期的校验和进行比较以进行验证。 综上所述,掌握STM32的Flash操作对于嵌入式系统的开发非常重要。上述示例代码可以帮助我们快速进行Flash操作,同时注意保护和数据校验可以提高数据的安全性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值