`
lph279430114
  • 浏览: 7748 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

多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里面的样式异常的问题。
分享到:
评论

相关推荐

    多个sheet内容 代码.zip

    标题中的“多个sheet内容代码.zip”表明这是一个关于使用编程方式处理包含多个工作表(Sheet)的Excel文件的项目。在IT行业中,特别是涉及到数据处理和报告生成时,这样的功能非常常见。Apache POI是一个广泛使用的...

    VBA自己学习笔记

    ### VBA学习笔记关键知识点详解 #### 一、工作簿管理与操作 VBA(Visual Basic for Applications)是Microsoft Office套件中的一种编程语言,特别适用于自动化Excel、Word等应用程序的任务。以下是从“VBA自己学习...

    PythonApplication1.rar

    总的来说,"PythonApplication1.rar"的压缩包文件内容可能涉及到了使用Python和VSCode 2019进行Excel数据处理,特别是如何合并多sheet的数据。掌握这些技能对于数据分析师和软件开发者来说是至关重要的,因为它们...

    datasheet:使用 POI 在 Railo 中处理 XLS 文件

    作为实验,Datasheet.cfc 是一个基于脚本的组件不使用分号Railo 特定功能。 为什么? 看看在没有 ; 的情况下编写脚本的感觉如何; 目前感觉还不错! Railo 中在语句末尾留下分号时有太多错误,因此现在将使用它们...

    excel函数学习笔记

    - **COUNTIF/COUNTIFS**: 单条件或多个条件统计。`=COUNTIF(E2:E10, "&gt;50")` 统计E2到E10中大于50的单元格数量。 7. **其他高级函数** - **OFFSET**: 基于起始单元格偏移返回一个范围。`=OFFSET(A1, 2, 3, 3, 2)`...

    jxl包的学习笔记。。。。。。

    `jxl`库提供了丰富的API,支持更多高级功能,如设置单元格样式、处理公式、读写图表、处理日期和数字格式等。例如,你可以通过`WritableFont`和`WritableCellFormat`设置单元格的字体、颜色和对齐方式: ```java ...

    JXL 学习笔记(看了就差不多了)

    本篇笔记将深入探讨JXL库的使用方法和核心功能。 ### JXL简介 JXL(Java Excel API)是Java平台上的一个开源库,它允许开发者读取、创建和修改Excel文件。JXL支持Excel 97到2003的格式(.xls),对于新版本的Excel...

    POI的学习笔记

    ### POI学习笔记知识点解析 #### 一、POI简介 Apache POI是一个开源的Java API,用于处理Microsoft Office格式的文件,包括Excel (.xls, .xlsx), PowerPoint (.ppt, .pptx) 和 Word (.doc, .docx)。POI提供了一套...

    POI导入导出excel文件 --- 个人珍藏笔记

    本笔记将介绍如何使用POI来导入和导出Excel文件。 首先,我们需要将`poi-3.1-FINAL.jar`库添加到项目的类路径中,这样才能使用POI提供的API。导入这个库后,我们就可以开始编写处理Excel文件的代码了。 在示例代码...

    matlab常用操做笔记

    这种模式下,`range`参数会被忽略,同时会以一种受限的方式读取数据,此时`sheet`必须是带引号的字符串且区分大小写。这种模式不使用Excel作为COM服务器。 7. **同时读取数字和文本数据** `[num, txt] = xlsread...

    我的VB自学笔记201105

    【VB自学笔记201105】是关于学习Visual Basic (VB)编程语言的个人笔记,主要聚焦于与Excel的交互以及问题总结。以下是对笔记中涉及知识点的详细解释: 1. **VB与Excel的交互**: - **指定位置最后非空行非空列的...

    java鬼混笔记:JAVA发邮箱(带附件)

    本笔记将深入探讨如何使用Java发送带有附件的电子邮件,同时涉及与Excel处理相关的`jxl`库。 首先,我们需要了解JavaMail API,这是一个用于处理邮件的开源库,提供创建、发送邮件的功能。在Java中发送邮件主要涉及...

    POI,读取文件工具类和笔记

    POI 将 Excel 工作簿(Workbook)理解为一系列的工作表(Sheet),每个工作表又由多个行(Row)组成,行中包含单元格(Cell)。通过这种方式,POI 实现了对 Excel 文件的结构化访问。 **3. 创建和读取 Excel 文件**...

    POI学习笔记

    对于Excel文件(.xls),使用`HSSFWorkbook`;对于Excel 2007及更高版本的文件(.xlsx),则使用`XSSFWorkbook`。 ```java Workbook wb = new HSSFWorkbook(); // 创建Excel 97-2003版本的工作簿 Workbook wb = new...

    matlab笔记

    ### MATLAB笔记:Excel数据处理与图论算法应用 #### 一、Excel数据处理 ##### 1.1 使用`xlsread`读取Excel数据 在MATLAB中,`xlsread`函数是一个非常实用的功能,用于从Excel文件中读取数据。这对于处理大量数据集...

    JXL教程 JXL开发文档 JXL学习笔记 JXL示例

    Sheet sheet = workbook.getSheet(0); // 读取单元格内容 Cell cell = sheet.getCell(0, 0); String content = cell.getContents(); System.out.println("内容: " + content); workbook.close(); } catch ...

    EtherCAT开发相关文档,含EtherCAT技术规范说明等等.rar

    这个压缩包包含了关于EtherCAT开发的多个关键文档,涵盖了从技术规范到硬件选择的各个方面。 1. **EtherCAT技术规范说明**:EtherCAT的核心在于其高效的数据传输机制,通过在以太网帧中嵌入控制数据,实现微秒级的...

    struts2导出excel笔记

    - **创建工作表(Sheet)**: 工作簿可以包含多个工作表,每个工作表代表Excel中的一个tab页。 - **创建行(Row)和单元格(Cell)**: 在工作表中,我们可以通过创建行和单元格来填充数据。 - **设置数据类型和...

    013_matlab读取ecxel(脚本读取).zip

    总的来说,这个压缩包是一个很好的学习资源,涵盖了MATLAB读取Excel的基础知识,包括使用不同函数和处理多个Excel文件。对于想要提高MATLAB数据处理能力的人来说,这是一个非常实用的参考资料。

Global site tag (gtag.js) - Google Analytics