sunny123456

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Springboot+Poi实现Excel的导入导出
https://blog.csdn.net/typ1805/article/details/83279532

目录

POI操作Excel

EasyPOI操作Excel

解决不同浏览器导出excel中文名称乱码问题

使用POI将HTML Table导出Excel


代码:https://gitee.com/typ1805/springboot-master

POI操作Excel

一、poi简介

          Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。

1、HSSF:HSSF 是Horrible SpreadSheet Format的缩写,通过HSSF,你可以用纯Java代码来读取、写入、修改Excel文件。HSSF 为读取操作提供了两类API:usermodel和eventusermodel,即“用户模型”和“事件-用户模型”。

2、POI EXCEL文档结构类

  • HSSFWorkbook excel文档对象
  • HSSFSheet excel的sheet HSSFRow excel的行
  • HSSFCell excel的单元格 HSSFFont excel字体
  • HSSFName 名称 HSSFDataFormat 日期格式
  • HSSFHeader sheet头
  • HSSFFooter sheet尾
  • HSSFCellStyle cell样式
  • HSSFDateUtil 日期
  • HSSFPrintSetup 打印
  • HSSFErrorConstants 错误信息表

3、导入Excel常用的方法:

  • POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("d:/test.xls"));    
  • HSSFWorkbook wb = new HSSFWorkbook(fs);  //得到Excel工作簿对象   
  • HSSFSheet sheet = wb.getSheetAt(0);   //得到Excel工作表对象   
  • HSSFRow row = sheet.getRow(i);  //得到Excel工作表的行   
  • HSSFCell cell = row.getCell((short) j);  //得到Excel工作表指定行的单元格 
  • cellStyle = cell.getCellStyle();  //得到单元格样式  

4、导出Excel常用的方法:

  • HSSFWorkbook wb = new HSSFWorkbook();  //创建Excel工作簿对象   
  • HSSFSheet sheet = wb.createSheet("new sheet");  //创建Excel工作表对象     
  • HSSFRow row = sheet.createRow((short)0);  //创建Excel工作表的行   
  • cellStyle = wb.createCellStyle();  //创建单元格样式   
  • row.createCell((short)0).setCellStyle(cellStyle);  //创建Excel工作表指定行的单元格   
  • row.createCell((short)0).setCellValue(1);  //设置Excel工作表的值  

二、springboot整合poi

    主要是springboot+myBatis+poi+mysql的简单应用,从数据库查询到结果集导出excel到本地,从本地中的excel文件导入到数据库表中。

1、添加依赖

  1. <dependency>
  2. <groupId>org.apache.poi</groupId>
  3. <artifactId>poi</artifactId>
  4. <version>RELEASE</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.apache.poi</groupId>
  8. <artifactId>poi-ooxml</artifactId>
  9. <version>RELEASE</version>
  10. </dependency>

2、创建一个ExcelUtil类,这里的实现比较简单

  1. package com.example.demo.utils;
  2. import com.example.demo.entity.ExcelData;
  3. import com.example.demo.entity.User;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.apache.poi.hssf.usermodel.*;
  6. import org.apache.poi.ss.usermodel.*;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.BufferedOutputStream;
  9. import java.io.FileInputStream;
  10. import java.io.InputStream;
  11. import java.io.OutputStream;
  12. import java.util.ArrayList;
  13. import java.util.List;
  14. import static org.apache.poi.ss.usermodel.CellType.*;
  15. /**
  16. * 路径:com.example.demo.utils
  17. * 类名:
  18. * 功能:导入导出
  19. * 备注:
  20. * 创建人:typ
  21. * 创建时间:2018/10/19 11:21
  22. * 修改人:
  23. * 修改备注:
  24. * 修改时间:
  25. */
  26. @Slf4j
  27. public class ExcelUtil {
  28. /**
  29. * 方法名:exportExcel
  30. * 功能:导出Excel
  31. * 描述:
  32. * 创建人:typ
  33. * 创建时间:2018/10/19 16:00
  34. * 修改人:
  35. * 修改描述:
  36. * 修改时间:
  37. */
  38. public static void exportExcel(HttpServletResponse response, ExcelData data) {
  39. log.info("导出解析开始,fileName:{}",data.getFileName());
  40. try {
  41. //实例化HSSFWorkbook
  42. HSSFWorkbook workbook = new HSSFWorkbook();
  43. //创建一个Excel表单,参数为sheet的名字
  44. HSSFSheet sheet = workbook.createSheet("sheet");
  45. //设置表头
  46. setTitle(workbook, sheet, data.getHead());
  47. //设置单元格并赋值
  48. setData(sheet, data.getData());
  49. //设置浏览器下载
  50. setBrowser(response, workbook, data.getFileName());
  51. log.info("导出解析成功!");
  52. } catch (Exception e) {
  53. log.info("导出解析失败!");
  54. e.printStackTrace();
  55. }
  56. }
  57. /**
  58. * 方法名:setTitle
  59. * 功能:设置表头
  60. * 描述:
  61. * 创建人:typ
  62. * 创建时间:2018/10/19 10:20
  63. * 修改人:
  64. * 修改描述:
  65. * 修改时间:
  66. */
  67. private static void setTitle(HSSFWorkbook workbook, HSSFSheet sheet, String[] str) {
  68. try {
  69. HSSFRow row = sheet.createRow(0);
  70. //设置列宽,setColumnWidth的第二个参数要乘以256,这个参数的单位是1/256个字符宽度
  71. for (int i = 0; i <= str.length; i++) {
  72. sheet.setColumnWidth(i, 15 * 256);
  73. }
  74. //设置为居中加粗,格式化时间格式
  75. HSSFCellStyle style = workbook.createCellStyle();
  76. HSSFFont font = workbook.createFont();
  77. font.setBold(true);
  78. style.setFont(font);
  79. style.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));
  80. //创建表头名称
  81. HSSFCell cell;
  82. for (int j = 0; j < str.length; j++) {
  83. cell = row.createCell(j);
  84. cell.setCellValue(str[j]);
  85. cell.setCellStyle(style);
  86. }
  87. } catch (Exception e) {
  88. log.info("导出时设置表头失败!");
  89. e.printStackTrace();
  90. }
  91. }
  92. /**
  93. * 方法名:setData
  94. * 功能:表格赋值
  95. * 描述:
  96. * 创建人:typ
  97. * 创建时间:2018/10/19 16:11
  98. * 修改人:
  99. * 修改描述:
  100. * 修改时间:
  101. */
  102. private static void setData(HSSFSheet sheet, List<String[]> data) {
  103. try{
  104. int rowNum = 1;
  105. for (int i = 0; i < data.size(); i++) {
  106. HSSFRow row = sheet.createRow(rowNum);
  107. for (int j = 0; j < data.get(i).length; j++) {
  108. row.createCell(j).setCellValue(data.get(i)[j]);
  109. }
  110. rowNum++;
  111. }
  112. log.info("表格赋值成功!");
  113. }catch (Exception e){
  114. log.info("表格赋值失败!");
  115. e.printStackTrace();
  116. }
  117. }
  118. /**
  119. * 方法名:setBrowser
  120. * 功能:使用浏览器下载
  121. * 描述:
  122. * 创建人:typ
  123. * 创建时间:2018/10/19 16:20
  124. * 修改人:
  125. * 修改描述:
  126. * 修改时间:
  127. */
  128. private static void setBrowser(HttpServletResponse response, HSSFWorkbook workbook, String fileName) {
  129. try {
  130. //清空response
  131. response.reset();
  132. //设置response的Header
  133. response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
  134. OutputStream os = new BufferedOutputStream(response.getOutputStream());
  135. response.setContentType("application/vnd.ms-excel;charset=gb2312");
  136. //将excel写入到输出流中
  137. workbook.write(os);
  138. os.flush();
  139. os.close();
  140. log.info("设置浏览器下载成功!");
  141. } catch (Exception e) {
  142. log.info("设置浏览器下载失败!");
  143. e.printStackTrace();
  144. }
  145. }
  146. /**
  147. * 方法名:importExcel
  148. * 功能:导入
  149. * 描述:
  150. * 创建人:typ
  151. * 创建时间:2018/10/19 11:45
  152. * 修改人:
  153. * 修改描述:
  154. * 修改时间:
  155. */
  156. public static List<Object[]> importExcel(String fileName) {
  157. log.info("导入解析开始,fileName:{}",fileName);
  158. try {
  159. List<Object[]> list = new ArrayList<>();
  160. InputStream inputStream = new FileInputStream(fileName);
  161. Workbook workbook = WorkbookFactory.create(inputStream);
  162. Sheet sheet = workbook.getSheetAt(0);
  163. //获取sheet的行数
  164. int rows = sheet.getPhysicalNumberOfRows();
  165. for (int i = 0; i < rows; i++) {
  166. //过滤表头行
  167. if (i == 0) {
  168. continue;
  169. }
  170. //获取当前行的数据
  171. Row row = sheet.getRow(i);
  172. Object[] objects = new Object[row.getPhysicalNumberOfCells()];
  173. int index = 0;
  174. for (Cell cell : row) {
  175. if (cell.getCellType().equals(NUMERIC)) {
  176. objects[index] = (int) cell.getNumericCellValue();
  177. }
  178. if (cell.getCellType().equals(STRING)) {
  179. objects[index] = cell.getStringCellValue();
  180. }
  181. if (cell.getCellType().equals(BOOLEAN)) {
  182. objects[index] = cell.getBooleanCellValue();
  183. }
  184. if (cell.getCellType().equals(ERROR)) {
  185. objects[index] = cell.getErrorCellValue();
  186. }
  187. index++;
  188. }
  189. list.add(objects);
  190. }
  191. log.info("导入文件解析成功!");
  192. return list;
  193. }catch (Exception e){
  194. log.info("导入文件解析失败!");
  195. e.printStackTrace();
  196. }
  197. return null;
  198. }
  199. //测试导入
  200. public static void main(String[] args) {
  201. try {
  202. String fileName = "f:/test.xlsx";
  203. List<Object[]> list = importExcel(fileName);
  204. for (int i = 0; i < list.size(); i++) {
  205. User user = new User();
  206. user.setId((Integer) list.get(i)[0]);
  207. user.setUsername((String) list.get(i)[1]);
  208. user.setPassword((String) list.get(i)[2]);
  209. user.setEnable((Integer) list.get(i)[3]);
  210. System.out.println(user.toString());
  211. }
  212. } catch (Exception e) {
  213. e.printStackTrace();
  214. }
  215. }
  216. }

具体业务代码在此不赘述,完整代码:https://download.csdn.net/download/typ1805/10737617

三、poi API简述

1、设置sheet名称和单元格内容

  1. workbook.setSheetName(1"工作表",HSSFCell.ENCODING_UTF_16);          
  2. cell.setEncoding((short1);      
  3. cell.setCellValue("单元格内容");  

2、取得sheet的数目 

workbook.getNumberOfSheets()   

3、据index取得sheet对象

HSSFSheet sheet = wb.getSheetAt(0);  

4、取得有效的行数

int rowcount = sheet.getLastRowNum();  

5、取得一行的有效单元格个数

row.getLastCellNum();    

6、单元格值类型读写

  1. cell.setCellType(HSSFCell.CELL_TYPE_STRING); //设置单元格为STRING类型   
  2. cell.getNumericCellValue();//读取为数值类型的单元格内容  

7、设置列宽、行高

  1. sheet.setColumnWidth((short)column,(short)width);      
  2. row.setHeight((short)height);    

8、添加区域,合并单元格

  1. // 合并从第rowFrom行columnFrom列
  2. Region region = new Region((short)rowFrom,(short)columnFrom,(short)rowTo(short)columnTo);  
  3. // 到rowTo行columnTo的区域 
  4. sheet.addMergedRegion(region);     
  5. // 得到所有区域       
  6. sheet.getNumMergedRegions()   

9、保存Excel文件

  1. FileOutputStream fileOut = new FileOutputStream(path);   
  2. wb.write(fileOut);   

10、根据单元格不同属性返回字符串数值

  1. public String getCellStringValue(HSSFCell cell) {      
  2.         String cellValue = "";      
  3.         switch (cell.getCellType()) {      
  4.         case HSSFCell.CELL_TYPE_STRING://字符串类型   
  5.             cellValue = cell.getStringCellValue();      
  6.             if(cellValue.trim().equals("")||cellValue.trim().length()<=0)      
  7.                 cellValue=" ";      
  8.             break;      
  9.         case HSSFCell.CELL_TYPE_NUMERIC//数值类型   
  10.             cellValue = String.valueOf(cell.getNumericCellValue());      
  11.             break;      
  12.         case HSSFCell.CELL_TYPE_FORMULA//公式   
  13.             cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);      
  14.             cellValue = String.valueOf(cell.getNumericCellValue());      
  15.             break;      
  16.         case HSSFCell.CELL_TYPE_BLANK:      
  17.             cellValue=" ";      
  18.             break;      
  19.         case HSSFCell.CELL_TYPE_BOOLEAN:      
  20.             break;      
  21.         case HSSFCell.CELL_TYPE_ERROR:      
  22.             break;      
  23.         default:      
  24.             break;      
  25.         }      
  26.        return cellValue;      
  27. }     

11、常用单元格边框格式

  1. HSSFCellStyle style = wb.createCellStyle();      
  2. style.setBorderBottom(HSSFCellStyle.BORDER_DOTTED);//下边框        
  3. style.setBorderLeft(HSSFCellStyle.BORDER_DOTTED);//左边框        
  4. style.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框        
  5. style.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框    

12、设置字体和内容位置

  1. HSSFFont f  = wb.createFont();      
  2. f.setFontHeightInPoints((short11);//字号       
  3. f.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);//加粗       
  4. style.setFont(f);      
  5. style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//左右居中       
  6. style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//上下居中       
  7. style.setRotation(short rotation);//单元格内容的旋转的角度       
  8. HSSFDataFormat df = wb.createDataFormat();      
  9. style1.setDataFormat(df.getFormat("0.00%"));//设置单元格数据格式       
  10. cell.setCellFormula(string);//给单元格设公式       
  11. style.setRotation(short rotation);//单元格内容的旋转的角度   

13、插入图片

  1. //先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray       
  2. ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();      
  3. BufferedImage bufferImg = ImageIO.read(new File("ok.jpg"));      
  4. ImageIO.write(bufferImg,"jpg",byteArrayOut);      
  5. //读进一个excel模版       
  6. FileInputStream fos = new FileInputStream(filePathName+"/stencil.xlt");       
  7. fs = new POIFSFileSystem(fos);      
  8. //创建一个工作薄       
  9. HSSFWorkbook wb = new HSSFWorkbook(fs);      
  10. HSSFSheet sheet = wb.getSheetAt(0);      
  11. HSSFPatriarch patriarch = sheet.createDrawingPatriarch();      
  12. HSSFClientAnchor anchor = new HSSFClientAnchor(0,0,1023,255,(short0,0,(short)10,10);           
  13. patriarch.createPicture(anchor , wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG));

14、调整工作表位置

  1. HSSFWorkbook wb = new HSSFWorkbook();     
  2. HSSFSheet sheet = wb.createSheet("format sheet");     
  3. HSSFPrintSetup ps = sheet.getPrintSetup();     
  4. sheet.setAutobreaks(true);     
  5. ps.setFitHeight((short)1);     
  6. ps.setFitWidth((short)1);   

15、设置打印区域

  1. HSSFSheet sheet = wordbook.createSheet("Sheet1");     
  2. wordbook.setPrintArea(0"$A$1:$C$2");    

16、标注脚注

  1. HSSFSheet sheet = wordbook.createSheet("format sheet");     
  2. HSSFFooter footer = sheet.getFooter()     
  3. footer.setRight"Page " + HSSFFooter.page() + " of " + HSSFFooter.numPages() );  

17、在工作单中清空行数据,调整行位置

  1. HSSFWorkbook wb = new HSSFWorkbook();     
  2. HSSFSheet sheet = wb.createSheet("row sheet");     
  3. // Create various cells and rows for spreadsheet.      
  4. // Shift rows 6 - 11 on the spreadsheet to the top (rows 0 - 5)      
  5. sheet.shiftRows(510-5);    

18、选中指定的工作表

  1. HSSFSheet sheet = wb.createSheet("row sheet");     
  2. heet.setSelected(true);  

19、工作表的放大缩小

  1. HSSFSheet sheet1 = wb.createSheet("new sheet");     
  2. sheet1.setZoom(1,2);   // 50 percent magnification    

20、头注和脚注

  1. HSSFSheet sheet = wb.createSheet("new sheet");     
  2. HSSFHeader header = sheet.getHeader();     
  3. header.setCenter("Center Header");     
  4. header.setLeft("Left Header");     
  5. header.setRight(HSSFHeader.font("Stencil-Normal""Italic") +     
  6. HSSFHeader.fontSize((short) 16) + "Right w/ Stencil-Normal Italic font and size 16");  

21、自定义颜色

  1. HSSFCellStyle style = wb.createCellStyle();     
  2. style.setFillForegroundColor(HSSFColor.LIME.index);     
  3. style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);     
  4. HSSFFont font = wb.createFont();     
  5. font.setColor(HSSFColor.RED.index);     
  6. style.setFont(font);     
  7. cell.setCellStyle(style);     

22、填充和颜色设置

  1. HSSFCellStyle style = wb.createCellStyle();     
  2. style.setFillBackgroundColor(HSSFColor.AQUA.index);     
  3. style.setFillPattern(HSSFCellStyle.BIG_SPOTS);     
  4. HSSFCell cell = row.createCell((short1);     
  5. cell.setCellValue("X");     
  6. style = wb.createCellStyle();     
  7. style.setFillForegroundColor(HSSFColor.ORANGE.index);     
  8. style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);     
  9. cell.setCellStyle(style);   

23、强行刷新单元格公式

  1. HSSFFormulaEvaluator eval=new HSSFFormulaEvaluator((HSSFWorkbook) wb);    
  2. private static void updateFormula(Workbook wb,Sheet s,int row){     
  3.         Row r=s.getRow(row);     
  4.         Cell c=null;     
  5.         FormulaEcaluator eval=null;     
  6.         if(wb instanceof HSSFWorkbook)     
  7.             eval=new HSSFFormulaEvaluator((HSSFWorkbook) wb);     
  8.         else if(wb instanceof XSSFWorkbook)     
  9.             eval=new XSSFFormulaEvaluator((XSSFWorkbook) wb);     
  10.         for(int i=r.getFirstCellNum();i
  11.             c=r.getCell(i);     
  12.             if(c.getCellType()==Cell.CELL_TYPE_FORMULA)     
  13.                 eval.evaluateFormulaCell(c);     
  14.         }     
  15. }    

24、设置不显示excel网格线 

sheet.setDisplayGridlines(false);//其中sheet是Sheet对象 

25、设置excel单元格中的内容换行 

cellStyle.setWrapText(true);

注意:其中cellStyle是WorkBook创建的CellStyle对象,然后将cellStyle设置到要换行的Cell对象,最后在要换行的对象(一般为字符串)加入"/r/n"。例如: 

topTile.append("/r/n" +"cellContent"); 

26、单元格的合并 

sheet.addMergedRegion(new CellRangeAddress(0, 4, 0, 2));// 本示例为合并4行2列 

27、设置页眉和页脚的页数 

  1. HSSFHeader header = sheet.getHeader(); 
  2. header.setCenter("Center Header"); 
  3.  header.setLeft("Left Header"); 
  4.  header.setRight(HSSFHeader.font("Stencil-Normal", "Italic") + 
  5.  HSSFHeader.fontSize((short) 16) + "Right w/ Stencil-Normal Italic font and size 16"); 
  6. HSSFFooter footer = (HSSFFooter )sheet.getFooter() 
  7.  footer.setRight( "Page " + HSSFFooter.page() + " of " + HSSFFooter.numPages() ); 

28、使得一个Sheet适合一页 

 sheet.setAutobreaks(true); 

29、设置放大属性(Zoom被明确为一个分数,例如下面的75%使用3作为分子,4作为分母) 

sheet.setZoom(3,4);   

30、设置打印 

  1. HSSFPrintSetup print = (HSSFPrintSetup) sheet.getPrintSetup(); 
  2.   print.setLandscape(true);//设置横向打印 
  3.   print.setScale((short) 70);//设置打印缩放70% 
  4.   print.setPaperSize(HSSFPrintSetup.A4_PAPERSIZE);//设置为A4纸张 
  5.   print.setLeftToRight(true);//設置打印顺序先行后列,默认为先列行            
  6.   print.setFitHeight((short) 10);设置缩放调整为10页高 
  7.   print.setFitWidth((short) 10);设置缩放调整为宽高 
  8.   sheet.setAutobreaks(false); 
  9.   if (i != 0 && i % 30 == 0) {
  10.       sheet.setRowBreak(i);//設置每30行分頁打印 
  11. }

31、反复的行和列(设置打印标题) 

  1. HSSFWorkbook wb = new HSSFWorkbook(); 
  2. wb.setRepeatingRowsAndColumns(0, 0, 12, 1, 6);//设置1到12列,行1到6每一页重复打印 

32、调整单元格宽度 

  1. sheet.setAutobreaks(true); 
  2. sheet.setColumnWidth((short)i,colsWidth[i]); //设定单元格长度 
  3. sheet.autoSizeColumn((short) i);//自动根据长度调整单元格长度 

使用poi对excel的操作到此结束。。。

 

EasyPOI操作Excel

注:使用easypoi API导出excel相对于poi的API比较简单。

一、导出Excel

1、添加依赖

  1. <dependency>
  2. <groupId>cn.afterturn</groupId>
  3. <artifactId>easypoi-spring-boot-starter</artifactId>
  4. <version>3.3.0</version>
  5. </dependency>

2、映射实体注解

  1. /**
  2. * 路径:com.example.demo.entity
  3. * 类名:
  4. * 功能:使用easypoi导出excel
  5. * 备注:
  6. * 创建人:typ
  7. * 创建时间:2019/5/19 20:54
  8. * 修改人:
  9. * 修改备注:
  10. * 修改时间:
  11. */
  12. @Data
  13. public class BrandInfo implements Serializable{
  14. @Excel(name = "brandGuid", width = 25,orderNum = "0")
  15. private String brandGuid;
  16. @Excel(name = "brandName", width = 25,orderNum = "0")
  17. private String brandName;
  18. @Excel(name = "ytFullcode", width = 25,orderNum = "0")
  19. private String ytFullcode;
  20. @Excel(name = "formatGuid", width = 25,orderNum = "0")
  21. private String formatGuid;
  22. @Excel(name = "flag", width = 25,orderNum = "0")
  23. private String flag;
  24. @Excel(name = "customerid", width = 25,orderNum = "0")
  25. private String customerid;
  26. @Excel(name = "createDatetime",width = 20,exportFormat = "yyyy-MM-dd HH:mm:ss", orderNum = "1")
  27. private String createDatetime;
  28. @Excel(name = "updateDatetime",width = 20,exportFormat = "yyyy-MM-dd HH:mm:ss", orderNum = "1")
  29. private String updateDatetime;
  30. @Excel(name = "source", width = 25,orderNum = "0")
  31. private Integer source;
  32. }

3、查询数据

3.1、service接口:

  1. public interface ExcelService {
  2. List<BrandInfo> list();
  3. }

3.2、service实现类:

  1. @Service
  2. public class ExcelServiceImlp implements ExcelService {
  3. @Autowired
  4. private ExcelMapper excelMapper;
  5. @Override
  6. public List<BrandInfo> list() {
  7. return excelMapper.list();
  8. }
  9. }

3.3、mapper接口 

  1. @Mapper
  2. public interface ExcelMapper {
  3. List<BrandInfo> list();
  4. }

 3.4、mapper对应的xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3. <mapper namespace="com.example.demo.mapper.ExcelMapper">
  4. <select id="list" resultType="com.example.demo.entity.BrandInfo">
  5. select brand_guid,brand_name,yt_fullcode,format_guid,flag,customerid,create_datetime,update_datetime,source from brand_info
  6. </select>
  7. </mapper>

4、导出Controller

  1. package com.example.demo.controller;
  2. import cn.afterturn.easypoi.excel.ExcelExportUtil;
  3. import cn.afterturn.easypoi.excel.entity.ExportParams;
  4. import com.example.demo.entity.BrandInfo;
  5. import com.example.demo.service.ExcelService;
  6. import org.apache.poi.ss.usermodel.Workbook;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.web.bind.annotation.GetMapping;
  11. import org.springframework.web.bind.annotation.RequestMapping;
  12. import org.springframework.web.bind.annotation.RestController;
  13. import javax.servlet.http.HttpServletResponse;
  14. import java.io.BufferedOutputStream;
  15. import java.io.IOException;
  16. import java.io.OutputStream;
  17. import java.util.List;
  18. /**
  19. * 路径:com.example.demo.controller
  20. * 类名:EasyPoiExcelController
  21. * 功能:使用easypoi注解进行导入导出
  22. * 备注:
  23. * 创建人:typ
  24. * 创建时间:2019/5/19 20:00
  25. * 修改人:
  26. * 修改备注:
  27. * 修改时间:
  28. */
  29. @RestController
  30. @RequestMapping("/easypoi")
  31. public class EasyPoiExcelController {
  32. private static final Logger log = LoggerFactory.getLogger(EasyPoiExcelController.class);
  33. @Autowired
  34. public ExcelService excelService;
  35. /**
  36. * 方法名:exportExcel
  37. * 功能:导出
  38. * 描述:
  39. * 创建人:typ
  40. * 创建时间:2019/5/19 20:03
  41. * 修改人:
  42. * 修改描述:
  43. * 修改时间:
  44. */
  45. @GetMapping("/exportExcel")
  46. public void exportExcel(HttpServletResponse response){
  47. log.info("请求 exportExcel start ......");
  48. // 获取用户信息
  49. List<BrandInfo> list = excelService.list();
  50. try {
  51. // 设置响应输出的头类型及下载文件的默认名称
  52. String fileName = new String("demo信息表.xls".getBytes("utf-8"), "ISO-8859-1");
  53. response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
  54. response.setContentType("application/vnd.ms-excel;charset=gb2312");
  55. //导出
  56. Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), BrandInfo.class, list);
  57. workbook.write(response.getOutputStream());
  58. log.info("请求 exportExcel end ......");
  59. } catch (IOException e) {
  60. log.info("请求 exportExcel 异常:{}", e.getMessage());
  61. }
  62. }
  63. }

5、浏览器请求 http://localhost:8081/easypoi/exportExcel导出结果如下

二、导入Excel

这里只是简单的测试了一下,没有把数据往数据库存储:

  1. public static void main(String[] args) {
  2. try{
  3. // 没有使用实体类注解的形式,这里用的Map
  4. List<Map<String,Object>> list = ExcelImportUtil.importExcel(
  5. new File(PoiPublicUtil.getWebRootPath("check.xls")),
  6. Map.class,
  7. new ImportParams()
  8. );
  9. // 数据打印
  10. for (Map<String, Object> map : list) {
  11. System.out.println(JSON.toJSON(map));
  12. }
  13. } catch (Exception e){
  14. log.info(" Excel 导入异常:{}", e.getMessage());
  15. }
  16. }

Excel原数据如图:

导入结果如下:

  1. DEBUG 2019-05-31 14:54:06,466 cn.afterturn.easypoi.excel.imports.ExcelImportServer: Excel import start ,class is interface java.util.Map
  2. DEBUG 2019-05-31 14:54:06,811 cn.afterturn.easypoi.excel.imports.ExcelImportServer: start to read excel by is ,startTime is 1559285646811
  3. DEBUG 2019-05-31 14:54:06,812 cn.afterturn.easypoi.excel.imports.ExcelImportServer: end to read excel by is ,endTime is 1559285646811
  4. DEBUG 2019-05-31 14:54:06,837 cn.afterturn.easypoi.excel.imports.ExcelImportServer: end to read excel list by pos ,endTime is 1559285646837
  5. {"name":"zhangsan","password":123,"id":1,"sex":"男"}
  6. {"name":"lisi","password":123456,"id":2,"sex":"男"}
  7. {"name":"wangwu","password":10002,"id":3,"sex":"女"}
  8. {"name":"zhaoliu","password":1587,"id":4,"sex":"男"}
  9. {"name":"maqi","password":45987,"id":5,"sex":"女"}
  10. {"name":"houjiu","password":23143,"id":6,"sex":"男"}
  11. {"name":"jishi","password":4543645,"id":7,"sex":"男"}

 

解决不同浏览器导出excel中文名称乱码问题

在Windows上以上的导出都是正常,而在Max上导出时,文件名称包含中文时会乱码,只需添加一下代码就可以完美的解决名称乱码问题。

  1. // 各浏览器基本都支持ISO编码
  2. String userAgent = request.getHeader("User-Agent").toUpperCase();
  3. if(userAgent.contains("TRIDENT") || userAgent.contains("EDGE")){
  4. fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
  5. } else if(userAgent.contains("MSIE")) {
  6. fileName = new String(fileName.getBytes(), "ISO-8859-1");
  7. } else {
  8. fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
  9. }
  10. response.addHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", fileName));

使用POI将HTML Table导出Excel

1、POI依赖

  1. <dependency>
  2. <groupId>org.apache.poi</groupId>
  3. <artifactId>poi</artifactId>
  4. <version>3.8</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.apache.poi</groupId>
  8. <artifactId>poi-ooxml</artifactId>
  9. <version>3.8</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.apache.poi</groupId>
  13. <artifactId>poi-ooxml-schemas</artifactId>
  14. <version>3.8</version>
  15. </dependency>

2、导出工具类

2.1、使用HSSFWorkbook

  1. package com.demo.utils;
  2. import com.demo.model.CrossRangeCellMeta;
  3. import org.apache.commons.lang3.StringUtils;
  4. import org.apache.commons.lang3.math.NumberUtils;
  5. import org.apache.poi.hssf.usermodel.*;
  6. import org.apache.poi.hssf.util.HSSFColor;
  7. import org.apache.poi.ss.util.CellRangeAddress;
  8. import org.dom4j.Document;
  9. import org.dom4j.DocumentException;
  10. import org.dom4j.DocumentHelper;
  11. import org.dom4j.Element;
  12. import java.io.File;
  13. import java.io.FileOutputStream;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. /**
  17. * 类名:Html2Excel.java
  18. * 路径:com.demo.utils.Html2Excel.java
  19. * 创建人:tanyp
  20. * 创建时间:2019/9/19 10:00
  21. * 功能:将html table转成excel
  22. * 修改人:
  23. * 修改时间:
  24. * 修改备注:
  25. */
  26. public class Html2Excel {
  27. /**
  28. * 方法名:table2Excel
  29. * 功能:html表格转excel
  30. * 创建人:tanyp
  31. * 创建时间:2019/9/19 10:00
  32. * 入参:html字符串:<table> ... </table>
  33. * 出参:excel
  34. * 修改人:
  35. * 修改时间:
  36. * 修改备注:
  37. */
  38. public static HSSFWorkbook table2Excel(String tableHtml) {
  39. HSSFWorkbook wb = new HSSFWorkbook();
  40. HSSFSheet sheet = wb.createSheet();
  41. HSSFCellStyle style = wb.createCellStyle();
  42. style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
  43. List<CrossRangeCellMeta> crossRowEleMetaLs = new ArrayList<>();
  44. int rowIndex = 0;
  45. try {
  46. Document data = DocumentHelper.parseText(tableHtml);
  47. // 生成表头
  48. Element thead = data.getRootElement().element("thead");
  49. HSSFCellStyle titleStyle = getTitleStyle(wb);
  50. if (thead != null) {
  51. List<Element> trLs = thead.elements("tr");
  52. for (Element trEle : trLs) {
  53. HSSFRow row = sheet.createRow(rowIndex);
  54. List<Element> thLs = trEle.elements("th");
  55. makeRowCell(thLs, rowIndex, row, 0, titleStyle, crossRowEleMetaLs);
  56. row.setHeightInPoints(17);
  57. rowIndex++;
  58. }
  59. }
  60. // 生成表体
  61. Element tbody = data.getRootElement().element("tbody");
  62. if (tbody != null) {
  63. HSSFCellStyle contentStyle = getContentStyle(wb);
  64. List<Element> trLs = tbody.elements("tr");
  65. for (Element trEle : trLs) {
  66. HSSFRow row = sheet.createRow(rowIndex);
  67. List<Element> thLs = trEle.elements("th");
  68. int cellIndex = makeRowCell(thLs, rowIndex, row, 0, titleStyle, crossRowEleMetaLs);
  69. List<Element> tdLs = trEle.elements("td");
  70. makeRowCell(tdLs, rowIndex, row, cellIndex, contentStyle, crossRowEleMetaLs);
  71. row.setHeightInPoints(18);
  72. rowIndex++;
  73. }
  74. }
  75. // 合并表头
  76. for (CrossRangeCellMeta crcm : crossRowEleMetaLs) {
  77. sheet.addMergedRegion(new CellRangeAddress(crcm.getFirstRow(), crcm.getLastRow(), crcm.getFirstCol(), crcm.getLastCol()));
  78. }
  79. } catch (DocumentException e) {
  80. e.printStackTrace();
  81. }
  82. //自动调整列宽
  83. for (int i = 0; i < 15; i++) {
  84. sheet.autoSizeColumn((short) i);
  85. }
  86. return wb;
  87. }
  88. /**
  89. * 方法名:makeRowCell
  90. * 功能:生产行内容
  91. * 创建人:tanyp
  92. * 创建时间:2019/9/19 10:01
  93. * 入参:
  94. * tdLs: th或者td集合;
  95. * rowIndex: 行号;
  96. * row: POI行对象;
  97. * startCellIndex;
  98. * cellStyle: 样式;
  99. * crossRowEleMetaLs: 跨行元数据集合
  100. * 出参:
  101. * 修改人:
  102. * 修改时间:
  103. * 修改备注:
  104. */
  105. private static int makeRowCell(List<Element> tdLs, int rowIndex, HSSFRow row, int startCellIndex, HSSFCellStyle cellStyle, List<CrossRangeCellMeta> crossRowEleMetaLs) {
  106. int i = startCellIndex;
  107. for (int eleIndex = 0; eleIndex < tdLs.size(); i++, eleIndex++) {
  108. int captureCellSize = getCaptureCellSize(rowIndex, i, crossRowEleMetaLs);
  109. while (captureCellSize > 0) {
  110. // 当前行跨列处理(补单元格)
  111. for (int j = 0; j < captureCellSize; j++) {
  112. row.createCell(i);
  113. i++;
  114. }
  115. captureCellSize = getCaptureCellSize(rowIndex, i, crossRowEleMetaLs);
  116. }
  117. Element thEle = tdLs.get(eleIndex);
  118. String val = thEle.getTextTrim();
  119. if (StringUtils.isBlank(val)) {
  120. Element e = thEle.element("a");
  121. if (e != null) {
  122. val = e.getTextTrim();
  123. }
  124. }
  125. HSSFCell c = row.createCell(i);
  126. if (NumberUtils.isNumber(val)) {
  127. c.setCellValue(Double.parseDouble(val));
  128. c.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
  129. } else {
  130. c.setCellValue(val);
  131. }
  132. c.setCellStyle(cellStyle);
  133. int rowSpan = NumberUtils.toInt(thEle.attributeValue("rowspan"), 1);
  134. int colSpan = NumberUtils.toInt(thEle.attributeValue("colspan"), 1);
  135. // 存在跨行或跨列
  136. if (rowSpan > 1 || colSpan > 1) {
  137. crossRowEleMetaLs.add(new CrossRangeCellMeta(rowIndex, i, rowSpan, colSpan));
  138. }
  139. // 当前行跨列处理(补单元格)
  140. if (colSpan > 1) {
  141. for (int j = 1; j < colSpan; j++) {
  142. i++;
  143. row.createCell(i);
  144. }
  145. }
  146. }
  147. return i;
  148. }
  149. /**
  150. * 方法名:getCaptureCellSize
  151. * 功能:获得因rowSpan占据的单元格
  152. * 创建人:tanyp
  153. * 创建时间:2019/9/19 10:03
  154. * 入参:
  155. * rowIndex:行号
  156. * colIndex:列号
  157. * crossRowEleMetaLs:跨行列元数据
  158. * 出参:当前行在某列需要占据单元格
  159. * 修改人:
  160. * 修改时间:
  161. * 修改备注:
  162. */
  163. private static int getCaptureCellSize(int rowIndex, int colIndex, List<CrossRangeCellMeta> crossRowEleMetaLs) {
  164. int captureCellSize = 0;
  165. for (CrossRangeCellMeta crossRangeCellMeta : crossRowEleMetaLs) {
  166. if (crossRangeCellMeta.getFirstRow() < rowIndex && crossRangeCellMeta.getLastRow() >= rowIndex) {
  167. if (crossRangeCellMeta.getFirstCol() <= colIndex && crossRangeCellMeta.getLastCol() >= colIndex) {
  168. captureCellSize = crossRangeCellMeta.getLastCol() - colIndex + 1;
  169. }
  170. }
  171. }
  172. return captureCellSize;
  173. }
  174. /**
  175. * 方法名:getTitleStyle
  176. * 功能:获得标题样式
  177. * 创建人:tanyp
  178. * 创建时间:2019/9/19 10:04
  179. * 入参:workbook
  180. * 出参:
  181. * 修改人:
  182. * 修改时间:
  183. * 修改备注:
  184. */
  185. private static HSSFCellStyle getTitleStyle(HSSFWorkbook workbook) {
  186. short titlebackgroundcolor = HSSFColor.GREY_25_PERCENT.index;
  187. short fontSize = 12;
  188. String fontName = "宋体";
  189. HSSFCellStyle style = workbook.createCellStyle();
  190. style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
  191. style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
  192. style.setBorderBottom((short) 1);
  193. style.setBorderTop((short) 1);
  194. style.setBorderLeft((short) 1);
  195. style.setBorderRight((short) 1);
  196. style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
  197. // 背景色
  198. style.setFillForegroundColor(titlebackgroundcolor);
  199. HSSFFont font = workbook.createFont();
  200. font.setFontName(fontName);
  201. font.setFontHeightInPoints(fontSize);
  202. font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
  203. style.setFont(font);
  204. return style;
  205. }
  206. /**
  207. * 方法名:getContentStyle
  208. * 功能:获得内容样式
  209. * 创建人:tanyp
  210. * 创建时间:2019/9/19 10:05
  211. * 入参:HSSFWorkbook
  212. * 出参:
  213. * 修改人:
  214. * 修改时间:
  215. * 修改备注:
  216. */
  217. private static HSSFCellStyle getContentStyle(HSSFWorkbook wb) {
  218. short fontSize = 12;
  219. String fontName = "宋体";
  220. HSSFCellStyle style = wb.createCellStyle();
  221. style.setBorderBottom((short) 1);
  222. style.setBorderTop((short) 1);
  223. style.setBorderLeft((short) 1);
  224. style.setBorderRight((short) 1);
  225. HSSFFont font = wb.createFont();
  226. font.setFontName(fontName);
  227. font.setFontHeightInPoints(fontSize);
  228. style.setFont(font);
  229. return style;
  230. }
  231. }

 异常:使用Html2Excel.java导出时列超过256时会报错:Invalid column index (256).  Allowable column range for BIFF8 is (0..255) or ('A'..'IV')。

原因:使用HSSFWorkbook最多只能创建256列,超过就会报上述的错误。

解决方法:使用XSSFWorkbook创建,最多可以创建16384列。修改Html2Excel工具类为XHtml2Excel.java,如下:

2.2、使用XSSFWorkbook

  1. package com.demo.utils;
  2. import com.demo.model.CrossRangeCellMeta;
  3. import org.apache.commons.lang3.StringUtils;
  4. import org.apache.commons.lang3.math.NumberUtils;
  5. import org.apache.poi.hssf.usermodel.HSSFCell;
  6. import org.apache.poi.hssf.usermodel.HSSFCellStyle;
  7. import org.apache.poi.hssf.usermodel.HSSFFont;
  8. import org.apache.poi.hssf.util.HSSFColor;
  9. import org.apache.poi.ss.util.CellRangeAddress;
  10. import org.apache.poi.xssf.usermodel.*;
  11. import org.dom4j.Document;
  12. import org.dom4j.DocumentException;
  13. import org.dom4j.DocumentHelper;
  14. import org.dom4j.Element;
  15. import java.io.File;
  16. import java.io.FileOutputStream;
  17. import java.util.ArrayList;
  18. import java.util.List;
  19. /**
  20. * 类名:XHtml2Excel.java
  21. * 路径:com.demo.utils.XHtml2Excel.java
  22. * 创建人:tanyp
  23. * 创建时间:2019/9/19 10:00
  24. * 功能:将html table转成excel
  25. * 修改人:
  26. * 修改时间:
  27. * 修改备注:
  28. */
  29. public class XHtml2Excel {
  30. /**
  31. * 方法名:table2Excel
  32. * 功能:html表格转excel
  33. * 创建人:tanyp
  34. * 创建时间:2019/9/19 10:00
  35. * 入参:html字符串:<table> ... </table>
  36. * 出参:excel
  37. * 修改人:
  38. * 修改时间:
  39. * 修改备注:
  40. */
  41. public static XSSFWorkbook table2Excel(String tableHtml) {
  42. XSSFWorkbook wb = new XSSFWorkbook();
  43. XSSFSheet sheet = wb.createSheet();
  44. XSSFCellStyle style = wb.createCellStyle();
  45. style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
  46. List<CrossRangeCellMeta> crossRowEleMetaLs = new ArrayList<>();
  47. int rowIndex = 0;
  48. try {
  49. Document data = DocumentHelper.parseText(tableHtml);
  50. // 生成表头
  51. Element thead = data.getRootElement().element("thead");
  52. XSSFCellStyle titleStyle = getTitleStyle(wb);
  53. if (thead != null) {
  54. List<Element> trLs = thead.elements("tr");
  55. for (Element trEle : trLs) {
  56. XSSFRow row = sheet.createRow(rowIndex);
  57. List<Element> thLs = trEle.elements("th");
  58. makeRowCell(thLs, rowIndex, row, 0, titleStyle, crossRowEleMetaLs);
  59. row.setHeightInPoints(17);
  60. rowIndex++;
  61. }
  62. }
  63. // 生成表体
  64. Element tbody = data.getRootElement().element("tbody");
  65. if (tbody != null) {
  66. XSSFCellStyle contentStyle = getContentStyle(wb);
  67. List<Element> trLs = tbody.elements("tr");
  68. for (Element trEle : trLs) {
  69. XSSFRow row = sheet.createRow(rowIndex);
  70. List<Element> thLs = trEle.elements("th");
  71. int cellIndex = makeRowCell(thLs, rowIndex, row, 0, titleStyle, crossRowEleMetaLs);
  72. List<Element> tdLs = trEle.elements("td");
  73. makeRowCell(tdLs, rowIndex, row, cellIndex, contentStyle, crossRowEleMetaLs);
  74. row.setHeightInPoints(18);
  75. rowIndex++;
  76. }
  77. }
  78. // 合并表头
  79. for (CrossRangeCellMeta crcm : crossRowEleMetaLs) {
  80. sheet.addMergedRegion(new CellRangeAddress(crcm.getFirstRow(), crcm.getLastRow(), crcm.getFirstCol(), crcm.getLastCol()));
  81. }
  82. } catch (DocumentException e) {
  83. e.printStackTrace();
  84. }
  85. //自动调整列宽
  86. for (int i = 0; i < 15; i++) {
  87. sheet.autoSizeColumn((short) i);
  88. }
  89. return wb;
  90. }
  91. /**
  92. * 方法名:makeRowCell
  93. * 功能:生产行内容
  94. * 创建人:tanyp
  95. * 创建时间:2019/9/19 10:01
  96. * 入参:
  97. * tdLs: th或者td集合;
  98. * rowIndex: 行号;
  99. * row: POI行对象;
  100. * startCellIndex;
  101. * cellStyle: 样式;
  102. * crossRowEleMetaLs: 跨行元数据集合
  103. * 出参:
  104. * 修改人:
  105. * 修改时间:
  106. * 修改备注:
  107. */
  108. private static int makeRowCell(List<Element> tdLs, int rowIndex, XSSFRow row, int startCellIndex, XSSFCellStyle cellStyle, List<CrossRangeCellMeta> crossRowEleMetaLs) {
  109. int i = startCellIndex;
  110. for (int eleIndex = 0; eleIndex < tdLs.size(); i++, eleIndex++) {
  111. int captureCellSize = getCaptureCellSize(rowIndex, i, crossRowEleMetaLs);
  112. while (captureCellSize > 0) {
  113. // 当前行跨列处理(补单元格)
  114. for (int j = 0; j < captureCellSize; j++) {
  115. row.createCell(i);
  116. i++;
  117. }
  118. captureCellSize = getCaptureCellSize(rowIndex, i, crossRowEleMetaLs);
  119. }
  120. Element thEle = tdLs.get(eleIndex);
  121. String val = thEle.getTextTrim();
  122. if (StringUtils.isBlank(val)) {
  123. Element e = thEle.element("a");
  124. if (e != null) {
  125. val = e.getTextTrim();
  126. }
  127. }
  128. XSSFCell c = row.createCell(i);
  129. if (NumberUtils.isNumber(val)) {
  130. c.setCellValue(Double.parseDouble(val));
  131. c.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
  132. } else {
  133. c.setCellValue(val);
  134. }
  135. c.setCellStyle(cellStyle);
  136. int rowSpan = NumberUtils.toInt(thEle.attributeValue("rowspan"), 1);
  137. int colSpan = NumberUtils.toInt(thEle.attributeValue("colspan"), 1);
  138. // 存在跨行或跨列
  139. if (rowSpan > 1 || colSpan > 1) {
  140. crossRowEleMetaLs.add(new CrossRangeCellMeta(rowIndex, i, rowSpan, colSpan));
  141. }
  142. // 当前行跨列处理(补单元格)
  143. if (colSpan > 1) {
  144. for (int j = 1; j < colSpan; j++) {
  145. i++;
  146. row.createCell(i);
  147. }
  148. }
  149. }
  150. return i;
  151. }
  152. /**
  153. * 方法名:getCaptureCellSize
  154. * 功能:获得因rowSpan占据的单元格
  155. * 创建人:tanyp
  156. * 创建时间:2019/9/19 10:03
  157. * 入参:
  158. * rowIndex:行号
  159. * colIndex:列号
  160. * crossRowEleMetaLs:跨行列元数据
  161. * 出参:当前行在某列需要占据单元格
  162. * 修改人:
  163. * 修改时间:
  164. * 修改备注:
  165. */
  166. private static int getCaptureCellSize(int rowIndex, int colIndex, List<CrossRangeCellMeta> crossRowEleMetaLs) {
  167. int captureCellSize = 0;
  168. for (CrossRangeCellMeta crossRangeCellMeta : crossRowEleMetaLs) {
  169. if (crossRangeCellMeta.getFirstRow() < rowIndex && crossRangeCellMeta.getLastRow() >= rowIndex) {
  170. if (crossRangeCellMeta.getFirstCol() <= colIndex && crossRangeCellMeta.getLastCol() >= colIndex) {
  171. captureCellSize = crossRangeCellMeta.getLastCol() - colIndex + 1;
  172. }
  173. }
  174. }
  175. return captureCellSize;
  176. }
  177. /**
  178. * 方法名:getTitleStyle
  179. * 功能:获得标题样式
  180. * 创建人:tanyp
  181. * 创建时间:2019/9/19 10:04
  182. * 入参:workbook
  183. * 出参:
  184. * 修改人:
  185. * 修改时间:
  186. * 修改备注:
  187. */
  188. private static XSSFCellStyle getTitleStyle(XSSFWorkbook workbook) {
  189. short titlebackgroundcolor = HSSFColor.GREY_25_PERCENT.index;
  190. short fontSize = 12;
  191. String fontName = "宋体";
  192. XSSFCellStyle style = workbook.createCellStyle();
  193. style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
  194. style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
  195. style.setBorderBottom((short) 1);
  196. style.setBorderTop((short) 1);
  197. style.setBorderLeft((short) 1);
  198. style.setBorderRight((short) 1);
  199. style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
  200. // 背景色
  201. style.setFillForegroundColor(titlebackgroundcolor);
  202. XSSFFont font = workbook.createFont();
  203. font.setFontName(fontName);
  204. font.setFontHeightInPoints(fontSize);
  205. font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
  206. style.setFont(font);
  207. return style;
  208. }
  209. /**
  210. * 方法名:getContentStyle
  211. * 功能:获得内容样式
  212. * 创建人:tanyp
  213. * 创建时间:2019/9/19 10:05
  214. * 入参:HSSFWorkbook
  215. * 出参:
  216. * 修改人:
  217. * 修改时间:
  218. * 修改备注:
  219. */
  220. private static XSSFCellStyle getContentStyle(XSSFWorkbook wb) {
  221. short fontSize = 12;
  222. String fontName = "宋体";
  223. XSSFCellStyle style = wb.createCellStyle();
  224. style.setBorderBottom((short) 1);
  225. style.setBorderTop((short) 1);
  226. style.setBorderLeft((short) 1);
  227. style.setBorderRight((short) 1);
  228. XSSFFont font = wb.createFont();
  229. font.setFontName(fontName);
  230. font.setFontHeightInPoints(fontSize);
  231. style.setFont(font);
  232. return style;
  233. }
  234. }

3、跨行列实体类

  1. package com.demo.model;
  2. /**
  3. * 类名:CrossRangeCellMeta.java
  4. * 路径:com.winner.model.CrossRangeCellMeta.java
  5. * 创建人:tanyp
  6. * 创建时间:2019/9/19 10:00
  7. * 功能:跨行元素元数据
  8. * 修改人:
  9. * 修改时间:
  10. * 修改备注:
  11. */
  12. public class CrossRangeCellMeta {
  13. public CrossRangeCellMeta(int firstRowIndex, int firstColIndex, int rowSpan, int colSpan) {
  14. super();
  15. this.firstRowIndex = firstRowIndex;
  16. this.firstColIndex = firstColIndex;
  17. this.rowSpan = rowSpan;
  18. this.colSpan = colSpan;
  19. }
  20. private int firstRowIndex;
  21. private int firstColIndex;
  22. // 跨越行数
  23. private int rowSpan;
  24. // 跨越列数
  25. private int colSpan;
  26. public int getFirstRow() {
  27. return firstRowIndex;
  28. }
  29. public int getLastRow() {
  30. return firstRowIndex + rowSpan - 1;
  31. }
  32. public int getFirstCol() {
  33. return firstColIndex;
  34. }
  35. public int getLastCol() {
  36. return firstColIndex + colSpan - 1;
  37. }
  38. public int getColSpan() {
  39. return colSpan;
  40. }
  41. }

4、controller调用

  1. /**
  2. * 类名:Html2ExcelController.java
  3. * 路径:com.demo.controller.Html2ExcelController.java
  4. * 创建人:tanyp
  5. * 创建时间:2019/9/19 10:00
  6. * 功能:HTML table导出excel
  7. * 修改人:
  8. * 修改时间:
  9. * 修改备注:
  10. */
  11. @Controller
  12. public class Html2ExcelController {
  13. private static final Logger log = LoggerFactory.getLogger(Html2ExcelController.class);
  14. /**
  15. * 方法名:exportExcel
  16. * 功能:导出
  17. * 创建人:tanyp
  18. * 创建时间:2019/9/19 11:07
  19. * 入参:dataTable
  20. * 出参:
  21. * 修改人:
  22. * 修改时间:
  23. * 修改备注:
  24. */
  25. @RequestMapping("exportExcel")
  26. public void exportExcel(HttpServletRequest request, HttpServletResponse response) {
  27. try {
  28. String dataTable = request.getParameter("dataTable");
  29. String fileName = "测试"+System.currentTimeMillis()+".xls";
  30. // 各浏览器基本都支持ISO编码
  31. String userAgent = request.getHeader("User-Agent").toUpperCase();
  32. if (userAgent.contains("TRIDENT") || userAgent.contains("EDGE")) {
  33. fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
  34. } else if (userAgent.contains("MSIE")) {
  35. fileName = new String(fileName.getBytes(), "ISO-8859-1");
  36. } else {
  37. fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
  38. }
  39. response.addHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", fileName));
  40. OutputStream os = new BufferedOutputStream(response.getOutputStream());
  41. response.setContentType("application/vnd.ms-excel;charset=gb2312");
  42. //将excel写入到输出流中
  43. HSSFWorkbook workbook = Html2Excel.table2Excel(dataTable);
  44. // XSSFWorkbook workbook = XHtml2Excel.table2Excel(dataTable);
  45. workbook.write(os);
  46. os.flush();
  47. os.close();
  48. } catch (Exception e) {
  49. e.printStackTrace();
  50. log.error("请求 exportExcel异常:{}", e.getMessage());
  51. }
  52. }
  53. }

备注:使用两个不同工具类时导包不同(HSSFWorkbook或XSSFWorkbook) 。

5、HTML代码

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <script type="text/javascript" src="js/jquery.js"></script>
  6. </head>
  7. <body>
  8. <div onclick="download()">导出</div>
  9. <div id="DateTable" style="overflow-x:scroll">
  10. <table id="myTable" class="gridtable w2000"><thead><tr><th rowspan="2" style="min-width: 100px; max-width: 100px;width: 100px;">名称</th><th rowspan="2" style="min-width: 80px; max-width: 80px;width: 80px;">客流总量(人次)</th><th rowspan="2" style="min-width: 80px; max-width: 80px;width: 80px;">编码</th><th rowspan="2" style="min-width: 80px; max-width: 80px;width: 80px;">单客流总量(人次)</th><th colspan="3">时段客流(人次)</th></tr><tr><th style="min-width: 80px; max-width: 80px;width: 80px;">01:05</th><th style="min-width: 80px; max-width: 80px;width: 80px;">01:10</th><th style="min-width: 80px; max-width: 80px;width: 80px;">01:15</th></tr></thead><tbody id="pointBasedDateTbody"><tr><td rowspan="2">购物一号门</td><td rowspan="2">5006</td><td>C001</td><td>3006</td><td>0</td><td>0</td><td>0</td></tr><tr><td>C002</td><td>2000</td><td>0</td><td>0</td><td>0</td></tr><tr><td rowspan="2">购物二号门</td><td rowspan="2">2796</td><td>C001</td><td>1542</td><td>0</td><td>0</td><td>0</td></tr><tr><td>C002</td><td>1254</td><td>0</td><td>0</td><td>0</td></tr><tr><td rowspan="1">购物三号门</td><td rowspan="1">1654</td><td>C005</td><td>1654</td><td>0</td><td>0</td><td>0</td></tr><tr><td rowspan="1">购物四号门</td><td rowspan="1">54365</td><td>C001</td><td>54365</td><td>0</td><td>0</td><td>0</td></tr></tbody></table>
  11. </div>
  12. <form action="exportExcel" id="exportExcle" method="POST">
  13. <input type="hidden" name="dataTable" id="dataTable">
  14. </form>
  15. </body>
  16. <script>
  17. function download() {
  18. var html = $("#tables").html();
  19. $("#dataTable").val(html);
  20. $("#exportExcle").submit();
  21. };
  22. </script>
  23. </html>

6、效果图

 

欢迎关注

 

posted on 2022-03-22 21:19  sunny123456  阅读(661)  评论(0编辑  收藏  举报