最近公司要求使用JAVA操作office ,研究了一天有关Excel的POI知识 ,也上网找了很多POI操作Excel的博客 ,无奈发现使用后多数代码都是过期内容,还有一部分代码使用起来操作时间过久,有的导出20000行数据慢到几乎可以睡一觉起来再看了 ,于是乎急眼自己着手搞了一个导出的Util,我是小菜鸟理解并不是太透彻,不过还是站在了巨人的肩膀上,多有借鉴各位巨人的经验,在此也多谢各位巨人们。
那么正文开始:
首先 导入Apache的POIjar包,没有Jar包的童鞋,可以去 ApachePOI的Jar包飞机票 下载
上图为下载位置
至于怎么导入我就不多说了(如果你不会导jar包的话,那你真该回炉了 -__-)。
这里我只是在本地搞了一个Util类,随便弄了一个简单的bean进行测试。时间不足,仅供参考!(有了实现,不怕别的)。
这里主要操作的是XSSFWorkBook ,03版本与07版本在代码区分改动,主要就是HSSF与XSSF的区别,命名上也就是xsl与xslx的区分,这里也就不多说了,简单研究一下,两者大同小异。
顺便多唠叨一嘴 POI 的创建流程,方便理解。
1、创建工作簿 (workbook)
2、创建sheet页 (可以多个创建)
3、创建样式 (可有可无)
4、创建 行
5、创建 单元格
以下就是导出Excel的梳理代码 **
package com.excel.org;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.text.SimpleDateFormat;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExportExcelUtil {
/**
*
* @param sheetName sheet页的名称
* @param titleName 表格标题的名称
* @param headers 表格列头的名称数组
* @param data 数据源
* @param resultUrl 本地的地址
* @param pattern 时间的格式
*/
private static void doExportExcel07(String sheetName,String titleName,String[] headers,Collection<?> data,String resultUrl,String pattern) {
// 声明一个工作薄
XSSFWorkbook workbook = new XSSFWorkbook();
OutputStream out=null;
// 生成一个工作表
XSSFSheet sheet = workbook.createSheet(sheetName);
// 设置工作表默认列宽度为20个字节
sheet.setDefaultColumnWidth((short) 20);
//设置工作表的默认高度为14个字节
// sheet.setDefaultRowHeight((short) 14);
//在工作表中合并首行并居中
sheet.addMergedRegion(new CellRangeAddress(0,0,0,headers.length-1));
/** start 关于标题 start **/
// 创建[标题]样式
XSSFCellStyle titleStyle = workbook.createCellStyle();
// 设置[标题]样式
titleStyle.setFillForegroundColor(IndexedColors.DARK_YELLOW.getIndex()); //屎黄色
titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); //填充模式
titleStyle.setBorderBottom(BorderStyle.THIN); //下边框样式
titleStyle.setBorderLeft(BorderStyle.THIN); //左边框样式
titleStyle.setBorderRight(BorderStyle.THIN); //右边框样式
titleStyle.setBorderTop(BorderStyle.THIN); //上边框样式
titleStyle.setAlignment(HorizontalAlignment.CENTER); //居中
//创建[标题]字体
XSSFFont titleFont = workbook.createFont();
//设置[标题]字体
titleFont.setColor(IndexedColors.BLUE.getIndex()); //蓝色
titleFont.setFontHeightInPoints((short) 24); //字体大小
titleFont.setFontName("Courier New"); //字体样式
titleFont.setBold(true); //是否粗体
// 应用
titleStyle.setFont(titleFont);
//设置标题的坐标 并 赋值
XSSFRow titleRow = sheet.createRow(0);
XSSFCell titleCell = titleRow.createCell(0);
titleCell.setCellStyle(titleStyle);
titleCell.setCellValue(titleName);
/** end 关于标题 end **/
/** start 关于列头 start **/
// 创建[列头]样式
XSSFCellStyle headersStyle = workbook.createCellStyle();
// 设置[列头]样式
headersStyle.setFillForegroundColor(IndexedColors.BLUE.index); //颜色
headersStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); //填充模式
headersStyle.setBorderBottom(BorderStyle.THIN); //下边框样式
headersStyle.setBorderLeft(BorderStyle.THIN); //左边框样式
headersStyle.setBorderRight(BorderStyle.THIN); //右边框样式
headersStyle.setBorderTop(BorderStyle.THIN); //上边框样式
headersStyle.setAlignment(HorizontalAlignment.CENTER); //居中
//创建[列头]字体
XSSFFont headersFont = workbook.createFont();
//设置[列头]字体
headersFont.setColor(HSSFColorPredefined.VIOLET.getIndex());
headersFont.setFontHeightInPoints((short) 12);
// 应用
headersStyle.setFont(headersFont);
// 设置列头的坐标 并 循环赋值
XSSFRow row = sheet.createRow(1);
for (short i = 0; i < headers.length; i++) {
XSSFCell cell = row.createCell(i);
cell.setCellStyle(headersStyle);
XSSFRichTextString text = new XSSFRichTextString(headers[i]);
cell.setCellValue(text);
}
/** end 关于列头 end **/
/** start 关于表中数据 start **/
// 创建[表中数据]样式
XSSFCellStyle dataSetStyle = workbook.createCellStyle();
// 设置[表中数据]样式
dataSetStyle.setFillForegroundColor(HSSFColorPredefined.LIGHT_ORANGE.getIndex());
dataSetStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
dataSetStyle.setBorderBottom(BorderStyle.THIN);
dataSetStyle.setBorderLeft(BorderStyle.THIN);
dataSetStyle.setBorderRight(BorderStyle.THIN);
dataSetStyle.setBorderTop(BorderStyle.THIN);
dataSetStyle.setAlignment(HorizontalAlignment.CENTER);
dataSetStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 创建[表中数据]字体
XSSFFont dataSetFont = workbook.createFont();
// 设置[表中数据]字体
dataSetFont.setColor(IndexedColors.BLUE.getIndex());
// 应用
dataSetStyle.setFont(dataSetFont);
/**此处多谢某位前辈省去了我一部分时间,我把前辈的代码稍作修改以达到更效率的方式,望见谅**/
// 创建表中数据行-增加样式-赋值
Iterator<?> it = data.iterator();
int index = 1;
while (it.hasNext()) {
index++;
row = sheet.createRow(index);
Object t = it.next();
// 利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
Field[] fields = t.getClass().getDeclaredFields();
for (short i = 0; i < fields.length; i++) {
XSSFCell cell = row.createCell(i);
cell.setCellStyle(dataSetStyle);
Field field = fields[i];
String fieldName = field.getName();
String getMethodName = "get"+ fieldName.substring(0, 1).toUpperCase()+ fieldName.substring(1);
try {
@SuppressWarnings("rawtypes")
Class tCls = t.getClass();
@SuppressWarnings("unchecked")
Method getMethod = tCls.getMethod(getMethodName,new Class[] {});
Object value = getMethod.invoke(t, new Object[] {});
// 如果是时间类型,按照格式转换
String textValue = null;
if (value instanceof Date) {
Date date = (Date) value;
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
textValue = sdf.format(date);
} else {
// 其它数据类型都当作字符串简单处理
if (value != null) {
textValue = value.toString();
}else {
textValue = "";
}
}
// 利用正则表达式判断textValue是否全部由数字组成
if (textValue != null) {
Pattern p = Pattern.compile("^\\d+(\\.\\d+)?$");
Matcher matcher = p.matcher(textValue);
if (matcher.matches()) {
// 是数字当作double处理
cell.setCellValue(Double.parseDouble(textValue));
} else {
// 不是数字做普通处理
cell.setCellValue(textValue);
}
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
try {
out = new FileOutputStream(resultUrl);
workbook.write(out);
out.flush();
out.close();
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception{
String sheetName="我是sheet页名字";
String titleName="我是标题";
String[] headers = { "我是列头1号", "我是列头2号", "我是列头3号", "我是列头4号" };
List<TestBean> data = new ArrayList<>();
for (int i = 0; i < 50000; i++) {
TestBean b = new TestBean(); //这里写一个javaBean 里面有几个参数 不多做介绍 循环添加了5万次
b.setid(String.valueOf(i));
b.setMoney("19.21");
b.setName("新年快乐" + i);
b.setDate(java.sql.Date.valueOf("2018-02-24"));
data.add(b);
}
//测试一下使用时间
long end,start;
start = System.currentTimeMillis();
String resultUrl="F:\\新建文件夹\\显灵吧!.xlsx";
String pattern="yyyy-MM-dd";
ExportExcelUtil.doExportExcel07(sheetName, titleName, headers, data, resultUrl, pattern);
end = System.currentTimeMillis();
System.out.println((end - start) /1000 );
}
}