java匯出excel 輕鬆匯出百萬條記錄
網上查了很多部落格,發現很多匯出excel 都是 存一個集合 然後利用poi 的api 匯出 ,這樣在資料量比較小的時候沒什麼問題,但是在資料量稍微大一點就會造成堆疊溢位了。所以寫了一個每次匯出一條記錄的工具類,分享給大家!完美匯出超大資料集合。不多說 ,直接貼程式碼
首先是一個註解類
package com.cmi.jego.activity.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by wl
*/
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExportAnnotation {
int order() default 100;//排序(屬性對應excel的列 的列數)
String method() default "";//屬性對應的get方法
//匯出title
String columnTitle() default "";//屬性對應的excel 的title
//title陣列長度
int length() default 20;//列的個數
}
匯出的實體物件 javaBean(例子)
package com.cmi.jego.activity.vo;
import com.cmi.jego.activity.annotation.ExportAnnotation;
/**
* Created by wl
*/
@ExportAnnotation(length = 9)
public class RedeemCodeExportVO {
@ExportAnnotation (order = 1,method = "getCouponId",columnTitle = "優惠券id")
private String couponId;
@ExportAnnotation(order = 2,method = "getCouponName",columnTitle = "優惠券名稱")
private String couponName;
@ExportAnnotation(order = 3,method = "getExchangeCode",columnTitle = "兌換碼")
private String exchangeCode;
@ExportAnnotation(order = 4,method = "getCommodityName",columnTitle = "商品名稱")
private String commodityName;
@ExportAnnotation(order = 5,method = "getCommodityIds",columnTitle = "商品id")
private String commodityIds;
@ExportAnnotation(order = 6,method = "getCreateDate",columnTitle = "生成日期")
private String createDate;
@ExportAnnotation(order = 7,method = "getNoEffectDate",columnTitle = "失效日期")
private String noEffectDate;
@ExportAnnotation(order = 8,method = "getStatus",columnTitle = "兌換狀態")
private String status;
@ExportAnnotation(order = 9,method = "getExchangeMobile",columnTitle = "兌換手機號")
private String exchangeMobile;
public String getCouponId() {
return couponId;
}
public void setCouponId(String couponId) {
this.couponId = couponId;
}
public String getCouponName() {
return couponName;
}
public void setCouponName(String couponName) {
this.couponName = couponName;
}
public String getExchangeCode() {
return exchangeCode;
}
public void setExchangeCode(String exchangeCode) {
this.exchangeCode = exchangeCode;
}
public String getCommodityName() {
return commodityName;
}
public void setCommodityName(String commodityName) {
this.commodityName = commodityName;
}
public String getCommodityIds() {
return commodityIds;
}
public void setCommodityIds(String commodityIds) {
this.commodityIds = commodityIds;
}
public String getCreateDate() {
return createDate;
}
public void setCreateDate(String createDate) {
this.createDate = createDate;
}
public String getNoEffectDate() {
return noEffectDate;
}
public void setNoEffectDate(String noEffectDate) {
this.noEffectDate = noEffectDate;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getExchangeMobile() {
return exchangeMobile;
}
public void setExchangeMobile(String exchangeMobile) {
this.exchangeMobile = exchangeMobile;
}
}
order 是從1開始的因為專案的需求 第一列都是序號
真正的工具類
package com.cmi.jego.activity.utils;
import com.cmi.jego.activity.annotation.ExportAnnotation;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Created by wl
*/
public class ExportExcelUtil{
private static final Logger logger = LoggerFactory.getLogger(ExportExcel.class);
//200rows flush
private final SXSSFWorkbook wbk = new SXSSFWorkbook(200);
//工作簿 當前sheet
private SXSSFSheet sheet;
//當前sheet的 當前row
private SXSSFRow row; //成員變數接收 不用每次都在棧中宣告
//當前cell
private SXSSFCell cell;
//標題樣式 初始化 分配一個堆記憶體空間
private final XSSFCellStyle titleStyle = (XSSFCellStyle) this.wbk.createCellStyle();
//cell樣式
private final XSSFCellStyle cellStyle = (XSSFCellStyle) this.wbk.createCellStyle();
//row 樣式
// private final XSSFCellStyle rowStyle = (XSSFCellStyle) this.wbk.createCellStyle();
//cell font
// private final Font font = this.wbk.createFont();
//// 使用太耗記憶體
// private XSSFRichTextString xssfRichTextString;
//接收cellValue 當前cellValue
private Object cellValue;
//標題[0][] 方法名[1][]
private final String[][] titlesAndMethods = new String[2][];
//匯出物件的 Class 物件 使用泛型獲取匯出物件的型別 只能獲取父類的泛型的型別 這裡通過構造器初始化
//Class.forName(((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName());
private final Class<?> exportClass;
public ExportExcelUtil(Class<?> clazz){
this.exportClass = clazz;
if(clazz == null)
throw new NullPointerException("clazz 不能為空");
this.initTitleAndMethod(this.exportClass);
}
//初始化 樣式
{
this.initStyle(this.titleStyle,false);
this.initStyle(this.cellStyle,true);
//this.initStyle(rowStyle,true);
}
private int count = 1;
public void exportRowSet(Object rowData) {
if(this.sheet ==null){
throw new NullPointerException("sheet 為空 , 先initSheet");
}
if(this.count % 10000 == 0){
logger.info("=========="+Runtime.getRuntime().totalMemory()/1024/1024+"M");
//System.runFinalization();
}
this.row = this.sheet.createRow(count);
//第一個cell 是序號
{
this.cell = this.row.createCell(0);
this.cell.setCellStyle(cellStyle);
this.cell.setCellValue(count);
}
for(int i=1;i<titlesAndMethods[0].length && titlesAndMethods[1][i] != null;i++) {
try {
this.cellValue = this.exportClass.getMethod(this.titlesAndMethods[1][i]).invoke(rowData);
this.cell = this.row.createCell(i);
this.createCellValue(i);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
//logger.error("匯出統計資料 反射獲取值 失敗,column:{}",i,e);
}
}
this.count++;
}
public void writeWbk(OutputStream os) {
try {
this.wbk.write(os);
} catch (IOException e) {
//
}finally {
try {
this.wbk.close();
} catch (IOException e) {
//
}
}
}
public void initSheet(String sheetName){
this.sheet = this.wbk.createSheet(sheetName);
this.sheet.setDefaultColumnWidth((short) 16);
this.row = this.sheet.createRow(0);
this.createRowTitle();
this.count = 1;
}
private void initTitleAndMethod(Class<?> clazz) {
ExportAnnotation exportAnnotation = clazz.getAnnotation(ExportAnnotation.class);
Field[] fields = clazz.getDeclaredFields();
//初始化 標題[0][0]
{
//第一個title 序號
int length = exportAnnotation.length();
this.titlesAndMethods[0] = new String[length+1];
this.titlesAndMethods[1] = new String[length+1];
this.titlesAndMethods[0][0] = "序號";
}
int index;
for(Field field :fields){
exportAnnotation = field.getAnnotation(ExportAnnotation.class);
if(exportAnnotation != null) {
index = exportAnnotation.order();
//標題
this.titlesAndMethods[0][index] = exportAnnotation.columnTitle();
this.titlesAndMethods[1][index] = exportAnnotation.method();
}
}
}
/**
* 建立標題行
*/
private void createRowTitle() {
String[] titles = titlesAndMethods[0];
for(int i=0;i<titles.length;i++){
this.cell = this.row.createCell(i);
this.cell.setCellStyle(this.titleStyle);
//每次都要例項化一個 如果為final cellValue 全部相同 太耗記憶體
// this.xssfRichTextString = new XSSFRichTextString();
// this.xssfRichTextString.setString(titles[i]);
this.cell.setCellValue(titles[i]);
}
}
private void initStyle(XSSFCellStyle style,boolean isBold) {
// 設定這些樣式SOLID_FOREGROUND
style.setFillForegroundColor(HSSFColor.WHITE.index);
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setAlignment(HorizontalAlignment.CENTER);
// 生成一個字型
XSSFFont font = (XSSFFont) this.wbk.createFont();
font.setColor(HSSFColor.BLACK.index);
font.setFontHeightInPoints((short) 12);
font.setBold(isBold);
style.setFont(font);
}
/**
* 建立 cell
*/
private void createCellValue(int columnIndex){
this.cell.setCellStyle(this.cellStyle);
// 判斷值的型別後進行強制型別轉換
String textValue = null;
if (this.cellValue instanceof Date) {
Date date = (Date) this.cellValue;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
textValue = sdf.format(date);
}
else if (this.cellValue instanceof byte[]) {
Drawing patriarch = this.sheet.createDrawingPatriarch();
// 有圖片時,設定行高為60px;
this.row.setHeightInPoints(60);
// 設定圖片所在列寬度為80px,注意這裡單位的一個換算
this.sheet.setColumnWidth(columnIndex, (short) (35.7 * 80));
// sheet.autoSizeColumn(i);
byte[] bsValue = (byte[]) this.cellValue;
ClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 255, (short) 6, columnIndex, (short) 6, columnIndex);
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_DONT_RESIZE);
patriarch.createPicture(anchor, this.wbk.addPicture(bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));
}
else {
// 其它資料型別都當作字串簡單處理
if (this.cellValue != null) textValue = this.cellValue.toString();
}
// 如果不是圖片資料,就判斷textValue是否全部由數字組成
if (textValue != null) {
if (this.cellValue instanceof Integer) {
//double 強制轉換 會有小數點
this.cell.setCellValue((int) this.cellValue);
}else if(this.cellValue instanceof Number){
this.cell.setCellValue((double) this.cellValue);
}
else {
// 資料量大每次例項化 太耗記憶體
// this.xssfRichTextString = new XSSFRichTextString();
// this.xssfRichTextString.setString(textValue);
// this.font.setColor(new XSSFColor().getIndexed());
// this.xssfRichTextString.applyFont(font);
this.cell.setCellValue(textValue);
}
}
}
}
工具類中的titleAndMethods[][] 是一個二維陣列titleAndMethods[0]用來存放title titleAndMethods[1]用來存放get方法 兩個長度是一樣的。 在ExportUtil初始化的時候 通過反射填充
注意 :這裡我的excel 匯出的第一列固定是“序號”如果你的第一列不是序號請在匯出的javaBean 屬性中新增一個 order=0的屬性 並增加title 和method 註解,並且將工具類做如下修改
註釋掉下面的程式碼
this.titlesAndMethods[0][0] = "序號";
//第一個cell 是序號
{
this.cell = this.row.createCell(0);
this.cell.setCellStyle(cellStyle);
this.cell.setCellValue(count);
}
迴圈從0開始
for(int i=0;i<titlesAndMethods[0].length && titlesAndMethods[1][i] != null;i++) {
try {
this.cellValue = this.exportClass.getMethod(this.titlesAndMethods[1][i]).invoke(rowData);
this.cell = this.row.createCell(i);
this.createCellValue(i);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
//logger.error("匯出統計資料 反射獲取值 失敗,column:{}",i,e);
}
}
使用該工具類共分為四部
- 例項化ExportUtil 注意構造器中的Class 引數 必須要有ExportAnnotation註解 且註解正確 ExportUtil exportUtil = new ExportUtil(RedeemCodeExportVO.class)
- 初始化sheet exportUtil.initSheet(“sheetName”);
- 匯出一個結果集 exportUtil.exportRowSet(redeemCodeExportVO) 匯出物件可能需要封裝
- 寫 exportUtil.writeWbk(os);
下面是一個匯出資料庫資料的例子使用的是jdbc 查詢每次匯出一個結果集 避免全部查詢儲存在匯出的高記憶體消耗
匯出流程大概是
- 建立檔案
- sql查詢(封裝jdbc 每次匯出一個封裝好的結果集)
- 上傳檔案到oss伺服器
將oss下載key返回瀏覽器
建立一個模板 程式碼如下(寫在內部類中)
//匯出模板 =============================================
//匯出步驟
//1.例項化ExportUtil ExportUtil exportUtil = new ExportUtil(clazz);
//2.呼叫匯出一個結果集方法 (封裝ResultSet) 模板 回撥
//3.寫出輸出流 exportUtil.write(os) 模板 回撥
//4.上傳到oss 模板 回撥
//5.返回oss key到前端
//6.前端通過 oss key 請求後端下載檔案
private static class ExportTemplate {
//excel 寫入的檔案
private final File file;
//匯出結果返回的物件
ExportStatisticResp exportStatisticResp;
//例項化 file
private ExportTemplate(String filePath, String fileName,ExportStatisticResp exportStatisticResp){
File pathFile = new File(filePath);
if (!mkdirs(pathFile)) {
logger.info("建立臨時目錄失敗,使用當前目錄");
file = new File(fileName);
} else {
file = new File(filePath, fileName);
}
this.exportStatisticResp = exportStatisticResp;
}
private ExportStatisticResp executeExport(ExportCallBackHandler exportCallBackHandler) {
OutputStream os = null;
try {
if (file == null)
throw new NullPointerException("file 不能為空");
//doSomething
os = new BufferedOutputStream(new FileOutputStream(file));
//回撥
return exportCallBackHandler.processExport(os,file,exportStatisticResp);
//doSomething
} catch (ParseException | IOException | RuntimeException e) {
logger.error(e.getMessage(),e);
} finally {
if(file != null) {
boolean isDeleted = file.delete();
if (!isDeleted)
logger.info("刪除臨時檔案失敗");
}
if(os != null){
try {
os.close();
} catch (IOException e) {
logger.info("匯出 輸出流關閉異常",e);
}
}
}
//失敗
exportStatisticResp.setStatus(ExportStatisticResp.StatusEnum.Failed.status);
exportStatisticResp.setMsg("匯出失敗");
return exportStatisticResp;
}
private boolean mkdirs(File file) {
return file.exists() || file.mkdirs();
}
//回撥介面
private interface ExportCallBackHandler {
// os 輸出流 到file file oss上傳的檔案 返回值 匯出物件
ExportStatisticResp processExport(OutputStream os,File file,ExportStatisticResp exportStatisticResp) throws ParseException, IOException;
}
}
ExportStatisticResp 是我定義的一個返回物件 大家可以自己定義
JDBC 使用的是spring 的JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
封裝查詢sql程式碼如下
/**
* 通過 MyRowCallBackHandler 處理結果集 防止查出所有資料記憶體溢位
*/
private void exportRedeemResultSet(RedeemCodeQueryVO queryVO, Map<String, ActivityInfoGiftVO> map, ExportExcelUtil exportExcelUtil) {
//拼裝sql
String sql = ObjectUtil.getRedeemCodeQuerySql(queryVO);
logger.info("sql:{}", sql);
//每次查10000個結果集
jdbcTemplate.setFetchSize(10000);
jdbcTemplate.query(sql, new MyRowCallBackHandler(map, exportExcelUtil));
}
/**
* 匯出一個結果集
*/
private static class MyRowCallBackHandler implements RowCallbackHandler {
private final Map<String, ActivityInfoGiftVO> map;
private final ExportExcelUtil exportExcelUtil;
private final RedeemCodeExportVO rowData = new RedeemCodeExportVO();
private MyRowCallBackHandler(Map<String, ActivityInfoGiftVO> map, ExportExcelUtil exportExcelUtil) {
this.map = map;
this.exportExcelUtil = exportExcelUtil;
exportExcelUtil.initSheet("yyh");
}
@Override
public void processRow(ResultSet rs) throws SQLException {
//封裝 RedeemCodeExportVO
ObjectUtil.fillRedeemCodeExportVO(map, rs, rowData);
exportExcelUtil.exportRowSet(rowData);
}
}
自定義一個 MyRowCallBackHandler 實現 JDBC 的RowCallbackHandler 介面 在回掉方法public void processRow(ResultSet rs)中封裝 匯出的物件 並且呼叫exportExcelUtil.exportRowSet(rowData);
在自定義MyRowCallBackHandler 類中還有一些成員變數 因為sql查詢出來的欄位可能不能完全滿足匯出的所有欄位要求,還需要外部的一些資料進行封裝 ,另外就是ExportExcelUtil物件由外層呼叫方法傳遞過來 (注意要保證一個請求只例項化一個ExportExcelUtil物件 )在構造器中新增引用
private final RedeemCodeExportVO rowData = new RedeemCodeExportVO(); 是一個final 的例項 是因為匯出的是rowData的資料 不用每次都例項化,只需要在裡面填充資料。
下面是接收請求的方法 程式碼如下
@RequestMapping("/exportCode")
public ResMesg exportCode(RedeemCodeQueryVO queryVO, HttpServletRequest request) {
ExportStatisticResp exportStatisticResp = new ExportStatisticResp();
if (queryVO.getActivityId() != null) {
List<ActivityInfoGiftVO> giftVOs = iActivityMicroService.findActivityInfoGiftListByActivityInfoId(queryVO.getActivityId());
//需要到processRow中封裝的資料(sql查詢出來的資料不滿足匯出要求 聯合查詢會降低效率)
Map<String, ActivityInfoGiftVO> map = new HashMap<>();
convertList2Map(giftVOs, map);
//檔名
String fileName = "fileName";
//檔案路徑
String filePath = request.getServletContext().getRealPath("/") + "/temp/";
//上傳的oss key
String exportOssKey = "activity/exportRedeem/" + fileName;
//模板模式
return new ExportTemplate(filePath, fileName, exportStatisticResp).executeExport(new ExportTemplate.ExportCallBackHandler() {
@Override
public ExportStatisticResp processExport(OutputStream os, File file, ExportStatisticResp exportStatisticResp) throws ParseException, IOException {
//回撥介面
//例項化匯出工具
ExportExcelUtil exportExcelUtil = new ExportExcelUtil(RedeemCodeExportVO.class);
//執行RowCallBackHandler 回掉介面 processRow
exportRedeemResultSet(queryVO, map, exportExcelUtil);
exportExcelUtil.writeWbk(os);
//上傳檔案到oss
ossFileService.putObject("xlsx", exportOssKey, file.length(), new BufferedInputStream(new FileInputStream(file)));
//封裝返回物件 exportStatisticResp.setStatus(ExportStatisticResp.StatusEnum.Success.status);
exportStatisticResp.setMsg("匯出成功");
exportStatisticResp.setOsskey(exportOssKey);
exportStatisticResp.setFileName(fileName);
logger.info("匯出地址=======>>>" + accessService.oss + exportOssKey);
return exportStatisticResp;
}
});
}
exportStatisticResp.setStatus(ExportStatisticResp.StatusEnum.SuccessWithoutData.status);
exportStatisticResp.setMsg("沒有查詢到相應資料");
return exportStatisticResp;
}
前端接收到oss的key在請求後端下載檔案
每一個匯出請求都可以按照上面的模式進行處理
下面貼一下直接匯出一個excel檔案的測試程式碼(每一萬行列印使用的記憶體 測試10萬 50萬 100萬 200萬)
程式碼如下(資料量自己設定)
public static void main(String[] args) throws Exception{
System.out.println("=========================>>>>>" + (Runtime.getRuntime().totalMemory() / 1024 / 1024) + "M");
long start = System.currentTimeMillis();
ExportExcelUtil exportExcelUtil = new ExportExcelUtil(RedeemCodeExportVO.class);
exportExcelUtil.initSheet("abcd");
RedeemCodeExportVO redeemCodeExportVO;
OutputStream os = new BufferedOutputStream(new FileOutputStream(new File("1234.xlsx")));
for(int i=0;i<100000;i++){
redeemCodeExportVO = new RedeemCodeExportVO();
redeemCodeExportVO.setExchangeMobile(i+"");
redeemCodeExportVO.setStatus("a" + i);
redeemCodeExportVO.setNoEffectDate("b"+i);
redeemCodeExportVO.setCreateDate("c" + i);
redeemCodeExportVO.setCommodityName("d"+i);
redeemCodeExportVO.setCommodityIds("e" +i);
redeemCodeExportVO.setExchangeCode("f"+i);
redeemCodeExportVO.setCouponName("h"+i);
redeemCodeExportVO.setCouponId("g"+i);
exportExcelUtil.exportRowSet(redeemCodeExportVO);
}
exportExcelUtil.writeWbk(os);
long end = System.currentTimeMillis();
System.out.println("================================>>" +(end - start) +"ms");
}
十萬
=========================>>>>>121M
03:16:29.555 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========121M
03:16:29.714 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========153M
03:16:29.857 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========154M
03:16:29.963 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========218M
03:16:30.075 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========218M
03:16:30.175 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========219M
03:16:30.345 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========296M
03:16:30.485 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========296M
03:16:30.641 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========296M
03:16:30.779 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========296M
================================>>7363ms
50萬
=========================>>>>>121M
03:20:39.931 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========153M
03:20:40.185 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========153M
03:20:40.311 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========218M
03:20:40.420 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========218M
03:20:40.528 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========218M
03:20:40.622 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========218M
03:20:40.750 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========346M
03:20:40.892 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========346M
03:20:41.004 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========346M
03:20:41.113 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========347M
03:20:41.222 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========347M
03:20:41.315 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========347M
03:20:41.404 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========347M
03:20:41.509 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:41.633 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:41.721 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:41.810 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:41.913 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:42.027 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:42.129 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:42.230 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:42.352 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:42.456 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:42.551 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:42.666 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========501M
03:20:42.761 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========475M
03:20:42.849 [main] INFO com.cmi.jego.activity.utils.ExportExcel - ==========475M
03:20:42.946 [main] INF