POI導入導出及動態複雜表頭生成

 在此以前打開POI分類已存在三篇文章介紹了POI的使用及流下載,近期項目發現以前的使用中是有缺陷的,今天作一下總結,從如今起咱們能夠忽略前三篇文章對POI的使用,可是流下載方式仍是能夠參考的,這裏仍是再提一筆,流下載使用ajax會出異常,不生效,我是用的是提交form表單的方式來進行流下載,很遺憾,暫時取不到返回值前端

       下面咱們繼續談一下POI的使用java

       首先須要強調幾點,POI對於Excel2003和Excel2007+是區別對待的,分別使用了HSSFWorkbook和XSSFWorkbook,但它們實現了同一個接口Workbook,這對咱們的編程實現提供了必定的靈活性node

   建議:對於導出,咱們直接使用XSSFWorkbook便可,HSSFWorkbook是存在必定缺陷,以前使用過HSSFWorkbook,數據量達到65536就會報錯導出失敗,近期作新的項目才發現緣由web

   相對於導入工做,須要動態對文件識別Excel2003或是Excel2007+,有些文章寫到經過後綴名來辨別,這存在一個問題,用戶修改後綴以後,結果可想而知,幸好POI提供了一個便利的方法Workbook create(InputStream inp),經過輸入流動態建立,GOOD!!!下面,我也會提供相關的用法。在這裏還要給一個提示,使用3.9版本這種方法報錯,在此,我來提供一個maven infoajax

 

<dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>3.15</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.15</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml-schemas</artifactId>
                <version>3.15</version>
            </dependency>

沒錯,這三個包都是須要的,正是爲了實現這個功能,我對此封裝了一個POI的工具包sql

 1 import org.apache.poi.hssf.usermodel.*;  2 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;  3 import org.apache.poi.ss.usermodel.*;  4 import org.apache.poi.ss.util.CellRangeAddress;  5 import org.apache.poi.ss.util.NumberToTextConverter;  6 import org.apache.poi.xssf.usermodel.XSSFWorkbook;  7 
 8 import java.io.FileOutputStream;  9 import java.io.IOException;  10 import java.io.InputStream;  11 import java.text.DateFormat;  12 import java.text.SimpleDateFormat;  13 import java.util.*;  14 
 15 public class PoiUtil {  16     private PoiUtil() {  17  }  18 
 19     /**  20  * Excel2003和Excel2007+建立方式不一樣  21  * Excel2003使用HSSFWorkbook 後綴xls  22  * Excel2007+使用XSSFWorkbook 後綴xlsx  23  * 此方法可保證動態建立Workbook  24  *  25  * @param is  26  * @return  27      */
 28     public static Workbook createWorkbook(InputStream is) throws IOException, InvalidFormatException {  29         return WorkbookFactory.create(is);  30  }  31 
 32     /**  33  *導入數據獲取數據列表  34  * @param wb  35  * @return  36      */
 37     public static List<List<Object>> getDataList(Workbook wb) {  38         List<List<Object>> rowList = new ArrayList<>();  39         for (int sheetNum = 0; sheetNum < wb.getNumberOfSheets(); sheetNum++) {  40             Sheet sheet = wb.getSheetAt(sheetNum);  41             for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {  42                 Row row = sheet.getRow(i);  43                 if (null == row)  44                     continue;  45                 List<Object> cellList = new ArrayList<>();  46                 for (int j = row.getFirstCellNum(); j < row.getLastCellNum(); j++) {  47                     Cell cell = row.getCell(j);  48  cellList.add(getCellValue(cell));  49  }  50  rowList.add(cellList);  51  }  52  }  53         return rowList;  54  }  55 
 56     private static String getCellValue(Cell cell) {  57         String cellvalue = "";  58         if (cell != null) {  59             // 判斷當前Cell的Type
 60             switch (cell.getCellType()) {  61                 // 若是當前Cell的Type爲NUMERIC
 62                 case HSSFCell.CELL_TYPE_NUMERIC: {  63                     short format = cell.getCellStyle().getDataFormat();  64                     if (format == 14 || format == 31 || format == 57 || format == 58) {   //excel中的時間格式
 65                         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");  66                         double value = cell.getNumericCellValue();  67                         Date date = DateUtil.getJavaDate(value);  68                         cellvalue = sdf.format(date);  69  }  70                     // 判斷當前的cell是否爲Date
 71                     else if (HSSFDateUtil.isCellDateFormatted(cell)) {  //先註釋日期類型的轉換,在實際測試中發現HSSFDateUtil.isCellDateFormatted(cell)只識別2014/02/02這種格式。  72                         // 若是是Date類型則,取得該Cell的Date值 // 對2014-02-02格式識別不出是日期格式
 73                         Date date = cell.getDateCellValue();  74                         DateFormat formater = new SimpleDateFormat("yyyy-MM-dd");  75                         cellvalue = formater.format(date);  76                     } else { // 若是是純數字  77                         // 取得當前Cell的數值
 78                         cellvalue = NumberToTextConverter.toText(cell.getNumericCellValue());  79 
 80  }  81                     break;  82  }  83                 // 若是當前Cell的Type爲STRIN
 84                 case HSSFCell.CELL_TYPE_STRING:  85                     // 取得當前的Cell字符串
 86                     cellvalue = cell.getStringCellValue().replaceAll("'", "''");  87                     break;  88                 case HSSFCell.CELL_TYPE_BLANK:  89                     cellvalue = null;  90                     break;  91                 // 默認的Cell值
 92                 default: {  93                     cellvalue = " ";  94  }  95  }  96         } else {  97             cellvalue = "";  98  }  99         return cellvalue; 100  } 101 
102     /** 103  * 此方法生成表頭並寫入表頭名稱 104  * 105  * @param nodes 節點 106  * @param sheet 工做簿 107  * @param style 單元格樣式 108  * @return 數據加載開始行 109      */
110     public static int generateHeader(List<HeaderNode> nodes, Sheet sheet, CellStyle style) { 111         Map<RowKey, Row> hssfRowMap = new HashMap<>(); 112         int dataStartRow = 0; 113         for (HeaderNode node : nodes) { 114             if (!(node.firstRow == node.getLastCol() || node.getFirstCol() == node.getLastCol())) { 115                 CellRangeAddress cra = new CellRangeAddress(node.getFirstRow(), node.getLastRow(), 116  node.getFirstCol(), node.getLastCol()); 117  sheet.addMergedRegion(cra); 118  } 119             dataStartRow = dataStartRow >= node.getLastRow() ? dataStartRow : node.getLastRow(); 120             RowKey key = new RowKey(); 121  key.setFirstRow(node.getFirstRow()); 122  key.setLastRow(node.getLastRow()); 123             Row row = hssfRowMap.get(key); 124             if (null == row) { 125                 row = sheet.createRow(node.getFirstRow()); 126  hssfRowMap.put(key, row); 127  } 128             Cell cell = row.createCell(node.getFirstCol()); 129  cell.setCellValue(node.getName()); 130  cell.setCellStyle(style); 131  } 132         return dataStartRow+1; 133  } 134 
135     public static class HeaderNode { 136         private String name; 137         private int firstRow; 138         private int lastRow; 139         private int firstCol; 140         private int lastCol; 141 
142         public String getName() { 143             return name; 144  } 145 
146         public void setName(String name) { 147             this.name = name; 148  } 149 
150         public int getFirstRow() { 151             return firstRow; 152  } 153 
154         public void setFirstRow(int firstRow) { 155             this.firstRow = firstRow; 156  } 157 
158         public int getLastRow() { 159             return lastRow; 160  } 161 
162         public void setLastRow(int lastRow) { 163             this.lastRow = lastRow; 164  } 165 
166         public int getFirstCol() { 167             return firstCol; 168  } 169 
170         public void setFirstCol(int firstCol) { 171             this.firstCol = firstCol; 172  } 173 
174         public int getLastCol() { 175             return lastCol; 176  } 177 
178         public void setLastCol(int lastCol) { 179             this.lastCol = lastCol; 180  } 181  } 182 
183     private static class RowKey { 184         private int firstRow; 185         private int lastRow; 186 
187         public int getFirstRow() { 188             return firstRow; 189  } 190 
191         public void setFirstRow(int firstRow) { 192             this.firstRow = firstRow; 193  } 194 
195         public int getLastRow() { 196             return lastRow; 197  } 198 
199         public void setLastRow(int lastRow) { 200             this.lastRow = lastRow; 201  } 202 
203  @Override 204         public boolean equals(Object o) { 205             if (this == o) return true; 206             if (!(o instanceof RowKey)) return false; 207             RowKey key = (RowKey) o; 208             return firstRow == key.firstRow &&
209                     lastRow == key.lastRow; 210  } 211 
212  @Override 213         public int hashCode() { 214             return Objects.hash(firstRow, lastRow); 215  } 216  } 217 
218     public static void main(String[] args) { 219         // 第一步,建立一個webbook,對應一個Excel文件
220         Workbook workbook = new XSSFWorkbook(); 221         // 第二步,在webbook中添加一個sheet,對應Excel文件中的sheet
222         Sheet sheet = workbook.createSheet("測試"); 223         // 第四步,建立單元格,並設置值表頭 設置表頭居中
224         CellStyle style = workbook.createCellStyle(); 225         style.setAlignment(HorizontalAlignment.CENTER); // 水平居中格式
226         style.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中
227         List<HeaderNode> nodes = new ArrayList<>(); 228         HeaderNode headerNode1 = new HeaderNode(); 229         headerNode1.setName("test1"); 230         headerNode1.setFirstRow(0); 231         headerNode1.setLastRow(1); 232         headerNode1.setFirstCol(0); 233         headerNode1.setLastCol(5); 234  nodes.add(headerNode1); 235         HeaderNode headerNode34 = new HeaderNode(); 236         headerNode34.setName("test4"); 237         headerNode34.setFirstRow(3); 238         headerNode34.setLastRow(4); 239         headerNode34.setFirstCol(0); 240         headerNode34.setLastCol(5); 241  nodes.add(headerNode34); 242         HeaderNode headerNode2 = new HeaderNode(); 243         headerNode2.setName("test2"); 244         headerNode2.setFirstRow(2); 245         headerNode2.setLastRow(2); 246         headerNode2.setFirstCol(0); 247         headerNode2.setLastCol(4); 248  nodes.add(headerNode2); 249         HeaderNode headerNode3 = new HeaderNode(); 250         headerNode3.setName("test3"); 251         headerNode3.setFirstRow(2); 252         headerNode3.setLastRow(2); 253         headerNode3.setFirstCol(5); 254         headerNode3.setLastCol(5); 255  nodes.add(headerNode3); 256  generateHeader(nodes, sheet, style); 257         try { 258             FileOutputStream output = new FileOutputStream("e:\\workbook.xls"); 259  workbook.write(output); 260  output.flush(); 261         } catch (IOException e) { 262  e.printStackTrace(); 263  } 264  } 265 }

下面是導出報表及流下載的代碼apache

 1        List<PoiUtil.HeaderNode> nodes = new ArrayList<>();  2         for (RpStyleItem item : styleItems){  3             PoiUtil.HeaderNode headerNode = new PoiUtil.HeaderNode();  4             headerNode.setFirstRow(item.getRow() - 1);  5             headerNode.setLastRow(headerNode.getFirstRow()+item.getSizeY() - 1);  6             headerNode.setFirstCol(item.getCol() - 1);  7             headerNode.setLastCol(headerNode.getFirstCol() + item.getSizeX() - 1);  8  headerNode.setName(item.getName());  9  nodes.add(headerNode); 10  } 11         // 第一步,建立一個webbook,對應一個Excel文件 12         // XSSFWorkbook針對於excel2007+ 13         // HSSFWorkbook針對於Excel2003(數據超過65536會報錯)
14         Workbook workbook = new XSSFWorkbook(); 15         // 第二步,在webbook中添加一個sheet,對應Excel文件中的sheet
16         Sheet sheet = workbook.createSheet(template.getName()); 17         // 第三步,建立單元格樣式
18         CellStyle style = workbook.createCellStyle(); 19         style.setAlignment(HorizontalAlignment.CENTER); // 水平居中格式
20         style.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中
21         int rowNum = PoiUtil.generateHeader(nodes,sheet,style); 22         String sql = template.getReportSql().replace("\n", " "); 23         String reportDate = com.jrq.components.date.DateUtil.dateFormat(new Date(), "yyyyMMdd"); 24         //測試數據 String reportDate = "20170711";
25         List<Map<String, Object>> datas = reportService.listReportData(reportDate, sql); 26         for (Map<String, Object> map : datas){ 27             Collection<Object> values = map.values(); 28             int index = 0; //cell單元格索引
29             Row row = sheet.createRow(rowNum++); 30             for (Object obj : values){ 31                 row.createCell(index++).setCellValue(obj.toString()); 32  } 33  } 34       /* 直接將將文件保存在本地,供測試樣式使用 35  try { 36  OutputStream output=new FileOutputStream("e:\\workbook.xls"); 37  workbook.write(output); 38  output.flush(); 39  output.close(); 40  } catch (IOException e) { 41  e.printStackTrace(); 42  }*/
43         String downFileName = new String(template.getType().getName()+reportDate+".xls"); 44         try { 45             //若不進行編碼在IE下會亂碼
46             downFileName = URLEncoder.encode(downFileName, "UTF-8"); 47         } catch (UnsupportedEncodingException e) { 48  e.printStackTrace(); 49  } 50         try { 51             // 清空response
52  response.reset(); 53             response.setContentType("application/msexcel");//設置生成的文件類型
54             response.setCharacterEncoding("UTF-8");//設置文件頭編碼方式和文件名
55             response.setHeader("Content-Disposition", "attachment; filename=" + downFileName); 56             OutputStream os=response.getOutputStream(); 57  workbook.write(os); 58  os.flush(); 59  os.close(); 60         } catch (IOException e) { 61             LOG.error("文件流操做異常"); 62             jr.setRet("文件流操做異常"); 63             return jr; 64  } 65  jr.setSuc(JsonResponse.SUCCESS); 66         return jr;

下面是導入功能的代碼編程

1         MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; 2         MultipartFile file = multipartRequest.getFile("fileUpload"); 3         if (!file.isEmpty()) { 4             Workbook workbook = PoiUtil.createWorkbook(file.getInputStream()); 5             if (null != workbook) { 6                 List<List<Object>> list = PoiUtil.getDataList(workbook);}}

能夠看到這裏是前端上傳了excel文件這裏,前端的HTML也貼一下app

<form method="POST" enctype="multipart/form-data" id="form1" action="/center/addition/list/uploadfile">
                                <input class="typeahead scrollable" type="file" id="fileUpload" name="fileUpload"/>
                                <input type="submit" value="上傳" id="btn_submit"/>
                            </form>

https://blog.csdn.net/ab7253957/article/details/76076600xss

相關文章
相關標籤/搜索