`
zhuyufufu
  • 浏览: 139581 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Java POI Excel sheet 合并遇到的问题解决

阅读更多
上接 Java POI Excel sheet
http://zhuyufufu.iteye.com/blog/2033386

在使用程序合并Excel的过程中可能会遇到下面两个问题:

  此文件中的某些文本格式可能已经更改,因为它已经超出最多允许字体数。关闭其他文档再试一次可能有用。

  文件错误。数据可能丢失。

  这两个问题都与样式的拷贝有关系:
//样式的设置
			    HSSFCellStyle cStyle = destWorkBook.createCellStyle();
			    cStyle.cloneStyleFrom(sourceCell.getCellStyle());
			    targetCell.setCellStyle(cStyle);


上面这段代码拷贝的样式生成的Excel文件在wps下是没问题的,但是在office下当合并单元格超过一定数量时就会出现上面的两个问题。

  具体的原因没有去深究,无非是office实现样式时做了什么限制,或者有什么情况没有考虑到。
  下面给出一种解决办法,就是不使用cloneStyleFrom拷贝样式,希望能够帮助到有需要的同行。

  代码如下:
/**
	 * 样式拷贝
	 * @param cStyle 目标style
	 * @param sourceCellStyle 源style
	 * @param sourceWorkBook 源workBook
	 * @return
	 */
	private static HSSFCellStyle copyCellStyle(HSSFCellStyle cStyle, HSSFCellStyle sourceCellStyle, HSSFWorkbook sourceWorkBook) {
		if(sourceCellStyle == null){
			return cStyle;
		}
		//是否换行
		cStyle.setWrapText(sourceCellStyle.getWrapText());
		//字体拷贝
		cStyle.setFont(sourceCellStyle.getFont(sourceWorkBook));
//		 cStyle.cloneStyleFrom(sourceCellStyle);
		//拷贝对齐方式
		cStyle.setAlignment(sourceCellStyle.getAlignment());
		cStyle.setVerticalAlignment(sourceCellStyle.getVerticalAlignment());
		//边框拷贝
		cStyle.setBorderBottom(sourceCellStyle.getBorderBottom());
		cStyle.setBorderLeft(sourceCellStyle.getBorderLeft());
		cStyle.setBorderRight(sourceCellStyle.getBorderRight());
		cStyle.setBorderTop(sourceCellStyle.getBorderTop());
		cStyle.setBottomBorderColor(sourceCellStyle.getBottomBorderColor());
		cStyle.setLeftBorderColor(sourceCellStyle.getLeftBorderColor());
		cStyle.setRightBorderColor(sourceCellStyle.getRightBorderColor());
		cStyle.setTopBorderColor(sourceCellStyle.getTopBorderColor());
		//别的样式的拷贝
		return cStyle;
	}



改变后的上篇文章的代码如下:
public static HSSFWorkbook mergeHSSFWorkbooks(HSSFWorkbook[] workbooks) {
		if(workbooks == null || workbooks.length == 0){
			return null;
		}else if(workbooks.length == 1){
			return workbooks[0];
		}
		HSSFWorkbook wbFirst = workbooks[0];
		HSSFSheet toSheet = wbFirst.getSheetAt(0);
		for (int i = 1; i < workbooks.length; i++) {
			HSSFWorkbook wb = workbooks[i];
			HSSFSheet fromsheet = wb.getSheetAt(0);
			copyRows(wbFirst, wb, fromsheet, toSheet, fromsheet.getFirstRowNum(), fromsheet.getLastRowNum(), (toSheet.getLastRowNum()));
		}
		return wbFirst;
	}
	
	/**
	 * @param destWorkBook 目标workbook
	 * @param sourceWorkBook 源workbook
	 * @param sourceSheet 源sheet
	 * @param targetSheet 目sheet
	 * @param pStartRow 起始读取行
	 * @param pEndRow 结束读取行
	 * @param pPosition 目标保存
	 */
	public static void copyRows(HSSFWorkbook destWorkBook, HSSFWorkbook sourceWorkBook, HSSFSheet sourceSheet,HSSFSheet targetSheet, int pStartRow, int pEndRow, int pPosition) {
		HSSFRow sourceRow = null;
		HSSFRow targetRow = null;
		HSSFCell sourceCell = null;
		HSSFCell targetCell = null;
		int cType;
		int i;
		int j;
		int targetRowFrom;
		int targetRowTo;

		if ((pStartRow == -1) || (pEndRow == -1)) {
			return;
		}

		List<CellRangeAddress> oldRanges = new ArrayList<CellRangeAddress>();
		for (i = 0; i < sourceSheet.getNumMergedRegions(); i++) {
			oldRanges.add(sourceSheet.getMergedRegion(i));
		}

		// 拷贝合并的单元格。原理:复制当前合并单元格后,原位置的格式会移动到新位置,需在原位置生成旧格式
		for (int k = 0; k < oldRanges.size(); k++) {
			CellRangeAddress oldRange = oldRanges.get(k);
			CellRangeAddress newRange = new CellRangeAddress(oldRange
					.getFirstRow(), oldRange.getLastRow(), oldRange
					.getFirstColumn(), oldRange.getLastColumn());

			if (oldRange.getFirstRow() >= pStartRow
					&& oldRange.getLastRow() <= pEndRow) {
				targetRowFrom = oldRange.getFirstRow() - pStartRow + pPosition;
				targetRowTo = oldRange.getLastRow() - pStartRow + pPosition;
				oldRange.setFirstRow(targetRowFrom);
				oldRange.setLastRow(targetRowTo);
				targetSheet.addMergedRegion(oldRange);
				sourceSheet.addMergedRegion(newRange);
			}
		}
		// 设置列宽
		for (i = pStartRow; i <= pEndRow; i++) {
			sourceRow = sourceSheet.getRow(i);
			if (sourceRow != null) {
				for (j = sourceRow.getLastCellNum(); j > sourceRow.getFirstCellNum(); j--) {
					targetSheet.setColumnWidth(j, sourceSheet.getColumnWidth(j));
					targetSheet.setColumnHidden(j, false);
				}
				break;
			}
		}
		// 拷贝行并填充数据
		for (; i <= pEndRow; i++) {
			sourceRow = sourceSheet.getRow(i);
			if (sourceRow == null) {
				continue;
			}
			targetRow = targetSheet.createRow(i - pStartRow + pPosition);
			targetRow.setHeight(sourceRow.getHeight());
			for (j = sourceRow.getFirstCellNum(); j <= sourceRow.getPhysicalNumberOfCells(); j++) {
				sourceCell = sourceRow.getCell(j);
				if (sourceCell == null) {
					continue;
				}
				targetCell = targetRow.createCell(j);
				//复制样式
				//样式的设置
				if(sourceWorkBook != null){
					HSSFCellStyle cStyle = destWorkBook.createCellStyle();
					cStyle = copyCellStyle(cStyle, sourceCell.getCellStyle(), sourceWorkBook);
					targetCell.setCellStyle(cStyle);
				}

				cType = sourceCell.getCellType();
				targetCell.setCellType(cType);
				switch (cType) {
				case HSSFCell.CELL_TYPE_BOOLEAN:
					targetCell.setCellValue(sourceCell.getBooleanCellValue());
					// System.out.println("--------TYPE_BOOLEAN:" + targetCell.getBooleanCellValue());
					break;
				case HSSFCell.CELL_TYPE_ERROR:
					targetCell.setCellErrorValue(sourceCell.getErrorCellValue());
					// System.out.println("--------TYPE_ERROR:" + targetCell.getErrorCellValue());
					break;
				case HSSFCell.CELL_TYPE_FORMULA:
					// parseFormula这个函数的用途在后面说明
					targetCell.setCellFormula(parseFormula(sourceCell.getCellFormula()));
					// System.out.println("--------TYPE_FORMULA:" + targetCell.getCellFormula());
					break;
				case HSSFCell.CELL_TYPE_NUMERIC:
					targetCell.setCellValue(sourceCell.getNumericCellValue());
					// System.out.println("--------TYPE_NUMERIC:" + targetCell.getNumericCellValue());
					break;
				case HSSFCell.CELL_TYPE_STRING:
					targetCell.setCellValue(sourceCell.getRichStringCellValue());
					// System.out.println("--------TYPE_STRING:" + i + targetCell.getRichStringCellValue());
					break;
				default:
					targetCell.setCellValue(sourceCell.getRichStringCellValue());
					// System.out.println("--------TYPE_STRING:" + i + targetCell.getRichStringCellValue());
					break;
				}
			}
		}
	}
	

	/**
	 * 样式拷贝
	 * @param cStyle 目标style
	 * @param sourceCellStyle 源style
	 * @param sourceWorkBook 源workBook
	 * @return
	 */
	private static HSSFCellStyle copyCellStyle(HSSFCellStyle cStyle, HSSFCellStyle sourceCellStyle, HSSFWorkbook sourceWorkBook) {
		if(sourceCellStyle == null){
			return cStyle;
		}
		//是否换行
		cStyle.setWrapText(sourceCellStyle.getWrapText());
		//字体拷贝
		cStyle.setFont(sourceCellStyle.getFont(sourceWorkBook));
//		 cStyle.cloneStyleFrom(sourceCellStyle);
		//拷贝对齐方式
		cStyle.setAlignment(sourceCellStyle.getAlignment());
		cStyle.setVerticalAlignment(sourceCellStyle.getVerticalAlignment());
		//边框拷贝
		cStyle.setBorderBottom(sourceCellStyle.getBorderBottom());
		cStyle.setBorderLeft(sourceCellStyle.getBorderLeft());
		cStyle.setBorderRight(sourceCellStyle.getBorderRight());
		cStyle.setBorderTop(sourceCellStyle.getBorderTop());
		cStyle.setBottomBorderColor(sourceCellStyle.getBottomBorderColor());
		cStyle.setLeftBorderColor(sourceCellStyle.getLeftBorderColor());
		cStyle.setRightBorderColor(sourceCellStyle.getRightBorderColor());
		cStyle.setTopBorderColor(sourceCellStyle.getTopBorderColor());
		//别的样式的拷贝
		return cStyle;
	}

	/**
	 * 处理公式
	 * @param pPOIFormula
	 * @return
	 */
	private static String parseFormula(String pPOIFormula) {
		final String cstReplaceString = "ATTR(semiVolatile)"; //$NON-NLS-1$
		StringBuffer result = null;
		int index;
		result = new StringBuffer();
		index = pPOIFormula.indexOf(cstReplaceString);
		if (index >= 0) {
			result.append(pPOIFormula.substring(0, index));
			result.append(pPOIFormula.substring(index + cstReplaceString.length()));
		} else {
			result.append(pPOIFormula);
		}
		return result.toString();
	}
0
0
分享到:
评论

相关推荐

    poi实现多sheet合并

    在IT行业中,尤其是在数据分析、报表处理等领域,经常需要对Excel...通过以上步骤,你可以实现将多个Excel文件的多个Sheet合并到一个新文件中,每个Sheet对应源文件的一个Sheet,满足了“poi实现多sheet合并”的需求。

    java excel poi合并单元格

    总结,Java通过Apache POI库可以方便地处理Excel文件,包括合并单元格。这个过程涉及到创建工作簿和工作表,定义合并范围,写入数据并保存文件。在开发过程中,灵活运用这些方法可以满足各种复杂的Excel操作需求。

    POI读取Excel合并单元格并储存

    本文将深入探讨如何使用Java的Apache POI库来读取Excel文件,并处理其中合并单元格的数据,同时将这些数据存储到实体类中以供后续使用。 Apache POI是一个强大的库,允许程序员使用Java来创建、修改和显示Microsoft...

    Poi 读写Excel 合并ExcelSheet Struts2实现

    总的来说,通过Apache POI与Struts2的结合,我们可以轻松地在Java Web应用中实现Excel文件的读写和合并操作。这在数据分析、报表生成、数据导入导出等场景下非常实用。但要注意处理大数据时性能问题,因为内存中存储...

    使用poi方式导出excel(分多个sheet导出)

    通过Apache POI,我们可以轻松地使用Java编程语言创建和操作Excel文件,包括创建多个Sheet。这个过程涉及了Workbook、Sheet、Row和Cell的创建、设置数据、合并单元格以及最终的文件导出。在实际应用中,可以根据需求...

    利用POI合并多个Excel表

    在IT领域,Apache POI是一个广泛使用的Java库,它允许开发者读取、写入和修改Microsoft Office格式的文件,特别是Excel工作簿。本教程将深入探讨如何利用Apache POI库来合并多个Excel工作表,这对于处理大量数据或者...

    poi获取合并单元格

    在本篇文章中,我们将详细介绍如何使用 POI 处理 Excel 文件中的合并单元格。 #### 二、关键概念与术语解释 1. **合并单元格**:在 Excel 中,可以通过选择相邻的多个单元格并将其合并为一个单元格来简化数据展示...

    poi获取exccel有合并单元格的数据

    ### 使用Apache POI获取含有合并单元格的Excel数据并存储为List 在处理Excel文档时,经常需要读取其中的数据并进行进一步的操作。当Excel文件中含有合并单元格时,简单的读取方法可能无法准确地获取到所有数据。...

    POI合并多个相同的Excel或者合并Word文件

    总的来说,Java的POI库为我们提供了处理Microsoft Office文件的强大工具,无论是合并Excel还是Word文档,都能有效地完成任务。通过熟练掌握POI的使用,可以极大地提升工作效率,简化数据管理和文档处理的工作流程。

    poi excel 模板读取 复制表 复制行且区分合并行

    本篇将详细介绍如何使用Apache POI来读取Excel模板,复制工作表(Sheet)以及复制行,并特别关注如何处理合并单元格的情况。 首先,我们需要引入Apache POI的相关依赖库到我们的项目中。在Maven项目中,可以在pom....

    POI导出Excel工具类,自动设置标题 列名 文件名,可插入图片,合并单元格

    Apache POI是一个强大的Java库,专门用于处理Microsoft Office格式的文件,尤其是Excel。在这个场景中,我们关注的是如何使用POI来创建一个功能丰富的Excel导出工具类,它能够自动设置标题、列名、文件名,并且支持...

    java poi操作excel小例子

    Java POI 操作 Excel 是一个常见的任务,在许多业务场景中都需要用到,比如数据导入导出、数据分析等。Apache POI 是一个流行的开源库,它允许开发者使用 Java 来读写 Microsoft Office 格式的文件,其中包括 Excel ...

    java使用poi在excel单元格添加超链接,设置字体颜色(csdn)————程序.pdf

    在Java开发中,Apache POI库是一个非常实用的工具,用于读取、写入和修改Microsoft Office格式的文件,特别是Excel。本篇文章主要探讨如何利用POI在Excel单元格中添加超链接,并设置字体颜色。 首先,为了使用...

    JAVA POI导出EXCEL代码

    Java POI库是Apache软件基金会的一个项目,专门用于读写Microsoft Office格式的文件,包括Excel。在Java开发中,我们经常使用POI库来处理Excel数据,如读取、写入和修改Excel文件。本篇文章将详细介绍如何使用JAVA ...

    java poi处理excel数据

    首先,`问题.docx`可能是你在使用POI过程中遇到的问题汇总,它可能包含了错误信息、解决步骤或常见问题的解决方案。通过阅读这份文档,你可以避免或解决类似的问题,提升开发效率。 其次,`统计年鉴示例.xlsx`是一...

    poi生成Excel及合并单元格示例

    在本示例中,我们将重点讨论如何使用 Apache POI 来生成 Excel 文件,并进行单元格的合并操作。 首先,我们需要引入 Apache POI 的相关依赖库。如果你使用的是 Maven,可以在项目的 `pom.xml` 文件中添加以下依赖:...

    java利用poi对Excel进行读写操作支持多sheet格式

    总之,Java POI库为开发者提供了强大而灵活的工具,使得在Java程序中处理Excel文件变得简单易行,无论是一份包含单Sheet的简单报表,还是带有复杂结构和逻辑的多Sheet文件,都能轻松应对。通过深入学习和实践,你...

    java poi 操作Excel

    Java POI 是一个开源项目,专门用于处理Microsoft Office格式的文件,包括Excel、Word和PowerPoint等。在Java世界中,如果你想对Excel进行读写操作,POI库是不可或缺的工具。下面将详细介绍如何使用Java POI来操作...

    Java POI 生成Excel(xlsx)文件

    Java POI 是一个开源项目,专门用于处理Microsoft Office格式的文件,包括Excel、Word和PowerPoint等。在Java中,如果你需要生成或操作Excel文件,尤其是.xlsx格式(这是Excel 2007及以上版本使用的Open XML格式),...

    java POI读取excel文件数据

    在这个场景中,我们将详细探讨如何使用Java POI读取Excel文件中的数据,包括获取总行数、列数、单元格内容、合并单元格、行高、列宽以及图片等信息。 首先,确保在项目中已经引入了Apache POI的依赖库。如果你使用...

Global site tag (gtag.js) - Google Analytics