ExcelUtil.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. package com.loan.system.utils;
  2. import com.loan.system.annotation.ExcelColumn;
  3. import org.apache.commons.collections4.CollectionUtils;
  4. import org.apache.commons.lang3.BooleanUtils;
  5. import org.apache.commons.lang3.CharUtils;
  6. import org.apache.commons.lang3.StringUtils;
  7. import org.apache.commons.lang3.math.NumberUtils;
  8. import org.apache.poi.hssf.usermodel.HSSFDateUtil;
  9. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  10. import org.apache.poi.ss.usermodel.*;
  11. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  12. import org.slf4j.Logger;
  13. import org.slf4j.LoggerFactory;
  14. import org.springframework.http.MediaType;
  15. import org.springframework.web.multipart.MultipartFile;
  16. import javax.servlet.http.HttpServletResponse;
  17. import java.io.File;
  18. import java.io.FileOutputStream;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.lang.reflect.Constructor;
  22. import java.lang.reflect.Field;
  23. import java.math.BigDecimal;
  24. import java.net.URLEncoder;
  25. import java.util.*;
  26. import java.util.concurrent.atomic.AtomicInteger;
  27. import java.util.stream.Collectors;
  28. import java.util.stream.Stream;
  29. /**
  30. * @author : EdwinXu
  31. * @date : Created in 2020/11/25 21:53
  32. */
  33. public class ExcelUtil {
  34. private final static Logger logger = LoggerFactory.getLogger(ExcelUtil.class);
  35. private final static String EXCEL2003 = "xls";
  36. private final static String EXCEL2007 = "xlsx";
  37. public static <T> List<T> readExcel(String path, Class<T> cls, MultipartFile file){
  38. String fileName = file.getOriginalFilename();
  39. if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
  40. logger.error("上传文件格式不正确");
  41. }
  42. List<T> dataList = new ArrayList<>();
  43. Workbook workbook = null;
  44. try {
  45. InputStream is = file.getInputStream();
  46. if (fileName.endsWith(EXCEL2007)) {
  47. // FileInputStream is = new FileInputStream(new File(path));
  48. workbook = new XSSFWorkbook(is);
  49. }
  50. if (fileName.endsWith(EXCEL2003)) {
  51. // FileInputStream is = new FileInputStream(new File(path));
  52. workbook = new HSSFWorkbook(is);
  53. }
  54. if (workbook != null) {
  55. //类映射 注解 value-->bean columns
  56. Map<String, List<Field>> classMap = new HashMap<>();
  57. List<Field> fields = Stream.of(cls.getDeclaredFields()).collect(Collectors.toList());
  58. fields.forEach(
  59. field -> {
  60. ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
  61. if (annotation != null) {
  62. String value = annotation.value();
  63. if (StringUtils.isBlank(value)) {
  64. return;//return起到的作用和continue是相同的 语法
  65. }
  66. if (!classMap.containsKey(value)) {
  67. classMap.put(value, new ArrayList<>());
  68. }
  69. field.setAccessible(true);
  70. classMap.get(value).add(field);
  71. }
  72. }
  73. );
  74. //索引-->columns
  75. Map<Integer, List<Field>> reflectionMap = new HashMap<>(16);
  76. //默认读取第一个sheet
  77. Sheet sheet = workbook.getSheetAt(0);
  78. boolean firstRow = true;
  79. for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
  80. Row row = sheet.getRow(i);
  81. //首行 提取注解
  82. if (firstRow) {
  83. for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
  84. Cell cell = row.getCell(j);
  85. String cellValue = getCellValue(cell);
  86. if (classMap.containsKey(cellValue)) {
  87. reflectionMap.put(j, classMap.get(cellValue));
  88. }
  89. }
  90. firstRow = false;
  91. } else {
  92. //忽略空白行
  93. if (row == null) {
  94. continue;
  95. }
  96. try {
  97. T t = cls.newInstance();
  98. //判断是否为空白行
  99. boolean allBlank = true;
  100. for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
  101. if (reflectionMap.containsKey(j)) {
  102. Cell cell = row.getCell(j);
  103. String cellValue = getCellValue(cell);
  104. if (StringUtils.isNotBlank(cellValue)) {
  105. allBlank = false;
  106. }
  107. List<Field> fieldList = reflectionMap.get(j);
  108. fieldList.forEach(
  109. x -> {
  110. try {
  111. handleField(t, cellValue, x);
  112. } catch (Exception e) {
  113. logger.error(String.format("reflect field:%s value:%s exception!", x.getName(), cellValue), e);
  114. }
  115. }
  116. );
  117. }
  118. }
  119. if (!allBlank) {
  120. dataList.add(t);
  121. } else {
  122. logger.warn(String.format("row:%s is blank ignore!", i));
  123. }
  124. } catch (Exception e) {
  125. logger.error(String.format("parse row:%s exception!", i), e);
  126. }
  127. }
  128. }
  129. }
  130. } catch (Exception e) {
  131. logger.error("parse excel exception!", e);
  132. } finally {
  133. if (workbook != null) {
  134. try {
  135. workbook.close();
  136. } catch (Exception e) {
  137. logger.error("parse excel exception!", e);
  138. }
  139. }
  140. }
  141. return dataList;
  142. }
  143. private static <T> void handleField(T t, String value, Field field) throws Exception {
  144. Class<?> type = field.getType();
  145. if (type == void.class || StringUtils.isBlank(value)) {
  146. return;
  147. }
  148. if (type == Object.class) {
  149. field.set(t, value);
  150. //数字类型
  151. } else if (type.getSuperclass() == null || type.getSuperclass() == Number.class) {
  152. if (type == int.class || type == Integer.class) {
  153. field.set(t, NumberUtils.toInt(value));
  154. } else if (type == long.class || type == Long.class) {
  155. field.set(t, NumberUtils.toLong(value));
  156. } else if (type == byte.class || type == Byte.class) {
  157. field.set(t, NumberUtils.toByte(value));
  158. } else if (type == short.class || type == Short.class) {
  159. field.set(t, NumberUtils.toShort(value));
  160. } else if (type == double.class || type == Double.class) {
  161. field.set(t, NumberUtils.toDouble(value));
  162. } else if (type == float.class || type == Float.class) {
  163. field.set(t, NumberUtils.toFloat(value));
  164. } else if (type == char.class || type == Character.class) {
  165. field.set(t, CharUtils.toChar(value));
  166. } else if (type == boolean.class) {
  167. field.set(t, BooleanUtils.toBoolean(value));
  168. } else if (type == BigDecimal.class) {
  169. field.set(t, new BigDecimal(value));
  170. }
  171. } else if (type == Boolean.class) {
  172. field.set(t, BooleanUtils.toBoolean(value));
  173. } else if (type == Date.class) {
  174. //
  175. field.set(t, value);
  176. } else if (type == String.class) {
  177. field.set(t, value);
  178. } else {
  179. Constructor<?> constructor = type.getConstructor(String.class);
  180. field.set(t, constructor.newInstance(value));
  181. }
  182. }
  183. private static String getCellValue(Cell cell) {
  184. if (cell == null) {
  185. return "";
  186. }
  187. if (cell.getCellType() == CellType.NUMERIC) {
  188. if (HSSFDateUtil.isCellDateFormatted(cell)) {
  189. return HSSFDateUtil.getJavaDate(cell.getNumericCellValue()).toString();
  190. } else {
  191. return BigDecimal.valueOf(cell.getNumericCellValue()).toString();
  192. }
  193. } else if (cell.getCellType() == CellType.STRING) {
  194. return StringUtils.trimToEmpty(cell.getStringCellValue());
  195. } else if (cell.getCellType() == CellType.FORMULA) {
  196. return StringUtils.trimToEmpty(cell.getCellFormula());
  197. } else if (cell.getCellType() == CellType.BLANK) {
  198. return "";
  199. } else if (cell.getCellType() == CellType.BOOLEAN) {
  200. return String.valueOf(cell.getBooleanCellValue());
  201. } else if (cell.getCellType() == CellType.ERROR) {
  202. return "ERROR";
  203. } else {
  204. return cell.toString().trim();
  205. }
  206. }
  207. public static <T> void writeExcel(HttpServletResponse response, List<T> dataList, Class<T> cls){
  208. Field[] fields = cls.getDeclaredFields();
  209. // 获得行标题
  210. List<Field> fieldList = Arrays.stream(fields)
  211. .filter(field -> {
  212. ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
  213. if (annotation != null && annotation.col() > 0) {
  214. field.setAccessible(true);
  215. return true;
  216. }
  217. return false;
  218. }).collect(Collectors.toList());
  219. // 这个排序没有必要
  220. // .sorted(Comparator.comparing(field -> {
  221. // int col = 0;
  222. // ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
  223. // if (annotation != null) {
  224. // col = annotation.col();
  225. // }
  226. // return col;
  227. // }))
  228. // 创建工作簿
  229. Workbook wb = new XSSFWorkbook();
  230. // 创建工作表
  231. Sheet sheet = wb.createSheet("Sheet1");
  232. AtomicInteger ai = new AtomicInteger();
  233. {
  234. // 行
  235. Row row = sheet.createRow(ai.getAndIncrement());
  236. AtomicInteger aj = new AtomicInteger();
  237. //写入头部
  238. fieldList.forEach(field -> {
  239. ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
  240. String columnName = "";
  241. if (annotation != null) {
  242. columnName = annotation.value();
  243. }
  244. // int i = fieldList.indexOf(field);
  245. // sheet.setColumnWidth(i,annotation.col());
  246. Cell cell = row.createCell(aj.getAndIncrement());
  247. CellStyle cellStyle = wb.createCellStyle();
  248. // cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); // 设置背景色
  249. // cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); //
  250. cellStyle.setAlignment(HorizontalAlignment.LEFT); // 居中
  251. cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
  252. cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
  253. cellStyle.setBorderTop(BorderStyle.THIN);//上边框
  254. cellStyle.setBorderRight(BorderStyle.THIN);//右边框
  255. Font font = wb.createFont();
  256. font.setFontName("宋体");
  257. cellStyle.setFont(font);
  258. cell.setCellStyle(cellStyle);
  259. cell.setCellValue(columnName);
  260. });
  261. }
  262. // 写入内容
  263. if (CollectionUtils.isNotEmpty(dataList)) {
  264. dataList.forEach(t -> {
  265. Row row1 = sheet.createRow(ai.getAndIncrement());
  266. AtomicInteger aj = new AtomicInteger();
  267. fieldList.forEach(field -> {
  268. // Class<?> type = field.getType();
  269. Object value = "";
  270. try {
  271. value = field.get(t);
  272. } catch (Exception e) {
  273. e.printStackTrace();
  274. }
  275. Cell cell = row1.createCell(aj.getAndIncrement());
  276. CellStyle cellStyle = wb.createCellStyle();
  277. cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
  278. cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
  279. cellStyle.setBorderTop(BorderStyle.THIN);//上边框
  280. cellStyle.setBorderRight(BorderStyle.THIN);//右边框
  281. Font font = wb.createFont();
  282. font.setFontName("宋体");
  283. cellStyle.setFont(font);
  284. cell.setCellStyle(cellStyle);
  285. if (value != null) {
  286. cell.setCellValue(value.toString());
  287. }
  288. });
  289. });
  290. }
  291. for (int i = 0; i < fieldList.size(); i++) {
  292. sheet.autoSizeColumn((short)i);
  293. }
  294. Sheet sheetAt = wb.getSheetAt(0);
  295. int physicalNumberOfRows = sheetAt.getPhysicalNumberOfRows();
  296. int col = 0;
  297. if (physicalNumberOfRows > 1 && sheet.getRow(0) != null) {
  298. col = sheet.getRow(0).getPhysicalNumberOfCells();
  299. }
  300. for(int i = 0;i<col;i++){
  301. Row row = sheetAt.getRow(0);
  302. Cell cell = row.getCell(i);
  303. if(cell != null&& cell.getStringCellValue().contains("金额") ){
  304. for(int j = 1;j<physicalNumberOfRows;j++){
  305. Row row1 = sheetAt.getRow(j);
  306. Cell cell1 = row1.getCell(i);
  307. if(cell1 != null) {
  308. if(StringUtils.isNotEmpty(cell1.getStringCellValue()))
  309. row1.getCell(i).setCellValue(Double.parseDouble(cell1.getStringCellValue()));
  310. }
  311. else{
  312. continue;
  313. }
  314. }
  315. }
  316. }
  317. //冻结窗格
  318. // wb.getSheet("Sheet1").createFreezePane(0, 1, 0, 1);
  319. //浏览器下载excel
  320. buildExcelDocument(UUID.randomUUID().toString()+".xlsx",wb,response);
  321. //生成excel文件
  322. // buildExcelFile(".\\default.xlsx",wb);
  323. }
  324. /**
  325. * 浏览器下载excel
  326. * @param fileName
  327. * @param wb
  328. * @param response
  329. */
  330. private static void buildExcelDocument(String fileName, Workbook wb, HttpServletResponse response){
  331. try {
  332. response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
  333. response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "utf-8"));
  334. response.flushBuffer();
  335. wb.write(response.getOutputStream());
  336. } catch (IOException e) {
  337. e.printStackTrace();
  338. }
  339. }
  340. /**
  341. * 生成excel文件
  342. * @param path 生成excel路径
  343. * @param wb
  344. */
  345. private static void buildExcelFile(String path, Workbook wb){
  346. File file = new File(path);
  347. if (file.exists()) {
  348. file.delete();
  349. }
  350. try {
  351. wb.write(new FileOutputStream(file));
  352. } catch (Exception e) {
  353. e.printStackTrace();
  354. }
  355. }
  356. }