package com.glxp.mipsdl.util; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import com.glxp.mipsdl.annotation.Excel; import com.glxp.mipsdl.res.udiwms.UdiwmsProductInfoResponse; import lombok.extern.slf4j.Slf4j; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.*; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.math.BigDecimal; import java.text.DecimalFormat; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; @Slf4j public class ExcelUtil { /** * Excel sheet最大行数,默认65536 */ public static final int sheetSize = 65536; /** * 工作表名称 */ private String sheetName; /** * 导出类型(EXPORT:导出数据;IMPORT:导入模板) */ private Excel.Type type; /** * 工作薄对象 */ private Workbook wb; /** * 工作表对象 */ private Sheet sheet; /** * 样式列表 */ private Map styles; /** * 导入导出数据列表 */ private List list; /** * 注解列表 */ private List fields; /** * 实体对象 */ public Class clazz; public ExcelUtil(Class clazz) { this.clazz = clazz; } public List importExcel(InputStream is) throws Exception { return importExcel("", is); } public List importExcel(String sheetName, InputStream is) throws Exception { this.type = Excel.Type.IMPORT; this.wb = WorkbookFactory.create(is); List list = new ArrayList(); Sheet sheet = null; if (!sheetName.isEmpty()) { // 如果指定sheet名,则取指定sheet中的内容. sheet = wb.getSheet(sheetName); } else { // 如果传入的sheet名不存在则默认指向第1个sheet. sheet = wb.getSheetAt(0); } if (sheet == null) { throw new IOException("文件sheet不存在"); } int rows = sheet.getPhysicalNumberOfRows(); if (rows > 0) { // 定义一个map用于存放excel列的序号和field. Map cellMap = new HashMap(); // 获取表头 Row heard = sheet.getRow(0); for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) { Cell cell = heard.getCell(i); if (!StrUtil.isEmptyIfStr(cell)) { String value = this.getCellValue(heard, i).toString(); cellMap.put(value, i); } else { cellMap.put(null, i); } } // 有数据时才处理 得到类的所有field. Field[] allFields = clazz.getDeclaredFields(); // 定义一个map用于存放列的序号和field. Map fieldsMap = new HashMap(); for (int col = 0; col < allFields.length; col++) { Field field = allFields[col]; Excel attr = field.getAnnotation(Excel.class); if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type)) { // 设置类的私有字段属性可访问. field.setAccessible(true); Integer column = cellMap.get(attr.name()); fieldsMap.put(column, field); } } for (int i = 1; i < rows; i++) { // 从第2行开始取数据,默认第一行是表头. Row row = sheet.getRow(i); // System.out.println("index = "+i); T entity = null; for (Map.Entry entry : fieldsMap.entrySet()) { Object val = this.getCellValue(row, entry.getKey()); // 如果不存在实例则新建. entity = (entity == null ? clazz.newInstance() : entity); // 从map中得到对应列的field. Field field = fieldsMap.get(entry.getKey()); // 取得类型,并根据对象类型设置值. Class fieldType = field.getType(); if (String.class == fieldType) { String s = Convert.toStr(val); if (StrUtil.endWith(s, ".0")) { val = StrUtil.subBefore(s, ".0", true); } else { val = Convert.toStr(val); } } else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) { val = Convert.toInt(val); } else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) { val = Convert.toLong(val); } else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) { val = Convert.toDouble(val); } else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) { val = Convert.toFloat(val); } else if (BigDecimal.class == fieldType) { val = Convert.toBigDecimal(val); } else if (Date.class == fieldType) { if (val instanceof String) { val = com.glxp.mipsdl.util.DateUtil.parseDate(val); } else if (val instanceof Double) { val = org.apache.poi.ss.usermodel.DateUtil.getJavaDate((Double) val); } } if (!StrUtil.isEmptyIfStr(fieldType)) { Excel attr = field.getAnnotation(Excel.class); String propertyName = field.getName(); if (StrUtil.isNotEmpty(attr.targetAttr())) { propertyName = field.getName() + "." + attr.targetAttr(); } else if (StrUtil.isNotEmpty(attr.convertExp())) { val = reverseByExp(String.valueOf(val), attr.convertExp()); } ReflectUtil.setFieldValue(entity, propertyName, val); } } list.add(entity); } } return list; } /** * 获取单元格值 * * @param row 获取的行 * @param column 获取单元格列号 * @return 单元格值 */ public Object getCellValue(Row row, int column) { if (row == null) { return row; } Object val = ""; try { Cell cell = row.getCell(column); if (cell != null) { if (cell.getCellTypeEnum() == CellType.NUMERIC || cell.getCellTypeEnum() == CellType.FORMULA) { val = cell.getNumericCellValue(); if (HSSFDateUtil.isCellDateFormatted(cell)) { val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 } else { if ((Double) val % 1 > 0) { val = new DecimalFormat("0.00").format(val); } else { val = new DecimalFormat("0").format(val); } } } else if (cell.getCellTypeEnum() == CellType.STRING) { val = cell.getStringCellValue(); } else if (cell.getCellTypeEnum() == CellType.BOOLEAN) { val = cell.getBooleanCellValue(); } else if (cell.getCellTypeEnum() == CellType.ERROR) { val = cell.getErrorCellValue(); } } } catch (Exception e) { return val; } return val; } /** * 反向解析值 男=0,女=1,未知=2 * * @param propertyValue 参数值 * @param converterExp 翻译注解 * @return 解析后值 * @throws Exception */ public static String reverseByExp(String propertyValue, String converterExp) throws Exception { try { String[] convertSource = converterExp.split(","); for (String item : convertSource) { String[] itemArray = item.split("="); if (itemArray[1].equals(propertyValue)) { return itemArray[0]; } } } catch (Exception e) { throw e; } return propertyValue; } /** * 直接解析返回产品信息集合 * * @param inputStream * @return */ public List importPi(InputStream inputStream) throws Exception{ List list = this.importExcel(inputStream); List result = new CopyOnWriteArrayList<>(); list.parallelStream().forEach(item -> { UdiwmsProductInfoResponse udiwmsProductInfoResponse = new UdiwmsProductInfoResponse(); BeanUtil.copyProperties(item, udiwmsProductInfoResponse); result.add(udiwmsProductInfoResponse); }); return result; } }