Excelレポートの自動化

7086 ワード

仕事ではdailyのレポートがよくありますが、毎回フォーマットが同じで、ソースも基本的にデータベースのテーブルで、毎回自分で貼り付けるのは面倒です.
pythonやsasなどのツールやパッケージを試したことがありますが、pythonのxlrdなどのシリーズは07以降のexcelファイルをサポートしていません.openpyxlはデータを置き換えた後、cellのフォーマットを失いやすく、sasは1位が有料で、2位も03バージョンのexcelのみをサポートしています.幸いpoiで処理できます.
本編では主にいくつかの関数と処理の考え方だけを記録し、デフォルトではSpring+Mybatisの組み合わせが完成しています.
まずmaybatisを使用するとORMを無視できます.長い間同じsqlで対応するオブジェクトを与えるのはまあまあですが、頻繁にフィールドが変動してしまうと面倒なので、mybatisはクエリ結果をHashMapに戻すことができるので、LinkedHashMapをそのまま使います.        
//    ,    
	public static SXSSFWorkbook createWorkbookWithoutBean2(List> 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 map = list.get(0);  //     map,       key
					Set keySet = map.keySet();
					Iterator iterator = keySet.iterator();
					ArrayList keys = new ArrayList();
					while(iterator.hasNext()){
						keys.add(iterator.next());
					}
					
										
					
					//    
					for(int i=0; i> iter1 = list.iterator();
					while(iter1.hasNext()){
						row = sheet.createRow(rowIndex++);
						map = iter1.next();
						for(int i=0; i

上記の関数は、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> list = session.selectList(sql, sqlParam);
			System.out.println(list.size());
			if(list.size()!=0){
				LinkedHashMap map = list.get(0);
				Set keySet = map.keySet();
				Iterator iterator = keySet.iterator();
				ArrayList keys = new ArrayList();
				while(iterator.hasNext()){
					keys.add(iterator.next());
				}
				
				//    
				Iterator> iter1 = list.iterator();
				while(iter1.hasNext()){
					row = sheet.createRow(rowIndex++);
					map = iter1.next();
					for(int i=0; i

これはテンプレート内のsheetを置き換えるために使用されます.レポートの形式が変わらない可能性があるため、後ろに隠されているsheetは前にマッピングされたデータとして使用されます(表示されているsheetはすべて数式で、実際のデータは後ろのhideのsheetの中にあります).開始行選択1は全sheet置換、選択2は2行目から置換を削除します.ここでstyleスタイルの問題があります.テンプレートを使用する場合、第1動作フィールドの名前、第2動作サンプルのデータをお勧めします.返されるオブジェクトは同じようにXSSFWORkbookで受信します.
最後にデータがリフレッシュされた後にリフレッシュする必要があるのは式です.poiは自動的にデータを生成した後、excelを開くと、式としての数値が自分でリフレッシュされないことがわかりやすいので、式をリフレッシュする関数もあります.
public static void updateFormula(Workbook wb){
			for(int sheet_index=0;sheet_index

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 transBean2Map(Object obj){
		if(obj == null){  
            return null;  
        }          
        LinkedHashMap map = new LinkedHashMap();  
        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ですが、削除操作には影響しませんので、この状況をスキップしただけです.具体的な原理がわかったら教えてください.
フォーマット処理の要求があれば、この文章を参考にしてください.
クリックしてリンクを開く