package com.utils;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
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.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
public class POIExport {
/**
* 根据所传入的参数生成一个Workbook
* @param sql 查询数据的sql
* @param columns sql中列名字符串,以英文逗号分隔,不区分大小写
* @param headers 表头字符串数组,如果是多表头,在需要合并的地方写"null",如:test1,test2,null,null,test3。
* 这表示test2将占三列。如果test2下面没有null,则占一行三列,有n个null,则占n行3列
* @param splitStr 分割表头字符串的分割符
* @return
*/
public static Workbook export(String sql,String columns,String[] headers, String splitStr){
SXSSFWorkbook wb = new SXSSFWorkbook(1000);//创建excel文档,内存中保留 1000 条数据,以免内存溢出
Font font = wb.createFont();//字体
font.setBoldweight(Font.BOLDWEIGHT_BOLD);//加粗
CellStyle cellStylehead = wb.createCellStyle();//表头样式
cellStylehead.setFont(font);//设置字体样式
cellStylehead.setAlignment(CellStyle.ALIGN_CENTER);//水平对齐
cellStylehead.setVerticalAlignment(CellStyle.VERTICAL_CENTER);//垂直对齐
cellStylehead.setWrapText(true);//自动换行
//设置边框
cellStylehead.setBorderTop(CellStyle.BORDER_THIN);
cellStylehead.setBorderRight(CellStyle.BORDER_THIN);
cellStylehead.setBorderBottom(CellStyle.BORDER_THIN);
cellStylehead.setBorderLeft(CellStyle.BORDER_THIN);
//表体样式
CellStyle cellStyleBody = wb.createCellStyle();//表体单元格样式
cellStyleBody.setAlignment(CellStyle.ALIGN_LEFT);//水平对齐
cellStyleBody.setVerticalAlignment(CellStyle.VERTICAL_CENTER);//垂直对齐
cellStyleBody.setWrapText(true);//自动换行
//设置边框
cellStyleBody.setBorderTop(CellStyle.BORDER_THIN);
cellStyleBody.setBorderRight(CellStyle.BORDER_THIN);
cellStyleBody.setBorderBottom(CellStyle.BORDER_THIN);
cellStyleBody.setBorderLeft(CellStyle.BORDER_THIN);
Sheet sheet = wb.createSheet("sheet1");//创建一个sheet
sheet.setDefaultColumnWidth(15);//设置默认列宽
//写表头
createHeader(wb,sheet,cellStylehead,headers,splitStr);
//写表体
int beginRowNumber = headers.length;//表体开始行
String[] cols = columns.split(",");//切分sql列名
int cellSize = cols.length;//列数
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
conn = DBUtil.getConnection();
try {
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
int count = 0;//记录行号
while(rs.next()){
Row row = sheet.createRow(count+beginRowNumber);
row.setHeightInPoints(14);//设置行高
for(int j=0;j<cellSize;j++){
Cell cell = row.createCell(j);
Object obj = rs.getObject(cols[j]);
String cv = obj==null?"":obj.toString();//取得对应列中的值
cell.setCellValue(cv);//设置单元格的值
cell.setCellStyle(cellStyleBody);//设置样式
}
count++;
}
System.out.println("共写入数据:"+count+"条");
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(stmt!=null){
stmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return wb;
}
/**
* 创建excel表头
* @param wb excel的workbook
* @param sheet excel的sheet
* @param cellStylehead excel的样式
* @param headers 表头字符串数组
* @param splitStr 表头字符串切割符
*/
private static void createHeader(SXSSFWorkbook wb, Sheet sheet,
CellStyle cellStylehead, String[] headers, String splitStr) {
//遍历创建单元格
for(int i=0;i<headers.length;i++){
Row row = sheet.createRow(i);
String[] header = headers[i].split(splitStr);
for(int r=0;r<header.length;r++){
Cell cell = row.createCell(r);
cell.setCellValue(header[r]);
cell.setCellStyle(cellStylehead);
}
}
//遍历合并单元格,如果是单表头则跳过
if(headers.length>1){
int[][][] mergeDatas = parseHeader(headers,splitStr);
for(int i=0;i<mergeDatas.length;i++){
int[][] mergeData = mergeDatas[i];
for(int j=0;j<mergeData.length;j++){
int[] merges = mergeData[j];
int mergesR = merges[1]-merges[0];
int mergesC = merges[3]-merges[2];
if(mergesR!=0||mergesC!=0){
//合并单元格
sheet.addMergedRegion(new CellRangeAddress(merges[0],merges[1],merges[2],merges[3]));
//合并单元格后重新设置单元格的样式
setMergedStyle(merges[0],merges[1],merges[2],merges[3],sheet,cellStylehead);
}
}
}
}
}
/**
* 设置合并单元格的样式
* @param i first row(0-based)
* @param j last row(0-based)
* @param k first column(0-based)
* @param l last column(0-based)
* @param sheet excel的sheet
* @param cellStylehead excel的样式
*/
private static void setMergedStyle(int i, int j, int k, int l, Sheet sheet, CellStyle cellStylehead) {
for(int mm=i;mm<=j;mm++){
Row row = sheet.getRow(mm);
if(row==null){
row = sheet.createRow(mm);
}
for(int nn=k;nn<=l;nn++){
Cell cell = row.getCell(nn);
if(cell==null){
cell = row.createCell(nn);
}
cell.setCellStyle(cellStylehead);
}
}
}
/**
* 解析复杂表头,表头为多行且有合并的情况。表头要符合约定格式。
* 格式例子:
* String h21 = "test,test,test,null,null,null,null,null,test,null,null,null,null,null,test";
* String h22 = "null,null,test,null,null,test,null,null,test,null,test,null,test,null,null";
* String h23 = "null,null,test,test,test,test,test,test,test,test,test,test,test,test,null";
* 这里表头有三行,且有合并情况。一行为一个字符串,字符串以英文逗号隔开,在需要合并的地方填写"null"字符串
* @param headers 要解析的表头字符串数组
* @param splitStr 切割表头字符串的分割符
* @return 返回一个三维数组,第三重数据中保存着合并数据
*/
private static int[][][] parseHeader(String[] headers, String splitStr){
//依据表头建立一个二维数组
String[][] doubleAry = new String[headers.length][];
//依据表头建立一个三维数组,用来保存合并单元格所需要的数据,单元格所需要的数据有四个,依次是开始合并的行,结束合并的行,开始合并的列,结束合并的列
//sheet.addMergedRegion(new CellRangeAddress(merges[0],merges[1],merges[2],merges[3]));
int[][][] rcs = new int[headers.length][][];
//遍历赋值
for(int i=0;i<headers.length;i++){
String[] header = headers[i].split(splitStr);
doubleAry[i] = header;
rcs[i] = new int[header.length][4];
}
//遍历二维数组
for(int i=0;i<doubleAry.length;i++){
String[] sub = doubleAry[i];
for(int j=0;j<sub.length;j++){
int sum = 0;//计算行标识
//计算i,j需要合并的行数
if(!sub[j].equals("null")){//如果单元格不为null
for(int m=i;m<doubleAry.length;m++){
String rs = doubleAry[m][j];
if(rs.equals("null")){//如果单元格为null
doubleAry[m][j] = "null2";//把null重赋值为null2,防止在计算列时交错了
sum++;//个数加1
}
}
}
rcs[i][j][0] = i;//赋合并的开始行,当前行
rcs[i][j][1] = i+sum;//赋合并的结束行,当前行加上它下面为null的行数
int sum2 = 0;//计算列标识
//计算i,j需要合并的列数
if(!sub[j].equals("null")){//如果单元格不为null
for(int m=j+1;m<doubleAry[i].length;m++){
String rs = doubleAry[i][m];
if(rs.equals("null")){//如果单元格为null
sum2++;
}else{
break;//一定要break,不然会算错
}
}
}
rcs[i][j][2] = j;//赋合并的开始列,当前列
rcs[i][j][3] = j+sum2;//赋合并的结束列,当前
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
利用poi3.9做的excel导出工具。 这是一个工程直接压缩而成的。 测试10万行*8列,从查询到生成文件所花时间13620毫秒 测试100万行*8列,从查询到生成文件所花时间121443毫秒 主要目录: src com.util ----DBUtil.java ----POIExport.java lib dom4j-1.6.1.jar ojdbc14.jar poi-3.9-20121203.jar poi-ooxml-3.9-20121203.jar poi-ooxml-schemas-3.9-20121203.jar xmlbeans-2.3.0.jar
资源推荐
资源详情
资源评论
收起资源包目录
poi39.zip (20个子文件)
poi39
.project 1KB
WebContent
WEB-INF
lib
dom4j-1.6.1.jar 307KB
xmlbeans-2.3.0.jar 2.54MB
poi-3.9-20121203.jar 1.78MB
poi-ooxml-3.9-20121203.jar 915KB
poi-ooxml-schemas-3.9-20121203.jar 4.58MB
ojdbc14.jar 1.48MB
web.xml 648B
META-INF
MANIFEST.MF 39B
src
com
utils
DBUtil.java 771B
POIExport.java 10KB
.settings
org.eclipse.wst.jsdt.ui.superType.container 49B
org.eclipse.wst.common.project.facet.core.xml 305B
org.eclipse.jdt.core.prefs 364B
org.eclipse.wst.jsdt.ui.superType.name 6B
org.eclipse.wst.common.component 469B
.jsdtscope 503B
build
classes
com
utils
DBUtil.class 1KB
POIExport.class 9KB
.classpath 588B
共 20 条
- 1
资源评论
- rsd43732016-06-20对初学者有用,不过还是谢谢
- love_shasha2016-03-10确实太简单了,
- jianghuta2018-11-09就是为了下载poi包。
- bianhuanmocedexiaowu2015-04-18方法有点简单呀~
yunsyz
- 粉丝: 18
- 资源: 27
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功