POI与JXL写Excel的性能对比

作者:无名 - 开源软件 -

         在java项目中,使用xml配置和反射写了一个通用POI导出Excel数据的方法,发现导出2500行40列数据用了大概30分钟,通过排查发现POI的createCell非常耗损性能。然后采用JXL重构通用Excel数据导出方法,时间只需1s左右。现在把POI和JXL两种导出方法对比如下,也方便以后用到,便于检索。

       POI方式写Excel

	/**
	 * POI方式数据导出 支持duo sheet导出,支持表名、sheet页、标题、副标题单独命名
	 * 该方法由于性能问题,已过期,不推荐使用
	 */ 
	@Deprecated 
	@SuppressWarnings({ "unchecked", "deprecation" })
	@RequestMapping(value = "/exportSheetsData")
	public void exportSheetsData(String reqObjs, String tableName, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
        long s=(new Date()).getTime();
        long s1=0;
		List<QueryCondition> queryConditions = JSON.parseArray(reqObjs, QueryCondition.class);
		int conCount = queryConditions.size();
		OutputStream fOut = null;
		
		// 产生工作簿对象
		HSSFWorkbook workbook = new HSSFWorkbook();

		// 定义标题样式
		HSSFFont titleFont = workbook.createFont();
		titleFont.setFontHeightInPoints((short) 18);
		titleFont.setFontName("宋体");
		titleFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		HSSFCellStyle title = workbook.createCellStyle();
		title.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 垂直居中
		title.setFont(titleFont);
		title.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		title.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		title.setWrapText(true);

		// 定义表头样式
		HSSFFont font = workbook.createFont();
		font.setFontHeightInPoints((short) 12);
		font.setFontName("宋体");
		HSSFCellStyle head = workbook.createCellStyle();
		head.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 垂直居中
		head.setFont(font);
		head.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		head.setBorderBottom((short) 1); // 设置边框样式
		head.setBorderLeft((short) 1); // 左边框
		head.setBorderRight((short) 1); // 右边框
		head.setBorderTop((short) 1); // 顶边框

		// 定义居中样式
		HSSFCellStyle center = workbook.createCellStyle();
		center.setFont(font);
		center.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		center.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		center.setBorderBottom((short) 1); // 设置边框样式
		center.setBorderLeft((short) 1); // 左边框
		center.setBorderRight((short) 1); // 右边框
		center.setBorderTop((short) 1); // 顶边框
		center.setWrapText(true);

		// 需要自动换行的样式
		HSSFCellStyle huanHang = workbook.createCellStyle();
		huanHang.setFont(font);
		huanHang.setAlignment(HSSFCellStyle.ALIGN_LEFT);
		huanHang.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		huanHang.setBorderBottom((short) 1); // 设置边框样式
		huanHang.setBorderLeft((short) 1); // 左边框
		huanHang.setBorderRight((short) 1); // 右边框
		huanHang.setBorderTop((short) 1); // 顶边框
		huanHang.setWrapText(true);

		// 定义小数数字样式
		HSSFCellStyle number = workbook.createCellStyle();
		number.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));// 小数保留两位
		number.setFont(font);
		number.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		number.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		number.setBorderBottom((short) 1); // 设置边框样式
		number.setBorderLeft((short) 1); // 左边框
		number.setBorderRight((short) 1); // 右边框
		number.setBorderTop((short) 1); // 顶边框

		// 定义整数数字样式
		HSSFCellStyle intNumber = workbook.createCellStyle();
		intNumber.setDataFormat(HSSFDataFormat.getBuiltinFormat("0"));// 小数保留两位
		intNumber.setFont(font);
		intNumber.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		intNumber.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		intNumber.setBorderBottom((short) 1); // 设置边框样式
		intNumber.setBorderLeft((short) 1); // 左边框
		intNumber.setBorderRight((short) 1); // 右边框
		intNumber.setBorderTop((short) 1); // 顶边框 

		// 定义居左样式
		HSSFCellStyle left = workbook.createCellStyle();
		left.setFont(font);
		left.setAlignment(HSSFCellStyle.ALIGN_LEFT); 
		left.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		left.setWrapText(true);

		try {
			for (int qindex = 0; qindex < conCount; qindex++) {
				/*--------------------------------------------
				该段代码为基于xml与反射的数据获取过程  已经略去
				-------------------------------------------------*/
				s1=(new Date()).getTime();
				// 产生工作表对象
				HSSFSheet sheet = workbook.createSheet();
				workbook.setSheetName(qindex, queryCondition.getSheetName() == null  tableName : queryCondition
						.getSheetName());

				int rowLen = objList.size();
				List<Column> colList = query.getColumnList();
				int colLen = colList.size();

				// 创建表头
				int hempty = 0;
           
				// 填充标题
				HSSFRow hrow = sheet.createRow(0);
				HSSFCell cell = hrow.createCell(0);
				hrow.setHeight((short) 1500);
				cell.setCellValue(new HSSFRichTextString(queryCondition.getSheetTitle() != null  queryCondition.getSheetTitle()
						: queryCondition.getSheetName()));
				cell.setCellStyle(title);
				int lastcol = -1;
				for (int h = 0; h < colLen; ++h) {
					Column hcolumn = colList.get(h);
					if (!hcolumn.getIsServerCondition() && !hcolumn.getHidden() && hcolumn.getIsExport()) {
						lastcol++;
					}
				}
				sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, lastcol));
                int titleRowCount=1;
                //填充副标题
                hrow = sheet.createRow(titleRowCount);
                if(queryCondition.getSheetSubTitle()!=null){
                	titleRowCount=2;
                    cell = hrow.createCell(0);
    				hrow.setHeight((short) 600);
    				cell.setCellValue(new HSSFRichTextString(queryCondition.getSheetSubTitle()));
    				cell.setCellStyle(left);  
    				sheet.addMergedRegion(new CellRangeAddress(1,1,0,lastcol));
    				hrow=sheet.createRow(titleRowCount);
                }       
				hrow.setHeight((short) 600);
				for (int h = 0; h < colLen; ++h) {
					Column hcolumn = colList.get(h);
					if ("rowIndex".equals(hcolumn.getKey())) {
						// 创建序号列
						HSSFCell hcell = hrow.createCell(0);
						hcell.setCellType(HSSFCell.CELL_TYPE_STRING);
						hcell.setCellStyle(head);
						hcell.setCellValue("序号");
						continue;
					}  
					if (!hcolumn.getIsServerCondition() && !hcolumn.getHidden() && hcolumn.getIsExport()) {
						// 创建表头列
						HSSFCell hcell = hrow.createCell(h - hempty);
						hcell.setCellType(HSSFCell.CELL_TYPE_STRING);
						hcell.setCellStyle(head);
						hcell.setCellValue(hcolumn.getHeader());
					} else { 
						++hempty;
					}
					sheet.autoSizeColumn((short) h);
				}   

				// 创建数据列表
				for (int b = 1; b <= rowLen; ++b) {
					// 创建一行数据列
					HSSFRow brow = sheet.createRow(b + titleRowCount);
					brow.setHeight((short) 500);
					int bempty = 0;
					Object obj = objList.get(b - 1);
					Row datarow = new Row();
					Map<String, Object> dataMap = null;
					if(objClass==null) {
						dataMap = (Map<String, Object>)obj;
						datarow.setId(dataMap.get(query.getKey()).toString());
					}else {
						Method method = objClass.getMethod(ObjectUtil.methodName(query.getKey(), "get"));
						datarow.setId((String) method.invoke(obj));
					} 

					for (int i = 0; i < colLen; ++i) {
						Column bcolumn = colList.get(i);
						if ("rowIndex".equals(bcolumn.getKey())) {
							// 设置当前列序号
							HSSFCell bcell = brow.createCell(i);
							bcell.setCellType(HSSFCell.CELL_TYPE_STRING);
							bcell.setCellStyle(intNumber);
							bcell.setCellValue(b);
							continue;
						} 
						String data = "";
						
						if(objClass!=null) {
							data = ObjectUtil.ObjectToString(obj, bcolumn.getKey(), bcolumn.getFormat());
						}else {
							if(Date.class.getName().equals(bcolumn.getClassType())||"date".equals(bcolumn.getClassType().toLowerCase())) {
								data = bcolumn.getFormat()!=null  DateUtil.format((Date)dataMap.get(bcolumn.getKey().toUpperCase()), bcolumn.getFormat())
										: DateUtil.format((Date)dataMap.get(bcolumn.getKey().toUpperCase()));
							}else {
								if(dataMap.get(bcolumn.getKey().toUpperCase())!=null) {
									data = dataMap.get(bcolumn.getKey().toUpperCase()).toString();
								}
							}
						}
						if (!bcolumn.getIsServerCondition() && !bcolumn.getHidden() && bcolumn.getIsExport()) {
							// 设置当前列值
							HSSFCell bcell = brow.createCell(i - bempty);

							// 单元格对齐
							if (bcolumn.getAlign().equals("center"))
								bcell.setCellStyle(center);
							else if (bcolumn.getAlign().equals("left"))
								bcell.setCellStyle(huanHang);
							// 单元格赋值
							if (bcolumn.getClassType().equals("java.lang.Double") && bcolumn.getSuffix() == null) {
								bcell.setCellStyle(number);
								bcell.setCellValue(Double.parseDouble(data));
							} else if (bcolumn.getClassType().equals("java.lang.Integer")) {
								bcell.setCellStyle(intNumber);
								bcell.setCellValue(Integer.parseInt(data));
							} else if (bcolumn.getSuffix() != null) {
								bcell.setCellValue(data + "%");
							} else {
								bcell.setCellValue(data);
							}
						} else {
							++bempty;
						}
						sheet.autoSizeColumn((short) i);
					}
				}
				//创建sheet完成后,根据前台参数执行 行合并、列合并、多表头等操作
				if(queryCondition.getSheetMethod()!=null){  
					String sheetMethod=queryCondition.getSheetMethod();
					String[] params=sheetMethod.split("_");
					//正文内容考试的行号索引
					int contentBeginIndex=1; 
					//含有副标题
					if(queryCondition.getSheetSubTitle()!=null)
						contentBeginIndex=2;
					if(params[0].equals("rowSpan")){ 
						  for(int i=1;i<params.length;i++){
							  sheet=ExcelUtil.rowSpan(sheet,Integer.valueOf(params[i]).intValue(),contentBeginIndex);
						  }
					}
					if(params[0].equals("display")) { //隐藏列 xxb 添加
						for(int i=1 ; i < params.length; i++){
							sheet.setColumnWidth(Integer.valueOf(params[i]).intValue(), (short) 0);
						}
					}
				}
			}
			
			String tempfile = System.currentTimeMillis()+"";
			fOut = new FileOutputStream(request.getRealPath("/") + "templates" + File.separator + "temp" + File.separator + tempfile + ".xls");
			// 导出excel 
			workbook.write(fOut);
			response.getWriter().print(tempfile);
			System.out.println(((new Date().getTime()-s1)/1000)+">>>>>>>>>>>>>>>>>>>>>>>>>>>"+((new Date()).getTime()-s)/1000);
		} catch (Exception e) {
		     e.printStackTrace();
		} finally {
			try {
				fOut.flush();
				fOut.close();
			} catch (Exception e2) {
			}
		}
	}
	


      JXL方式写Excel

   

	 /*
         * JXL方式数据导出 支持多 sheet导出,支持表名、sheet页、标题、副标题单独命名
	 * 2014-5-6性能优化
	 */ 
	
	@SuppressWarnings({ "unchecked", "deprecation" })
	@RequestMapping(value = "/exportSheetsDataJXL")
	public void exportSheetsDataJXL(String reqObjs, String tableName, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
        long s=(new Date()).getTime();
        long s1=0;
		List<QueryCondition> queryConditions = JSON.parseArray(reqObjs, QueryCondition.class);
		int conCount = queryConditions.size();
		String tempfile = System.currentTimeMillis()+"";
		OutputStream fOut = new FileOutputStream(request.getRealPath("/") + "templates" + File.separator + "temp" + File.separator + tempfile + ".xls");
		
		// 产生工作簿对象
		WritableWorkbook  workbook=Workbook.createWorkbook(fOut);

		// 定义标题样式
		WritableFont  titleFont = new WritableFont(WritableFont.TIMES,18,WritableFont.BOLD,false);
		WritableCellFormat title=new WritableCellFormat(titleFont);
		title.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
		title.setAlignment(jxl.format.Alignment.CENTRE);
		title.setBorder(Border.BOTTOM,BorderLineStyle.THIN);
		title.setBorder(Border.LEFT,BorderLineStyle.THIN);
		title.setBorder(Border.RIGHT,BorderLineStyle.THIN);
		title.setBorder(Border.TOP,BorderLineStyle.THIN);
		title.setWrap(true);
		// 定义表头样式
		WritableFont headfont = new WritableFont(WritableFont.TIMES,12,WritableFont.BOLD,false);;
		WritableCellFormat head = new WritableCellFormat(headfont);
		head.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
		head.setAlignment(jxl.format.Alignment.CENTRE);
		head.setBorder(Border.BOTTOM,BorderLineStyle.THIN);
		head.setBorder(Border.LEFT,BorderLineStyle.THIN);
		head.setBorder(Border.RIGHT,BorderLineStyle.THIN);
		head.setBorder(Border.TOP,BorderLineStyle.THIN);
		 
		WritableFont font = new WritableFont(WritableFont.TIMES,12,WritableFont.NO_BOLD,false);;
		// 定义居中样式
		WritableCellFormat center = new WritableCellFormat(font);
		center.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
		center.setAlignment(jxl.format.Alignment.CENTRE);
		center.setBorder(Border.BOTTOM,BorderLineStyle.THIN);
		center.setBorder(Border.LEFT,BorderLineStyle.THIN);
		center.setBorder(Border.RIGHT,BorderLineStyle.THIN);
		center.setBorder(Border.TOP,BorderLineStyle.THIN);

		// 需要自动换行的样式
		WritableCellFormat huanHang = new WritableCellFormat(font);
		huanHang.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
		huanHang.setAlignment(jxl.format.Alignment.CENTRE);
		huanHang.setBorder(Border.BOTTOM,BorderLineStyle.THIN);
		huanHang.setBorder(Border.LEFT,BorderLineStyle.THIN);
		huanHang.setBorder(Border.RIGHT,BorderLineStyle.THIN);
		huanHang.setBorder(Border.TOP,BorderLineStyle.THIN);
		huanHang.setWrap(true);

		// 定义小数数字样式
		NumberFormat nf = new NumberFormat("#.##"); 
		WritableCellFormat number = new WritableCellFormat(nf);
		number.setFont(font);
		number.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
		number.setAlignment(jxl.format.Alignment.CENTRE);
		number.setBorder(Border.BOTTOM,BorderLineStyle.THIN);
		number.setBorder(Border.LEFT,BorderLineStyle.THIN);
		number.setBorder(Border.RIGHT,BorderLineStyle.THIN);
		number.setBorder(Border.TOP,BorderLineStyle.THIN);
		
		// 定义整数数字样式
		NumberFormat intnf = new NumberFormat("#"); 
		WritableCellFormat intNumber = new WritableCellFormat(intnf);
		intNumber.setFont(font);
		intNumber.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
		intNumber.setAlignment(jxl.format.Alignment.CENTRE);
		intNumber.setBorder(Border.BOTTOM,BorderLineStyle.THIN);
		intNumber.setBorder(Border.LEFT,BorderLineStyle.THIN);
		intNumber.setBorder(Border.RIGHT,BorderLineStyle.THIN);
		intNumber.setBorder(Border.TOP,BorderLineStyle.THIN);
		
		// 定义居左样式
		WritableCellFormat left = new WritableCellFormat(font);
		left.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
		left.setBorder(Border.BOTTOM,BorderLineStyle.THIN);
		left.setBorder(Border.LEFT,BorderLineStyle.THIN);
		left.setBorder(Border.RIGHT,BorderLineStyle.THIN);
		left.setBorder(Border.TOP,BorderLineStyle.THIN);		
		left.setWrap(true); 

		CellView cv = new CellView();
		cv.setAutosize(true);
        cv.setSize(18); 
		try {
			for (int qindex = 0; qindex < conCount; qindex++) {
				/*--------------------------------------------
				该段代码为基于xml与反射的数据获取过程  已经略去
				-------------------------------------------------*/				
				s1=(new Date()).getTime();
				// 产生工作表对象
				WritableSheet sheet = workbook.createSheet(queryCondition.getSheetName() == null  tableName : queryCondition
						.getSheetName(),qindex);

				int rowLen = objList.size();
				List<Column> colList = query.getColumnList();
				int colLen = colList.size();

				// 创建表头
				int hempty = 0;
           
				// 填充标题
				Label label=new Label(0,0,queryCondition.getSheetTitle() != null queryCondition.getSheetTitle(): queryCondition.getSheetName(),title);
				int lastcol = -1;
				for (int h = 0; h < colLen; ++h) {
					Column hcolumn = colList.get(h);
					if (!hcolumn.getIsServerCondition() && !hcolumn.getHidden() && hcolumn.getIsExport()) {
						lastcol++;
					}
				}
				sheet.addCell(label);
				//sheet.mergeCells(int col1,int row1,int col2,int row2);//左上角到右下角
				sheet.setRowView(0,1500);
				sheet.mergeCells(0, 0, lastcol,0);
                int titleRowCount=1;
                //填充副标题
                if(queryCondition.getSheetSubTitle()!=null){
                	titleRowCount=2;
    				label=new Label(0,1,queryCondition.getSheetSubTitle(),left);
    				sheet.addCell(label);
    				sheet.setRowView(1,600,false);
    				sheet.mergeCells(0,1,lastcol,1);
                }       
                sheet.setRowView(titleRowCount,600,false);
				for (int h = 0; h < colLen; ++h) {
					Column hcolumn = colList.get(h);
					if ("rowIndex".equals(hcolumn.getKey())) {
						// 创建序号列
						label=new Label(0,titleRowCount,"序号",head);
						sheet.addCell(label);
						sheet.setColumnView(0,cv);
						continue;
					}  
					if (!hcolumn.getIsServerCondition() && !hcolumn.getHidden() && hcolumn.getIsExport()) {
						// 创建表头列
						label=new Label(h - hempty,titleRowCount,hcolumn.getHeader(),head);
						sheet.addCell(label);
						sheet.setColumnView(h-hempty,cv);
					} else { 
						++hempty;
					}					 
					
				}      

				// 创建数据列表
				for (int b = 1; b <= rowLen; ++b) {
					// 创建一行数据列
					sheet.setRowView(b+titleRowCount, 500);
					int bempty = 0;
					Object obj = objList.get(b - 1);
					Row datarow = new Row(); 
					Map<String, Object> dataMap = null;
					if(objClass==null) {
						dataMap = (Map<String, Object>)obj;
						datarow.setId(dataMap.get(query.getKey()).toString());
					}else {
						Method method = objClass.getMethod(ObjectUtil.methodName(query.getKey(), "get"));
						datarow.setId((String) method.invoke(obj));
					} 

					for (int i = 0; i < colLen; ++i) {
						Column bcolumn = colList.get(i);
						if ("rowIndex".equals(bcolumn.getKey())) {
							// 设置当前列序号
							jxl.write.Number num=new jxl.write.Number(0,b+titleRowCount,b,intNumber);
							sheet.addCell(num);
							continue; 
						} 
						String data = "";
						 
						if(objClass!=null) {
							data = ObjectUtil.ObjectToString(obj, bcolumn.getKey(), bcolumn.getFormat());
						}else {
							if(Date.class.getName().equals(bcolumn.getClassType())||"date".equals(bcolumn.getClassType().toLowerCase())) {
								data = bcolumn.getFormat()!=null  DateUtil.format((Date)dataMap.get(bcolumn.getKey().toUpperCase()), bcolumn.getFormat())
										: DateUtil.format((Date)dataMap.get(bcolumn.getKey().toUpperCase()));
							}else {
								if(dataMap.get(bcolumn.getKey().toUpperCase())!=null) {
									data = dataMap.get(bcolumn.getKey().toUpperCase()).toString();
								}
							}
						}
						if (!bcolumn.getIsServerCondition() && !bcolumn.getHidden() && bcolumn.getIsExport()) {
							// 设置当前列值
                            WritableCellFormat format=center;
							// 单元格对齐
							if (bcolumn.getAlign().equals("center")){
								 format=center;
							}
							else if (bcolumn.getAlign().equals("left")){
							     format=left;
							}
								//bcell.setCellStyle(huanHang);
							// 单元格赋值
							
							if (bcolumn.getClassType().equals("java.lang.Double") && bcolumn.getSuffix() == null) {
								jxl.write.Number num1=new jxl.write.Number(i-bempty,b+titleRowCount,Double.parseDouble(data),number);
								sheet.addCell(num1);
								sheet.setColumnView(i-bempty,cv);
							} else if (bcolumn.getClassType().equals("java.lang.Integer")) {
								jxl.write.Number num2=new jxl.write.Number(i-bempty,b+titleRowCount,Integer.parseInt(data),intNumber);
								sheet.addCell(num2);
								sheet.setColumnView(i-bempty,cv);
							} else if (bcolumn.getSuffix() != null) {
								label=new Label(i-bempty,b+titleRowCount,data+"%",format);
								sheet.addCell(label);
								sheet.setColumnView(i-bempty,cv);
							} else {  
								label=new Label(i-bempty,b+titleRowCount,data,format);
								sheet.addCell(label);
								sheet.setColumnView(i-bempty,cv);
							} 
						} else { 
							++bempty;
						} 
						
					}
				}
				//创建sheet完成后,根据前台参数执行 行合并、列合并、多表头等操作
				if(queryCondition.getSheetMethod()!=null){  
					String sheetMethod=queryCondition.getSheetMethod();
					String[] params=sheetMethod.split("_");
					//正文内容考试的行号索引
					int contentBeginIndex=1; 
					//含有副标题
					if(queryCondition.getSheetSubTitle()!=null)
						contentBeginIndex=2;
					if(params[0].equals("rowSpan")){ 
						  for(int i=1;i<params.length;i++){
							  sheet=JXLExcelUtil.rowSpan(sheet,Integer.valueOf(params[i]).intValue(),contentBeginIndex);
						  }
					}
					if(params[0].equals("display")) { 
						for(int i=1 ; i < params.length; i++){
							sheet.setColumnView(Integer.valueOf(params[i]).intValue(), 0);
						}
					}
				} 
				
			}
			// 导出excel 
			workbook.write(); 
			workbook.close();
			response.getWriter().print(tempfile);
			System.out.println(((new Date().getTime()-s1)/1000)+">>>>>>>>>>>>>>>>>>>>>>>>>>>"+((new Date()).getTime()-s)/1000);
		} catch (Exception e) {
		     e.printStackTrace();
		} finally {
			try {
				fOut.flush();
				fOut.close();
			} catch (Exception e2) {
			}
		}
	}


其中,JXL合并单元格的方法为


package com.cnpc.framework.utils;

import jxl.Cell;
import jxl.write.WritableSheet;

public final class JXLExcelUtil {

	/**
	 * 合并单元格(行合并),合并规则:内容相同则合并
	 * 
	 * @param sheet	       合并的sheet
	 * @param colIndex      合并列索引
	 * @return
	 */
	@SuppressWarnings("deprecation")
	public static WritableSheet rowSpan(WritableSheet sheet, int colindex, int contentBeginIndex) throws Exception {
		// 总行数
		int rowNum = sheet.getRows();
		Cell[] cells = sheet.getRow(1);
		// 正文内容应该从第二行开始,第一行为表头的标题
		int startRow = contentBeginIndex;
		String startValue = "";
		for (int i = contentBeginIndex; i <= rowNum; i++) {
			cells = sheet.getRow(i);
			String value = cells[colindex].getContents();
			if (i == contentBeginIndex) {
				startValue = value;
				continue;
			}
			if (StrUtil.isNotBlank(startValue) && StrUtil.isNotBlank(value) && startValue.equals(value)) {
				if (i == rowNum) //sheet.mergeCells(int col1,int row1,int col2,int row2);//左上角到右下角
					sheet.mergeCells(colindex,startRow, colindex,i);
				else
					continue;
			} else {
				if((i-1)>startRow)
					sheet.mergeCells(colindex,startRow, colindex,i - 1);
				startRow = i;
			}
			startValue=value;
		}
		return sheet;
	}
}

IT人知识库 该篇知识地址:http://www.itpeo.net/15310/3488249.html





编写框架代码的注意事项

错误处理: 对于运行时可能出现的环境运行错误,在框架内部不要用try完全处理掉,而是要显示向外部... ...

怎样在线程外部控制线程运行

一个在外部控制线程运行的一个论证实例。标准的java因为安全问题取消了stop等控制方法,我想看看能不能自己把它们... ...

推荐给每个找工作的IT毕业生--打鸡血书

本文忘了在哪里下载的了,转过来与各位共享 一、 求职历程总结 2007年1月10日,随着在三方协... ...

linux(ubuntu)下安装nginx 笔记

这两天突然想在ubuntu下 安装nginx模拟真实环境,第一次安装还真是一个充满奇异的旅程,走了很多歪路但也从中... ...

Unix crontab命令 添加定时任务

Unix crontab命令 添加定时任务 使用crontab命令要求root身份1. cr... ...

rfedfre

随手写了个android应用

最近比较闲,就边学边写,做了个android下的 dota 攻略型应用。 目前还没发布到市场上,也没有加广告,... ...

rfedfre

高仿QQ空间-进阶篇

更新说明: 一 增加了照片的墙的功能,可以让你的照片可以流动哦!不信,你去试试就知道啦,O(∩_∩)O哈哈哈~... ...

rfedfre

1.变量和常量

1 标识符 标识符就是用于给 Java 程序中变量、类、方法等命名的符号。 1>.  ... ...

The working copy "xxx" has uncommitted changes.

    进到它说提示的目录中,使用git reset --hard命... ...

zencart模板

我们是谁?      我们是对电子商务,zencart,Oscomme... ...

memcmp与strcmp区别

一、memcmp含义 Compare characters in two buffers. i... ...

map的用法(初级)

C++中map容器提供一个键值对容器,map与multimap差别仅仅在于multiple允许一个键对应多个值。本... ...

慎用异常(Exception)

异常对性能不利。 1.抛出异常首先要创建一个新的对象。 2.Throwable接口的构造函数调用名为fil... ...

改进fastjson的WriteClassName特性时的输出数据容量

在使用fastjson输出省市县三级信息时,数量高达300K,由于我们的数据结构相同,因此每个类都输出了完整的类名... ...

mongodb建立索引时怎么指定超时时间

mongodb自从2.2版本起为索引建立了TTL(time to live),可以指定一个类型为日期的字段为文档的... ...

JS日期格式化(从YYYY-MM-DD到日期类)

字符串格式日期利用阅读,但不利于标准化存储,可以通过以下函数转化为Javascript日期类: // date... ...

(翻译)H5数据流消息推送机制Event Source

关于数据推送,传统方法是前端(不)定时发送HTTP请求进行轮询。但这种方式非常的损耗服务器资源,不适合访问量高的情... ...

linux命令后台运行技巧整理(1)

所有内容搜集于网络,部分做了简单翻译 Linux提供了fg和bg命令,让你轻松调度正在运行的任务。 假设你... ...

rfedfre

基于标签方式的工作流启动及任务执行开发说明

基于现在的系统的整合需求,本系统提供基于标签的工作流整合方式,工作流的启动及执行下一步时,均需要通过可以通... ...

rfedfre

厦门 测试夹具

厦门 测试夹具    我司专\业制\作测试工装夹具治具、过锡炉回流焊治具、老化架、热... ...