MergeReadsExcelUtil.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. package com.zksy.utils;
  2. import com.zksy.common.exception.ServiceException;
  3. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  4. import org.apache.poi.ss.usermodel.*;
  5. import org.apache.poi.ss.util.CellRangeAddress;
  6. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  7. import org.springframework.web.multipart.MultipartFile;
  8. import java.io.FileInputStream;
  9. import java.io.IOException;
  10. import java.io.InputStream;
  11. import java.lang.reflect.Field;
  12. import java.text.DecimalFormat;
  13. import java.util.*;
  14. import java.util.regex.Pattern;
  15. public class MergeReadsExcelUtil<T> {
  16. /**
  17. * 读取excel数据
  18. * @param file
  19. */
  20. public static <T> List<Map<String,String>> readExcelToObj(MultipartFile file, int headerColumn, int number, int headerLine, Class<T> classEntity) {
  21. Workbook wb = null;
  22. String fileName = file.getOriginalFilename();//获取文件名
  23. List<Map<String,String>> result = null;
  24. try {
  25. if (!validateExcel(fileName)) {// 验证文件名是否合格
  26. return null;
  27. }
  28. boolean isExcel2003 = true;// 根据文件名判断文件是2003版本还是2007版本
  29. if (isExcel2007(fileName)) {
  30. isExcel2003 = false;
  31. }
  32. if (isExcel2003) {// 当excel是2003时,创建excel2003
  33. wb = new HSSFWorkbook(file.getInputStream());
  34. } else {// 当excel是2007时,创建excel2007
  35. wb = new XSSFWorkbook(file.getInputStream());
  36. }
  37. result = readExcel(wb, 0, 1, 0, headerColumn, number, headerLine,classEntity);
  38. } catch (IOException e) {
  39. e.printStackTrace();
  40. }
  41. return result;
  42. }
  43. /**
  44. * 读取excel文件
  45. * @param wb
  46. * @param sheetIndex sheet页下标:从0开始
  47. * @param startReadLine 开始读取的行:从0开始
  48. * @param tailLine 去除最后读取的行
  49. */
  50. private static <T> List<Map<String,String>> readExcel(Workbook wb, int sheetIndex, int startReadLine, int tailLine,int headerColumn,int number,int headerLine,Class<T> classEntity) {
  51. Sheet sheet = wb.getSheetAt(sheetIndex);
  52. Row row = null;
  53. List<Map<String,String>> result = new ArrayList<Map<String,String>>();
  54. List<String> stringList = getEntityProp(classEntity);
  55. List<String> serialNumberColumn = new ArrayList<>();
  56. /*if(sheet.getRow(sheet.getFirstRowNum()).getLastCellNum() != headerColumn){
  57. throw new ServiceException("导入模板不正确");
  58. }*/
  59. for(int i=startReadLine; i<sheet.getLastRowNum()-tailLine+1; i++) {
  60. row = sheet.getRow(i);
  61. Map<String,String> map = new HashMap<String,String>();
  62. for(Cell c : row) {
  63. String returnStr = "";
  64. boolean isMerge = isMergedRegion(sheet, i, c.getColumnIndex());
  65. //判断是否具有合并单元格
  66. if(isMerge) {
  67. String rs = getMergedRegionValue(sheet, row.getRowNum(), c.getColumnIndex());
  68. returnStr = rs;
  69. }else {
  70. //设置单元格类型
  71. returnStr = getCellValue(c);
  72. }
  73. //将值存进list
  74. serialNumberColumn.add(returnStr);
  75. if(serialNumberColumn.contains("序号")){
  76. //去掉第一列数据
  77. if(c.getColumnIndex() <= headerColumn && c.getColumnIndex() >= number && i > headerLine) {
  78. map.put(stringList.get(c.getColumnIndex() - 1), returnStr);
  79. }
  80. }else{
  81. //不去第一列数据
  82. if(c.getColumnIndex() < headerColumn && i > headerLine) {
  83. map.put(stringList.get(c.getColumnIndex()), returnStr);
  84. }
  85. }
  86. }
  87. if(map.size() > 0) {
  88. result.add(map);
  89. }
  90. }
  91. if(result.size() > 0 && result.get(0).size() != headerColumn){
  92. throw new ServiceException("导入模板不正确");
  93. }
  94. return result;
  95. }
  96. //错误信息接收器
  97. private static String errorMsg;
  98. public static boolean validateExcel(String filePath) {
  99. if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))) {
  100. errorMsg = "文件名不是excel格式";
  101. return false;
  102. }
  103. return true;
  104. }
  105. // @描述:是否是2003的excel,返回true是2003
  106. public static boolean isExcel2003(String filePath) {
  107. return filePath.matches("^.+\\.(?i)(xls)$");
  108. }
  109. //@描述:是否是2007的excel,返回true是2007
  110. public static boolean isExcel2007(String filePath) {
  111. return filePath.matches("^.+\\.(?i)(xlsx)$");
  112. }
  113. public static <T> List<String> getEntityProp(Class<T> clazz) {
  114. Field[] fields = clazz.getDeclaredFields();
  115. List<String> fieldNames = new ArrayList<>();
  116. for (Field field : fields) {
  117. fieldNames.add(field.getName());
  118. }
  119. fieldNames.remove("serialVersionUID");
  120. fieldNames.remove("id");
  121. return fieldNames;
  122. }
  123. /**
  124. * 获取合并单元格的值
  125. * @param sheet
  126. * @param row
  127. * @param column
  128. * @return
  129. */
  130. public static String getMergedRegionValue(Sheet sheet, int row, int column){
  131. int sheetMergeCount = sheet.getNumMergedRegions();
  132. for(int i = 0 ; i < sheetMergeCount ; i++){
  133. CellRangeAddress ca = sheet.getMergedRegion(i);
  134. int firstColumn = ca.getFirstColumn();
  135. int lastColumn = ca.getLastColumn();
  136. int firstRow = ca.getFirstRow();
  137. int lastRow = ca.getLastRow();
  138. if(row >= firstRow && row <= lastRow){
  139. if(column >= firstColumn && column <= lastColumn){
  140. Row fRow = sheet.getRow(firstRow);
  141. Cell fCell = fRow.getCell(firstColumn);
  142. return getCellValue(fCell) ;
  143. }
  144. }
  145. }
  146. return null ;
  147. }
  148. /**
  149. * 判断合并了行
  150. * @param sheet
  151. * @param row
  152. * @param column
  153. * @return
  154. */
  155. private boolean isMergedRow(Sheet sheet,int row ,int column) {
  156. int sheetMergeCount = sheet.getNumMergedRegions();
  157. for (int i = 0; i < sheetMergeCount; i++) {
  158. CellRangeAddress range = sheet.getMergedRegion(i);
  159. int firstColumn = range.getFirstColumn();
  160. int lastColumn = range.getLastColumn();
  161. int firstRow = range.getFirstRow();
  162. int lastRow = range.getLastRow();
  163. if(row == firstRow && row == lastRow){
  164. if(column >= firstColumn && column <= lastColumn){
  165. return true;
  166. }
  167. }
  168. }
  169. return false;
  170. }
  171. /**
  172. * 判断指定的单元格是否是合并单元格
  173. * @param sheet
  174. * @param row 行下标
  175. * @param column 列下标
  176. * @return
  177. */
  178. private static boolean isMergedRegion(Sheet sheet, int row, int column) {
  179. int sheetMergeCount = sheet.getNumMergedRegions();
  180. for (int i = 0; i < sheetMergeCount; i++) {
  181. CellRangeAddress range = sheet.getMergedRegion(i);
  182. int firstColumn = range.getFirstColumn();
  183. int lastColumn = range.getLastColumn();
  184. int firstRow = range.getFirstRow();
  185. int lastRow = range.getLastRow();
  186. if(row >= firstRow && row <= lastRow){
  187. if(column >= firstColumn && column <= lastColumn){
  188. return true;
  189. }
  190. }
  191. }
  192. return false;
  193. }
  194. /**
  195. * 判断sheet页中是否含有合并单元格
  196. * @param sheet
  197. * @return
  198. */
  199. private boolean hasMerged(Sheet sheet) {
  200. return sheet.getNumMergedRegions() > 0 ? true : false;
  201. }
  202. /**
  203. * 合并单元格
  204. * @param sheet
  205. * @param firstRow 开始行
  206. * @param lastRow 结束行
  207. * @param firstCol 开始列
  208. * @param lastCol 结束列
  209. */
  210. private void mergeRegion(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
  211. sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
  212. }
  213. /**
  214. * 获取单元格的值
  215. * @param cell
  216. * @return
  217. */
  218. public static String getCellValue(Cell cell){
  219. if(cell == null) {
  220. return "";
  221. }
  222. if(cell.getCellType() == CellType.STRING){
  223. return cell.getStringCellValue();
  224. }else if(cell.getCellType() == CellType.BOOLEAN){
  225. return String.valueOf(cell.getBooleanCellValue());
  226. }else if(cell.getCellType() == CellType.FORMULA){
  227. return convertToPercentage(cell);
  228. }else if(cell.getCellType() == CellType.NUMERIC){
  229. double numericValue = cell.getNumericCellValue();
  230. DecimalFormat df = new DecimalFormat("0"); // 设置格式化模式,保留小数点后的所有位数
  231. // 判断是否为科学计数法
  232. if(String.valueOf(numericValue).contains("E")) {
  233. DataFormatter dataFormatter = new DataFormatter();
  234. String formattedValue = dataFormatter.formatCellValue(cell); // 使用 DataFormatter 获取格式化后的值
  235. return formattedValue;
  236. }/*else if(String.valueOf(numericValue).contains("-")){
  237. //时间格式
  238. DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("d-LLL-yyyy", Locale.CHINESE);
  239. LocalDate date = LocalDate.parse(cell.toString(), inputFormatter);
  240. return date.toString();
  241. } */else {
  242. String formattedValue = df.format(numericValue); // 格式化数值为完整形式
  243. return formattedValue;
  244. }
  245. /* String s = cell.getNumericCellValue() + "";
  246. // 去掉尾巴上的小数点0
  247. if (Pattern.matches(".*\\.0*", s)) {
  248. return s.split("\\.")[0];
  249. } else {
  250. return s;
  251. }*/
  252. }
  253. return "";
  254. }
  255. public static String convertToPercentage(Cell cell) {
  256. try {
  257. if (cell.getCellType() == CellType.FORMULA) {
  258. String s = cell.getNumericCellValue() + "";
  259. // 去掉尾巴上的小数点0
  260. if (Pattern.matches(".*\\.0*", s)) {
  261. return s.split("\\.")[0];
  262. } else if(s.contains("E")){
  263. DecimalFormat decimalFormat = new DecimalFormat("0");
  264. String decimalNumber = decimalFormat.format(Double.parseDouble(s));
  265. return decimalNumber;
  266. }else{
  267. return s;
  268. }
  269. /*double value = cell.getNumericCellValue();
  270. return String.format("%.2f%%", value * 100); // 保留两位小数*/
  271. }
  272. }catch (Exception e){
  273. //return "0%"; // 如果不是数字类型,返回"NaN%"
  274. }
  275. return null;
  276. }
  277. /**
  278. * 从excel读取内容
  279. */
  280. public static void readContent(String fileName) {
  281. boolean isE2007 = false; //判断是否是excel2007格式
  282. if(fileName.endsWith("xlsx")) {
  283. isE2007 = true;
  284. }
  285. try {
  286. InputStream input = new FileInputStream(fileName); //建立输入流
  287. Workbook wb = null;
  288. //根据文件格式(2003或者2007)来初始化
  289. if(isE2007) {
  290. wb = new XSSFWorkbook(input);
  291. } else {
  292. wb = new HSSFWorkbook(input);
  293. }
  294. Sheet sheet = wb.getSheetAt(0); //获得第一个表单
  295. Iterator<Row> rows = sheet.rowIterator(); //获得第一个表单的迭代器
  296. while (rows.hasNext()) {
  297. Row row = rows.next(); //获得行数据
  298. System.out.println("Row #" + row.getRowNum()); //获得行号从0开始
  299. Iterator<Cell> cells = row.cellIterator(); //获得第一行的迭代器
  300. while (cells.hasNext()) {
  301. Cell cell = cells.next();
  302. System.out.println("Cell #" + cell.getColumnIndex());
  303. switch (cell.getCellType()) { //根据cell中的类型来输出数据
  304. case NUMERIC:
  305. System.out.println(cell.getNumericCellValue());
  306. break;
  307. case STRING:
  308. System.out.println(cell.getStringCellValue());
  309. break;
  310. case BOOLEAN:
  311. System.out.println(cell.getBooleanCellValue());
  312. break;
  313. case FORMULA:
  314. System.out.println(cell.getCellFormula());
  315. break;
  316. default:
  317. System.out.println("unsuported sell type======="+cell.getCellType());
  318. break;
  319. }
  320. }
  321. }
  322. } catch (IOException ex) {
  323. ex.printStackTrace();
  324. }
  325. }
  326. }