批量導出大數據量到EXCEL

用到的jar包是 POI 3.8,注意導包的時候,那幾個包都要導進去,下包就不用說了吧,官網上有。http://poi.apache.org/

接着是個工具類,無意中在網上發現了,感覺封裝的不錯,我就稍微修改了下,導出大數據量(30W數據,70列)到EXCEL2007,目前沒有出現內存溢出問題。

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Calendar;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

public class ExcelWriter {
	// 定製浮點數格式
	private static String NUMBER_FORMAT = "#,##0.00";
	// 定製日期格式
	private static String DATE_FORMAT = "m/d/yy"; // "m/d/yy h:mm"
	private OutputStream out = null;
	private Workbook workbook = null;
	private Sheet sheet = null;
	private Row row = null;
	public ExcelWriter() {
	}
	public ExcelWriter(OutputStream out) {
		this.out = out;
		this.workbook = new SXSSFWorkbook(128);//POI3.8最新的API,解決問題的關鍵。
		this.sheet = workbook.createSheet();
	}
	/**
	 * 導出Excel文件
	 * @throws IOException
	 */
	public void export() throws FileNotFoundException, IOException {
		try {
			workbook.write(out);
			out.flush();
			out.close();
		} catch (FileNotFoundException e) {
			throw new IOException(" 生成導出Excel文件出錯! ", e);
		} catch (IOException e) {
			throw new IOException(" 寫入Excel文件出錯! ", e);
		}
	}

	/**
	 * 增加一行
	 * @param index 行號
	 */
	public void createRow(int index) {
		this.row = this.sheet.createRow(index);
	}

	/**
	 * 獲取單元格的值
	 * @param index 列號
	 */
	public String getCell(int index){
		Cell cell = this.row.getCell((short) index);
		String strExcelCell = "";
		if (cell != null) { // add this condition
			// judge
			switch (cell.getCellType()) {
			case Cell.CELL_TYPE_FORMULA:
				strExcelCell = "FORMULA ";
				break;
			case Cell.CELL_TYPE_NUMERIC: {
				strExcelCell = String.valueOf(cell.getNumericCellValue());
			}
				break;
			case Cell.CELL_TYPE_STRING:
				strExcelCell = cell.getStringCellValue();
				break;
			case Cell.CELL_TYPE_BLANK:
				strExcelCell = "";
				break;
			default:
				strExcelCell = "";
				break;
			}
		}
		return strExcelCell;
	}

	/**
	 * 設置單元格
	 * @param index 列號
	 * @param value 單元格填充值
	 */
	public void setCell(int index, int value) {
		Cell cell = this.row.createCell((short) index);
		cell.setCellType(Cell.CELL_TYPE_NUMERIC);
		cell.setCellValue(value);
	}

	/**
	 * 設置單元格
	 * @param index 列號
	 * @param value 單元格填充值
	 */
	public void setCell(int index, double value) {
		Cell cell = this.row.createCell((short) index);
		cell.setCellType(Cell.CELL_TYPE_NUMERIC);
		cell.setCellValue(value);
		CellStyle cellStyle = workbook.createCellStyle(); // 建立新的cell樣式
		DataFormat format = workbook.createDataFormat();
		cellStyle.setDataFormat(format.getFormat(NUMBER_FORMAT));//設置cell樣式爲定製的浮點數格式
		cell.setCellStyle(cellStyle); // 設置該cell浮點數的顯示格式
	}

	/**
	 * 設置單元格
	 * @param index 列號
	 * @param value 單元格填充值
	 */
	public void setCell(int index, String value) {
		Cell cell = this.row.createCell((short) index);
		cell.setCellType(Cell.CELL_TYPE_STRING);
		cell.setCellValue(value);
	}

	/**
	 * 設置單元格
	 * @param index 列號
	 * @param value 單元格填充值
	 */
	public void setCell(int index,Calendar value) {
		Cell cell = this.row.createCell((short) index);
		cell.setCellValue(value.getTime());
		CellStyle cellStyle = workbook.createCellStyle(); // 建立新的cell樣式
		DataFormat format = workbook.createDataFormat();
		cellStyle.setDataFormat(format.getFormat(DATE_FORMAT)); // 設置cell樣式爲定製的日期格式
		cell.setCellStyle(cellStyle); // 設置該cell日期的顯示格式
	}
	public static void main(String[] args) {
		System.out.println(" 開始導出Excel文件 ");

		File f = new File("C:\\qt.xls");
		ExcelWriter e = new ExcelWriter();

		try {
			e = new ExcelWriter(new FileOutputStream(f));
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		e.createRow(0);
		e.setCell(0, "試題編碼 ");
		e.setCell(1, "題型");
		e.setCell(2, "分值");
		e.setCell(3, "難度");
		e.setCell(4, "級別");
		e.setCell(5, "知識點");
		e.createRow(1);
		e.setCell(0, "t1");
		e.setCell(1, 1);
		e.setCell(2, 3.0);
		e.setCell(3, 1);
		e.setCell(4, "重要");
		e.setCell(5, "專業");
		try {
			e.export();
			System.out.println(" 導出Excel文件[成功] ");
		} catch (IOException ex) {
			System.out.println(" 導出Excel文件[失敗] ");
			ex.printStackTrace();
		}
	}
}

這個只是個util。接着你就可以運用到你的工程中去了。下面是個測試類。

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestExcelPOI {

    public static void main(String[] args) throws FileNotFoundException {
        String newFileName = "test_performance.xlsx";
        int rows = 100000;
        int cols = 70;
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(newFileName));
        ExcelWriter excelWriter = new ExcelWriter(out);
        long start =System.currentTimeMillis();
        for (int rowNum = 0; rowNum < rows; rowNum++){
        	excelWriter.createRow(rowNum);
            for (int colNum = 0; colNum < cols; colNum++) {
                String value = rowNum + "_" + colNum;//模擬數據
                excelWriter.setCell(colNum, value);
            }
        }
        try{
			excelWriter.export();
			System.out.println(" 導出Excel文件[成功]");
		} catch (IOException ex) {
			System.out.println(" 導出Excel文件[失敗]");
			ex.printStackTrace();
		}
		long end =System.currentTimeMillis();
		double seconds = (end -start)/Math.pow(10, 3);
		System.out.println(seconds);
		
    }
}
/***************運行結果**************************
*導出Excel文件[成功]
*         48.293
*************************************************/

本人運行的30W,差不多2分鐘左右,感覺還是比這個快些的。

總結:

開始沒用POI最新的API,還是很容易就溢出了,大概6000行,70列,就溢出,效果不好,用了POI3.8 的最新API,請注意ExcelWriter裏面的代碼。

在此之前還嘗試過csv和table導出數據,csv是用逗號分隔,table用標籤把數據封裝起來。這兩個還沒出現內存溢出,也沒做具體的測試,有個缺點就是格式不好控制。如果你對格式要求不高,或者數據只是用來看的,可以考慮這種。

還有就是寫成多個EXCEL,然後在合併,可惜效果也不佳。

這是問題的鏈接,部分項目代碼可以參考一下。

http://topic.csdn.net/u/20120821/16/ac109bbe-c002-4490-93da-bf02b42f0400.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章