實現思路java
實現步驟c++
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-excelant</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-examples</artifactId> <version>3.17</version> </dependency>
ExcelUtils utils = new ExcelUtils(); //字段名讀取開始索引 utils.setFieldReadIndex(4); //數據讀取開始索引 utils.setDataReadIndex(6); List<Map> maps = utils.getExcelInfo(file.getOriginalFilename(), file);
for(Map map :maps){ //這裏Bean是要用來接收的自定義實體類 Bean obj = MapToBeanUtils.getModel(map,Bean.class); //處理相關業務邏輯 }
實現思路web
實現步驟spring
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-excelant</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-examples</artifactId> <version>3.17</version> </dependency>
@Target(ElementType.FIELD) @Documented @Retention(RetentionPolicy.RUNTIME) public @interface ExcelColumn { String title(); }
@ExcelColumn(title="uuid") private String uuid;
//這裏Bean是要用來導出的自定義實體類 ExcelUtils.export(Bean.class, list, DateUtil.format(new Date(),DateUtil.INT_STRING_FORMAT), response);
ExcelUtils.javashell
package com.demo.util; import com.andacx.core.log.LogFactory; import com.andacx.tool.Asserts; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellUtil; import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.slf4j.Logger; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.commons.CommonsMultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.lang.reflect.Field; import java.util.*; /** * <p>@description:【Excel寫入和導出工具】</p> * <p>@author:【Boomer】</p> * <p>@date:【2018/1/11 11:18】</p> **/ public class ExcelUtils { private static final Logger LOGGER = LogFactory.get(ExcelUtils.class); /*** 總行數 **/ private int totalRows = 0; /*** 總條數 **/ private int totalCells = 0; /*** 數據讀取開始索引 **/ private int dataReadIndex = 3; /*** 字段名讀取開始索引 **/ private int fieldReadIndex = 2; public ExcelUtils() { } public int getTotalRows() { return totalRows; } public int getTotalCells() { return totalCells; } public int getDataReadIndex() { return dataReadIndex; } public void setDataReadIndex(int dataReadIndex) { this.dataReadIndex = dataReadIndex; } public int getFieldReadIndex() { return fieldReadIndex; } public void setFieldReadIndex(int fieldReadIndex) { this.fieldReadIndex = fieldReadIndex; } /** * <p>Description:【驗證EXCEL文件】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/11 14:07】</p> * @param filePath * @return **/ public boolean validateExcel(String filePath) { Asserts.notNull(filePath, "文件名不是excel格式"); Asserts.isTrue((isExcel2003(filePath) || isExcel2007(filePath)), "文件名不是excel格式"); return true; } /** * <p>Description:【是不是2003的excel,返回true是2003】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/11 14:07】</p> * @param filePath * @return **/ public static boolean isExcel2003(String filePath) { return filePath.matches("^.+.(xls)$"); } /** * <p>Description:【是不是2007的excel,返回true是2007】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/11 14:07】</p> * @param filePath * @return **/ public static boolean isExcel2007(String filePath) { return filePath.matches("^.+.(xlsx)$"); } /** * <p>Description:【讀EXCEL文件,獲取客戶信息集合】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/11 14:07】</p> * @param fileName * @param Mfile * @return **/ public List<Map> getExcelInfo(String fileName, MultipartFile Mfile) { //把spring文件上傳的MultipartFile轉換成CommonsMultipartFile類型 CommonsMultipartFile cf = (CommonsMultipartFile) Mfile; //獲取本地存儲路徑 File fileFolder = new File(Sysutils.getUploadFilePath()); if (!fileFolder.exists()) { fileFolder.mkdirs(); } //新建一個文件 File uploadFile = new File(Sysutils.getUploadFilePath() + System.currentTimeMillis() + ".xlsx"); //將上傳的文件寫入新建的文件中 try { cf.getFileItem().write(uploadFile); } catch (Exception e) { e.printStackTrace(); } //初始化信息的集合 List<Map> list = new ArrayList<>(); //初始化輸入流 InputStream is = null; try { //驗證文件名是否合格 if (!validateExcel(fileName)) { return null; } //根據新建的文件實例化輸入流 is = new FileInputStream(uploadFile); //根據excel裏面的內容讀取客戶信息 list = getExcelInfo(is, isExcel2003(fileName)); is.close(); } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return list; } /** * <p>Description:【根據excel裏面的內容讀取客戶信息】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/11 14:07】</p> * @param is 輸入流 * @param isExcel2003 excel是2003仍是2007版本 * @return * @throws IOException **/ public List<Map> getExcelInfo(InputStream is, boolean isExcel2003) { List<Map> list; try { /** 根據版本選擇建立Workbook的方式 */ Workbook wb; //當excel是2003時 if (isExcel2003) { wb = new HSSFWorkbook(is); } else {//當excel是2007時 wb = new XSSFWorkbook(is); } //讀取Excel裏面客戶的信息 list = readExcelValue(wb); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } catch (NumberFormatException e) { throw new RuntimeException("讀取錯誤,請確認Excel是否包含錯誤字符"); } return list; } /** * <p>Description:【讀取Excel裏面客戶的信息】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/11 14:07】</p> * @param wb * @return **/ private List<Map> readExcelValue(Workbook wb) { //獲得第一個shell Sheet sheet = wb.getSheetAt(0); //獲得Excel的行數 this.totalRows = sheet.getPhysicalNumberOfRows(); //獲得Excel的列數(前提是有行數) if (totalRows >= this.dataReadIndex && sheet.getRow(0) != null) { this.totalCells = sheet.getRow(0).getPhysicalNumberOfCells(); } List<Map> list = new ArrayList<>(); Map tempMap; //獲取列數據對應的字段 Row title = sheet.getRow(this.fieldReadIndex); List<String> header = new ArrayList<>(); //循環Excel的列 for (int c = 0; c < this.totalCells; c++) { Cell cell = title.getCell(c); header.add(cell.getStringCellValue()); } //循環Excel行數,從第二行開始。標題不入庫 for (int r = this.dataReadIndex; r < totalRows; r++) { Row row = sheet.getRow(r); if (row == null) { continue; } tempMap = new HashMap(this.totalCells); //循環Excel的列 for (int c = 0; c < this.totalCells; c++) { Cell cell = row.getCell(c); if (null != cell) { cell.setCellType(CellType.STRING); tempMap.put(header.get(c), cell.getStringCellValue()); } } //添加客戶 list.add(tempMap); } return list; } /** * <p>Description:【導出到file】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/11 14:07】</p> * @param clz * @param data * @param filePath * @param <T> * @throws IOException **/ public static <T> void export(Class<T> clz, List<? extends T> data, String filePath) throws IOException { FileOutputStream out = new FileOutputStream(filePath); getBook(clz, data).write(out); out.close(); } /** * <p>Description:【導出到httpServletResponse】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/11 14:07】</p> * @param clz * @param data * @param fileName * @param response * @param <T> **/ public static <T> void export(Class<T> clz, List<? extends T> data, String fileName, HttpServletResponse response) { try { response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-disposition", "attachment;filename=\"" + new String(fileName.getBytes("gb2312"), "ISO8859-1") + ".xlsx" + "\""); getBook(clz, data).write(response.getOutputStream()); } catch (Exception e) { throw new RuntimeException("系統異常"); } finally { try { response.getOutputStream().close(); } catch (IOException e) { LOGGER.error("流關閉異常:" + e.getMessage()); } } } /** * <p>Description:【生成Excel】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/11 14:07】</p> * @param clz * @param data * @return **/ private static <T> SXSSFWorkbook getBook(Class<T> clz, List<? extends T> data) { if (null == clz || null == data || data.size() <= 0) { throw new RuntimeException("參數異常"); } XSSFWorkbook workbook = new XSSFWorkbook(); SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(workbook, 100); //第一個工做本 SXSSFSheet sheet = sxssfWorkbook.createSheet(); sheet.trackAllColumnsForAutoSizing(); //表頭 Row header = sheet.createRow(0); //讀取類字段、註解信息 Field[] fields = clz.getDeclaredFields(); //寫入表頭 int invalidFieldNum = 0; for (Field field : fields) { ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class); if (excelColumn == null) { continue; } Cell headerCell = header.createCell(invalidFieldNum++); headerCell.setCellStyle(headerCellStyle(sxssfWorkbook)); headerCell.setCellValue(excelColumn.title()); } //寫入數據 for (int i = 0; i < data.size(); i++) { //第0行爲表頭 Row row = sheet.createRow(i + 1); //循環讀取字段 int cellIndex = 0; for (int j = 0; j < fields.length; j++) { Field field = fields[j]; field.setAccessible(true); Object cellValue; ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class); if (null == excelColumn) { continue; } Object o; try { o = field.get(data.get(i)); cellValue = o; } catch (Exception e) { throw new RuntimeException("系統異常"); } CellUtil.createCell(row, cellIndex++, String.valueOf(cellValue)); } } //自適應寬度 for (int i = 0; i < invalidFieldNum; i++) { sheet.autoSizeColumn(i); } return sxssfWorkbook; } /** * <p>Description:【設置Excel表頭樣式】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/11 14:07】</p> * @param wb * @return **/ public static CellStyle headerCellStyle(Workbook wb) { CellStyle style = wb.createCellStyle(); Font font = wb.createFont(); font.setFontName("宋體"); //設置字體大小 font.setFontHeightInPoints((short) 12); //加粗 font.setBold(true); // 設置背景色 style.setFillForegroundColor(HSSFColor.HSSFColorPredefined.SKY_BLUE.getIndex()); style.setFillPattern(FillPatternType.SOLID_FOREGROUND); //讓單元格居中 style.setAlignment(HorizontalAlignment.CENTER_SELECTION); // 左右居中 style.setAlignment(HorizontalAlignment.CENTER); // 上下居中 style.setVerticalAlignment(VerticalAlignment.CENTER); //設置自動換行 style.setWrapText(true); style.setFont(font); return style; } }
map轉實體工具類apache
package com.andacx.lbs.util; import com.andacx.tool.StringUtil; import org.apache.commons.collections.MapUtils; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * Created by Boomer on 2017/5/19. * @author Boomer */ public class MapToBeanUtils { /** * 獲取類類型的全部Field包括父類中的Field * * @param clazz 類類型 * @return 返回類類型的全部Field包括父類中的Field */ public static Field[] getAllFields(Class clazz) { Map<String, Field> map = new HashMap<String, Field>(); for (Field field : clazz.getDeclaredFields()) { Class fieldType = field.getType(); String fieldName = field.getName(); if(isBaseType(fieldType)){ try { map.put(fieldName, field); } catch (Exception e) { e.printStackTrace(); } } } while (clazz.getSuperclass() != null) { clazz = clazz.getSuperclass(); if (clazz == Object.class) { break; } for (Field field : clazz.getDeclaredFields()) { if (!map.containsKey(field.getName())) { map.put(field.getName(), field); } } } return map.values().toArray(new Field[map.size()]); } /** * <p>Description:【判斷是不是基本類型】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/8 16:13】</p> * @param fieldType * @return **/ public static Boolean isBaseType(Class fieldType){ if (fieldType == String.class) { return true; } else if (fieldType == double.class || fieldType == Double.class) { return true; } else if (fieldType == int.class || fieldType == Integer.class) { return true; } else if (fieldType == Boolean.class || fieldType == boolean.class) { return true; } else if (fieldType == Date.class) { return true; } return false; } /** * <p>Description:【將首字母轉換爲大寫】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/5 15:54】</p> * * @param a * @return **/ public static String firstCharToUpper(String a) { return (new StringBuilder()).insert(0, a.substring(0, 1).toUpperCase()).append(a.substring(1)).toString(); } /** * <p>Description:【將map隱射到實體類】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/5 16:27】</p> * * @param map * @param model * @return **/ public static <T> T getModel(Map map, Class<T> model) { Field[] fields = getAllFields(model); String value; Method method; T obj; try { obj = model.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } for (Field field : fields) { int modifiers = field.getModifiers(); if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) { continue; } //根據傳入的獲取str來判斷用哪一個字符串獲取參數 value = MapUtils.getString(map, field.getName()); if (StringUtil.isEmpty(value)) { if (field.getType() == String.class) { try { method = model.getMethod("get" + firstCharToUpper(field.getName())); Object invokeValue = method.invoke(obj); if (invokeValue != null) { value = invokeValue.toString(); } } catch (Exception e) { if (field.getType() == Boolean.class || field.getType() == boolean.class) { try { String fieldName = field.getName(); method = model.getMethod("get" + firstCharToUpper(fieldName.startsWith("is") ? fieldName.replace("is", "") : fieldName)); Object invokeValue = method.invoke(obj); if (invokeValue != null) { value = invokeValue.toString(); } } catch (Exception e1) { System.out.println(e1.getMessage()); } } else { System.out.println(e.getMessage()); } } } } if (StringUtil.isNotEmpty(value)) { invokeMethod(model, obj, value, field.getName(), field.getType()); } } return obj; } /** * <p>Description:【調用方法】</p> * <p>Author:【Boomer】</p> * <p>Date:【2018/1/5 16:26】</p> * * @param modelClass * @param object * @param value * @param fieldName * @param fieldType * @return **/ private static <T> void invokeMethod(Class<T> modelClass, T object, String value, String fieldName, Class fieldType) { Method method = null; try { method = modelClass.getMethod("set" + firstCharToUpper(fieldName), fieldType); } catch (NoSuchMethodException e) { if (fieldType == Boolean.class || fieldType == boolean.class) { try { method = modelClass.getMethod("set" + firstCharToUpper(fieldName.startsWith("is") ? fieldName.replace("is", "") : fieldName), fieldType); } catch (NoSuchMethodException e1) { } } else { } } try { if (null != method) { if (fieldType == String.class) { method.invoke(object, value); } else if (fieldType == double.class || fieldType == Double.class) { try { method.invoke(object, Double.parseDouble(value)); } catch (NumberFormatException e) { e.printStackTrace(); } } else if (fieldType == int.class || fieldType == Integer.class) { try { method.invoke(object, Integer.parseInt(value)); } catch (NumberFormatException e) { e.printStackTrace(); } } else if (fieldType == Boolean.class || fieldType == boolean.class) { try { method.invoke(object, Boolean.parseBoolean(value)); } catch (Exception e) { e.printStackTrace(); } } else if (fieldType == Date.class) { try { SimpleDateFormat sdf = (value.length() == 10 ? new SimpleDateFormat("yyyy-MM-dd") : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); method.invoke(object, sdf.parse(value)); } catch (Exception e) { e.printStackTrace(); } } } } catch (Exception e) { e.printStackTrace(); } } }
public static <T> List<T> mapToBean(List<Map> maps, Class<T> obj) throws IllegalAccessException, InstantiationException { List<T> list = new ArrayList<>(); for (Map<String, Object> map : maps) { T module = obj.newInstance(); BeanWrapper wapper = new BeanWrapperImpl(module); for (Map.Entry entry : map.entrySet()) { if (wapper.isWritableProperty(entry.getKey().toString())) { wapper.setPropertyValue(entry.getKey().toString(), entry.getValue().toString()); } } list.add(module); } return list; }