1. <dependency>
  2. <groupId>org.apache.poi</groupId>
  3. <artifactId>poi</artifactId>
  4. <version>3.9</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.apache.poi</groupId>
  8. <artifactId>poi-ooxml</artifactId>
  9. <version>3.9</version>
  10. </dependency>
  1. import com.isyscore.ibo.neo.NeoMap;
  2. import lombok.experimental.UtilityClass;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  5. import org.apache.poi.ss.usermodel.Cell;
  6. import org.apache.poi.ss.usermodel.Row;
  7. import org.apache.poi.ss.usermodel.Sheet;
  8. import org.apache.poi.ss.usermodel.Workbook;
  9. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  10. import java.io.File;
  11. import java.io.FileInputStream;
  12. import java.io.IOException;
  13. import java.io.InputStream;
  14. import java.text.DecimalFormat;
  15. import java.util.ArrayList;
  16. import java.util.Collections;
  17. import java.util.List;
  18. import static org.apache.poi.ss.usermodel.Cell.*;
  19. /**
  20. * @author shizi
  21. * @since 2020/3/27 5:35 PM
  22. */
  23. @Slf4j
  24. @UtilityClass
  25. public class ExcelUtil {
  26. private static final String XLS = "xls";
  27. private static final String XLSX = "xlsx";
  28. /**
  29. * 读取xls和xlsx 对应的文件的某一个sheet对应的数据
  30. *
  31. * 注意:
  32. * 这里会默认跳过第一行,因为第一行一般都是列的描述
  33. *
  34. * @param fileName excel对应的文件
  35. * @param sheetNum sheet的下标
  36. * @param columnMap 某一sheet中列和对应的别名对应:key为从0开始的索引
  37. * @return 读取到的key和value对应的数据
  38. */
  39. public List<NeoMap> read(String fileName, Integer sheetNum, NeoMap columnMap) {
  40. Workbook workbook;
  41. FileInputStream inputStream = null;
  42. try {
  43. // 获取Excel后缀名
  44. String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
  45. // 获取Excel文件
  46. File excelFile = new File(fileName);
  47. if (!excelFile.exists()) {
  48. log.warn("指定的Excel文件不存在!");
  49. return null;
  50. }
  51. // 获取Excel工作簿
  52. inputStream = new FileInputStream(excelFile);
  53. workbook = getWorkbook(inputStream, fileType);
  54. // 读取excel中的数据
  55. return parseExcel(sheetNum, workbook, columnMap);
  56. } catch (Exception e) {
  57. log.warn("解析Excel失败,文件名:" + fileName + " 错误信息:" + e.getMessage(), e);
  58. return Collections.emptyList();
  59. } finally {
  60. try {
  61. if (null != inputStream) {
  62. inputStream.close();
  63. }
  64. } catch (Exception e) {
  65. log.warn("关闭数据流出错!错误信息:" + e.getMessage(), e);
  66. }
  67. }
  68. }
  69. /**
  70. * 解析Excel数据
  71. * @param workbook Excel工作簿对象
  72. * @return 解析结果
  73. */
  74. private List<NeoMap> parseExcel(Integer sheetNum, Workbook workbook, NeoMap columnMap) {
  75. List<NeoMap> resultDataList = new ArrayList<>();
  76. // 解析sheet
  77. Sheet sheet = workbook.getSheetAt(sheetNum);
  78. // 校验sheet是否合法
  79. if (sheet == null) {
  80. return Collections.emptyList();
  81. }
  82. // 获取第一行数据
  83. int firstRowNum = sheet.getFirstRowNum();
  84. Row firstRow = sheet.getRow(firstRowNum);
  85. if (null == firstRow) {
  86. log.warn("解析Excel失败,在第一行没有读取到任何数据!");
  87. }
  88. // 解析每一行的数据,构造数据对象
  89. int rowStart = firstRowNum + 1;
  90. int rowEnd = sheet.getPhysicalNumberOfRows();
  91. for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
  92. Row row = sheet.getRow(rowNum);
  93. if (null == row) {
  94. continue;
  95. }
  96. NeoMap resultData = convertRowToData(row, columnMap);
  97. if (null == resultData) {
  98. log.warn("第 " + row.getRowNum() + "行数据不合法,已忽略!");
  99. continue;
  100. }
  101. resultDataList.add(resultData);
  102. }
  103. return resultDataList;
  104. }
  105. /**
  106. * 提取每一行中需要的数据,构造成为一个结果数据对象
  107. *
  108. * 当该行中有单元格的数据为空或不合法时,忽略该行的数据
  109. *
  110. * @param row 行数据
  111. * @return 解析后的行数据对象,行数据错误时返回null
  112. */
  113. private NeoMap convertRowToData(Row row, NeoMap columnMap) {
  114. NeoMap resultData = new NeoMap();
  115. Cell cell;
  116. int cellNum = 0;
  117. // 获取姓名
  118. while ((cell = row.getCell(cellNum)) != null){
  119. resultData.put(columnMap.getString(String.valueOf(cellNum)), convertCellValueToString(cell));
  120. cellNum++;
  121. }
  122. return resultData;
  123. }
  124. /**
  125. * 将单元格内容转换为字符串
  126. */
  127. private String convertCellValueToString(Cell cell) {
  128. if(cell==null){
  129. return null;
  130. }
  131. String returnValue = null;
  132. switch (cell.getCellType()) {
  133. case CELL_TYPE_NUMERIC:
  134. Double doubleValue = cell.getNumericCellValue();
  135. // 格式化科学计数法,取一位整数
  136. DecimalFormat df = new DecimalFormat("0");
  137. returnValue = df.format(doubleValue);
  138. break;
  139. case CELL_TYPE_STRING:
  140. returnValue = cell.getStringCellValue();
  141. break;
  142. case CELL_TYPE_BOOLEAN:
  143. Boolean booleanValue = cell.getBooleanCellValue();
  144. returnValue = booleanValue.toString();
  145. break;
  146. case CELL_TYPE_BLANK:
  147. break;
  148. case CELL_TYPE_FORMULA:
  149. returnValue = cell.getCellFormula();
  150. break;
  151. case CELL_TYPE_ERROR:
  152. break;
  153. default:
  154. break;
  155. }
  156. return returnValue;
  157. }
  158. /**
  159. * 根据文件后缀名类型获取对应的工作簿对象
  160. * @param inputStream 读取文件的输入流
  161. * @param fileType 文件后缀名类型(xls或xlsx)
  162. * @return 包含文件数据的工作簿对象
  163. */
  164. private Workbook getWorkbook(InputStream inputStream, String fileType) throws IOException {
  165. Workbook workbook = null;
  166. if (fileType.equalsIgnoreCase(XLS)) {
  167. workbook = new HSSFWorkbook(inputStream);
  168. } else if (fileType.equalsIgnoreCase(XLSX)) {
  169. workbook = new XSSFWorkbook(inputStream);
  170. }
  171. return workbook;
  172. }
  173. }

比如像这种
image.png
解析得到的数据可以达到这种程度

  1. [
  2. {
  3. "address":"杭州耿迪医药科技有限公司",
  4. "idCard":"330326********5421",
  5. "inputType":"引进往届大专生",
  6. "name":"asdf"
  7. },
  8. {
  9. "address":"浙江泽大律师事务所",
  10. "idCard":"332501********0021",
  11. "inputType":"引进往届本科生",
  12. "name":"asdf"
  13. }
  14. ]

将文件流导出到表格

  1. @Test
  2. public void test21() {
  3. HashMap<String, String> fieldMap = new HashMap<>();
  4. fieldMap.put("name","测试");
  5. List<DataEntity> dataList = new ArrayList<>();
  6. dataList.add(new DataEntity("数据1"));
  7. dataList.add(new DataEntity("数据2"));
  8. dataList.add(new DataEntity("数据3"));
  9. ExcelUtil.export("分页1", dataList, fieldMap);
  10. }
  1. import lombok.experimental.UtilityClass;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.apache.poi.hssf.usermodel.*;
  4. import javax.servlet.http.HttpServletResponse;
  5. import java.io.File;
  6. import java.io.FileOutputStream;
  7. import java.io.OutputStream;
  8. import java.io.UnsupportedEncodingException;
  9. import java.lang.reflect.Field;
  10. import java.text.SimpleDateFormat;
  11. import java.util.*;
  12. /**
  13. * @author shizi
  14. * @since 2021-04-14 10:27:34
  15. */
  16. @Slf4j
  17. @UtilityClass
  18. public class ExcelUtil {
  19. /**
  20. * 导出Excel
  21. *
  22. * @param sheetName 分页名
  23. * @param list 要导出的数据集合
  24. * @param fieldMap 中英文字段对应Map,即要导出的excel表头
  25. */
  26. public <T> void export(String file, String sheetName, List<T> list, Map<String, String> fieldMap) {
  27. try {
  28. //创建一个WorkBook,对应一个Excel文件
  29. HSSFWorkbook wb = new HSSFWorkbook();
  30. //在Workbook中,创建一个sheet,对应Excel中的工作薄(sheet)
  31. HSSFSheet sheet = wb.createSheet(sheetName);
  32. //创建单元格,并设置值表头 设置表头居中
  33. HSSFCellStyle style = wb.createCellStyle();
  34. //创建一个居中格式
  35. style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
  36. // 填充工作表
  37. fillSheet(sheet, list, fieldMap, style);
  38. //将文件输出
  39. // OutputStream ouputStream = response.getOutputStream();
  40. FileOutputStream ouputStream = new FileOutputStream(new File(file));
  41. wb.write(ouputStream);
  42. ouputStream.flush();
  43. ouputStream.close();
  44. } catch (Exception e) {
  45. log.info("导出Excel失败!");
  46. log.error(e.getMessage());
  47. }
  48. log.info("导出Excel成功,位置:" + file);
  49. }
  50. /**
  51. * 根据字段名获取字段对象
  52. *
  53. * @param fieldName 字段名
  54. * @param clazz 包含该字段的类
  55. * @return 字段
  56. */
  57. public static Field getFieldByName(String fieldName, Class<?> clazz) {
  58. // log.info("根据字段名获取字段对象:getFieldByName()");
  59. // 拿到本类的所有字段
  60. Field[] selfFields = clazz.getDeclaredFields();
  61. // 如果本类中存在该字段,则返回
  62. for (Field field : selfFields) {
  63. //如果本类中存在该字段,则返回
  64. if (field.getName().equals(fieldName)) {
  65. return field;
  66. }
  67. }
  68. // 否则,查看父类中是否存在此字段,如果有则返回
  69. Class<?> superClazz = clazz.getSuperclass();
  70. if (superClazz != null && superClazz != Object.class) {
  71. //递归
  72. return getFieldByName(fieldName, superClazz);
  73. }
  74. // 如果本类和父类都没有,则返回空
  75. return null;
  76. }
  77. /**
  78. * 根据字段名获取字段值
  79. *
  80. * @param fieldName 字段名
  81. * @param object 对象
  82. * @return 字段值
  83. * @throws Exception 异常
  84. */
  85. public static Object getFieldValueByName(String fieldName, Object object) throws Exception {
  86. Object value = null;
  87. //根据字段名得到字段对象
  88. Field field = getFieldByName(fieldName, object.getClass());
  89. //如果该字段存在,则取出该字段的值
  90. if (field != null) {
  91. field.setAccessible(true);//类中的成员变量为private,在类外边使用属性值,故必须进行此操作
  92. value = field.get(object);//获取当前对象中当前Field的value
  93. } else {
  94. throw new Exception(object.getClass().getSimpleName() + "类不存在字段名 " + fieldName);
  95. }
  96. return value;
  97. }
  98. /**
  99. * 根据带路径或不带路径的属性名获取属性值,即接受简单属性名,
  100. * 如userName等,又接受带路径的属性名,如student.department.name等
  101. *
  102. * @param fieldNameSequence 带路径的属性名或简单属性名
  103. * @param object 对象
  104. * @return 属性值
  105. * @throws Exception 异常
  106. */
  107. public static Object getFieldValueByNameSequence(String fieldNameSequence, Object object) throws Exception {
  108. Object value = null;
  109. // 将fieldNameSequence进行拆分
  110. String[] attributes = fieldNameSequence.split("\\.");
  111. if (attributes.length == 1) {
  112. value = getFieldValueByName(fieldNameSequence, object);
  113. } else {
  114. // 根据数组中第一个连接属性名获取连接属性对象,如student.department.name
  115. Object fieldObj = getFieldValueByName(attributes[0], object);
  116. //截取除第一个属性名之后的路径
  117. String subFieldNameSequence = fieldNameSequence.substring(fieldNameSequence.indexOf(".") + 1);
  118. //递归得到最终的属性对象的值
  119. value = getFieldValueByNameSequence(subFieldNameSequence, fieldObj);
  120. }
  121. return value;
  122. }
  123. /**
  124. * 向工作表中填充数据
  125. *
  126. * @param sheet excel的工作表名称
  127. * @param list 数据源
  128. * @param fieldMap 中英文字段对应关系的Map
  129. * @param style 表格中的格式
  130. * @throws Exception 异常
  131. */
  132. public static <T> void fillSheet(HSSFSheet sheet, List<T> list, Map<String, String> fieldMap, HSSFCellStyle style) throws Exception {
  133. // 定义存放英文字段名和中文字段名的数组
  134. String[] enFields = new String[fieldMap.size()];
  135. String[] cnFields = new String[fieldMap.size()];
  136. // 填充数组
  137. int count = 0;
  138. for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
  139. enFields[count] = entry.getKey();
  140. cnFields[count] = entry.getValue();
  141. count++;
  142. }
  143. //在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
  144. HSSFRow row = sheet.createRow((int) 0);
  145. // 填充表头
  146. for (int i = 0; i < cnFields.length; i++) {
  147. HSSFCell cell = row.createCell(i);
  148. cell.setCellValue(cnFields[i]);
  149. cell.setCellStyle(style);
  150. sheet.autoSizeColumn(i);
  151. }
  152. // 填充内容
  153. for (int index = 0; index < list.size(); index++) {
  154. row = sheet.createRow(index + 1);
  155. // 获取单个对象
  156. T item = list.get(index);
  157. for (int i = 0; i < enFields.length; i++) {
  158. Object objValue = getFieldValueByNameSequence(enFields[i], item);
  159. String fieldValue = objValue == null ? "" : objValue.toString();
  160. row.createCell(i).setCellValue(fieldValue);
  161. }
  162. }
  163. }
  164. }

excel的导出示例

  1. import com.alibaba.fastjson.JSON;
  2. import com.alibaba.fastjson.JSONArray;
  3. import lombok.SneakyThrows;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.apache.poi.hssf.usermodel.HSSFCellStyle;
  6. import org.apache.poi.hssf.usermodel.HSSFSheet;
  7. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  8. import org.junit.Test;
  9. import java.io.File;
  10. import java.io.FileNotFoundException;
  11. import java.io.FileOutputStream;
  12. import java.util.*;
  13. import java.util.stream.Collectors;
  14. import java.util.stream.Stream;
  15. /**
  16. * @author shizi
  17. * @since 2022-03-30 12:00:04
  18. */
  19. @Slf4j
  20. public class ExcepDemo {
  21. @Test
  22. @SneakyThrows
  23. public void test21() {
  24. HashMap<String, String> fieldMap = new HashMap<>();
  25. fieldMap.put("name","名字");
  26. fieldMap.put("memory","内存");
  27. fieldMap.put("cpu","cpu");
  28. fieldMap.put("storage","存储");
  29. fieldMap.put("time","时间");
  30. String equalContent = FileUtil.readFromResource(ExcepDemo.class, "/json/service.txt");
  31. List<ServiceEntity> dataList = Arrays.stream(equalContent.split("\n")).flatMap(e->JSON.parseArray(e, ServiceEntity.class).stream()).collect(Collectors.toList());
  32. Map<String, List<ServiceEntity>> dataMap = dataList.stream().collect(Collectors.groupingBy(ServiceEntity::getName));
  33. HSSFWorkbook wb = new HSSFWorkbook();
  34. FileOutputStream ouputStream = null;
  35. ouputStream = new FileOutputStream(new File("/Users/zhouzhenyong/tem/export/service_final1.xls"));
  36. dataMap.forEach((k, v) -> {
  37. HSSFSheet sheet = wb.createSheet(k);
  38. HSSFCellStyle style = wb.createCellStyle();
  39. style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
  40. try {
  41. ExcelUtil.fillSheet(sheet, v, fieldMap, style);
  42. } catch (Throwable e) {
  43. e.printStackTrace();
  44. }
  45. });
  46. wb.write(ouputStream);
  47. ouputStream.flush();
  48. ouputStream.close();
  49. }
  50. @Test
  51. @SneakyThrows
  52. public void test22() {
  53. HashMap<String, String> fieldMap = new HashMap<>();
  54. fieldMap.put("cpuUsage","cpu使用");
  55. fieldMap.put("diskTotal","磁盘总量(有问题)");
  56. fieldMap.put("diskUsed","磁盘使用量(有问题)");
  57. fieldMap.put("diskRatio","磁盘比率");
  58. fieldMap.put("memoryUsage","内存使用");
  59. fieldMap.put("createTime","搜集时间");
  60. String equalContent = FileUtil.readFromResource(ExcepDemo.class, "/json/total.txt");
  61. List<TotalEntity> dataList = Arrays.stream(equalContent.split("\n")).map(e->{
  62. TotalEntity data = JSON.parseObject(e, TotalEntity.class);
  63. data.setCpuUsage(data.getCpuUsage().substring(0, 5) + "%");
  64. Long totalSize = Long.valueOf(data.getDiskTotal());
  65. Long useSize = Long.valueOf(data.getDiskUsed());
  66. String ratio = String.valueOf((useSize * 100 )/totalSize);
  67. data.setDiskRatio(ratio + "%");
  68. data.setDiskTotal(changeSize(data.getDiskTotal()));
  69. data.setDiskUsed(changeSize(data.getDiskUsed()));
  70. data.setMemoryUsage(data.getMemoryUsage() + "%");
  71. return data;
  72. }).collect(Collectors.toList());
  73. ExcelUtil.export("/Users/zhouzhenyong/tem/export/total_final1.xls", "总况", dataList, fieldMap);
  74. }
  75. private Integer ByteSize = 1024;
  76. private String changeSize(String disk) {
  77. Long data = Long.valueOf(disk);
  78. if (data < ByteSize) {
  79. return data + "B";
  80. }
  81. data /= ByteSize;
  82. if (data < ByteSize) {
  83. return data + "KB";
  84. }
  85. data /= ByteSize;
  86. if (data < ByteSize) {
  87. return data + "MB";
  88. }
  89. data /= ByteSize;
  90. if (data < ByteSize) {
  91. return data + "GB";
  92. }
  93. return data + "TB";
  94. }
  95. }