1. 程式人生 > >【設計模式】模板模式實現報表模板

【設計模式】模板模式實現報表模板

需求:報表生產都大同小異,流程一樣,但是具體的實現不同(如資料不同,報表名不同,報表列不同)。

如果每一次報表都複製貼上就太碼農。所以很自然的想到了模板模式。

設計:

        1.抽象類包含方法createReport(流程方法,既建立報表,生產表頭,將資料放入報表中,生產報表)

        2.抽象方法(各個報表不同的實現):

                        getReportName:獲取報表名

                        getCloumName:獲取列名生產表頭

                        getReportData:獲取資料

使用:

        1.繼承此類,實現抽象方法。呼叫createReport方法即可生成報表

        2.預設生成的報表規則是根據類的屬性順序對應報表列順序(表達能力欠缺,沒關係直接看下圖)


        3.提供方法getDataCloumName(),可重寫此方法指定順序列,此方法返回List<String> 。

        例:指定返回值為[b,a,c,d],則生成的報表如下


    4.若物件中含有Date型別,會預設轉換為"yyyy-MM-dd HH:mm:ss"。若想修改Date型別的格式可重寫getDateFormate方法。

程式碼:

package com.gls.manage.service;
import com.gls.pojo.Admin; import org.apache.poi.hssf.usermodel.*; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletWebRequest; import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @Author Stephen Hu * @Description //TODO 報表模板 * 繼承此類 提供報表名 列名 報表資料 即可生成報表 * @Date 15:26 2018/7/4 **/ public abstract class ReportTemplateService<T> { private static final String defualtDateFormate = "yyyy-MM-dd HH:mm:ss"; public void createReport(HttpServletResponse response){ try { //獲取報表名 String reportName = getReportName(); //獲取列名 List<String> cloumName = getCloumName(); //獲取報表資料 List<T> reportData = getReportData(); HSSFWorkbook hssfWorkbook = new HSSFWorkbook(); HSSFSheet sheet = hssfWorkbook.createSheet(); //設定表頭 setReportHead(hssfWorkbook, sheet, cloumName); //填充資料 setReportData(hssfWorkbook, sheet, reportData, cloumName); //返回報表 String codedFileName = java.net.URLEncoder.encode(reportName, "UTF-8"); response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-disposition", "attachment;filename=" + codedFileName + ".xlsx"); OutputStream ouputStream = response.getOutputStream(); hssfWorkbook.write(ouputStream); ouputStream.flush(); ouputStream.close(); }catch (Exception e){ e.printStackTrace(); } } private void setReportData(HSSFWorkbook hssfWorkbook,HSSFSheet sheet,List<T> reportData,List<String> cloumName){ if(reportData.isEmpty()){ return; } List<String> dataCloumName = getDataCloumName(); //無序列指定 if(dataCloumName==null||dataCloumName.isEmpty()){ noOraderSetReportData(hssfWorkbook,sheet,reportData,cloumName); }else{//有序列指定 oraderSetReportData(hssfWorkbook,sheet,reportData,cloumName,dataCloumName); } } private void oraderSetReportData(HSSFWorkbook hssfWorkbook,HSSFSheet sheet,List<T> reportData,List<String> cloumName,List<String> dataCloumName){ //行迴圈 for (int i = 0; i < reportData.size(); i++) { HSSFRow row = sheet.createRow(i + 1); //列迴圈 T data = reportData.get(i); for (int j = 0; j <cloumName.size();j++ ) { Object value = getGetMethodValue(data, dataCloumName.get(j)); if (value==null){ continue; } //如果為Date型別則轉換為字串 if("Date".equals(value.getClass().getSimpleName())){ value = Date2String(value); } HSSFCell cell = row.createCell(j); cell.setCellValue(value.toString()); //設定列的樣式 cell.setCellStyle(getCellStyle(hssfWorkbook)); //設定列的寬度 sheet.setColumnWidth(j, value.toString().getBytes().length*2*256); } } } private void noOraderSetReportData(HSSFWorkbook hssfWorkbook,HSSFSheet sheet,List<T> reportData,List<String> cloumName){ Class<?> aClass1 = reportData.get(0).getClass(); //獲取類中所有的屬性 Field[] declaredFields = aClass1.getDeclaredFields(); //行迴圈 for (int i = 0; i < reportData.size(); i++) { HSSFRow row = sheet.createRow(i + 1); //列迴圈 T data = reportData.get(i); for (int j = 0,k=0; j <cloumName.size();k++ ) { Object value = getGetMethodValue(data, declaredFields[k].getName()); if (value==null){ continue; } //如果為Date型別則轉換為字串 if("Date".equals(declaredFields[k].getType().getSimpleName())){ value = Date2String(value); } HSSFCell cell = row.createCell(j); cell.setCellValue(value.toString()); //設定列的樣式 cell.setCellStyle(getCellStyle(hssfWorkbook)); //設定列的寬度 sheet.setColumnWidth(j, 5000); j++; } } } private String Date2String(Object value){ String dateFormate = getDateFormate(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormate); return simpleDateFormat.format(value); } private Object getGetMethodValue(T data,String methodName){ if("serialVersionUID".equals(methodName)){ return null; } Object value = null; //獲取物件get方法 Class<?> aClass = data.getClass(); methodName = ("get"+methodName.substring(0,1).toUpperCase()+methodName.substring(1)); try { Method method = aClass.getMethod(methodName); value = method.invoke(data); } catch (Exception e) { e.printStackTrace(); } return value; } /** * @Author Stephen Hu * @Description //TODO 設定報表頭 * @Date 15:52 2018/7/4 * @Param [hssfWorkbook, sheet, cloumName] * @return void **/ private void setReportHead(HSSFWorkbook hssfWorkbook,HSSFSheet sheet,List<String> cloumName){ HSSFRow row = sheet.createRow(0); for (int i = 0; i < cloumName.size(); i++) { //建立列 HSSFCell cell = row.createCell(i); cell.setCellValue(cloumName.get(i)); //設定列的樣式 cell.setCellStyle(getCellStyle(hssfWorkbook)); //設定列的寬度 sheet.setColumnWidth(i, cloumName.get(i).getBytes().length*2*256); } } /** * @Author Stephen Hu * @Description //TODO 獲取樣式 * @Date 15:52 2018/7/4 * @Param [hssfWorkbook] * @return org.apache.poi.hssf.usermodel.HSSFCellStyle **/ private HSSFCellStyle getCellStyle(HSSFWorkbook hssfWorkbook){ //建立設定屬性物件 HSSFCellStyle CellStyle = hssfWorkbook.createCellStyle(); //設定居中 CellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); CellStyle.setAlignment(HSSFCellStyle.ALIGN_RIGHT); CellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下邊框 CellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左邊框 CellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上邊框 CellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右邊框 //設定字型 HSSFFont font = hssfWorkbook.createFont(); font.setFontName("微軟雅黑"); font.setFontHeightInPoints((short) 12);//設定字型大小 CellStyle.setFont(font); return CellStyle; } public abstract String getReportName(); public abstract List<String> getCloumName(); public abstract List<T> getReportData(); /** * @Author Stephen Hu * @Description //TODO * 1.此方法不重寫 預設按照物件的屬性順序對應表頭 * 例: * 表頭 A B C * 類屬性 private int id; private String name;private int age; * 則對應: A B C * id值 name值 age值 * 2.此方法重寫 按照此方法指定的類屬性順序對應表頭 * 例: * 表頭 A B C * 類屬性 private int id; private String name;private int age; * 重寫方法返回的list ["name","id","age"] * 則對應:A B C * name值 id值 age值 * @Date 17:47 2018/7/4 * @Param [] * @return java.util.List<java.lang.String> **/ public List<String> getDataCloumName(){return null;}; /** * @Author Stephen Hu * @Description //TODO 如有date型別需要轉成相應的格式 預設格式yyyy-MM-dd * @Date 18:13 2018/7/4 * @Param [dateFormate] * @return java.lang.String **/ public String getDateFormate(){ return defualtDateFormate; } }

基本功能都實現了 ,只是還有很多細節需要優化 。

若有好的建議或者疑問歡迎加群:474586959