package com.sjdf.erp.common.utils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.HttpURLConnection; import java.net.URL; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFClientAnchor; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFPatriarch; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Drawing; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.multipart.MultipartFile; import com.sjdf.erp.common.annotation.ExcelDesc; import com.sjdf.erp.common.annotation.IsDictionary; import com.sjdf.erp.common.constant.CommonPlatformConstant; import com.sjdf.erp.common.constant.ConstBusiness; import com.sjdf.erp.common.constant.purchase.Msg; import com.sjdf.erp.common.dictionary.bean.sys.PlatformConstant; import com.sjdf.erp.common.dictionary.cache.ConfigManager; import com.sjdf.erp.common.net.HttpSocket; import com.sjdf.erp.common.vo.Message; import net.sf.json.JSONArray; import net.sf.json.JSONObject; public class ExcelUtils { private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtils.class); public static final String XLSX = ".xlsx"; public static final String XLS=".xls"; public static final int IMG_HEIGTH = 30; // 圖片高度顯示像素 public static final int IMG_WIDTH = 30; // 圖片寬度顯示像素 /** * 解析Excel文件(.xls和.xlsx都支持) * @param file Excel的File對象 * @return 解析後的JSONArray對象 * @throws Exception */ public static Message readExcel(File file) throws Exception { if (file == null || file.getName() == null) { throw new NullPointerException(Msg.UPLOAD_FILE_NULL); } String fileName = file.getName().toLowerCase(); Workbook book = null; if (fileName.endsWith(XLSX)) { book = new XSSFWorkbook(file); } else if (fileName.endsWith(XLS)) { POIFSFileSystem poifsFileSystem = new POIFSFileSystem(new FileInputStream(file)); book = new HSSFWorkbook(poifsFileSystem); } if (book != null) { Message message = read(book); book.close(); return message; } return Message.createMessage(Msg.FILE_MUST_BE_XLS_OR_XLSX, Collections.emptyList()); } /** * 解析Excel文件(.xls和.xlsx都支持) * @param file Excel的MultipartFile 對象 * @return 解析後的JSONArray對象 * @throws Exception */ public static Message readExcel(MultipartFile file)throws Exception { if (file == null || file.getOriginalFilename() == null) { return Message.createMessage(Msg.UPLOAD_FILE_NULL, Collections.emptyList()); } Workbook book = null; String name = file.getOriginalFilename().toLowerCase(); if (name.endsWith(XLSX)) { book =new XSSFWorkbook(file.getInputStream()); } else if (name.endsWith(XLS)) { book = new HSSFWorkbook(file.getInputStream()); } if (book != null) { Message message = read(book); book.close(); return message; } return Message.createMessage(Msg.FILE_MUST_BE_XLS_OR_XLSX, Collections.emptyList()); } /** * 讀取不定列excel * @param file * @return List<List<String>> * @throws Exception */ public static Message readIndeterminateExcel(MultipartFile file)throws Exception { if (file == null || file.getOriginalFilename() == null) { return Message.createMessage(Msg.UPLOAD_FILE_NULL, Collections.emptyList()); } Workbook book = null; String name = file.getOriginalFilename().toLowerCase(); if (name.endsWith(XLSX)) { book =new XSSFWorkbook(file.getInputStream()); } else if (name.endsWith(XLS)) { book = new HSSFWorkbook(file.getInputStream()); } if (book != null) { Message message = readIndeterminate(book); book.close(); return message; } return Message.createMessage(Msg.FILE_MUST_BE_XLS_OR_XLSX, Collections.emptyList()); } private static Message readIndeterminate(Workbook book) throws IOException { Sheet sheet = book.getSheetAt(0); int rowEnd = sheet.getLastRowNum(); // 尾行下標 Row firstRow = sheet.getRow(0); if (firstRow == null) { return Message.createMessage(Msg.EXCEL_ERROR, Collections.emptyList()); } List<List<String>> data = new ArrayList<>(); for(int i = 0; i <= rowEnd ; i++) { Row eachRow = sheet.getRow(i); if(eachRow == null) { continue; } int cellEnd = eachRow.getLastCellNum(); List<String> rowData = new ArrayList<>(); data.add(rowData); for (int k = 0; k < cellEnd; k++) { String val = null; try { val = getValue(eachRow.getCell(k)); } catch (Exception e) { LOGGER.error(i + "行" + k + "列獲取值錯誤", e); } rowData.add(val); } } Message message = Message.createMessage(); message.setReturnData(data); return message; } /** * 獲取excel 表頭 * @param file Excel的MultipartFile 對象 * @return 返回解析json * @throws IOException */ public static Message getExcelHead(MultipartFile file) throws IOException { if (file == null || file.getOriginalFilename() == null) { return Message.createMessage(Msg.UPLOAD_FILE_NULL, Collections.emptyList()); } Workbook book = null; String name = file.getOriginalFilename().toLowerCase(); if (name.endsWith(XLSX)) { book =new XSSFWorkbook(file.getInputStream()); } else if (name.endsWith(XLS)) { book = new HSSFWorkbook(file.getInputStream()); } if (book != null) { Sheet sheetAt = book.getSheetAt(0); int firstRowNum = sheetAt.getFirstRowNum(); Row row = sheetAt.getRow(firstRowNum); if (row == null) { return Message.createMessage(Msg.EXCEL_ERROR, Collections.emptyList()); } int cellStart = row.getFirstCellNum(); int cellEnd = row.getLastCellNum(); JSONObject obj = new JSONObject(); Integer num = 0; for (int j = cellStart; j < cellEnd; j++) { // 表頭遇到空格跳過 String val = getValue(row.getCell(j)); if (val == null || val.trim().length() == 0) { continue; } obj.put(num, val); num += 1; } book.close(); if (obj.isEmpty()) { return Message.createMessage(Msg.EXCEL_ERROR, Collections.emptyList()); } Message message = Message.createMessage(); message.setReturnData(obj); return message; } return Message.createMessage(Msg.FILE_MUST_BE_XLS_OR_XLSX, Collections.emptyList()); } /** * 解析數據 * @param sheet 表格sheet對象 * @param book 用於流關閉 * @return excel錶轉換後的JSONArray對象 * @throws IOException */ private static Message read(Workbook book) throws IOException { Sheet sheet = book.getSheetAt(0); int rowStart = sheet.getFirstRowNum(); // 首行下標 int rowEnd = sheet.getLastRowNum(); // 尾行下標 // 獲取第一行JSON對象鍵 Row firstRow = sheet.getRow(rowStart); if (firstRow == null) { return Message.createMessage(Msg.EXCEL_ERROR, Collections.emptyList()); } int cellStart = firstRow.getFirstCellNum(); int cellEnd = firstRow.getLastCellNum(); Map<Integer, String> keyMap = new HashMap<Integer, String>(); for (int j = cellStart; j < cellEnd; j++) { // 表頭遇到空格中止解析 String val = getValue(firstRow.getCell(j)); if (val == null || val.trim().length() == 0) { cellEnd = j; break; } keyMap.put(j,val); } if (PlatformUtils.isEmpty(keyMap)) { return Message.createMessage(Msg.EXCEL_ERROR, Collections.emptyList()); } // 獲取每行JSON對象的值 JSONArray array = new JSONArray(); // 若是首行與尾行相同,代表只有一行,返回表頭數據 if (rowStart == rowEnd) { JSONObject object = new JSONObject(); for (int i : keyMap.keySet()) { object.put(keyMap.get(i), ""); } array.add(object); Message message = Message.createMessage(); message.setReturnData(array); return message; } for(int i = rowStart+1; i <= rowEnd ; i++) { Row eachRow = sheet.getRow(i); JSONObject obj = new JSONObject(); StringBuffer sb = new StringBuffer(); for (int k = cellStart; k < cellEnd; k++) { if (eachRow != null) { Cell cell = eachRow.getCell(k); String val = getValue(cell); sb.append(val); // 全部數據添加到裏面,用於判斷該行是否爲空 obj.put(keyMap.get(k),val); } } if (sb.toString().length() > 0) { array.add(obj); } } Message message = Message.createMessage(); message.setReturnData(array); return message; } /** * 獲取每一個單元格的數據 * @param cell 單元格對象 * @param isKey 是否爲鍵:true-是,false-不是。 若是解析Json鍵,值爲空時報錯;若是不是Json鍵,值爲空不報錯 * @return 該單元格數據 * @throws IOException */ private static String getValue(Cell cell) throws IOException { // 空白或空 if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK ) { return ""; } // 0. 數字 類型 if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { if (HSSFDateUtil.isCellDateFormatted(cell)) { Date date = cell.getDateCellValue(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return df.format(date); } cell.setCellType(Cell.CELL_TYPE_STRING); String val = cell.getStringCellValue()+""; return getEValue(val); } // 1. String類型 if (cell.getCellType() == Cell.CELL_TYPE_STRING) { String val = cell.getStringCellValue(); if (val == null || val.trim().length() == 0) { return ""; } return PlatformUtils.xssFilter(val.trim()); } // 2. 公式 CELL_TYPE_FORMULA if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) { try { double cellValue = cell.getNumericCellValue(); return String.valueOf(cellValue); } catch (Exception e) { return "0.00"; } } // 4. 布爾值 CELL_TYPE_BOOLEAN if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) { return cell.getBooleanCellValue()+""; } // 5. 錯誤 CELL_TYPE_ERROR return ""; } public static String getEValue(String s){ // 非科學技術方法,直接去掉 if (!s.contains("E")) { return s; } BigDecimal b = null; try { b = new BigDecimal(s); } catch (Exception e) { return s; } int len = Integer.valueOf(s.split("E")[1]); if (len < 0) { // 小數狀況(如:5.0000000000000001E-4)保留10位,去掉末尾的0 return b.setScale(10, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toString(); } else { // 其餘狀況:5.236E8 String num = s.split("E")[0]; if (len > 20) { // len 大於20位的話,數字過大,直接返回字符串 return s; } num = num + "00000000000000000000"; // 小數點向後移動 len 位,不夠添0 return num.replace(".", "").substring(0, num.split("\\.")[0].length() + len); } } /** * 解析Excel,獲取List<Bean> * @param c Bean對象類型 * @param file 上傳文件Excel * @return 數據合法的List<Bean>(前提是Bean屬性作了字段驗證) * @throws Exception 模版不正確異常 */ @SuppressWarnings("unchecked") public static <T> Message getBeanList(Class<T> c, MultipartFile file) { try { // 解析上傳文件爲JsonArray JSONArray arr = null; Message msg = readExcel(file); if (msg.hasErrorMessage()) { return msg; } arr = (JSONArray) msg.getReturnData(); // 解析List<Bean> List<T> list = new ArrayList<T>(); for (int i = 0; i < arr.size(); i++) { JSONObject obj = (JSONObject) arr.get(i); Message msg1 = getBean(c, obj); if (msg1.hasErrorMessage()) { return msg1; } else { list.add((T) msg1.getReturnData()); } } Message msg2 = Message.createMessage(); msg2.setReturnData(list); return msg2; } catch (Exception e) { LOGGER.error(e.getMessage(), e); return Message.createMessage(e.getMessage(), Collections.emptyList()); } } /** * 獲取單個Bean * @param c * @param obj * @return * @throws Exception */ private static <T> Message getBean(Class<T> c, JSONObject obj) throws Exception{ T t = c.newInstance(); List<Field> fields = ASMUtils.getDeclaredFieldsRecursionSupper(c); for (int i = 0; i < fields.size(); i++) { Field field = fields.get(i); String fieldName = field.getName(); // 獲取ExcleDesc註解屬性 ExcelDesc excelDesc = field.getAnnotation(ExcelDesc.class); if (excelDesc != null) { String cname = excelDesc.cname(); if (cname == null || cname.trim().length() == 0) { throw new NullPointerException(String.format("the field '%s' without cname value.", fieldName)); } // 判斷是否必須爲必須字段,判斷cname String val = null; if (obj.has(cname)) { val = obj.getString(cname); } else { if (excelDesc.isRequired()) { return Message.createMessage(Msg.EXCEL_ERROR); } else { continue; } } // 判斷字段是否爲空,判斷iskey if (!PlatformUtils.hasText(val)) { if (excelDesc.isKey()) { return Message.createMessage(Msg.XXX_DATA_CAN_NOT_BE_NULL, cname); } // 非必須字段爲空狀況不繼續解析 continue; } // 獲取具體值 field.setAccessible(true); // 獲取IsDictionary註解屬性 IsDictionary dict = field.getAnnotation(IsDictionary.class); if (dict != null) { int intVal = ConfigManager.getInstance().getAttrByName(dict.clazz(), dict.filed(), val); field.set(t,intVal); continue; } // 其他狀況根據類型賦值 String fieldClassName = field.getType().getSimpleName(); try { if ("String".equalsIgnoreCase(fieldClassName)) { field.set(t, val); } else if ("boolean".equalsIgnoreCase(fieldClassName)) { field.set(t, obj.getBoolean(cname)); } else if ("int".equalsIgnoreCase(fieldClassName) || "Integer".equals(fieldClassName)) { field.set(t, obj.getInt(cname)); } else if ("double".equalsIgnoreCase(fieldClassName)) { field.set(t, obj.getDouble(cname)); } else if ("long".equalsIgnoreCase(fieldClassName)) { field.set(t, obj.getLong(cname)); } else if ("BigDecimal".equalsIgnoreCase(fieldClassName)) { field.set(t, new BigDecimal(val)); } } catch (Exception e) { LOGGER.error(e.getMessage(), e); return Message.createMessage(Msg.XXX_DATA_ERROR, cname); } } } Message message = Message.createMessage(); message.setReturnData(t); return message; } /** * Excel導出 * @param title 導出Excel文件名稱 * @param rowList 第一個List爲表頭,其他行爲表數據 * @param resp HttpServletResponse 對象。不要用注入的resp,用controler方法中聲明的resp。不然會去尋找jsp * @throws IOException */ public static void writeExcel(String title,List<List<Object>> rowList,HttpServletResponse resp) throws IOException{ if (resp == null) { throw new NullPointerException("the HttpServletResponse is null"); } SXSSFWorkbook book = warpSingleWorkbook(title, rowList); // 響應客戶端 String filename = new String(title.getBytes("UTF-8"), "ISO-8859-1"); resp.reset(); resp.setHeader("Content-disposition", "attachment; filename=" + filename +XLS); resp.setContentType("application/vnd.ms-excel;charset=UTF-8"); // 輸出Excel文件 ServletOutputStream outputStream = resp.getOutputStream(); book.write(outputStream); book.close(); outputStream.close(); } /** * Excel導出設置Workbook * @param title 導出Excel文件名稱 * @param rowList 第一個List爲表頭,其他行爲表數據 * @throws IOException */ public static SXSSFWorkbook warpSingleWorkbook(String title,List<List<Object>> rowList) throws IOException { String filename = title; if (!PlatformUtils.hasText(title)) { filename = new SimpleDateFormat("yyMMddHHmmss").format(new Date()); } if (rowList == null || rowList.isEmpty()) { throw new NullPointerException("the row list is null"); } SXSSFWorkbook book = new SXSSFWorkbook(); // 建立表 setWorkBookData(book, filename, rowList); return book; } private static void setWorkBookData(SXSSFWorkbook book, String sheetName, List<List<Object>> rowList){ Sheet sheet = book.createSheet(sheetName); Drawing patriarch = sheet.createDrawingPatriarch(); // 設置表頭樣式 CellStyle style = book.createCellStyle(); // 設置居左 style.setAlignment(HSSFCellStyle.ALIGN_LEFT); // 檢測表頭數據(表頭不容許數據爲空) List<Object> head = rowList.get(0); for (Object key : head) { if (!PlatformUtils.hasText(key.toString())) { throw new NullPointerException("there is a blank exist head row"); } } // 寫數據 int size = rowList.get(0).size(); for (int i = 0; i < rowList.size(); i++) { List<Object> row = rowList.get(i); if (row == null || row.isEmpty()) { throw new NullPointerException("the "+(i+1)+"th row is null"); } if (size != row.size()) { throw new IllegalArgumentException("the cell number of "+(i+1)+"th row is different form the first"); } Row sr = sheet.createRow(i); for (int j = 0; j < row.size(); j++) { if (row.get(j) != null && row.get(j) instanceof URL) { URL url = (URL)row.get(j); sr.setHeight((short)(IMG_HEIGTH * IMG_WIDTH)); drawPictureIntoExcel(book, patriarch, i, j, url); } else { setExcelValue(sr.createCell(j), row.get(j), style); } } } } /** * 導出多頁Excel * @param sheetMap key爲每一個頁的名稱,value爲表頭行+數據行 * @return * @throws IOException */ public static SXSSFWorkbook warpSingleWorkbook(Map<String, List<List<Object>>> sheetMap) throws IOException { SXSSFWorkbook book = new SXSSFWorkbook(); for (String key : sheetMap.keySet()) { String sheetName = Pattern.compile("[[/*#]]").matcher(key).replaceAll(""); setWorkBookData(book, sheetName, sheetMap.get(key)); } return book; } /** * Excel導出設置Workbook(表頭自動換行) * @param title 導出Excel文件名稱 * @param rowList 第一個List爲表頭,其他行爲表數據 * @throws IOException */ public static SXSSFWorkbook getSingleWorkbook(String title,List<List<Object>> rowList) throws IOException { String filename = title; if (!PlatformUtils.hasText(title)) { filename = new SimpleDateFormat("yyMMddHHmmss").format(new Date()); } if (rowList == null || rowList.isEmpty()) { throw new NullPointerException("the row list is null"); } SXSSFWorkbook book = new SXSSFWorkbook(); // 建立表 Sheet sheet = book.createSheet(filename); Font headFont = book.createFont(); Drawing patriarch = sheet.createDrawingPatriarch(); // 設置表頭樣式 XSSFCellStyle style = (XSSFCellStyle)book.createCellStyle(); CellStyle headStyle = book.createCellStyle(); // 設置居左 style.setAlignment(HSSFCellStyle.ALIGN_LEFT); headStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); headStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 水平居中 headStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//設置垂直居中 headStyle.setWrapText(true);// 自動換行 headFont.setBoldweight(Font.BOLDWEIGHT_BOLD);// 加粗 headStyle.setFont(headFont); // 檢測表頭數據(表頭不容許數據爲空) List<Object> head = rowList.get(0); Row headRow = sheet.createRow(0); for (int i = 0; i < head.size(); i++) { if (!PlatformUtils.hasText(head.get(i).toString())) { book.close(); throw new NullPointerException("there is a blank exist head row"); } setExcelValue(headRow.createCell(i), head.get(i), headStyle); } // 寫數據 style.setWrapText(true); createBodyData(rowList, book, sheet, style, patriarch, false); return book; } /** * Excel寫網絡圖片 * @param wb * @param patriarch * @param rowIndex * @param url */ private static void drawPictureIntoExcel(SXSSFWorkbook wb,Drawing patriarch,int rowIndex, int cloumIndex, URL url){ // rowIndex表明當前行 try(InputStream is = url.openStream(); ByteArrayOutputStream swapStream = new ByteArrayOutputStream();) { byte[] buff = new byte[100]; int rc = 0; while ((rc = is.read(buff, 0, 100)) > 0) { swapStream.write(buff, 0, rc); } // 設置圖片位置 XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, cloumIndex, rowIndex, cloumIndex+1, rowIndex+1); anchor.setAnchorType(0); patriarch.createPicture(anchor, wb.addPicture(swapStream.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG)); swapStream.close(); } catch (Exception e) { LOGGER.error("圖片請求失敗:" + url.toString()); } } /** * Excel導出 * @param title 導出Excel文件名稱 * @param sheets 包含多個模塊的sheets也就是多個rowList,rowList 第一個List爲表頭,其他行爲表數據 * object 是一個list<Object> * @param resp HttpServletResponse 對象 * @throws IOException */ public static void writeExcels(String title, List<List<Object>> sheets, HttpServletResponse resp) throws IOException { if (resp == null) { throw new NullPointerException("the HttpServletResponse is null"); } String filename = title; if (!PlatformUtils.hasText(filename)) { filename = new SimpleDateFormat("yyMMddHHmmss").format(new Date()); } if (sheets == null || sheets.isEmpty()) { throw new NullPointerException("the row list is null"); } // 建立表 HSSFWorkbook book = wrapMultWorkbook(filename, sheets); // 響應客戶端 filename = new String(filename.getBytes("UTF-8"), "ISO-8859-1"); resp.reset(); resp.setHeader("Content-disposition", "attachment; filename=" + filename +XLS); resp.setContentType("application/vnd.ms-excel;charset=UTF-8"); // 輸出Excel文件 book.write(resp.getOutputStream()); book.close(); } /** * Excel導出到項目目錄下 * @param title 導出Excel文件名稱 * @param sheets 包含多個模塊的sheets也就是多個rowList,rowList 第一個List爲表頭,其他行爲表數據 * object 是一個list<Object> * @param filePath * @param resp HttpServletResponse 對象 * @throws IOException */ public static String writeExcelInWeb(String title, List<List<Object>> sheets, String filePath) throws IOException { String filename = title; if (!PlatformUtils.hasText(filename)) { filename = new SimpleDateFormat("yyMMddHHmmss").format(new Date()); } if (sheets == null || sheets.isEmpty()) { throw new NullPointerException("the row list is null"); } // 建立表 String fileName = filename +".xls"; HSSFWorkbook book = wrapMultWorkbook(filename, sheets); FileOutputStream stream = new FileOutputStream(filePath +"/" + fileName); book.write(stream); book.close(); return fileName; } /** * 將數據寫入多個Excel sheet中 * @param title 標題 * @param sheets sheet * @param book Excel對象 * @throws IOException */ public static HSSFWorkbook wrapMultWorkbook(String title, List<List<Object>> sheets) throws IOException { HSSFWorkbook book = new HSSFWorkbook(); for (int p = 0; p < sheets.size(); p++) { HSSFSheet sheet = book.createSheet(title+"_"+p); sheet.setDefaultRowHeightInPoints(CommonPlatformConstant.INT_15); // 檢測表頭數據(表頭不容許數據爲空) @SuppressWarnings("unchecked") List<String> head = (List<String>) sheets.get(p).get(0); for (Object key : head) { if (!PlatformUtils.hasText(key.toString())) { book.close(); throw new NullPointerException("there is a blank exist head row"); } } // 寫數據 @SuppressWarnings("unchecked") List<Object> data = (List<Object>) sheets.get(p).get(0); int size = data.size(); for (int i = 0; i < sheets.get(p).size(); i++) { @SuppressWarnings("unchecked") List<Object> row = (List<Object>) sheets.get(p).get(i); if (row == null || row.isEmpty()) { book.close(); throw new NullPointerException("the "+(i+1)+"th row is null"); } if (size != row.size()) { book.close(); throw new IllegalArgumentException("the cell number of "+(i+1)+"th row is different form the first"); } HSSFRow sr = sheet.createRow(i); for (int j = 0; j < row.size(); j++) { if (row.get(j) == null) { sr.createCell(j).setCellValue(""); } else { Object value = row.get(j); if (value instanceof Integer) { HSSFCell cell = sr.createCell(j); cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellValue(Double.valueOf(value.toString())); } else if (value instanceof BigDecimal) { HSSFCell cell = sr.createCell(j); cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellValue(((BigDecimal)value).setScale(CommonPlatformConstant.INT_3, RoundingMode.HALF_UP).doubleValue()); } else { sr.createCell(j).setCellValue(value.toString()); } } } } for (int i = 0; i < head.size(); i++) { sheet.autoSizeColumn(i); } } return book; } /** * 設置Excel浮點數可作金額等數據統計 * @param cell 單元格類 * @param value 傳入的值 */ public static void setExcelValue(Cell cell, Object value, CellStyle style){ cell.setCellStyle(style); // 寫數據 if (value == null) { cell.setCellValue(""); }else { if (value instanceof Integer || value instanceof Long) { cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellValue(Long.valueOf(value.toString())); } else if (value instanceof BigDecimal) { cell.setCellType(Cell.CELL_TYPE_NUMERIC); cell.setCellValue(((BigDecimal)value).setScale(CommonPlatformConstant.INT_3, RoundingMode.HALF_UP).doubleValue()); } else { cell.setCellValue(value.toString()); } } } /** * 設置Excel表體數據 * @param rowList 表數據 : index 爲0 爲表頭 * @param hasHead 是否包含表頭 */ public static void createBodyData(List<List<Object>> rowList, SXSSFWorkbook book, Sheet sheet, XSSFCellStyle style, Drawing patriarch, Boolean hasHead) throws IOException{ int size = rowList.get(0).size(); int startNum = 1; if(hasHead) { startNum = 0; } for (int i = startNum; i < rowList.size(); i++) { List<Object> row = rowList.get(i); if (row == null || row.isEmpty()) { book.close(); throw new NullPointerException("the "+(i+1)+"th row is null"); } if (size != row.size()) { book.close(); throw new IllegalArgumentException("the cell number of "+(i+1)+"th row is different form the first"); } Row sr = sheet.createRow(i); for (int j = 0; j < row.size(); j++) { if (patriarch != null && row.get(j) != null && row.get(j) instanceof URL) { URL url = (URL)row.get(j); sr.setHeight((short)(IMG_HEIGTH * IMG_WIDTH)); drawPictureIntoExcel(book, patriarch, i, j, url); } else { setExcelValue(sr.createCell(j), row.get(j), style); } } } } /** * Excel單行設置值通常用於合併單元格 * @param row 行對象 */ public static void writeSingleRowExcel(Row row, List<Object> rowList, CellStyle style){ if (row == null) { throw new NullPointerException("the HSSFRow is null"); } if (PlatformUtils.isEmpty(rowList)) { return; } // 設置行數據 for (int i = 0; i < rowList.size(); i++) { setExcelValue(row.createCell(i), rowList.get(i), style); } } /** * 將Excel轉化爲輸入流 * @param book Excel對象 * @return 輸入流 * @throws IOException */ public static InputStream sxssfWorkbookToInputStream(SXSSFWorkbook book) throws IOException { ByteArrayInputStream bais = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); book.write(baos); bais = new ByteArrayInputStream(baos.toByteArray()); baos.close(); book.close(); return bais; } /** * 上傳臨時文件 * @param url * @param fileName 文件名 * @param is 文件輸入流 * @return 文件返回路徑 * @throws Exception */ public static String uploadTempFile(String url, String fileName, InputStream is) throws Exception { HttpSocket socket = new HttpSocket(); socket.setUrl(url); // 爲了能使用到華爲存儲的自動刪除功能, 將臨時文件所有放到comId=1的目錄下 socket.addParameter(ConstBusiness.COM_ID, "1"); socket.addParameter("savePath", ConfigManager.getInstance().getValue(PlatformConstant.class, PlatformConstant.PICTURE_SERVER_PATH)); socket.addAttachment(fileName, fileName, "text/plain", is); socket.doPostMultipart(); is.close(); JSONObject result = JSONObject.fromObject(socket.getResponseData()); if (result.getInt("code") > 0) { throw new RuntimeException(result.getString("msg")); } return result.getString("msg"); } /** * Excel導出設置Workbook(包含下載圖片) * @param title 導出Excel文件名稱 * @param rowList 第一個List爲表頭,其他行爲表數據 * @param downLoadPic 是否下載圖片 (若是要下載圖片,圖片的信息放Excel維度的第一列) * @throws IOException */ public static HSSFWorkbook wrapSingleWorkbook(String title,List<List<Object>> rowList, Boolean downLoadPic) throws IOException { String filename = title; if (!PlatformUtils.hasText(title)) { filename = new SimpleDateFormat("yyMMddHHmmss").format(new Date()); } if (rowList == null || rowList.isEmpty()) { throw new NullPointerException("the row list is null"); } HSSFWorkbook book = new HSSFWorkbook(); // 建立表 HSSFSheet sheet = book.createSheet(filename); // 設置單元格默認寬度爲15個字符 sheet.setDefaultColumnWidth(15); HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); // 設置表頭樣式 HSSFCellStyle style = book.createCellStyle(); // 設置居左 style.setAlignment(HSSFCellStyle.ALIGN_LEFT); // 這種自動換行 style.setWrapText(true); // 檢測表頭數據(表頭不容許數據爲空) List<Object> head = rowList.get(0); for (Object key : head) { if (!PlatformUtils.hasText(key.toString())) { book.close(); throw new NullPointerException("there is a blank exist head row"); } } // 寫數據 int size = rowList.get(0).size(); for (int i = 0; i < rowList.size(); i++) { List<Object> row = rowList.get(i); if (row == null || row.isEmpty()) { book.close(); throw new NullPointerException("the "+(i+1)+"th row is null"); } if (size != row.size()) { book.close(); throw new IllegalArgumentException("the cell number of "+(i+1)+"th row is different form the first"); } HSSFRow sr = sheet.createRow(i); for (int j = 0; j < row.size(); j++) { // 在每行的第一個單元格插入圖片 if (downLoadPic && i > 0 && j == 0) { sr.setHeight((short) (800)); drawPictureIntoExcel(book, patriarch, i, row.get(0).toString()); } else { HSSFCell cell = sr.createCell(j); setExcelValue(cell, row.get(j), style); } } } return book; } /**將圖片寫入excel * @param wb * @param patriarch * @param rowIndex 當前行數 * @param pictureUrl 圖片連接 * */ private static void drawPictureIntoExcel(HSSFWorkbook wb, HSSFPatriarch patriarch, int rowIndex, String pictureUrl) { try { if (PlatformUtils.hasText(pictureUrl)) { URL url = new URL(pictureUrl); // 打開連接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 設置請求方式爲"GET" conn.setRequestMethod("GET"); // 超時響應時間爲5秒 conn.setConnectTimeout(5 * 1000); // 經過輸入流獲取圖片數據 InputStream inStream = conn.getInputStream(); // 獲得圖片的二進制數據,以二進制封裝獲得數據 byte[] data = readInputStream(inStream); // anchor主要用於設置圖片的位置 HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) 0, rowIndex, (short) 1, rowIndex+1); // Sets the anchor type (圖片在單元格的位置) // 0 = Move and size with Cells, 2 = Move but don't size with // cells, 3 = Don't move or size with cells. anchor.setAnchorType(3); patriarch.createPicture(anchor, wb.addPicture(data, HSSFWorkbook.PICTURE_TYPE_JPEG)); } } catch (IOException e) { LOGGER.error(e.getMessage(), e); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } } private static byte[] readInputStream(InputStream inStream) throws Exception { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); // 建立一個Buffer字符串 byte[] buffer = new byte[1024]; // 每次讀取的字符串長度,若是爲-1,表明所有讀取完畢 int len = 0; // 使用一個輸入流從buffer裏把數據讀取出來 while ((len = inStream.read(buffer)) != -1) { // 用輸出流往buffer裏寫入數據,中間參數表明從哪一個位置開始讀,len表明讀取的長度 outStream.write(buffer, 0, len); } // 關閉輸入流 inStream.close(); // 把outStream裏的數據寫入內存 return outStream.toByteArray(); } }