突发凌想,用java swing写了一个小工具,可以将数据库中的表直接导成一个Excel2007版本的文件,经过测试最多可以导出120000条左右,和设置的jvm内存大小有关,小批量数据用下还可以,不适合大数据,由于读取表头的sql语句可能和其它数据库不通用,暂时可能只支持Oracle数据库。
下载地址在文章最后面。
整体效果:
先看下效果图:
工程结构与配置文件:
部分源码分析:
源代码部分很简单,分为以下部分:
1、数据库连接
此部分略过,properties文件配置 + JDBC都懂。
2、读取数据
A:先获取数据表的总列数,
获取表列名(Excel表头)SQL语句:
select t1.column_name as fieldName ,t1.data_type as fieldType, t1.data_length as fieldLength,t1.data_precision,t1.nullable as isNull,t1.data_default as data_default,t2.comments as fieldDirections,(select m.constraint_type from user_constraints m,user_cons_columns n where m.constraint_name = n.constraint_name and m.constraint_type='P'and n.column_name = t1.column_name and n.table_name =t1.table_name) as isPK from user_tab_cols t1 inner join user_col_comments t2 on t2.table_name=t1.table_name and t2.column_name=t1.column_name and t1.table_name='你的表名称'
B:再获取每次读取的条数,然后就可以封装成一个二维数组,分页循环读取数据。
// 总行数
int rowLength = this.getCurrentCount(tableName, startIndex, endIndex);
// 总列数
int colLength = tableFields.size();
// 储存数据,二维数组
Object [][] tableData = null;
tableData = new Object[rowLength][colLength];
3、写入文件
这部分循环读取数据,然后用POI写入Excel文件,代码很简单,如下:
/**
* 写入文件,适用多线程
* @return
* @throws IOException
* @throws InterruptedException
*/
public String poiWriteFile(){
String result = "";
String value = null;
TableQuery tableQuery = new TableQuery();
// 判断数据表是否存在
if(!tableQuery.checkExists(tableName)){
result = "数据表:"+tableName+" 不存在。";
}else{
// 获取数据总量
int dataCount = tableQuery.getCount(tableName);
if(dataCount > DBConfig.getDataUpperLimit()){
result = "数据表:"+tableName+" 共"+dataCount+"条数据,超出上限"+DBConfig.getDataUpperLimit()+"条,\n请选择数量较小的表。";
return result;
}
// 记录执行开始时间
long startTime = System.currentTimeMillis();
this.initProgressBar(dataCount);
this.setProgress(dataCount, 0);
// 计算分页
int pageSize = DBConfig.getPageSize();
int pageCount = (dataCount + pageSize - 1) / pageSize;
// 获取数据表列信息
List<TableField> tableFields = tableQuery.getTableField(tableName);
XSSFWorkbook workBook = new XSSFWorkbook();
XSSFSheet sheet = workBook.createSheet(tableName); // 创建一个工作薄对象
XSSFRow row; // 创建一个行对象
int rowIndex = 0; // 当前行下标
XSSFCell cell; // 创建单元格
// 写文件头(Excel的第一行)
row = sheet.createRow(rowIndex);
for(int h = 0; h < tableFields.size(); h++){
cell = row.createCell(h);
cell.setCellValue(tableFields.get(h).getName());
}
rowIndex ++;
// 分页读取数据,写入文件
for(int page = 1; page <= pageCount; page ++){
int startIndex = (page-1)*pageSize;
int endIndex = page*pageSize;
Object [][] tableData = tableQuery.getTableData(tableName, tableFields, startIndex, endIndex);
/*
if(page != 1){ // 分批次追加文件
FileInputStream is = new FileInputStream(saveFile); // 读取上次创建的文件
workBook = new XSSFWorkbook(is);
sheet = workBook.getSheet(tableName);
}
*/
for(int i = 0; i < tableData.length; i++){
row = sheet.createRow(rowIndex);
for(int j = 0; j < tableFields.size(); j++){
cell = row.createCell(j);
if(tableData[i][j] != null){
value = tableData[i][j].toString();
if(tableFields.get(j).getType().equalsIgnoreCase("NUMBER")){
cell.setCellType(XSSFCell.CELL_TYPE_NUMERIC);
cell.setCellValue(Double.parseDouble(value));
}else{
cell.setCellType(XSSFCell.CELL_TYPE_STRING);
cell.setCellValue(value);
}
}
}
rowIndex ++;
this.setProgress(dataCount, rowIndex);
}
/*
// 写文件,分批次追加
FileOutputStream os = new FileOutputStream(file);
// 将文档对象写入文件输出流
workBook.write(os);
// 关闭文件输出流
os.close();
*/
//System.out.println("已经导出:"+rowIndex+" 条。");
System.gc();
}
if(frame != null){
frame.setProgressBarLabel("数据导出完毕,正在生成文件……");
}
String fileOk = "文件生成失败!";
// 写文件
try {
FileOutputStream os = new FileOutputStream(saveFile);
// 将文档对象写入文件输出流
workBook.write(os);
// 关闭文件输出流
os.close();
fileOk = "文件生成完毕!";
} catch (IOException e) {
e.printStackTrace();
}
String expOk = "失败!";
if(fileOk.equalsIgnoreCase("文件生成完毕!")){
expOk = "成功!";
}
// 记录执行结束时间
long endTime = System.currentTimeMillis();
// 计算执行历时时间
long timeDifference = (endTime - startTime)/(1000);
result = "导出"+expOk+"\n历时:"+timeDifference+" 秒";
System.out.println(result);
if(frame != null){
frame.setProgressBarLabel(fileOk);
}
}
return result;
}
分页读取数据时,把数据全部写入XSSFWorkbook,再生成文件。若没读取一次数据就保存文件,以后每次都以追加的形式写入文件,效率低得很。
4、Java Swing UI
UI是用NetBeans画的,很简单,没什么技术含量,有兴趣的可以看下关键部分源代码,NetBeans自动生成的那部分就不要看了。
demo下载地址:
下载文件压缩包内含源代码与编译后的文件
百度网盘地址:http://pan.baidu.com/s/1pJJkgrD
POI下载地址:http://poi.apache.org/download.html 官方当前最新版3.11