對於javaweb開發者來說,對於Excel的操作是必須要了解的知識點,自己原先也做過一些excel的操作,但是沒有系統的整理過,所以每回使用的時候都是在重新查找信息,所以做了如下整理:
其實在javaweb開發中經常用到的Excel操作便是導出、解析。下面就從這兩個方面來總結。
首先便是導出,在這個方面其實我主要用到的是兩種方式:一種是依賴於freemarker,另一種則是POI
一、依賴於freemarker的Excel導出:
首先如果要使用freemarker的導出方式,在框架中必須使用了freemarker這個模板引擎,對於現在主流的mvc框架來說:spring mvc是可以集成freemarker的,spring boot則更近一步,spring mvc推薦使用jsp,而spring boot 推薦使用freemarker。至於Struts2本人沒有涉及過不是很清楚,需要自己去探索啊!!不過應該也是沒有問題的。然后就是Struts這個東西,我想現在應該沒有公司在用Struts了吧!!!
好!!閑話不多直接上操作步驟,我這里的代碼是使用的spring boot+freemarker的方式,至於dao層本文檔不會涉及其內容:
(一)、首先要做的便是將要導出的Excel的模板准備好,接編寫一個Excel表格,如圖:
(二)、將Excel另存為xml格式:
然后用文本編輯器打開Excel文件看到內容為:
<?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"> <Created>2006-09-16T00:00:00Z</Created> <LastSaved>2018-10-22T03:45:04Z</LastSaved> <Version>15.00</Version> </DocumentProperties> <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"> <AllowPNG/> <RemovePersonalInformation/> </OfficeDocumentSettings> <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"> <WindowHeight>8010</WindowHeight> <WindowWidth>14805</WindowWidth> <WindowTopX>240</WindowTopX> <WindowTopY>105</WindowTopY> <ProtectStructure>False</ProtectStructure> <ProtectWindows>False</ProtectWindows> </ExcelWorkbook> <Styles> <Style ss:ID="Default" ss:Name="Normal"> <Alignment ss:Vertical="Bottom"/> <Borders/> <Font ss:FontName="宋體" ss:Size="11" ss:Color="#000000"/> <Interior/> <NumberFormat/> <Protection/> </Style> <Style ss:ID="s16"> <Alignment ss:Horizontal="Center" ss:Vertical="Center"/> </Style> <Style ss:ID="s17"> <Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/> </Style> <Style ss:ID="s18"> <Alignment ss:Vertical="Center" ss:WrapText="1"/> </Style> <Style ss:ID="s19"> <Alignment ss:Horizontal="Center" ss:Vertical="Center"/> <NumberFormat ss:Format="yyyy/m/d\ hh:mm:ss"/> </Style> </Styles> <Worksheet ss:Name="存儲池"> <Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="2" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="13.5"> <Column ss:AutoFitWidth="0" ss:Width="123.75" ss:Span="3"/> <Row> <Cell ss:StyleID="s16"><Data ss:Type="String">存儲池名</Data></Cell> <Cell ss:StyleID="s16"><Data ss:Type="String">總容量(TB)</Data></Cell> <Cell ss:StyleID="s16"><Data ss:Type="String">已使用容量(TB)</Data></Cell> <Cell ss:StyleID="s16"><Data ss:Type="String">未使用容量(TB)</Data></Cell> </Row> <Row> <Cell ss:StyleID="s16"><Data ss:Type="String">pool0</Data></Cell> <Cell ss:StyleID="s16"><Data ss:Type="Number">5.68</Data></Cell> <Cell ss:StyleID="s16"><Data ss:Type="Number">1.23</Data></Cell> <Cell ss:StyleID="s17"><Data ss:Type="Number">2.33</Data></Cell> </Row> </Table> <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"> <PageSetup> <Header x:Margin="0.3"/> <Footer x:Margin="0.3"/> <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/> </PageSetup> <Print> <ValidPrinterInfo/> <PaperSizeIndex>9</PaperSizeIndex> <HorizontalResolution>600</HorizontalResolution> <VerticalResolution>600</VerticalResolution> </Print> <Selected/> <Panes> <Pane> <Number>3</Number> <ActiveCol>4</ActiveCol> </Pane> </Panes> <ProtectObjects>False</ProtectObjects> <ProtectScenarios>False</ProtectScenarios> </WorksheetOptions> </Worksheet> <Worksheet ss:Name="報錯日志"> <Table ss:ExpandedColumnCount="3" ss:ExpandedRowCount="2" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="13.5"> <Column ss:AutoFitWidth="0" ss:Width="153"/> <Column ss:AutoFitWidth="0" ss:Width="81.75"/> <Column ss:AutoFitWidth="0" ss:Width="605.25"/> <Row ss:AutoFitHeight="0" ss:Height="20.0625"> <Cell ss:StyleID="s16"><Data ss:Type="String">時間</Data></Cell> <Cell ss:StyleID="s16"><Data ss:Type="String">級別</Data></Cell> <Cell ss:StyleID="s16"><Data ss:Type="String">內容</Data></Cell> </Row> <Row ss:Height="27"> <Cell ss:StyleID="s19"><Data ss:Type="String" x:Ticked="1">2017/12/12 11:11:11</Data></Cell> <Cell ss:StyleID="s16"><Data ss:Type="String">error</Data></Cell> <Cell ss:StyleID="s18"><Data ss:Type="String">fdsafdsafdsafdsafdsafdsafdsafdsafdsafdsafdsafdsafdsafdsafdsafdsafdsafdsafdsasdfdsafsddddddddddddddddddddddddddfsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</Data></Cell> </Row> </Table> <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"> <PageSetup> <Header x:Margin="0.3"/> <Footer x:Margin="0.3"/> <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/> </PageSetup> <Print> <ValidPrinterInfo/> <PaperSizeIndex>9</PaperSizeIndex> <HorizontalResolution>600</HorizontalResolution> <VerticalResolution>600</VerticalResolution> </Print> <Panes> <Pane> <Number>3</Number> <ActiveRow>1</ActiveRow> </Pane> </Panes> <ProtectObjects>False</ProtectObjects> <ProtectScenarios>False</ProtectScenarios> </WorksheetOptions> </Worksheet> </Workbook>
(三)、接下來便是將xml代碼復制到一個新建的freemarker模板文件中便可以了
(四)、下面便是java代碼的編寫了,廢話不多直接上代碼:
1 @RequestMapping("/exportreport") 2 private String exportReport(Model model,HttpServletRequest request,HttpServletResponse response,int did) { 3 4 //獲取要導入的信息 5 List<DPool> poolList=reportService.selectPoolByDid(did); 6 List<DAlarm> alarmList=reportService.selectAlarmByDid(did); 7 Device device = deviceDao.selectByPrimaryKey(did); 8 9 10 //將需要到導入的信息存入model中 11 model.addAttribute("poolList", poolList); 12 model.addAttribute("alarmList", alarmList); 13 14 15 //設置下載頭部,通過response實現 16 response.reset(); 17 response.setContentType("application/vnd.ms-excel;charset=utf-8"); 18 try { 19 response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(device.getName()+"-report.xls", "UTF8")); 20 } catch (UnsupportedEncodingException e) { 21 e.printStackTrace(); 22 } 23 //帶導出數據跳轉到freemarker模板 24 return "generate_reports"; 25 }
(五)、最后便是利用freemarker的知識去編寫,上面新建的模板了,將數據插入到模板中,其中有些地方需要注意一下:
這個地方的數字代表了這張工作表中有多少行
二、第二種方式便是利用POI了,步驟如下:
(一)、利用poi生成Excel表格
1 package cn.tools; 2 3 import java.text.DecimalFormat; 4 import java.util.List; 5 6 import org.apache.poi.hssf.usermodel.HSSFCellStyle; 7 import org.apache.poi.hssf.usermodel.HSSFFont; 8 import org.apache.poi.hssf.usermodel.HSSFRow; 9 import org.apache.poi.hssf.usermodel.HSSFSheet; 10 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 11 import org.apache.poi.ss.usermodel.HorizontalAlignment; 12 import org.apache.poi.ss.usermodel.VerticalAlignment; 13 14 import cn.entitys.DAlarm; 15 import cn.entitys.DPool; 16 17 public class GenerateReport { 18 public static HSSFWorkbook Generate(List<DPool> poolList, List<DAlarm> alarmList){ 19 HSSFWorkbook workbook = new HSSFWorkbook(); 20 HSSFSheet firstsheet = workbook.createSheet("存儲池"); 21 22 HSSFFont font = workbook.createFont(); 23 font.setFontName("宋體"); 24 font.setFontHeightInPoints((short) 11); 25 26 HSSFCellStyle cellStyle1 = workbook.createCellStyle(); 27 cellStyle1.setAlignment(HorizontalAlignment.CENTER); 28 cellStyle1.setVerticalAlignment(VerticalAlignment.CENTER); 29 cellStyle1.setFont(font); 30 31 firstsheet.setColumnWidth(0, 20*265); 32 firstsheet.setColumnWidth(1, 20*265); 33 firstsheet.setColumnWidth(2, 20*265); 34 firstsheet.setColumnWidth(3, 20*265); 35 firstsheet.setDefaultColumnStyle(0, cellStyle1); 36 firstsheet.setDefaultColumnStyle(1, cellStyle1); 37 firstsheet.setDefaultColumnStyle(2, cellStyle1); 38 firstsheet.setDefaultColumnStyle(3, cellStyle1); 39 40 HSSFRow row = firstsheet.createRow(0); 41 row.setHeight((short) (13.5*20)); 42 row.createCell(0).setCellValue("存儲池名"); 43 row.createCell(1).setCellValue("總容量(TB)"); 44 row.createCell(2).setCellValue("已使用容量(TB)"); 45 row.createCell(3).setCellValue("未使用容量(TB)"); 46 47 double d = Math.random()*10; 48 DecimalFormat dFormat = new DecimalFormat("#.00"); 49 for (int i=0;i<poolList.size();i++) { 50 DPool pool=poolList.get(i); 51 row = firstsheet.createRow(i+1); 52 row.setHeight((short) (13.5*20)); 53 row.createCell(0).setCellValue(pool.getName()); 54 row.createCell(1).setCellValue(pool.getCapacity()); 55 row.createCell(2).setCellValue(pool.getUsed_capacity()); 56 row.createCell(3).setCellValue(pool.getFree_capacity()); 57 } 58 59 HSSFSheet secondsheet = workbook.createSheet("報錯日志"); 60 61 HSSFCellStyle cellStyle2 = workbook.createCellStyle(); 62 cellStyle2.setVerticalAlignment(VerticalAlignment.CENTER); 63 cellStyle2.setAlignment(HorizontalAlignment.LEFT); 64 cellStyle2.setFont(font); 65 cellStyle2.setWrapText(true); 66 67 HSSFCellStyle cellStyle3 = workbook.createCellStyle(); 68 cellStyle3.setAlignment(HorizontalAlignment.CENTER); 69 cellStyle3.setFont(font); 70 71 secondsheet.setColumnWidth(0, 25*265); 72 secondsheet.setColumnWidth(1, 13*265); 73 secondsheet.setColumnWidth(2, 100*265); 74 secondsheet.setDefaultColumnStyle(0, cellStyle1); 75 secondsheet.setDefaultColumnStyle(1, cellStyle1); 76 secondsheet.setDefaultColumnStyle(2, cellStyle2); 77 78 HSSFRow row2 = secondsheet.createRow(0); 79 row2.setHeight((short) (20*20)); 80 row2.createCell(0).setCellValue("時間"); 81 row2.createCell(1).setCellValue("級別"); 82 row2.createCell(2).setCellValue("內容"); 83 row2.getCell(2).setCellStyle(cellStyle3); 84 for(int i=0;i<alarmList.size();i++){ 85 DAlarm alarm=alarmList.get(i); 86 row2 = secondsheet.createRow(i+1); 87 row2.setHeight((short) (27*20)); 88 row2.createCell(0).setCellValue(alarm.getTime()); 89 row2.createCell(1).setCellValue(alarm.getLevel()); 90 row2.createCell(2).setCellValue(alarm.getContext()); 91 } 92 return workbook; 93 } 94 }
(二)、設置control中的下載頭部,這里和freemarker的導出是一樣的。
(三)、利用輸入輸出流,輸出到瀏覽器
1 package cn.Controllers; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.io.UnsupportedEncodingException; 6 import java.net.URLEncoder; 7 import java.text.DecimalFormat; 8 import java.util.List; 9 10 import javax.servlet.ServletOutputStream; 11 import javax.servlet.http.HttpServletRequest; 12 import javax.servlet.http.HttpServletResponse; 13 14 import org.apache.poi.hssf.usermodel.HSSFCellStyle; 15 import org.apache.poi.hssf.usermodel.HSSFFont; 16 import org.apache.poi.hssf.usermodel.HSSFRow; 17 import org.apache.poi.hssf.usermodel.HSSFSheet; 18 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 19 import org.apache.poi.ss.usermodel.HorizontalAlignment; 20 import org.apache.poi.ss.usermodel.VerticalAlignment; 21 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.stereotype.Controller; 23 import org.springframework.ui.Model; 24 import org.springframework.web.bind.annotation.RequestMapping; 25 import org.springframework.web.bind.annotation.ResponseBody; 26 27 import cn.dao.DeviceMapper; 28 import cn.entitys.DAlarm; 29 import cn.entitys.DPool; 30 import cn.entitys.Device; 31 import cn.service.ReportService; 32 import cn.service.ThreadService; 33 import cn.tools.GenerateReport; 34 35 @Controller 36 @RequestMapping("/report") 37 public class ReportController { 38 39 @Autowired 40 ReportService reportService; 41 42 @Autowired 43 ThreadService threadService; 44 45 @Autowired 46 DeviceMapper deviceDao; 47 48 @RequestMapping("/exportreport") 49 private void exportReport(Model model,HttpServletRequest request,HttpServletResponse response,int did) throws IOException { 50 51 //獲取要導入的信息 52 List<DPool> poolList=reportService.selectPoolByDid(did); 53 List<DAlarm> alarmList=reportService.selectAlarmByDid(did); 54 Device device = deviceDao.selectByPrimaryKey(did); 55 56 57 //生成Excel表 58 HSSFWorkbook workbook = GenerateReport.Generate(poolList, alarmList); 59 60 61 //設置下載頭部,通過response實現 62 response.reset(); 63 response.setContentType("application/vnd.ms-excel;charset=utf-8"); 64 try { 65 response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(device.getName()+"-report.xls", "UTF8")); 66 } catch (UnsupportedEncodingException e) { 67 e.printStackTrace(); 68 } 69 ServletOutputStream fileOut = response.getOutputStream(); 70 workbook.write(fileOut); 71 } 72 98 }
這里沒有編寫代碼,后續會跟上的。
三、Excel的解析:
其實這一部分可以分為兩部分來講解 ,首先涉及到的便是文件的上傳,畢竟有文件上傳了才能進行解析,然后便是利用POI解析上傳后的文件獲取數據,
至於POI 的操作會在下一篇博客中整理。