多xls单sheet合并单xls多sheet的笔记

2013-08-29修改:
下面这个代码在实际使用中发现,这个实现方案会导致xls文件内部的样式过多的问题。直接表现的症状就是在多个sheet的情况下后面的sheet会出现整个页面乱码的情况。

老实说彻底解决这个问题我还没有想到什么好的办法,但是测试在66个sheet的情况下还是由解决办法的。

解决方案:
首先是样式创建限制,在这里我由于自己系统的特性,所以使用了单元格的二个背景色中间以“:”符号相隔以作为一个key存放在map里面,然后获取复制源的单元格的颜色来或创建或获取来设置单元格的样式。由于多个sheet里面的表格大多数情况下就只有二个颜色,所以66个sheet生成后最多也就10个左右的样式。
而这个样式数量在多少是符合规范呢?估计再4000个以内,这个问题是在查看poi-3.9的源码中发现的。当然这个具体值我不敢确定是4000,所以各位大哥大姐,自己看着办~


2013-08-30,在昨天的修改后发现一个问题,就是这个分享的代码中如果不适用获取单元格的字符串来实现复制单元格内容也可能导致乱码的问题。
所以讲POIUtils修改成下面的样子。


/**
* 复制单元格
*
* @param srcCell
* @param distCell
* @param copyValueFlag
* true则连同cell的内容一起复制
*/
public void copyCell(HSSFWorkbook wb, HSSFCell srcCell, HSSFCell distCell, boolean copyValueFlag, HSSFSheet fromSheet, int rowNum) {
...
distCell.setCellType(srcCellType);
if (copyValueFlag) {

if(srcCell.getCellComment() == null) {
distCell.setCellValue(srcCell.toString());
} else {
distCell.setCellValue(srcCell.getCellComment().getString());
}
}
}


------------------------------------------------------------------
首先呢通过这次的学习知道在Java上,有poi和jxl来做xls的操作。
而jxl的优点我在网上搜索到是写文件快,但是我没体验出来...
因为我觉得poi也很快。但是jxl的api调用简单很多,代码量少很多到觉得没错的。

然后呢,我是先实现了一个jxl的方法,但是就存在一个读取文件的时候耗时比较多的问题。而且有点自己还没弄明白的,就是要添加import下面的addCell,否则在我只有一个xls文件的前提下会出现异常。

String basePath = ExportModule.BASE_EXPORT_PATH + ExportModule.BASE_FOLDER_NAME + "/" + user;
String userPath = ExportModule.BASE_EXPORT_PATH + ExportModule.BASE_FOLDER_NAME + "/" + fileName + "_" + user + ".xls";
WritableWorkbook wwb = null;
try {
File file = new File(userPath);
wwb = Workbook.createWorkbook(file);
file = new File(basePath);
File[] files = file.listFiles();
int rowIndex = 0, cellIndex = 0, i = 0;
Workbook rwb = null;
Sheet st = null;
WritableSheet sheet = null;
Label label = null;
WritableCellFormat format = null;
List<String> sheetNames = new ArrayList<String>();
long start = System.currentTimeMillis();
for (i = 0; i < files.length; i++) {
/***/

//start = System.currentTimeMillis();
rwb = Workbook.getWorkbook(files[i]);
//System.out.println("1、获取WorkBook耗时:" + (System.currentTimeMillis() - start) + "ms");
//start = System.currentTimeMillis();
st = rwb.getSheet(0);
//System.out.println("2、获取sheet耗时:" + (System.currentTimeMillis() - start) + "ms");
//start = System.currentTimeMillis();
sheet = wwb.importSheet(st.getName(), i, st);
//System.out.println("3、导入sheet耗时:" + (System.currentTimeMillis() - start) + "ms");
sheetNames.add(sheet.getName());//这个是用于给索引页添加名字用的


/***/
for (rowIndex = 0; rowIndex < st.getRows(); rowIndex++) {
for (cellIndex = 0; cellIndex < st.getColumns(); cellIndex++) {
if (st.getCell(cellIndex, rowIndex).getCellFormat() != null) {
format = new WritableCellFormat(st.getCell(cellIndex, rowIndex).getCellFormat());
label = new Label(cellIndex, rowIndex, st.getCell(cellIndex, rowIndex).getContents());
label.setCellFormat(format);
sheet.addCell(label);
}
}
}
rwb.close();
}
sheet = wwb.createSheet("索引页", 0);
String name = null;
rowIndex = 0;
cellIndex = 0;
i = 1;
WritableHyperlink hyperlink = null;
//为xls文件添加一个索引页
for (Iterator<String> iterator = sheetNames.iterator(); iterator.hasNext(); rowIndex+=2, i++) {
name = iterator.next();
label = new Label(cellIndex, rowIndex, name);
sheet.addCell(label);
hyperlink = new WritableHyperlink(cellIndex, rowIndex, name, wwb.getSheet(i), 0, 0);
sheet.addHyperlink(hyperlink);
}
wwb.write();
} catch (IOException e) {
e.printStackTrace();
throw e;
} catch (RowsExceededException e) {
e.printStackTrace();
throw e;
} catch (WriteException e) {
e.printStackTrace();
throw e;
} catch (BiffException e) {
e.printStackTrace();
throw e;
} finally {
if(wwb != null) {
try {
wwb.close();
wwb = null;
} catch (WriteException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

在这份代码里面/***/这个符号之间用的时间占了每个文件处理的90%的时间了。
而如果使用Poi呢,在我测试用66个文件的情况下每个文件总行数不超过50,列数平均150,1秒以内完成。
但是我当初没有用这个方法,因为我不知道用poi怎么copy内容。
但是我找到这个http://blog.csdn.net/wutbiao/article/details/8696446
所以我使用poi实现了。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.Region;

public class POIUtils {
/**
* 把一个excel中的cellstyletable复制到另一个excel,这里会报错,不能用这种方法,不明白呀?????
* @param fromBook
* @param toBook
*/
/*public static void copyBookCellStyle(HSSFWorkbook fromBook, HSSFWorkbook toBook) {
for(short i = 0;i < fromBook.getNumCellStyles(); i++) {
HSSFCellStyle fromStyle = fromBook.getCellStyleAt(i);
HSSFCellStyle toStyle = toBook.getCellStyleAt(i);
if(toStyle == null) {
toStyle=toBook.createCellStyle();
}
copyCellStyle(fromStyle, toStyle);
}
}*/

/**
* 复制一个单元格样式到目的单元格样式
*
* @param fromStyle
* @param toStyle
*/
public static void copyCellStyle(HSSFCellStyle fromStyle, HSSFCellStyle toStyle) {
toStyle.setAlignment(fromStyle.getAlignment());
// 边框和边框颜色
toStyle.setBorderBottom(fromStyle.getBorderBottom());
toStyle.setBorderLeft(fromStyle.getBorderLeft());
toStyle.setBorderRight(fromStyle.getBorderRight());
toStyle.setBorderTop(fromStyle.getBorderTop());
toStyle.setTopBorderColor(fromStyle.getTopBorderColor());
toStyle.setBottomBorderColor(fromStyle.getBottomBorderColor());
toStyle.setRightBorderColor(fromStyle.getRightBorderColor());
toStyle.setLeftBorderColor(fromStyle.getLeftBorderColor());

// 背景和前景
toStyle.setFillBackgroundColor(fromStyle.getFillBackgroundColor());
toStyle.setFillForegroundColor(fromStyle.getFillForegroundColor());

toStyle.setDataFormat(fromStyle.getDataFormat());
toStyle.setFillPattern(fromStyle.getFillPattern());
// toStyle.setFont(fromStyle.getFont(null));
toStyle.setHidden(fromStyle.getHidden());
toStyle.setIndention(fromStyle.getIndention());// 首行缩进
toStyle.setLocked(fromStyle.getLocked());
toStyle.setRotation(fromStyle.getRotation());// 旋转
toStyle.setVerticalAlignment(fromStyle.getVerticalAlignment());
toStyle.setWrapText(fromStyle.getWrapText());

}

/**
* Sheet复制
*
* @param fromSheet
* @param toSheet
* @param copyValueFlag
*/
public static void copySheet(HSSFWorkbook wb, HSSFSheet fromSheet, HSSFSheet toSheet, boolean copyValueFlag) {
// 合并区域处理
mergerRegion(fromSheet, toSheet);
for (Iterator rowIt = fromSheet.rowIterator(); rowIt.hasNext();) {
HSSFRow tmpRow = (HSSFRow) rowIt.next();
HSSFRow newRow = toSheet.createRow(tmpRow.getRowNum());
// 行复制
copyRow(wb, tmpRow, newRow, copyValueFlag);
}
}

/**
* 行复制功能
*
* @param fromRow
* @param toRow
*/
public static void copyRow(HSSFWorkbook wb, HSSFRow fromRow, HSSFRow toRow, boolean copyValueFlag) {
HSSFCell tmpCell = null, newCell = null;
for (Iterator<HSSFCell> cellIt = fromRow.cellIterator(); cellIt.hasNext();) {
tmpCell = cellIt.next();
newCell = toRow.createCell(tmpCell.getCellNum());
copyCell(wb, tmpCell, newCell, copyValueFlag);
}
}

/**
* 复制原有sheet的合并单元格到新创建的sheet
*
* @param sheetCreat
* 新创建sheet
* @param sheet
* 原有的sheet
*/
public static void mergerRegion(HSSFSheet fromSheet, HSSFSheet toSheet) {
int sheetMergerCount = fromSheet.getNumMergedRegions();
for (int i = 0; i < sheetMergerCount; i++) {
Region mergedRegionAt = fromSheet.getMergedRegionAt(i);
toSheet.addMergedRegion(mergedRegionAt);
}
}

/**
* 复制单元格
*
* @param srcCell
* @param distCell
* @param copyValueFlag
* true则连同cell的内容一起复制
*/
public static void copyCell(HSSFWorkbook wb, HSSFCell srcCell, HSSFCell distCell, boolean copyValueFlag) {
HSSFCellStyle newstyle = wb.createCellStyle();
copyCellStyle(srcCell.getCellStyle(), newstyle);
distCell.setEncoding(srcCell.getEncoding());
// 样式
distCell.setCellStyle(newstyle);
// 评论
if (srcCell.getCellComment() != null) {
distCell.setCellComment(srcCell.getCellComment());
}
// 不同数据类型处理
int srcCellType = srcCell.getCellType();
distCell.setCellType(srcCellType);
if (copyValueFlag) {
if (srcCellType == HSSFCell.CELL_TYPE_NUMERIC) {
if (HSSFDateUtil.isCellDateFormatted(srcCell)) {
distCell.setCellValue(srcCell.getDateCellValue());
} else {
distCell.setCellValue(srcCell.getNumericCellValue());
}
} else if (srcCellType == HSSFCell.CELL_TYPE_STRING) {
distCell.setCellValue(srcCell.getRichStringCellValue());
} else if (srcCellType == HSSFCell.CELL_TYPE_BLANK) {
// nothing21
} else if (srcCellType == HSSFCell.CELL_TYPE_BOOLEAN) {
distCell.setCellValue(srcCell.getBooleanCellValue());
} else if (srcCellType == HSSFCell.CELL_TYPE_ERROR) {
distCell.setCellErrorValue(srcCell.getErrorCellValue());
} else if (srcCellType == HSSFCell.CELL_TYPE_FORMULA) {
distCell.setCellFormula(srcCell.getCellFormula());
} else {
// nothing29
}
}
}

public static void main(String[] args) {
long start = System.currentTimeMillis();
final String userId = "ADMIN", userName = "admin", date = "201304";
final File BaseFile = new File(POIUtils.class.getResource(".").getFile() + "/batchExportReportsTmp/" + userId);
File[] files = BaseFile.listFiles();
System.out.println("获取文件列表耗时:" + (System.currentTimeMillis() - start) + "ms");
start = System.currentTimeMillis();
InputStream is = null;
HSSFWorkbook tmpWorkBook = null, fileWorkBook = null;
HSSFSheet tmpSheet = null, finalSheet = null;
HSSFRow tmpRow = null, finalRow = null;
Iterator<HSSFRow> tmpRows = null, finalRows = null;
HSSFCell tmpCell = null, finalCell = null;
Iterator<HSSFCell> tmpCells = null, finalCells = null;
File finalFile = new File(POIUtils.class.getResource(".").getFile() + "/batchExportReportsTmp/成本白皮书" + date + "_" + userName + ".xls");
try {
List<String> sheetNames = new ArrayList<String>();
FileOutputStream os = new FileOutputStream(finalFile);
System.out.println(finalFile.getPath());
fileWorkBook = new HSSFWorkbook();
fileWorkBook.setSelectedTab((short)0);
String sheetname = null;
for (int i = 0; i < files.length; i++) {
is = new FileInputStream(files[i]);
tmpWorkBook = new HSSFWorkbook(is);
tmpSheet = tmpWorkBook.getSheetAt(0);
sheetname = tmpWorkBook.getSheetName(0);
sheetNames.add(sheetname);
finalSheet = fileWorkBook.createSheet(sheetname);
copySheet(fileWorkBook, tmpSheet, finalSheet, true);
is.close();
}
fileWorkBook.write(os);
os.close();
System.out.println("生成文件耗时:" + (System.currentTimeMillis() - start) + "ms");
} catch (IOException e) {
e.printStackTrace();
}
}
}


与2013-06-07发现代码有重复调用的地方,并修改完成。主要是重复调用复制行、单元格,导致在多xls的情况下会出现部分sheet里面的样式异常的问题。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值