POI 导出Excel 并且根据内容设置列宽自适应
package com.**;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.util.HSSFColor;
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 com.eos.system.annotation.Bizlet;
import commonj.sdo.DataObject;
public class ExcelExportUtil {
/**
* Excel导出
*
* @param criteriaEntity DataObject 获取填充数据源的查询对象
* @param fileName 生成的文件名前缀
* @param response HttpServletResponse响应
* @param colToProperty 表格列名和DataObject对象Property应的LinkedHashMap
* @param datePattern 日期格式数据格式
* @param HttpServletRequest request 请求对象,用于无数据输出时,内部跳转
* @param backPage 执行查询后无数据时返回画面
* @author RangoLan
*/
@Bizlet("数据写入Excel并生成下载")
public static void exportExcel(String fileName, HttpServletRequest request, HttpServletResponse response, DataObject criteriaEntity, LinkedHashMap<String, String> colToProperty, String datePattern, String backPage) throws Exception {
//根据查询对象criteria填充数据源
DataObject[] datas = (DataObject[]) com.eos.foundation.database.DatabaseUtil.queryEntitiesByCriteriaEntity("default", criteriaEntity);
if (datas != null && datas.length > 0) {
if (datePattern == null) {
datePattern = "yyyy-MM-dd";
}
SXSSFWorkbook workbook = new SXSSFWorkbook(1000);
/** 设置格式* */
workbook.setCompressTempFiles(true);
// 表头样式
CellStyle headerStyle = workbook.createCellStyle();
//水平居中
headerStyle.setAlignment(CellStyle.ALIGN_CENTER);
//垂直居中
headerStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
//设置边框
headerStyle.setBorderTop(CellStyle.BORDER_THIN);
headerStyle.setBorderRight(CellStyle.BORDER_THIN);
headerStyle.setBorderBottom(CellStyle.BORDER_THIN);
headerStyle.setBorderLeft(CellStyle.BORDER_THIN);
//设置颜色
headerStyle.setFillForegroundColor(HSSFColor.LIGHT_GREEN.index);
headerStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
Font headerFont = workbook.createFont();
headerFont.setFontHeightInPoints((short) 12);
headerFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
headerStyle.setFont(headerFont);
// 单元格样式
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
//垂直居中
cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
//设置边框
cellStyle.setBorderTop(CellStyle.BORDER_THIN);
cellStyle.setBorderRight(CellStyle.BORDER_THIN);
cellStyle.setBorderBottom(CellStyle.BORDER_THIN);
cellStyle.setBorderLeft(CellStyle.BORDER_THIN);
//设置自动换行
cellStyle.setWrapText(true);
//设置字体
Font cellFont = workbook.createFont();
cellFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
cellStyle.setFont(cellFont);
//DataObject属性Property数组
String[] properties = new String[colToProperty.size()];
//表头数组
String[] headers = new String[colToProperty.size()];
int ii = 0;
for (Iterator<String> iter = colToProperty.keySet().iterator(); iter.hasNext(); ) {
String fieldName = iter.next();
headers[ii] = fieldName;
properties[ii] = colToProperty.get(fieldName);
ii++;
}
// 遍历集合数据,产生数据行,填充Excel
int rowIndex = 0;
Sheet sheet = null;
for (DataObject data : datas) {
if (rowIndex == 65535 || rowIndex == 0) {
sheet = workbook.createSheet();// 如果数据超过了,则在第二页显示
Row headerRow = sheet.createRow(0);// 表头 rowIndex=0
for (int i = 0; i < headers.length; i++) {
headerRow.createCell(i).setCellValue(headers[i]);
//设置表头样式
headerRow.getCell(i).setCellStyle(headerStyle);
}
rowIndex = 1;// 数据内容从 rowIndex=1开始
}
//创建行
Row dataRow = sheet.createRow(rowIndex);
for (int i = 0; i < properties.length; i++) {
//创建单元格
Cell newCell = dataRow.createCell(i);
Object o = data.get(properties[i]);
String cellValue = "";
if (o == null) {//为空处理
cellValue = "";
} else if (o instanceof Date) {//日期格式化处理
cellValue = new SimpleDateFormat(datePattern).format(o);
} else {
cellValue = o.toString();
}
//单元格赋值
newCell.setCellValue(cellValue);
//单元格格式设置
newCell.setCellStyle(cellStyle);
}
rowIndex++;
}
OutputStream out = null;
//设置自动列宽
for (int i = 0; i < headers.length; i++) {
sheet.autoSizeColumn(i);
sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 17 / 10);
}
try {
out = response.getOutputStream();
fileName = fileName
+ "_"
+ new SimpleDateFormat("yyyyMMDDhh24mmssSSS")
.format(System.currentTimeMillis()) + ".xlsx";
response.setContentType("application/x-msdownload");
response.setHeader("Content-Disposition",
"attachment; filename="
+ URLEncoder.encode(fileName, "UTF-8"));
// 保存报表文件
workbook.write(out);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null)
out.close();
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
// 无导出数据
request.setAttribute("noDataToExport", "没有数据可以导出!");
request.getRequestDispatcher(backPage).forward(request, response);
}
}
}
强调的是设置自适应列宽:sheet.autoSizeColumn(i);
只这样设置是没有很好的效果的。
所以采取了以下两步:
//先设置自动列宽
sheet.autoSizeColumn(i);
//设置列宽为自动列宽的1.7倍(当然不是严格的1.7倍,int的除法恕不再讨论),这个1.6左右也可以,这是本人测试的经验值
sheet.setColumnWidth(i,sheet.getColumnWidth(i)17/10);
经过测试,能够将excel的列宽很好的更具单元格的内容进行设置。
poi生成excel整理(设置边框/字体/颜色/加粗/居中/)
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFCellStyle setBorder = wb.createCellStyle();
一、设置背景色:
setBorder.setFillForegroundColor((short) 13);// 设置背景色
setBorder.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
二、设置边框:
setBorder.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框
setBorder.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框
setBorder.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框
setBorder.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框
三、设置居中:
setBorder.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 居中
四、设置字体:
HSSFFont font = wb.createFont();
font.setFontName("黑体");
//设置字体大小
font.setFontHeightInPoints((short) 16);
HSSFFont font2 = wb.createFont();
font2.setFontName("仿宋_GB2312");
//粗体显示
font2.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font2.setFontHeightInPoints((short) 12);
//选择需要用到的字体格式
setBorder.setFont(font);
五、设置列宽:
//第一个参数代表列id(从0开始),第2个参数代表宽度值
sheet.setColumnWidth(0, 3766);
六、设置自动换行:
//设置自动换行
setBorder.setWrapText(true);
七、通过row 对象设置行高
HSSFRow row = sheet.createRow(0);
//heightInPoints 设置的值永远是height属性值的20倍
row.setHeightInPoints(20);
HSSFRow row1 = sheet.createRow(5);
row1.setHeight((short) (25 * 20));
八、设置默认宽度、高度值
HSSFSheet sheet2 = wb.createSheet("sheet2");
sheet2.setDefaultColumnWidth(20);
sheet2.setDefaultRowHeightInPoints(20);
九、设置cell宽度(通过sheet 对象,setColumnWidth设置cell的宽度)
HSSFSheet sheet = wb.createSheet("sheet1");
sheet.setColumnWidth(0, 20 * 256);
十、合并单元格:
// 参数1:行号 参数2:起始列号 参数3:行号 参数4:终止列号
Region region1 = new Region(0, (short) 0, 0, (short) 6);
// 此方法在POI3.8中已经被废弃,建议使用下面一个
CellRangeAddress region1 = new CellRangeAddress(rowNumber, rowNumber, (short) 0, (short) 11);
// 参数1:起始行 参数2:终止行 参数3:起始列 参数4:终止列
// 但应注意两个构造方法的参数不是一样的,具体使用哪个取决于POI的不同版本。
sheet.addMergedRegion(region1);
目前用过的就这么多,后续有新的会继续添加。
十一、加边框
HSSFCellStyle cellStyle= wookBook.createCellStyle();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cellStyle.setBorderBottom(HSSFCellStyle.BorderBORDER_MEDIUM);
cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
cellStyle.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM);
cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
cellStyle.setBorderRight(HSSFCellStyle.BORDER_MEDIUM);
cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
cellStyle.setBorderTop(HSSFCellStyle.BORDER_MEDIUM);
cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
十二、字体颜色
Font font = wb.createFont();
font.setFontHeightInPoints((short) 12); // 字体高度
font.setFontName("宋体"); // 字体
font.setColor(HSSFColor.RED.index); //颜色
cellStyle.setFont(font);//选择需要用到的字体格式