poi對Excel報表的自動化
工作中經常會有一些daily的報告,每次的格式都是一樣的,來源也基本都是資料庫的表,每次要自己去貼上很麻煩。
嘗試過python以及sas等工具或者包,python的xlrd等系列不支援07以後的excel檔案,openpyxl在替換資料後容易莫名的失去cell的格式,sas第一是收費,第二也是隻支援03版本的excel。好在還是可以通過poi來處理。
本篇主要只記錄下幾個函式,以及處理的思路,預設各位已經完成了Spring + Mybatis的搭。
首先使用maybatis可以忽略ORM。因為如果是長期相同的sql給個對應的物件還可以,但是一旦經常欄位變動搞起來也很麻煩,mybatis是可以將查詢結果返回為一個HashMap的,所以我就直接使用LinkedHashMap。
<select id="test" resultType="java.util.LinkedHashMap">
sql語句
</select>
//流式資料,優先選用 public static SXSSFWorkbook createWorkbookWithoutBean2(List<LinkedHashMap<String, Object>> list, Object adb){ SXSSFWorkbook workbook = new SXSSFWorkbook(1000); SXSSFSheet sheet = workbook.createSheet("sheet"); SXSSFRow row = sheet.createRow(0); //從第一行開始寫入bean的具體資訊 SXSSFCell cell = row.createCell(0); cell.setCellValue(adb.toString()); row = sheet.createRow(1); if(list.size()!=0) try { //獲得所有的key值並將其匯入一個ArrayList中 LinkedHashMap<String, Object> map = list.get(0); //得到第一個map,然後獲得所有的key Set keySet = map.keySet(); Iterator<String> iterator = keySet.iterator(); ArrayList<String> keys = new ArrayList<String>(); while(iterator.hasNext()){ keys.add(iterator.next()); } //寫入列名 for(int i=0; i<keys.size(); i++){ cell = row.createCell(i); cell.setCellValue(keys.get(i)); } //寫入值 int rowIndex = 2; Iterator<LinkedHashMap<String, Object>> iter1 = list.iterator(); while(iter1.hasNext()){ row = sheet.createRow(rowIndex++); map = iter1.next(); for(int i=0; i<keys.size(); i++){ cell = row.createCell(i); if(map.get(keys.get(i)) != null){ String name = map.get(keys.get(i)).getClass().getName(); if(name.equals("java.math.BigDecimal")){ BigDecimal bigDecimal = (BigDecimal) map.get(keys.get(i)); cell.setCellValue(bigDecimal.doubleValue()); }else if(name.equals("java.sql.Timestamp")){ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//定義格式,不顯示毫秒 String str = df.format((Timestamp)map.get(keys.get(i))); cell.setCellValue(str); }else if(name.equals("java.lang.Integer")||name.equals("java.sql.Integer")){ cell.setCellValue((Integer)map.get(keys.get(i))); }else{ cell.setCellValue((String)map.get(keys.get(i))); } } } } return workbook; }catch(Exception e){ e.printStackTrace(); } return workbook;
上面這個函式假設你已經通過mabatis查詢的到一個返回的map物件,那麼呼叫後就可以直接得到一個新的SXSSFWorkBook物件,這是poi中用於大資料匯出的物件,接收也很簡單,在main裡面new一個XSSFWorkBook接收就可以了。
/** * * @param wb * @param sheetName * @param sql 不是真正意義上的sql,而是你sql對應的mapper.xml檔案裡面的id * @param start_line excel如果是模板的話,資料要從第二行開始替換 * @param sqlParam 查詢的引數 Object物件,和mapper.xml裡面的對應 * @return */ public static synchronized XSSFWorkbook replaceSheet(XSSFWorkbook wb, String sheetName, String sql, int start_line, String sqlParam){ try { XSSFSheet sheet = wb.getSheet(sheetName); int lastRow = sheet.getLastRowNum(); XSSFRow row; XSSFCell cell; XSSFCellStyle style = wb.createCellStyle(); row = sheet.getRow(start_line-1); int rowIndex = start_line-1; if(row.getCell(0)!=null){ style = row.getCell(0).getCellStyle(); }else{ style.setBorderBottom(BorderStyle.THIN); style.setBorderTop(BorderStyle.THIN); style.setBorderLeft(BorderStyle.THIN); style.setBorderRight(BorderStyle.THIN); } for(int i=start_line-1; i<=lastRow; i++){ row = sheet.getRow(i); if(row!=null){ myRemoveRow(sheet, row); } }//刪除完成 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); System.out.println(sql); System.out.println(sqlParam); List<LinkedHashMap<String,Object>> list = session.selectList(sql, sqlParam); System.out.println(list.size()); if(list.size()!=0){ LinkedHashMap<String, Object> map = list.get(0); Set keySet = map.keySet(); Iterator<String> iterator = keySet.iterator(); ArrayList<String> keys = new ArrayList<String>(); while(iterator.hasNext()){ keys.add(iterator.next()); } //寫入列名 Iterator<LinkedHashMap<String, Object>> iter1 = list.iterator(); while(iter1.hasNext()){ row = sheet.createRow(rowIndex++); map = iter1.next(); for(int i=0; i<keys.size(); i++){ cell = row.createCell(i); if(map.get(keys.get(i)) != null){ String name = map.get(keys.get(i)).getClass().getName(); if(name.equals("java.math.BigDecimal")){ BigDecimal bigDecimal = (BigDecimal) map.get(keys.get(i)); cell.setCellValue(bigDecimal.doubleValue()); }else if(name.equals("java.sql.Timestamp")){ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//定義格式,不顯示毫秒 String str = df.format((Timestamp)map.get(keys.get(i))); cell.setCellValue(str); }else if(name.equals("java.lang.Integer")||name.equals("java.sql.Integer")){ cell.setCellValue((Integer)map.get(keys.get(i))); }else{ cell.setCellValue((String)map.get(keys.get(i))); } } cell.setCellStyle(style); } } } } catch (Exception e) { e.printStackTrace(); } return wb; } private static synchronized void myRemoveRow(XSSFSheet sheet, Row row) { sheet.removeRow(row); }
這個是用於替換模板裡面的sheet的,因為可能報表的形式不變,後面隱藏的sheet作為對映到前面的資料(就是顯示的sheet全是公式,實際的資料在後面hide的sheet裡面)。開始行選1就是全sheet替換,選2就是從第二行開始刪除替換,這裡有個style樣式的問題,建議使用模板的時候,第一行為欄位的名字,第二行為樣例的資料。返回的物件一樣用XSSFWorkbook接收。
最後資料重新整理了以後需要重新整理的是公式,poi自動生成資料後你開啟excel,很容易發現作為公式的數值並不會自己重新整理,所以還有一個函式用於重新整理公式
public static void updateFormula(Workbook wb){
for(int sheet_index=0;sheet_index<wb.getNumberOfSheets();sheet_index++){
Sheet s = wb.getSheetAt(sheet_index);
int maxRow = s.getLastRowNum();
Row r;
for(int row_index=0; row_index<=maxRow; row_index++){
r=s.getRow(row_index);
if(r!=null){
Cell c=null;
XSSFFormulaEvaluator eval=null;
if(wb instanceof XSSFWorkbook)
eval=new XSSFFormulaEvaluator((XSSFWorkbook) wb);
else if(wb instanceof XSSFWorkbook)
eval=new XSSFFormulaEvaluator((XSSFWorkbook) wb);
for(int i=r.getFirstCellNum();i<r.getLastCellNum();i++){
c=r.getCell(i);
if(c != null)
if(c.getCellType()==Cell.CELL_TYPE_FORMULA)
eval.evaluateFormulaCell(c);
}
}
}
}
傳入一個XSSFWorkbook物件即可。
最後一個問題,如果你提前已經做好了ORM的對映,這個時候你不想寫一個新的方法而只想呼叫這種返回為HashMap的通用方法,就要把物件轉為一個Map。
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;
public class BeanMapTrans {
public static LinkedHashMap<String, Object> transBean2Map(Object obj){
if(obj == null){
return null;
}
LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
// 過濾class屬性
if (!key.equals("class")) {
// 得到property對應的getter方法
Method getter = property.getReadMethod();
Object value = getter.invoke(obj);
map.put(key, value);
}
}
} catch (Exception e) {
System.out.println("transBean2Map Error " + e);
}
return map;
}
}
函式見上。
另外說一句在替換多個sheet,使用removeRow的時候會出現空指標異常,因為Row的儲存非執行緒安全的TreeMap,但是對於刪除操作不會影響,所以我只是將這個情況跳過了,如有大神明白具體原理請告知。
如果你還有對格式處理的要求,可以參考這一篇文章
相關推薦
poi對Excel報表的自動化
工作中經常會有一些daily的報告,每次的格式都是一樣的,來源也基本都是資料庫的表,每次要自己去貼上很麻煩。 嘗試過python以及sas等工具或者包,python的xlrd等系列不支援07以後的excel檔案,openpyxl在替換資料後容易莫名的
POI對Excel單元格進行顏色設置
dex .so nbsp set exceptio except www span 單元格 POI對Excel單元格進行顏色設置 學習了:http://www.myexception.cn/program/1932587.html HSSFWorkbook workboo
POI對Excel自定義日期格式的讀取
大數 -i ride 字符串 所有 sfc ats http 錯誤 cell.getCellStyle().getDataFormat();根據這個值進行時間、日期格式的判斷;POI讀取出來的結果也是有些變化的;需要在實際項目中進行確認; 時間格式的遍歷:
POI對Excel單元格內容修改
// XLSX版本 const in= new Packages.java.io.FileInputStream("C:\\LJT\\test.xlsx"); const wb= Packages.org.apache.poi.xssf.usermodel.XSSFWorkbook("in"
學以致用——Excel報表自動化方案 (Automation solution of complicated manual Excel Report)
經過整整兩年多的實踐加理論學習,總算實現了一套Excel報表自動化方案。思路總結如下: 1. 使用批處理檔案呼叫批處理檔案(call batch file through batch file) 2. 在batch檔案中呼叫sqlplus程式,同時指定要連線的資料庫及登入密碼,並指定co
Web使用Apache poi對EXCEL操作(匯入)
第一次嘗試Web專案上傳Excel資料進行匯入 如果有哪裡做的不對不好或者有更好的方法請聯絡我,謝謝 pom.xml中新增 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --&
使用Apache POI 進行Excel報表的匯出下載(GET 請求 && POST請求)
簡介:之前專案有這樣的需求:按各種條件進行篩選資料,然後匯出Excel到本地 針對條件條件很少的情況下,使用的是GET請求的方式,直接在URL上拼接請求引數,這種形式很簡單就能匯出Excel。但是當條件很多很複雜時,就不適合使用GET請求的方式了,所以我使用了
POI對EXCEL的操作【重點:如何設定CELL格式為文字格式】
轉載至:http://javacrazyer.iteye.com/blog/894758 實際開發過程中通常用到的就是從資料庫匯出EXCEL表格了,JXL可以這樣做,其實POI也可以(關於JXL與POI的異同可訪問我之前總結的文章),之前寫過POI對七種文件(當然也
POI對Excel進行讀取操作,工具類,便於操作資料
一:首先POI對Excel 操作進行了一系列的封裝,匯入,匯出Excel這裡藉助於POI提供的jar包 專案當中匯入POI提供的Jar包,這裡使用Maven管理 進行匯入jar包 <!-- https://mvnrepository.c
Java POI對Excel操作,專案開發中遇到的問題,及解決方案
java POI官網地址,裡面有介紹POI的使用,以及各種例子程式碼:說下在專案開發中遇到的java操作Excel的棘手問題,以及解決方案:首先記下2007版及以上Excel版本(.xlsx)的檔案讀取、輸出程式碼:讀取:public static Workbook getT
學以致用——Excel報表自動化方案探索
準備進一步提高Excel報表的自動化生成程度。 看到一篇文章,收到了啟發,暫存一下。 '' --main.sql set linesize 200 set term off verify of
POI對EXCEL中時間格式資料的讀取
1、Excel儲存日期、時間均以數值型別進行儲存,讀取時POI先判斷是是否是數值型別,再進行判斷,判斷數值: HSSFCell.CELL_TYPE_NUMERIC==cell.getCellType() 2.日期
POI 對excel表格基本操作Demo
今天熟悉了一下POI對excel的一些基本操作與大家分享一下 import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.hssf.usermodel.HSSFC
POI對Excel的單元格格式區分
圖中的資料有數值、貨幣、時間、日期、文字等格式。這些資料格式在POI中的HSSFDataFormat類裡都有相應的定義。 HSSFDataFormat是HSSF子專案裡面定義的一個類。類HSSFDataFormat允許使用者新建資料格式型別。HSSFDataFormat類包含靜態方法static java.
使用poi對excel條件格式設定字型顏色使用自定義的顏色
在poi中設定條件格式也是使用如下程式碼 XSSFSheetConditionalFormatting scf = target.getSheetConditionalFormatting(); //獲得條件格式物件 //紅色格式 XSSFConditionalFo
使用poi對Excel表的寫入修改,再匯出
本文介紹將一個Excel檔案上傳後,修改Excel表中資料,再從新寫入到新的Excel表 1.使用myeclipse建立web工程, 2.新增struts2 使用struts2的分裝工具將檔案 上傳 3.匯入poi-3.0.2-FINAL-20080204.jar 4
poi匯出Excel報表多表頭雙層表頭、合併單元格
效果圖: controller層方法: /** * * 匯出Excel報表 * @param request * @return * */ @RequestMapping("/export")
POI對Excel操作——java儲存資料到Excel
1、常見的java操作Excel API介紹 1.1 Java Aspose Cells Java Aspose Cells是一種純粹的Java授權的Excel API,開發和供應商Aspose釋出。這個API的最新版本是8.1.2,是一個豐富而厚重的API
接口自動化測試Python(2)_使用python對excel進行操作
pip安裝 print eight tps cell .com family logs 運行 如何使用Python對excel進行簡單的操作 一. 通過pip安裝xlwt, xlrd這兩個模塊 *pip install xlwt *pip insta
Java自動化——使用Selenium+POI實現Excel自動化批量查單詞
寫在最前 相信大家都對爬蟲非常熟悉,一般來說,利用HttpClient傳送請求並獲取響應以獲得想要提取的資料應該是最常用的方法。最近工作中頻繁使用了Selenium,在本文中,我們將使用Selenium和POI(讀寫Excel)來完成一個入門級的自動化程式,原始碼地址見附錄。 步驟一覽 使用Mav