All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.rxyor.common.util.xlsx.ExcelHelper Maven / Gradle / Ivy

There is a newer version: 1.0.14.17
Show newest version
package com.github.rxyor.common.util.xlsx;

import com.github.rxyor.common.core.exception.CarpIOException;
import com.github.rxyor.common.util.io.IOUtil;
import com.github.rxyor.common.util.io.NIOUtil;
import com.github.rxyor.common.util.reflect.ReflectUtil;
import com.github.rxyor.common.util.string.CharSequenceUtil;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

/**
 *

*Excel导入导出工具 *

* * @author liuyang * @date 2019-07-13 Sat 21:02:00 * @since 1.0.0 */ public class ExcelHelper { /** * java 对象类型 */ private final Class type; /** * 导入使用NIO */ private Boolean useNIO = false; /** * 导入数据源模式 */ private Mode mode; /** * 导入文件路径 */ private String path; /** * 导入文件 */ private File file; /** * 导入输入流 */ private InputStream inputStream; /** * 导出数据集合 */ private Collection data; /** * 导入工作簿 */ private Workbook importWorkbook; /** * 导出工作簿 */ private Workbook exportWorkbook; private ExcelHelper(Class type) { Objects.requireNonNull(type, "type can't be null"); this.type = type; } /** * 生成一个实例 * * @param type java 对象类型 * @param 类型 * @return ExcelHelper */ public static ExcelHelper instance(Class type) { return new ExcelHelper<>(type); } /** * 是否使用NIO * * @param useNIO Boolean * @return */ public ExcelHelper useNIO(Boolean useNIO) { this.useNIO = (useNIO == null || !useNIO) ? false : true; return this; } /** * 导入Excel * * @return */ public List doImport() { this.createImportWorkbook(); return this.parseExcel(this.importWorkbook); } /** * 设置导入文件路径 * * @param path 文件路径 * @return */ public ExcelHelper input(String path) { this.mode = Mode.PATH; this.path = path; return this; } /** * 设置导入文件 * * @param file 文件 * @return */ public ExcelHelper input(File file) { this.mode = Mode.FILE; this.file = file; return this; } /** * 设置导入文件流 * * @param inputStream 输入流 * @return */ public ExcelHelper input(InputStream inputStream) { this.mode = Mode.INPUT_STREAM; this.inputStream = inputStream; return this; } /** * 创建导入工作簿 */ private void createImportWorkbook() { Objects.requireNonNull(mode, "you must set input of path or file or inputStream..."); InputStream is = null; try { if (useNIO != null && useNIO) { switch (mode) { case PATH: is = new ByteArrayInputStream(NIOUtil.readFile(this.path)); this.importWorkbook = WorkbookUtil.createXSSFWorkbook(is); break; case FILE: is = new ByteArrayInputStream(NIOUtil.readFile(this.file)); this.importWorkbook = WorkbookUtil.createXSSFWorkbook(is); break; default: this.importWorkbook = WorkbookUtil.createXSSFWorkbook(this.inputStream); break; } } else { switch (mode) { case PATH: this.importWorkbook = WorkbookUtil.createXSSFWorkbook(this.path); break; case FILE: this.importWorkbook = WorkbookUtil.createXSSFWorkbook(this.file); break; case INPUT_STREAM: this.importWorkbook = WorkbookUtil.createXSSFWorkbook(this.inputStream); break; default: break; } } } catch (Exception e) { throw new CarpIOException(e); } finally { IOUtil.close(is); IOUtil.close(inputStream); } } /** * 解析Excel * * @param workbook 导入工作簿 * @return 对象List */ private List parseExcel(Workbook workbook) { Sheet sheet = workbook.getSheetAt(0); if (workbook == null || sheet == null) { throw new CarpIOException("read excel file fail"); } return readData(sheet); } /** * 读取Excel文件的标题行 * * @param sheet 报表 * @return TitleFieldColumn List */ private List readTitle(Sheet sheet) { if (sheet == null || sheet.getRow(0) == null) { return new ArrayList<>(0); } Row titleRow = sheet.getRow(0); int index = 0; List titleFieldColumns = new ArrayList<>(32); Iterator iterator = titleRow.cellIterator(); while (iterator.hasNext()) { titleFieldColumns.add(new TitleFieldColumn(index++, CharSequenceUtil.trim(iterator.next().getStringCellValue()))); } return titleFieldColumns; } /** * 读取数据数据行 * * @param sheet 报表 * @return */ private List readData(Sheet sheet) { if (sheet == null) { return new ArrayList<>(0); } List titleFieldColumns = this.readTitle(sheet); if (titleFieldColumns == null || titleFieldColumns.size() == 0) { return new ArrayList<>(0); } List data = new ArrayList<>(512); this.matchAndSetFieldByTitle(titleFieldColumns); Iterator iterator = sheet.rowIterator(); while (iterator.hasNext()) { Row row = iterator.next(); //跳过标题列 if (row.getRowNum() == 0) { continue; } data.add(readRow(row, titleFieldColumns)); } return data; } /** * 读取单行数据 * * @param row 行 * @param titleFieldColumns * @return java 对象 */ private T readRow(Row row, List titleFieldColumns) { if (HashMap.class.equals(type) || AbstractMap.class.equals(type)) { return (T) readMapRow(row, titleFieldColumns); } else { return readPojoRow(row, titleFieldColumns); } } /** * 目标对象是pojo时,读取单行数据 * * @param row 行 * @param titleFieldColumns * @return java Pojo对象 */ private T readPojoRow(Row row, List titleFieldColumns) { T instance = ReflectUtil.newInstance(type); for (int i = 0; i < titleFieldColumns.size(); i++) { TitleFieldColumn column = titleFieldColumns.get(i); if (column == null || column.field == null) { continue; } Object value = CellUtil.getCellValue(row.getCell(i), column.field.getType()); try { ReflectUtil.setFieldValue(instance, titleFieldColumns.get(i).field, value); } catch (Exception e) { //ignore exception } } return instance; } /** * 目标对象是map时,读取单行数据 * * @param row 行 * @param titleFieldColumns * @return hash map */ private Map readMapRow(Row row, List titleFieldColumns) { Map rowData = new HashMap<>(32); for (int i = 0; i < titleFieldColumns.size(); i++) { Object value = CellUtil.getCellValue(row.getCell(i), Object.class); rowData.put(titleFieldColumns.get(i).getTitle(), value); } return rowData; } /** *Excel标题与Java 对象的Filed匹配 * * @param titleColumns */ private void matchAndSetFieldByTitle(List titleColumns) { List fields = ReflectUtil.getDeclaredFields(type, true); Map map = new HashMap<>(fields.size()); for (Field field : fields) { Column column = field.getAnnotation(Column.class); if (column != null) { String title = Optional.ofNullable(column.title()).filter(StringUtils::isNotBlank) .orElse(field.getName()); map.put(title, field); } } titleColumns.forEach(column -> column.setField(map.get(column.title))); } /** * 导出Excel * * @return */ public byte[] doExport() { List titleFieldColumns = this.generateTitle(); this.createExportWorkbook(titleFieldColumns); this.writeData(1, titleFieldColumns); WorkbookUtil.autoSizeColumn(this.exportWorkbook.getSheetAt(0), titleFieldColumns.size()); return this.writeExportWorkbook2Byes(); } /** * 设置导出的数据 * * @param data 要导出的数据 * @return */ public ExcelHelper input(Collection data) { this.data = data; return this; } /** * 创建导出工作簿 * * @param titleFieldColumns */ private void createExportWorkbook(List titleFieldColumns) { List titles = titleFieldColumns.stream().map(TitleFieldColumn::getTitle).collect(Collectors.toList()); this.exportWorkbook = WorkbookUtil.createXSSFWorkbookWithTitle(titles); } /** * 写数据到工作簿 * * @param beginRowIndex 开始行的索引 * @param titleFieldColumns */ private void writeData(int beginRowIndex, List titleFieldColumns) { if (data == null || data.size() == 0) { return; } int offset = (beginRowIndex < 0) ? 0 : beginRowIndex; Sheet sheet = this.exportWorkbook.getSheetAt(0); for (T item : data) { offset = writeRow(titleFieldColumns, offset, sheet, item); } } /** * 写入行到工作簿 * * @param titleFieldColumns * @param offset 当前行索引 * @param sheet 报表 * @param item 数据项 * @return 最新行索引 */ private int writeRow(List titleFieldColumns, int offset, Sheet sheet, T item) { if (item == null) { return offset; } Row row = sheet.createRow(offset++); for (int i = 0; i < titleFieldColumns.size(); i++) { Cell cell = row.createCell(i); Field field = Optional.ofNullable(titleFieldColumns.get(i)).map(TitleFieldColumn::getField) .orElse(null); Object value = null; try { value = ReflectUtil.getFieldValue(item, field); } catch (Exception e) { //ignore exception } CellUtil.setCellValue(cell, value); } return offset; } /** * 导出Excel为字节数组 * * @return byte[] */ private byte[] writeExportWorkbook2Byes() { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { this.exportWorkbook.write(outputStream); return outputStream.toByteArray(); } catch (IOException e) { throw new CarpIOException(e); } finally { IOUtil.close(outputStream); } } /** * 读取标题 * * @return */ public List generateTitle() { List fields = ReflectUtil.getDeclaredFields(type, true); List list = new ArrayList<>(fields.size()); for (Field field : fields) { Column column = field.getAnnotation(Column.class); int index = Optional.ofNullable(column).map(Column::index).orElse(Integer.MAX_VALUE); String title = Optional.ofNullable(column).map(Column::title).orElse(null); if (title == null || title.trim().length() == 0) { continue; } list.add(new TitleFieldColumn(index, title, field)); } list.sort(Comparator.comparingInt(value -> value.index)); return list; } /** * 清空配置 * * @return */ public ExcelHelper clear() { this.path = null; this.file = null; this.inputStream = null; this.data = null; this.importWorkbook = null; this.exportWorkbook = null; return this; } /** * 包装列对象 */ @Data public class TitleFieldColumn { /** * 列下标 */ private Integer index; /** * 列标题 */ private String title; /** * 列对应类字段 */ private Field field; public TitleFieldColumn() { } public TitleFieldColumn(Integer index, String title) { this.index = index; this.title = title; } public TitleFieldColumn(Integer index, String title, Field field) { this.index = index; this.title = title; this.field = field; } } /** * 数据来源模式 */ private enum Mode { PATH, FILE, INPUT_STREAM } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy