Java导出报表

1.场景描述

  使用java实现导出excel报表。使用Apache POI。

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

2.Maven依赖

 


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

 

3.代码编写

3.1导出报表类

 


  
  
  1. import com.nnkc.util.ExcelUtil;
  2. import org.apache.commons.lang.StringUtils;
  3. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  4. import org.apache.poi.xssf.streaming.SXSSFWorkbook;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.io.OutputStream;
  9. import java.net.URLEncoder;
  10. import java.util.List;
  11. /**
  12. *功能描述:导出报表
  13. */
  14. public class ReportExcel {
  15. /**
  16. * 功能: Excel导出公共方法
  17. * 记录条数大于50000时 导出.xlsx文件(excel07+) 小于等于50000时导出 .xls文件(excel97-03)
  18. * 开发:wangkecheng
  19. * @param list 需要导出的列表数据
  20. * @param title 导出文件的标题
  21. * @param className 导出对象的类名
  22. * @param exportType 针对同一个pojo可能有多个不同的导出模板时,可以通过此属性来决定导出哪一套模板,默认第一套
  23. * @param response 用来获取输出流
  24. * @param request 针对火狐浏览器导出时文件名乱码的问题,也可以不传入此值
  25. * @throws IOException
  26. */
  27. public void excelExport(List list, String title, Class className, Integer exportType, HttpServletResponse response, HttpServletRequest request) throws IOException {
  28. OutputStream out = response.getOutputStream();
  29. try {
  30. ExcelUtil excel = new ExcelUtil();
  31. if(list!=null && list.size()>ExcelUtil.EXPORT_07_LEAST_SIZE){
  32. dealBigNumber(list, title, className, exportType, response, request, out, excel);
  33. }else{
  34. HSSFWorkbook hss = new HSSFWorkbook();
  35. if(exportType==null){
  36. hss = excel.exportExcel(list,title,className,0);
  37. }else{
  38. hss = excel.exportExcel(list, title, className, exportType);
  39. }
  40. String disposition = "attachment;filename=";
  41. if(request!=null&&request.getHeader("USER-AGENT")!=null&& StringUtils.contains(request.getHeader("USER-AGENT"), "Firefox")){
  42. disposition += new String((title+".xls").getBytes(),"ISO8859-1");
  43. }else{
  44. disposition += URLEncoder.encode(title+".xls", "UTF-8");
  45. }
  46. response.setContentType("application/vnd.ms-excel;charset=UTF-8");
  47. response.setHeader("Content-disposition", disposition);
  48. hss.write(out);
  49. }
  50. } catch (Exception e) {
  51. System.out.println(e.getMessage());
  52. } finally {
  53. out.close();
  54. }
  55. }
  56. private void dealBigNumber(List list, String title, Class className, Integer exportType,
  57. HttpServletResponse response, HttpServletRequest request, OutputStream out, ExcelUtil excel)
  58. throws Exception{
  59. SXSSFWorkbook hss;
  60. if(exportType==null){
  61. hss = excel.exportExcel07S(list,title,className,0);
  62. }else{
  63. hss = excel.exportExcel07S(list, title, className, exportType);
  64. }
  65. String disposition = "attachment;filename=";
  66. if(request!=null && request.getHeader("USER-AGENT") != null && StringUtils.contains(request.getHeader("USER-AGENT"), "Firefox")){
  67. disposition += new String((title+".xlsx").getBytes(),"ISO8859-1");
  68. }else{
  69. disposition += URLEncoder.encode(title+".xlsx", "UTF-8");
  70. }
  71. response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
  72. response.setHeader("Content-disposition", disposition);
  73. hss.write(out);
  74. }
  75. }

 

3.2工具类

 


  
  
  1. import org.apache.poi.hssf.usermodel.*;
  2. import org.apache.poi.hssf.util.HSSFColor;
  3. import org.apache.poi.ss.usermodel.*;
  4. import org.apache.poi.ss.util.CellRangeAddress;
  5. import org.apache.poi.xssf.streaming.SXSSFWorkbook;
  6. import org.apache.poi.xssf.usermodel.XSSFRichTextString;
  7. import java.lang.reflect.Field;
  8. import java.lang.reflect.InvocationTargetException;
  9. import java.lang.reflect.Method;
  10. import java.text.SimpleDateFormat;
  11. import java.util.*;
  12. /**
  13. * excel工具类
  14. * @author wangkecheng
  15. * @param <T>
  16. */
  17. public class ExcelUtil <T> {
  18. public static final int EXPORT_07_LEAST_SIZE = 50000;
  19. /**
  20. * 功能 :获取表单导出数据
  21. * 开发:wangkecheng
  22. * @param list 数据列表
  23. * @param title 首行标题
  24. * @param className 实体对象class
  25. * @param exportType 模板标号
  26. * @return
  27. * @throws Exception
  28. */
  29. public HSSFWorkbook exportExcel(List <T> list, String title, Class className,Integer exportType) throws Exception {
  30. // 获取属性
  31. Field[] fields = className.getDeclaredFields();
  32. List <Field> fieldList = new ArrayList <Field>();
  33. for (Field fie : fields) {
  34. if (fie.isAnnotationPresent(ExcelAnnotation.class)) {
  35. fieldList.add(fie);
  36. }
  37. }
  38. // 按照id进行排序
  39. Collections.sort(fieldList, new Comparator <Field>() {
  40. public int compare(Field f1, Field f2) {
  41. return f1.getAnnotation(ExcelAnnotation.class).id() - f2.getAnnotation(ExcelAnnotation.class).id();
  42. }
  43. });
  44. int columnsize = fieldList.size(), rowindex = 0;
  45. // 创建一个HSSFWorbook对象(excel的文档对象)
  46. HSSFWorkbook hWorkbook = new HSSFWorkbook();
  47. // 创建一个HSSFSheet对象(excll的表单)
  48. HSSFSheet hSheet = hWorkbook.createSheet();
  49. // 创建行(excel的行)
  50. HSSFRow hRow = hSheet.createRow(rowindex++);
  51. //设置行高度
  52. hRow.setHeight((short)380);
  53. // 创建单元格(从0开始)
  54. HSSFCell hCell = hRow.createCell((short) 0);
  55. //样式对象
  56. HSSFCellStyle cellStyle = getCellStyle(hWorkbook, (short) 300, (short) 500);
  57. // 将上面获得的样式对象给对应单元格
  58. hCell.setCellStyle(cellStyle);
  59. //设置标题行
  60. hCell.setCellValue(title);
  61. if (getHuoResult(fieldList.isEmpty(),list == null,list.isEmpty())) {
  62. return hWorkbook;
  63. }
  64. //创建第二行,代表列名
  65. hRow = hSheet.createRow(rowindex++);
  66. cellStyle = getCellStyle(hWorkbook, (short) 270, (short) 500);
  67. generateTitle(exportType, fieldList, columnsize, hSheet, hRow, cellStyle);
  68. //组装excel的数据
  69. cellStyle = getCellStyle(hWorkbook, (short) 220, (short) 500);// 设置单元格格式
  70. generateData(list, fieldList, columnsize, rowindex, hSheet, cellStyle);
  71. /**
  72. * 第1个参数:从哪一行开始
  73. * 第2个参数:到哪一行结束
  74. * 第3个参数:从哪一列开始
  75. * 第4个参数:到哪一列结束
  76. */
  77. hSheet.addMergedRegion(new CellRangeAddress(0,0,0,columnsize-1));
  78. // 固定表头(前一个参数代表列,后一个参数单表行)
  79. hSheet.createFreezePane(0, 1);
  80. return hWorkbook;
  81. }
  82. /**
  83. * 功能:組裝列明
  84. * @param exportType 模板编号
  85. * @param fieldList 列名
  86. * @param columnsize 列数
  87. * @param hSheet sheet页
  88. * @param hRow 行
  89. * @param cellStyle 样式
  90. */
  91. private void generateTitle(Integer exportType, List <Field> fieldList, int columnsize, HSSFSheet hSheet, HSSFRow hRow,
  92. HSSFCellStyle cellStyle) {
  93. HSSFCell hCell;
  94. for (int i = 0; i < columnsize; i++) {
  95. Field field = fieldList.get(i);
  96. if (field.isAnnotationPresent(ExcelAnnotation.class)) {
  97. // 获取该字段的注解对象
  98. ExcelAnnotation anno = field.getAnnotation(ExcelAnnotation.class);
  99. hCell = hRow.createCell((short) i);
  100. String colName = field.getAnnotation(ExcelAnnotation.class).name().length>exportType
  101. ?field.getAnnotation(ExcelAnnotation.class).name()[exportType]
  102. :field.getAnnotation(ExcelAnnotation.class).name()[0];
  103. hCell.setCellValue(colName);
  104. hCell.setCellStyle(cellStyle);
  105. hSheet.setColumnWidth((short) i, (short) anno.width());
  106. }
  107. }
  108. }
  109. /**
  110. * 组装excel的数据
  111. * @param list 具体数据
  112. * @param fieldList 列名
  113. * @param columnsize 列数
  114. * @param rowindex 行数计数
  115. * @param hSheet sheet页
  116. * @param cellStyle 样式
  117. * @return
  118. * @throws NoSuchMethodException
  119. * @throws IllegalAccessException
  120. * @throws InvocationTargetException
  121. */
  122. private int generateData(List <T> list, List <Field> fieldList, int columnsize, int rowindex, HSSFSheet hSheet,
  123. HSSFCellStyle cellStyle) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
  124. HSSFRow hRow;
  125. HSSFCell hCell;
  126. for (Object model : list) {
  127. hRow = hSheet.createRow(rowindex++);
  128. //获取该类
  129. Class clazz = model.getClass();
  130. for (int i = 0; i < columnsize; i++) {
  131. Field field =fieldList.get(i);
  132. //获取方法名
  133. String methodName = "get" + field.getName().substring(0, 1).toUpperCase()+field.getName().substring(1);
  134. Method method = clazz.getMethod(methodName);
  135. try {
  136. // 获取该字段的注解对象
  137. Object result = method.invoke(model);
  138. hCell = hRow.createCell((short) i);
  139. if (result != null) {
  140. if (result.getClass().isAssignableFrom(Date.class)) {
  141. SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd日");
  142. result = format.format(result);
  143. }
  144. hCell.setCellValue(new HSSFRichTextString(result.toString()));
  145. } else {
  146. hCell.setCellValue(new HSSFRichTextString("-"));
  147. }
  148. hCell.setCellStyle(cellStyle);
  149. } catch (IllegalArgumentException e) {
  150. System.out.println(e.getMessage());
  151. }
  152. }
  153. }
  154. return rowindex;
  155. }
  156. /**
  157. * 生成07格式的excel对象 使用流方式防止内存溢出
  158. * @param list
  159. * @param title
  160. * @param className
  161. * @param exportType
  162. * @return
  163. * @throws Exception
  164. */
  165. public SXSSFWorkbook exportExcel07S(List<T> list, String title, Class className,Integer exportType) throws Exception {
  166. // 获取属性
  167. Field[] fields = className.getDeclaredFields();
  168. List <Field> fieldList = new ArrayList <Field>();
  169. for (Field fie : fields) {
  170. if (fie.isAnnotationPresent(ExcelAnnotation.class)){
  171. fieldList.add(fie);
  172. }
  173. }
  174. // 按照id进行排序
  175. Collections.sort(fieldList, new Comparator <Field>() {
  176. public int compare(Field f1, Field f2) {
  177. return f1.getAnnotation(ExcelAnnotation.class).id() - f2.getAnnotation(ExcelAnnotation.class).id();
  178. }
  179. });
  180. int columnsize = fieldList.size(), rowindex = 0;
  181. // 创建一个HSSFWorbook对象s
  182. SXSSFWorkbook hWorkbook = new SXSSFWorkbook();
  183. // 创建一个HSSFSheet对象(sheet页)
  184. Sheet hSheet = hWorkbook.createSheet();
  185. // 创建第一行(此行作为头)
  186. Row hRow = hSheet.createRow(rowindex++);
  187. hRow.setHeight((short)380);
  188. // 创建单元格(第一(0)个)
  189. Cell hCell = hRow.createCell((short) 0);
  190. // 设置样式
  191. CellStyle cellStyle = getCellStyle07S(hWorkbook, (short) 300, (short) 500);
  192. // 将上面获得的样式对象给对应单元格
  193. hCell.setCellStyle(cellStyle);
  194. //设置标题行
  195. hCell.setCellValue(title);
  196. if (getHuoResult(fieldList.isEmpty(),list == null,list.isEmpty())) {
  197. return hWorkbook;
  198. }
  199. // 创建第二列,列名
  200. hRow = hSheet.createRow(rowindex++);
  201. cellStyle = getCellStyle07S(hWorkbook, (short) 270, (short) 500);
  202. createTitle07S(exportType, fieldList, columnsize, hSheet, hRow, cellStyle);
  203. //生成数据
  204. cellStyle = getCellStyle07S(hWorkbook, (short) 220, (short) 500);// 设置单元格格式
  205. dealCreateRow07S(list, fieldList, columnsize, rowindex, hSheet, cellStyle);
  206. /**
  207. * 第1个参数:从哪一行开始
  208. * 第2个参数:到哪一行结束
  209. * 第3个参数:从哪一列开始
  210. * 第4个参数:到哪一列结束
  211. */
  212. hSheet.addMergedRegion(new CellRangeAddress(0,0,0,columnsize-1));
  213. // 固定表头(前一个参数代表列,后一个参数单表行)
  214. hSheet.createFreezePane(0, 1);
  215. return hWorkbook;
  216. }
  217. private int dealCreateRow07S(List <T> list, List <Field> fieldList, int columnsize, int rowindex, Sheet hSheet,
  218. CellStyle cellStyle) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
  219. Row hRow;
  220. Cell hCell;
  221. for (Object model : list) {
  222. hRow = hSheet.createRow(rowindex++);
  223. // 获取该类 并获取自身方法
  224. Class clazz = model.getClass();
  225. for (int i = 0; i < columnsize; i++) {
  226. Field field = fieldList.get(i);
  227. String methodName = "get" + field.getName().substring(0, 1).toUpperCase()
  228. + field.getName().substring(1);
  229. Method method = clazz.getMethod(methodName);
  230. try {
  231. // 获取该字段的注解对象
  232. Object result = method.invoke(model);
  233. hCell = hRow.createCell((short) i);
  234. if (result != null) {
  235. if (result.getClass().isAssignableFrom(Date.class)) {
  236. SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd日");
  237. result = format.format(result);
  238. }
  239. hCell.setCellValue(new XSSFRichTextString(result.toString()));
  240. } else {
  241. hCell.setCellValue(new XSSFRichTextString("-"));
  242. }
  243. hCell.setCellStyle(cellStyle);
  244. } catch (IllegalArgumentException e) {
  245. System.out.println(e.getMessage());
  246. }
  247. }
  248. }
  249. return rowindex;
  250. }
  251. /**
  252. * 生成列名
  253. * @param exportType 模板编号
  254. * @param fieldList 列名
  255. * @param columnsize 列数
  256. * @param hSheet
  257. * @param hRow
  258. * @param cellStyle
  259. */
  260. private void createTitle07S(Integer exportType, List<Field> fieldList, int columnsize, Sheet hSheet, Row hRow,
  261. CellStyle cellStyle) {
  262. Cell hCell;
  263. for (int i = 0; i < columnsize; i++) {
  264. Field field = (Field) fieldList.get(i);
  265. if (field.isAnnotationPresent(ExcelAnnotation.class)) {
  266. // 获取该字段的注解对象
  267. ExcelAnnotation anno = field.getAnnotation(ExcelAnnotation.class);
  268. hCell = hRow.createCell((short) i);
  269. String colName = field.getAnnotation(ExcelAnnotation.class).name().length>exportType
  270. ?field.getAnnotation(ExcelAnnotation.class).name()[exportType]
  271. :field.getAnnotation(ExcelAnnotation.class).name()[0];
  272. hCell.setCellValue(colName);
  273. hCell.setCellStyle(cellStyle);
  274. hSheet.setColumnWidth((short) i, (short) anno.width());
  275. }
  276. }
  277. }
  278. /**
  279. * 功能 :设置excel表格默认样式
  280. * @param hWorkbook 需导出Excel数据
  281. * @param fontHeight 字体粗度
  282. * @param boldWeight 表格线的粗度
  283. * @return
  284. */
  285. public HSSFCellStyle getCellStyle(HSSFWorkbook hWorkbook, short fontHeight, short boldWeight) {
  286. HSSFCellStyle cellStyle;
  287. HSSFFont font;
  288. cellStyle = hWorkbook.createCellStyle();
  289. cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
  290. cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
  291. cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
  292. cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
  293. cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
  294. cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
  295. cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
  296. cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
  297. font = hWorkbook.createFont();
  298. font.setFontHeight(fontHeight);
  299. font.setBoldweight(boldWeight);
  300. font.setFontName("宋体");
  301. cellStyle.setFont(font);
  302. cellStyle.setWrapText(true);
  303. cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
  304. cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
  305. return cellStyle;
  306. }
  307. /**
  308. * 功能 :设置excel 07表格默认样式
  309. * @param hWorkbook 需导出Excel数据
  310. * @param fontHeight 字体粗度
  311. * @param boldWeight 表格线的粗度
  312. * @return
  313. */
  314. public CellStyle getCellStyle07S(SXSSFWorkbook hWorkbook, short fontHeight, short boldWeight) {
  315. CellStyle cellStyle;
  316. Font font;
  317. cellStyle = hWorkbook.createCellStyle();
  318. cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
  319. cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
  320. cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
  321. cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
  322. cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
  323. cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
  324. cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
  325. cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
  326. font = hWorkbook.createFont();
  327. font.setFontHeight(fontHeight);
  328. font.setBoldweight(boldWeight);
  329. font.setFontName("宋体");
  330. cellStyle.setFont(font);
  331. cellStyle.setWrapText(true);
  332. cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
  333. cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
  334. return cellStyle;
  335. }
  336. /*
  337. * 获取或运算结果
  338. */
  339. private static boolean getHuoResult(Boolean... bs){
  340. for(boolean b:bs){
  341. if(b){
  342. return b;
  343. }
  344. }
  345. return false;
  346. }
  347. }

复制代码

3.3注解类

 


  
  
  1. import java.lang.annotation.*;
  2. /**
  3. * <p>
  4. * 功能:excel模板设置
  5. * </p>
  6. */
  7. @Documented
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Target(ElementType.FIELD)
  10. public @interface ExcelAnnotation {
  11. //Excel列ID(Excel列排序序号)
  12. int id();
  13. //Excel列名
  14. String[] name();
  15. //Excel列宽
  16. int width() default 5000;
  17. }

 

3.4pojo对象

 


  
  
  1. import com.nnkc.util.ExcelAnnotation;
  2. import java.util.Date;
  3. /**
  4. * Created by chengcheng on 2017/12/5.
  5. */
  6. public class Product {
  7. @ExcelAnnotation(id=1,name={"产品名称","商品名称"},width = 5000)
  8. private String name;
  9. @ExcelAnnotation(id=2,name={"产品价格","商品价格"},width = 5000)
  10. private double price;
  11. @ExcelAnnotation(id=3,name={"生产日期"},width = 5000)
  12. private Date date;
  13. public String getName() {
  14. return name;
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. public double getPrice() {
  20. return price;
  21. }
  22. public void setPrice(double price) {
  23. this.price = price;
  24. }
  25. public Date getDate() {
  26. return date;
  27. }
  28. public void setDate(Date date) {
  29. this.date = date;
  30. }
  31. }

 

3.5测试类

 


  
  
  1. import com.nnkc.pojo.Product;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.http.HttpServlet;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import java.io.IOException;
  7. import java.util.ArrayList;
  8. import java.util.Date;
  9. import java.util.List;
  10. /**
  11. * Created by chengcheng on 2017/12/5.
  12. */
  13. public class ReportExcelTest extends HttpServlet {
  14. @Override
  15. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  16. System.out.println("调用成功");
  17. }
  18. @Override
  19. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  20. List <Product> list = new ArrayList <Product>();
  21. for (int i = 0 ; i <60000 ; i++) {
  22. //组装测试数据
  23. Product product = new Product();
  24. product.setName("爱奇艺会员"+i);
  25. product.setPrice(9.99);
  26. product.setDate(new Date());
  27. list.add(product);
  28. }
  29. ReportExcel reportExcel = new ReportExcel();
  30. reportExcel.excelExport(list,"测试",Product.class,1,resp,req);
  31. }
  32. }

 

3.5测试结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值