Apache poi导出excel的一个工具类,同时进行了列宽中文兼容

直接上代码

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 导出excel的工具类,鉴于数据量采用SXSSFWorkbook, 不使用追加的方式,会产生bug
 * 注意:如果真要采用读写已知文件,得使用流的方式,随着数据量增加效率可能会变低
 * @author lxd
 * @version 创建时间:2020年5月13日 下午2:53:20
 * @param <T> 数据源类型,例如ResultSet
 */
public abstract class ExportExcel<T> {
	private static final Logger logger = LoggerFactory.getLogger(ExportExcel.class);
	/**
	 * 全局的工作表
	 */
	private SXSSFWorkbook wb;
	private String stationUUID;
	/**
	 * 存储相应的sheet的行数
	 */
	private Map<String,Integer> rownum = new HashMap<String, Integer>();
	/**
	 * 所有相应的文件信息
	 */
	public static final String PREFIX = "f:/excel/";
	
	public String path;
	
	static {
		File file = new File(PREFIX);
		if(!file.exists()) {
			file.mkdir();
		}
	}
	
	
	
	private ExportExcel() {
		super();
		//大量数据处理的类,1000设置内存中存在的行数
		wb = new SXSSFWorkbook(1000);
	}
	


	public ExportExcel(String sn, String fileName) {
		this();
		this.path = PREFIX + fileName +".xlsx";
	}




	
	/**
	 * 
	 * @param sheetName 表名
	 * @param columns 列名
	 * @param rs 要处理的结果集
	 */
	public void export(String sheetName,String[] columns, T dataSource) {
		Sheet sheet = null;
		Row row = null;
		Cell cell = null;
		
		// 创建表头单元格样式
		CellStyle headerStyle = wb.createCellStyle();
		headerStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		headerStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		headerStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
		headerStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
		headerStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		headerStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		Font headerFont = wb.createFont();
		headerFont.setFontHeightInPoints((short) 12);
		headerFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		headerStyle.setFont(headerFont);
		headerStyle.setWrapText(false);// 自动换行

		// 创建数据行单元格样式
		CellStyle style = wb.createCellStyle();
		style.setAlignment(CellStyle.ALIGN_LEFT); // 创建一个居中格式
		style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
		style.setBorderBottom(CellStyle.BORDER_THIN); // 下边框
		style.setBorderLeft(CellStyle.BORDER_THIN);// 左边框
		style.setBorderTop(CellStyle.BORDER_THIN);// 上边框
		style.setBorderRight(CellStyle.BORDER_THIN);// 右边框
		style.setWrapText(false);//是否自动换行文字内容
		//获取相应的sheet
		sheet = wb.getSheet(sheetName);
		if(null == sheet) {
			sheet = wb.createSheet(sheetName);
			//设置列名,相关的电站名称和YBU2
			row = sheet.createRow(0);
			for (int i = 0; i < columns.length; i++) {
				cell = row.createCell(i);
				cell.setCellValue(columns[i]);
				cell.setCellStyle(headerStyle);
				sheet.setColumnWidth(i, (columns[i].getBytes().length+2)*256*3/4);
				//与中文不兼容
//				sheet.autoSizeColumn(i);
			}
			rownum.put(sheetName, 1);
		}
		
		dataHandle(sheet, dataSource);
	
		
		
	}
	
	/**
	 * 需要被实现的数据处理的方法
	 * @param sheet 处理的表单页面
	 * @param dataSource 需要处理的数据源
	 */
	public abstract void dataHandle(Sheet sheet,T dataSource);
	
	
	public void flush2disk() {
		//写入相关文件
		try {
			FileOutputStream fos = new FileOutputStream(new File(path));
			try {
				wb.write(fos);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			fos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	

}

 

几点说明

1、示例代码采用的是SXSSFWorkbook,支持大数据量写入,不支持文件的追加方式

2、poi本身提供了sheet.autoSizeColumn(i); 方法,但是只支持英文;对于中文采用sheet.setColumnWidth(i, (columns[i].getBytes().length+2)*256*3/4); 这种方式,具体计算值可以调整

3、由于采用的SXSSFWorkbook(1000),当写入行数超过1000时,会将多余的行写入硬盘,所以这时候去读取第一行的时候会报错,所以在最开始就根据中文列名进行列宽设置

4、具体使用的时候继承上面的类,实现dataHandle方法即可

posted @ 2020-05-28 20:14  MarshWinter  阅读(466)  评论(0编辑  收藏  举报