用到的技術有EasyPOIjavascript
# 一.導入導出的認識html
> 操做辦公軟件(word,excel,ppt) 03,07
>> JXL(只支持excel,內存優化) POI(功能強大,支持普遍)java
# POI的基本使用
## 1.1 導包web
<!-- poi支持的jar包 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.11</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.11</version> </dependency>
## 1.2 建立 excel文件 [可經過官方文檔查詢例子]spring
``` //建立一個新的excel,而且寫99乘法表:導出 @Test public void testCreateExcel() throws Exception{ //1.建立一個工做薄(在內存中) SXSSFWorkbook wb = new SXSSFWorkbook(); //2.建立一張表格 Sheet sheet = wb.createSheet("99乘法表"); //3.在表格建立行 for(int i=1;i<=9;i++){ Row row = sheet.createRow(i-1); //4.在表格中建立列(格子) for(int j=1;j<=i;j++){ Cell cell = row.createCell(j-1); //5.格子中寫東西 cell.setCellValue(i+"*"+j+"="+(i*j)); } } FileOutputStream out = new FileOutputStream("99.xlsx"); wb.write(out); out.close(); }
```
## 1.2 讀取excel文件
```數據庫
//讀取excel:導入 @Test public void testReadExcel() throws Exception{ //讀取了emp-poi.xlsx ,建立了Workbook(內存) InputStream inp = new FileInputStream("emp-poi.xlsx"); Workbook wb = WorkbookFactory.create(inp); //拿到對應的表 Sheet sheet = wb.getSheetAt(0); //拿到這表的總行數 int lastRowNum = sheet.getLastRowNum(); for (int i = 1; i <= lastRowNum; i++) { //拿到每一行 Row row = sheet.getRow(i); //拿到這一行的總列數 short lastCellNum = row.getLastCellNum(); for (int j = 0; j < lastCellNum; j++) { //拿到這一個格子與它的數據 Cell cell = row.getCell(j); System.out.print(cell.getStringCellValue()+" "); } System.out.println(); } }
# 三.EasyPOI的使用
> 文檔:http://easypoi.mydoc.io/apache
## 3.1 導包
> 注意:今天使用EasyPOI須要把以前的poi導包去掉緩存
```app
<!-- easypoi的支持 --> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>3.2.0</version> </dependency>
```dom
## 3.2 準備domain
@Excel(name="對應Excel表中的頭")
### POIEmployee ``` @ExcelTarget("emp") public class PoiEmployee { @Excel(name = "名稱") private String name; @Excel(name="郵件",width = 25) private String email; @Excel(name="年齡") private Integer age; @Excel(name="性別",replace = {"男_true","女_false"}) private Boolean sex; @Excel(name="出生日期",format = "yyyy-MM-dd") private Date bornDate = new Date(); //type=2:表明這是一張圖片 @Excel(name = "頭像",type = 2,height = 25) private String headImage; @ExcelEntity private PoiDepartment department; // 不要忘了加上getter,setter } ``` ### POIDepartment ``` @ExcelTarget("dept") public class PoiDepartment { @Excel(name="部門名稱_emp,名稱_dept") private String name; @Excel(name="部門地址_emp,地址_dept") private String address; @Excel(name="郵件_dept") private String email; // 不要忘了加上getter,setter }
```
## 3.3 EasyPOI建立excel文件
```
/** list的值本身準備一下 * new ExportParams(title,sheetName):導出的屬性設置 title:表頭名稱 sheetName:sheet表的名稱 * PoiEmployee .class:導出的實體類型 * list:導出的數據(List<PoiEmployee>) */ Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("部門名稱","bbb"), PoiEmployee.class, list); FileOutputStream fos = new FileOutputStream("poidept.xlsx"); workbook.write(fos); fos.close(); ```
## 3.4 EasyPOI讀取excel文件
```
ImportParams params = new ImportParams(); //params.setTitleRows(1); params.setHeadRows(1); List<PoiEmployee> list = ExcelImportUtil.importExcel( new File("poiemp.xlsx"), PoiEmployee.class, params); list.forEach(e -> { System.out.println(e+","+e.getDepartment()); });
```
# 四 EasyPOI集成SpringMVC完成導入導出
## 4.1 導出功能
> EasyPOI支持SpringMVC
### 4.1.1 掃描view
`<context:component-scan base-package="cn.afterturn.easypoi.view" />
`
### 4.1.2 配置視圖解析器
> p:order="0" 先找這個bean的解析,再找其它的
`
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="0" />
`
### 4.1.3 前臺傳入相應的查詢數據
```
<form id="searchForm" method="post" action="/employee/download"> 用戶名: <input name="username" class="easyui-textbox" style="width:80px"> 郵件: <input name="email" class="easyui-textbox" style="width:80px"> 部門: <input name="departmentId" class="easyui-combobox" data-options="panelHeight:'auto',valueField:'id',textField:'name',url:'/util/deptlist'" /> <a href="javascript:;" data-method="search" class="easyui-linkbutton" iconCls="icon-search">查詢</a> <!-- button不寫type,它就是提交 --> <button class="easyui-linkbutton" iconCls="icon-redo">導出</button> </form>
```
### 4.1.4 後臺接收參數進行導出
> 注:頭像路徑必需是真實路徑,若是打印出來的路徑有誤能夠用字符串工具修改
@RequestMapping("/download") public String download(ModelMap map, HttpServletRequest request,EmployeeQuery query){ //拿到全部員工 List<Employee> employeeList = employeeService.findByQuery(query); //拿到當前項目的路徑 String realPath = request.getServletContext().getRealPath(""); //修改(拼接)員工頭像的路徑 employeeList.forEach(e -> { e.setHeadImage(realPath+e.getHeadImage()); }); ExportParams params = new ExportParams("員工信息", "列表", ExcelType.XSSF); params.setFreezeCol(5); map.put(NormalExcelConstants.DATA_LIST, employeeList); // 數據集合 map.put(NormalExcelConstants.CLASS, Employee.class);//導出實體 map.put(NormalExcelConstants.PARAMS, params);//參數 map.put(NormalExcelConstants.FILE_NAME, "employee");//文件名稱 //easypoiExcelView return NormalExcelConstants.EASYPOI_EXCEL_VIEW;//View名稱 }
```
## 4.2 導入功能
### 4.2.1 訪問頁面
#### ImportController```
@RequestMapping("/import") public class ImportController { @RequestMapping("/index") public String index(){ return "import"; } }
```
#### import.jsp
```
<!-- 注意:上傳須要加enctype --> <form method="post" action="/import/empXlsx" enctype="multipart/form-data"> <input class="easyui-filebox" name="empFile" data-options="prompt:'選擇一個excel文件..'" style="width:80%"> <button class="easyui-linkbutton">導入</button> </form>
```
### 4.2.1 導入實現
> 上傳解析器必定要有名字:multipartResolver
> 必需加一個默認密碼,由於配有默認的密碼加密,因此咱們也須要加密後再存,這裏直接用
> 員工對應的部門必需有id(根據名稱拿到對應的部門)
```
@RequestMapping("/empXlsx")
public String empXlsx(MultipartFile empFile) throws Exception{
// System.out.println(empFile);
// System.out.println(empFile.getName()); //empFile:上傳控件名稱
// System.out.println(empFile.getOriginalFilename()); //emp.xlsx:上傳的文件名稱
// System.out.println(empFile.getSize()); //文件大小
// System.out.println(empFile.getContentType());//文件的memi類型
// System.out.println(empFile.getInputStream());
//準備一些導入的參數
ImportParams params = new ImportParams();
params.setTitleRows(1);
params.setHeadRows(1);
//把上傳的excel文件中的數據變成Employee
List<Employee> list = ExcelImportUtil.importExcel(
empFile.getInputStream(),
Employee.class, params);
//把員工進行保存
list.forEach(e -> {
//設置一個默認密碼
e.setPassword("123456");
//根據名稱到數據庫中拿到部門
Department department = e.getDepartment();
if(department!=null){
Department dbDept = departmentService.findByName(department.getName());
e.setDepartment(dbDept);
}
employeeService.save(e);
});
return "import";
}
```
## 4.3 導入驗證
> 使用的是JSR 303 規範----缺乏這個包會致使驗證功能失敗/報錯
### 4.3.1 導入驗證包
```
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.4.Final</version> </dependency>
```
### 4.3.2 加上驗證的註解```
@Excel(name = "用戶名") @NotNull(message = "用戶名不能爲空") private String username; private String password; @Excel(name = "郵箱",width = 25) private String email; @Excel(name = "年齡") @Max(value=80,message = "年齡不能超過80歲") @Min(value = 20,message = "年齡不能小於20歲") private Integer age; @Excel(name="頭像",type = 2,height = 25) private String headImage; //頭像 //jpa在管理的懶加載對象 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="department_id") @ExcelEntity //缺乏這個註解沒法再表格中讀取到這個屬性 private Department department;
```
### 4.3.3 加上自定義註解
> 不要忘了,這個類型是須要Spring掃描
```
@Component public class EmployeeExcelVerifyHandler implements IExcelVerifyHandler<Employee> { @Autowired private IEmployeeService employeeService; @Override public ExcelVerifyHandlerResult verifyHandler(Employee employee) { //若是用戶存在,咱們就返回一個false // checkUsername:這個用戶名是否可使用 if(!employeeService.checkUsername(employee.getUsername())){ ExcelVerifyHandlerResult result = new ExcelVerifyHandlerResult(false); result.setMsg("用戶名已經存在!"); return result; } return new ExcelVerifyHandlerResult(true); } }
```
### 4.3.3 導入功能修改
> 要驗證,必需設置 params.setNeedVerfiy(true);
>> 自定義驗證:params.setVerifyHandler(employeeExcelVerifyHandler);
>>> result.getList(); 拿到全部經過驗證的數據
>> result.getFailList():拿到全部錯誤的數據
> result.getFailWorkbook();拿到錯誤的文本```
@Autowired private EmployeeExcelVerifyHandler employeeExcelVerifyHandler; ... @RequestMapping("/empXlsx") public String empXlsx(MultipartFile empFile, HttpServletResponse response) throws Exception{ //準備一些導入的參數 ImportParams params = new ImportParams(); params.setTitleRows(1); params.setHeadRows(1); params.setNeedVerfiy(true); //須要作驗證 //設置驗證處理器 params.setVerifyHandler(employeeExcelVerifyHandler); //把上傳的excel文件中的數據變成Employee ExcelImportResult<Employee> result = ExcelImportUtil.importExcelMore( empFile.getInputStream(), Employee.class, params); //拿到相應的值 List<Employee> list = result.getList(); //把員工進行保存 list.forEach(e -> { //設置一個默認密碼 e.setPassword("123456"); //根據名稱到數據庫中拿到部門 Department department = e.getDepartment(); if(department!=null){ Department dbDept = departmentService.findByName(department.getName()); e.setDepartment(dbDept); } employeeService.save(e); }); //拿到錯誤的值 // List<Employee> errList = result.getFailList(); // errList.forEach(e -> System.out.println("錯誤的:"+e)); //有錯誤的狀況進行導出 if(result.isVerfiyFail()){ //拿到錯誤的文件 Workbook failWorkbook = result.getFailWorkbook(); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); //mime類型 response.setHeader("Content-disposition", "attachment;filename=error.xlsx"); response.setHeader("Pragma", "No-cache");//設置不要緩存 OutputStream ouputStream = response.getOutputStream(); failWorkbook.write(ouputStream); ouputStream.flush(); ouputStream.close(); } return "import"; }
```