`
53873039oycg
  • 浏览: 841318 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

POI导出Excel(1000列)优化方案记录

    博客分类:
  • poi
阅读更多

      中午我想了下,其实上午写的那个导出方法瓶颈在删除Excel的列,如果能提前删除,那速度就很快了,我也看了下项目的导出方法,发现是写List<List>数据,并不是我想象中的使用ResultSet,所以中午把我写的方法优化了下,导出速度还不错,现在我对我的方法很满意

 

   思路:

    (1)先遍历数据集得到满足值全部为0的index位置,记录到nullList中

    (2)删除表头中下标和nullList下标相同的数据

    (3)数据集写入时候判断是否在nullList中,有则跳过。

 

    下面直接上代码了,我就不解释了

    

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

import org.apache.poi.POIXMLProperties;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class 删除Excel的零值 {
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		删除Excel的零值 t = new 删除Excel的零值();
		XSSFWorkbook wb = new XSSFWorkbook();
		Map<String, XSSFCellStyle> styles = t.createStyles(wb);
		String sheetName = "测试数据";
		int startR = 2;// 第二行开始写数据
		int totalCol = 1000;
		XSSFSheet sheet = wb.createSheet(sheetName);
		int[] headInfo = new int[] { 9 + totalCol * 3, 9, 3 };
		System.out.println(headInfo[0] + "---=" + headInfo[1] + "---="
				+ headInfo[2]);
		long start = System.currentTimeMillis();
		// 填充数据
		t.createSheetBody(wb, sheet, styles, totalCol, startR, 40, headInfo);
		t.createExcelInfo(wb);
		String fileName = "f:/saveFile/temp/" + System.currentTimeMillis()
				+ ".xlsx";
		t.writeExcel(wb, fileName);
		System.out.println((System.currentTimeMillis() - start) / 1000 + "秒");
		styles = null;
		wb = null;
		startR = 0;// 删除标题列
	}

	private void createSheetTitle(XSSFSheet sheet, List headList,
			XSSFCellStyle headStyle) {
		createSheetTitle(sheet, 0, headList, headStyle);
	}

	/**
	 * 
	 * @param sheet
	 * @param styles
	 * @param startR
	 *            开始行
	 * @param totalNum
	 * @param headinfo
	 *            0:列总长度 1子列开始位置 2子列长度
	 * @throws Exception
	 */
	public void createSheetBody(XSSFWorkbook wb, XSSFSheet sheet,
			Map<String, XSSFCellStyle> styles, int totalCol, int startR,
			int totalNum, int[] headinfo) throws Exception {
		// 先产生所有的List数据,在挑选满足等于0的index,干掉index,在写如Excel
		XSSFCellStyle cell_style = styles.get("cell_center");
		XSSFCellStyle long_style = styles.get("cell_long");
		XSSFRow row = null;
		XSSFCell cell = null;
		//得到测试数据
		List<List<Object>> tmpDataList = generateTestData(startR, totalNum,
				headinfo);
		//产生表头数据
		List<String> header = generateExcelHead(totalCol);
		List<String> realHeader = new ArrayList<String>();
		List<Integer> nullList = deleteListNullValue(tmpDataList, headinfo);
		// 删除表头空的数据
		List<Object> dataList = null;
		int n = 0, col = 0;
		for (int i = 0, len = header.size(); i < len; i++) {
			if (n < nullList.size() && i == nullList.get(n)) {
				//注意为空的子标题数量
				for (int k = 1; k < headinfo[2]; k++) {
					i++;
				}
				n++;
			} else {
				realHeader.add(header.get(i));
			}
		}
		header = null;
		n = 0;
		// 创建表头
		createExcelHeader(wb, sheet, styles, realHeader);
		realHeader = null;
		for (int i = 0; i < totalNum; i++) {
			n = 0;
			col = 0;
			dataList = tmpDataList.get(i);
			row = sheet.createRow(startR);
			startR++;
			//公告列
			for (int s3 = 0, len3 = headinfo[1]; s3 < len3; s3++) {
				cell = row.createCell(s3);
				cell.setCellStyle(cell_style);
				cell.setCellValue(dataList.get(s3).toString());
				col++;
			}
			//判断下标是否满足条件
			for (int s4 = headinfo[1], len4 = headinfo[0]; s4 < len4; s4++) {
				//满足值为0,跳过
				if (n < nullList.size() && s4 == nullList.get(n)) {
					for (int k = 1; k < headinfo[2]; k++) {
						s4++;
					}
					n++;
				} else {
					cell = row.createCell(col);
					cell.setCellStyle(long_style);
					cell.setCellValue((Integer) dataList.get(s4));
					col++;
				}
			}
			cell = null;
			row = null;
			dataList.clear();
			dataList = null;
		}
		cell = null;
		row = null;
		dataList = null;
		nullList = null;
		tmpDataList = null;
	}

	// 产生随机数据
	public List<List<Object>> generateTestData(int startR, int totalNum,
			int[] headinfo) {
		int subTotal = (headinfo[0] - headinfo[1]) / headinfo[2] - 1;
		Random random = new Random();
		// 产生随机为0的列
		List<Integer> tmpList = new ArrayList<Integer>();
		for (int i = 0, len = subTotal * 3 / 4; i < len; i++) {
			tmpList.add(random.nextInt(subTotal) % (subTotal + 1));
		}
		// 去重
		Set<Integer> nullValue = new TreeSet(tmpList);
		int[] nullIndex = new int[nullValue.size()];
		int j = 0, n = 0;
		// 赋值给数组,保存为0的列的index
		for (Integer it : nullValue) {
			nullIndex[j++] = it;
		}
		System.out.println();
		List<List<Object>> tmpDataList = new ArrayList<List<Object>>();
		List<Object> dataList = null;
		random = new Random();
		for (int i = 1, len = totalNum + 1; i < len; i++) {
			dataList = new ArrayList<Object>();
			n = 0;
			dataList.add(i);
			for (int k = 1; k < headinfo[1]; k++) {
				dataList.add("测试" + (i));
			}
			j++;
			for (int k = 0; k < subTotal; k++) {
				if (n < nullIndex.length && k == nullIndex[n]) {
					for (int l = 0; l < headinfo[2]; l++) {
						dataList.add(0);
					}
					n++;
				} else {
					for (int l = 0; l < headinfo[2]; l++) {
						dataList.add(random.nextInt(8000));
					}
				}
			}
			for (int l = 0; l < headinfo[2]; l++) {
				dataList.add(random.nextInt(20000));
			}
			tmpDataList.add(dataList);
			dataList = null;
		}
		return tmpDataList;
	}

	public List<Integer> deleteListNullValue(List<List<Object>> tmpValueList,
			int[] headinfo) {
		List<Integer> tmpNullIndexList = new ArrayList<Integer>();
		List<Integer> nullIndexList = null;
		int startIndex = headinfo[1];
		int subLen = headinfo[2];
		int beforeIndex = 0;
		List<Object> list = null;
		boolean isFirst = true;
		for (int j = 0, len2 = tmpValueList.size(); j < len2; j++) {
			list = tmpValueList.get(j);
			nullIndexList = new ArrayList<Integer>();
			isFirst = true;
			for (int i = startIndex, len = list.size(); i < len; i++) {
				if (isFirst && "0".equals(list.get(i).toString())) {
					beforeIndex = i;
					isFirst = false;
				} else if (!"0".equals(list.get(i).toString())) {
					beforeIndex = i;
					isFirst = true;
				} else if (!isFirst && (i - beforeIndex + 1) == subLen) {
					nullIndexList.add(beforeIndex);
					isFirst = true;
				}
			}
			if (j == 0) {
				tmpNullIndexList = new ArrayList(nullIndexList);
			} else {
				tmpNullIndexList.retainAll(nullIndexList);
				tmpNullIndexList = new ArrayList(tmpNullIndexList);
			}
			nullIndexList.clear();
			nullIndexList = null;
		}
		for (Integer it : tmpNullIndexList) {
			System.out.print(it + ",");
		}
		System.out.println();
		list = null;
		nullIndexList = null;
		return tmpNullIndexList;
	}

	public void createExcelInfo(XSSFWorkbook workbook) {
		POIXMLProperties.CoreProperties coreProp = workbook.getProperties()
				.getCoreProperties();
		coreProp.setCreator("测试作者属性");
		coreProp.setCategory("测试类别属性");
		coreProp.setTitle("Excel标题属性");
		coreProp.setSubjectProperty("测试主题属性");
		coreProp.setKeywords("报表测试,POI测试");
	}

	/**
	 * 主要思路:优先把第一行跨多列的数据先合并,再合并第2行子数据,暂只支持2行N列 如果要修改该功能,建议重写一个更简单,如果看不懂我写的
	 * 
	 * @param sheet
	 * @startR 从第几行开始(下标从0开始)
	 * @param headList
	 * @param headStyle
	 */
	private void createSheetTitle(XSSFSheet sheet, int startR, List headList,
			XSSFCellStyle headStyle) {
		XSSFRow row_head_0 = null;
		XSSFRow row_head_1 = null;
		XSSFCell cell = null;
		// 保存未拆分时的值
		String attr = null;
		// 保存第一次拆分时的值
		String[] tmp = null;
		// 拆分后第一行的值
		String[] tmp2 = null;
		// 拆分后第2行的值
		String[] tmp3 = null;
		// 第一次匹配时的值
		String preAttr = null;
		// 下一次匹配时的值
		String lastAttr = null;
		int preIdx = 0;
		int start_row = startR;// 起始行
		int start_col = 0;// 起始列
		row_head_0 = sheet.createRow(start_row + 0);
		row_head_1 = sheet.createRow(start_row + 1);
		CellRangeAddress range = new CellRangeAddress(0, 0, 0, 0);
		for (int i = 0; i < headList.size(); i++) {
			attr = String.valueOf(headList.get(i));
			// 以$分割数据
			tmp = attr.split("\\$");
			if (tmp.length == 1) {
				cell = row_head_0.createCell(start_col + i);
				// #分割的是行 列信息
				cell.setCellValue(tmp[0].split("\\#")[0]);
				cell.setCellStyle(headStyle);
				cell = row_head_1.createCell(start_col + i);
				cell.setCellStyle(headStyle);
				// 创建cell主要是指定样式,防止跨列时少样式
				for (int k = start_col + i + 1; k <= start_col + i; k++) {
					row_head_0.createCell(k).setCellStyle(headStyle);
					row_head_1.createCell(k).setCellStyle(headStyle);
				}
				range.setFirstRow(start_row + 0);
				range.setLastRow(start_row + 1);
				range.setFirstColumn(start_col + i);
				range.setLastColumn(start_col + i);
				sheet.addMergedRegion(range);
				if ("xsd".equalsIgnoreCase(tmp[0].split("\\#")[0])) {
					sheet.setColumnWidth(i, 50 * 256); // 256基本单位
				} else if (tmp[0].split("\\#")[0].getBytes().length > 16) {
					sheet.setColumnWidth(i, 25 * 256); // 256基本单位
				}
				preIdx = i + 1;
			} else if (tmp.length == 2) {
				preAttr = tmp[0];
				tmp2 = tmp[0].split("\\#");
				tmp3 = tmp[1].split("\\#");
				int tmpI = Integer.parseInt(tmp2[2]);
				int tmpI2 = Integer.parseInt(tmp3[2]);
				if (!preAttr.equals(lastAttr)) {
					lastAttr = tmp[0];
					cell = row_head_0.createCell(start_col + i);
					cell.setCellValue(tmp2[0]);
					cell.setCellStyle(headStyle);
					// 创建cell主要是指定样式,防止跨列时少样式
					for (int k = start_col + preIdx + 1; k <= start_col
							+ preIdx + tmpI - 1; k++) {
						row_head_0.createCell(k).setCellStyle(headStyle);
					}
					range.setFirstRow(start_row + 0);
					range.setLastRow(start_row + 0);
					range.setFirstColumn(start_col + preIdx);
					range.setLastColumn(start_col + preIdx + tmpI - 1);
					sheet.addMergedRegion(range);
				}
				cell = row_head_1.createCell(start_col + i);
				cell.setCellValue(tmp3[0]);
				cell.setCellStyle(headStyle);
				// 第二行跨列
				if (tmpI2 != 1) {
					// 创建cell主要是指定样式,防止跨列时少样式
					for (int k = start_col + preIdx + 1; k <= start_col
							+ preIdx + tmpI2 - 1; k++) {
						row_head_1.createCell(k).setCellStyle(headStyle);
					}
					range.setFirstRow(start_row + 1);
					range.setLastRow(start_row + 1);
					range.setFirstColumn(start_col + preIdx);
					range.setLastColumn(start_col + preIdx + tmpI2 - 1);
					sheet.getRow(start_row + 1)
							.createCell(start_col + preIdx + tmpI2 - 1)
							.setCellStyle(headStyle);
					sheet.addMergedRegion(range);
					start_col = start_col + tmpI2 - 1;
				}
				preIdx++;
			}
		}
	}

	// 创建样式库
	private Map<String, XSSFCellStyle> createStyles(XSSFWorkbook wb) {
		Map<String, XSSFCellStyle> stylesMap = new HashMap<String, XSSFCellStyle>();
		XSSFCellStyle style = null;
		XSSFFont sheetFont = wb.createFont();
		sheetFont.setColor(IndexedColors.WHITE.getIndex());
		sheetFont.setFontName("楷体");
		sheetFont.setFontHeightInPoints((short) 10);
		sheetFont.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
		style = wb.createCellStyle();
		style.setFont(sheetFont);
		style.setFillForegroundColor(IndexedColors.AQUA.getIndex());
		style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
		style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
		style.setBorderTop(XSSFCellStyle.BORDER_DOTTED);
		style.setTopBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderLeft(XSSFCellStyle.BORDER_DOTTED);
		style.setLeftBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderRight(XSSFCellStyle.BORDER_DOTTED);
		style.setRightBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderBottom(XSSFCellStyle.BORDER_DOTTED);
		style.setBottomBorderColor(IndexedColors.WHITE.getIndex());
		stylesMap.put("sheet_title", style);

		sheetFont = wb.createFont();
		sheetFont.setColor(IndexedColors.WHITE.getIndex());
		sheetFont.setFontName("楷体");
		sheetFont.setFontHeightInPoints((short) 10);
		sheetFont.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
		style = wb.createCellStyle();
		style.setFont(sheetFont);
		style.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.getIndex());
		style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
		style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
		style.setBorderTop(XSSFCellStyle.BORDER_DOTTED);
		style.setTopBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderLeft(XSSFCellStyle.BORDER_DOTTED);
		style.setLeftBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderRight(XSSFCellStyle.BORDER_DOTTED);
		style.setRightBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderBottom(XSSFCellStyle.BORDER_DOTTED);
		style.setBottomBorderColor(IndexedColors.WHITE.getIndex());
		stylesMap.put("sheet_title_style", style);

		style = wb.createCellStyle();
		style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
		stylesMap.put("cell_center", style);

		style = wb.createCellStyle();
		XSSFDataFormat format = wb.createDataFormat();
		style.setDataFormat(format.getFormat("0"));
		style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
		stylesMap.put("cell_long", style);
		return stylesMap;
	}

	public void writeExcel(XSSFWorkbook wb, String fileName) {
		if (wb != null) {
			try {
				FileOutputStream fileOutStream = new FileOutputStream(fileName);
				wb.write(fileOutStream);
				if (fileOutStream != null) {
					fileOutStream.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public List<String> generateExcelHead(int subTotal) {
		List<String> header = new ArrayList<String>();
		header = new ArrayList<String>();
		// 表头_行数_列数$
		header.add("编号#2#1$");
		header.add("MSN#2#1$");
		header.add("一级标题#2#1$");
		header.add("二级标题#2#1$");
		header.add("品牌名#2#1$");
		header.add("型号#2#1$");
		header.add("颜色#2#1$");
		header.add("性质#2#1$");
		header.add("状态#2#1$");

		for (int i = 1; i < subTotal; i++) {
			header.add("下游合作商_" + i + "#1#3$数量#1#1$");
			header.add("下游合作商_" + i + "#1#3$金额#1#1$");
			header.add("下游合作商_" + i + "#1#3$小计#1#1$");
		}
		header.add("总数量#2#1$");
		header.add("总金额#2#1$");
		header.add("总计#2#1$");
		return header;
	}

	public void createExcelHeader(XSSFWorkbook wb, XSSFSheet sheet,
			Map<String, XSSFCellStyle> styles, List<String> header)
			throws Exception {
		XSSFCellStyle titleStyle = null;
		titleStyle = styles.get("sheet_title");
		// 为某一位sheet填充数据
		createSheetTitle(sheet, header, titleStyle);
		titleStyle = null;
		header = null;
	}
}

 

    结果为: 

 

   

 

    也可以使用SXSSFWorkbook,导出100行,1000列速度还不错

   

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

public class 删除Excel零值优化版 {
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		删除Excel零值优化版 t = new 删除Excel零值优化版();
		Workbook wb = new SXSSFWorkbook(200);
		Map<String, CellStyle> styles = t.createStyles(wb);
		String sheetName = "测试数据";
		int startR = 2;// 第二行开始写数据
		int totalCol = 1000;
		Sheet sheet = wb.createSheet(sheetName);
		int[] headInfo = new int[] { 9 + totalCol * 3, 9, 3 };
		System.out.println(headInfo[0] + "---=" + headInfo[1] + "---="
				+ headInfo[2]);
		long start = System.currentTimeMillis();
		// 填充数据
		t.createSheetBody(wb, sheet, styles, totalCol, startR, 100, headInfo);
		String fileName = "f:/saveFile/temp/" + System.currentTimeMillis()
				+ ".xlsx";
		t.writeExcel(wb, fileName);
		System.out.println((System.currentTimeMillis() - start) / 1000 + "秒");
		styles = null;
		wb = null;
		startR = 0;// 删除标题列
	}

	private void createSheetTitle(Sheet sheet, List headList,
			CellStyle headStyle) {
		createSheetTitle(sheet, 0, headList, headStyle);
	}

	/**
	 * 
	 * @param sheet
	 * @param styles
	 * @param startR
	 *            开始行
	 * @param totalNum
	 * @param headinfo
	 *            0:列总长度 1子列开始位置 2子列长度
	 * @throws Exception
	 */
	public void createSheetBody(Workbook wb, Sheet sheet,
			Map<String, CellStyle> styles, int totalCol, int startR,
			int totalNum, int[] headinfo) throws Exception {
		// 先产生所有的List数据,在挑选满足等于0的index,干掉index,在写如Excel
		CellStyle cell_style = styles.get("cell_center");
		CellStyle long_style = styles.get("cell_long");
		Row row = null;
		Cell cell = null;
		// 得到测试数据
		List<List<Object>> tmpDataList = generateTestData(startR, totalNum,
				headinfo);
		// 产生表头数据
		List<String> header = generateExcelHead(totalCol);
		List<String> realHeader = new ArrayList<String>();
		List<Integer> nullList = deleteListNullValue(tmpDataList, headinfo);
		// 删除表头空的数据
		List<Object> dataList = null;
		int n = 0, col = 0;
		for (int i = 0, len = header.size(); i < len; i++) {
			if (n < nullList.size() && i == nullList.get(n)) {
				// 注意为空的子标题数量
				for (int k = 1; k < headinfo[2]; k++) {
					i++;
				}
				n++;
			} else {
				realHeader.add(header.get(i));
			}
		}
		header = null;
		n = 0;
		// 创建表头
		createExcelHeader(wb, sheet, styles, realHeader);
		realHeader = null;
		for (int i = 0; i < totalNum; i++) {
			n = 0;
			col = 0;
			dataList = tmpDataList.get(i);
			row = sheet.createRow(startR);
			startR++;
			// 公告列
			for (int s3 = 0, len3 = headinfo[1]; s3 < len3; s3++) {
				cell = row.createCell(s3);
				cell.setCellStyle(cell_style);
				cell.setCellValue(dataList.get(s3).toString());
				col++;
			}
			// 判断下标是否满足条件
			for (int s4 = headinfo[1], len4 = headinfo[0]; s4 < len4; s4++) {
				// 满足值为0,跳过
				if (n < nullList.size() && s4 == nullList.get(n)) {
					for (int k = 1; k < headinfo[2]; k++) {
						s4++;
					}
					n++;
				} else {
					cell = row.createCell(col);
					cell.setCellStyle(long_style);
					cell.setCellValue((Integer) dataList.get(s4));
					col++;
				}
			}
			dataList.clear();
			dataList = null;
		}
		cell = null;
		row = null;
		dataList = null;
		nullList = null;
		tmpDataList = null;
	}

	// 产生随机数据
	public List<List<Object>> generateTestData(int startR, int totalNum,
			int[] headinfo) {
		int subTotal = (headinfo[0] - headinfo[1]) / headinfo[2] - 1;
		Random random = new Random();
		// 产生随机为0的列
		List<Integer> tmpList = new ArrayList<Integer>();
		for (int i = 0, len = subTotal * 3 / 4; i < len; i++) {
			tmpList.add(random.nextInt(subTotal) % (subTotal + 1));
		}
		// 去重
		Set<Integer> nullValue = new TreeSet(tmpList);
		int[] nullIndex = new int[nullValue.size()];
		int j = 0, n = 0;
		// 赋值给数组,保存为0的列的index
		for (Integer it : nullValue) {
			nullIndex[j++] = it;
		}
		System.out.println();
		List<List<Object>> tmpDataList = new ArrayList<List<Object>>();
		List<Object> dataList = null;
		random = new Random();
		for (int i = 1, len = totalNum + 1; i < len; i++) {
			dataList = new ArrayList<Object>();
			n = 0;
			dataList.add(i);
			for (int k = 1; k < headinfo[1]; k++) {
				dataList.add("测试" + (i));
			}
			j++;
			for (int k = 0; k < subTotal; k++) {
				if (n < nullIndex.length && k == nullIndex[n]) {
					for (int l = 0; l < headinfo[2]; l++) {
						dataList.add(0);
					}
					n++;
				} else {
					for (int l = 0; l < headinfo[2]; l++) {
						dataList.add(random.nextInt(8000));
					}
				}
			}
			for (int l = 0; l < headinfo[2]; l++) {
				dataList.add(random.nextInt(20000));
			}
			tmpDataList.add(dataList);
			dataList = null;
		}
		return tmpDataList;
	}

	public List<Integer> deleteListNullValue(List<List<Object>> tmpValueList,
			int[] headinfo) {
		List<Integer> tmpNullIndexList = new ArrayList<Integer>();
		List<Integer> nullIndexList = null;
		int startIndex = headinfo[1];
		int subLen = headinfo[2];
		int beforeIndex = 0;
		List<Object> list = null;
		boolean isFirst = true;
		for (int j = 0, len2 = tmpValueList.size(); j < len2; j++) {
			list = tmpValueList.get(j);
			nullIndexList = new ArrayList<Integer>();
			isFirst = true;
			for (int i = startIndex, len = list.size(); i < len; i++) {
				if (isFirst && "0".equals(list.get(i).toString())) {
					beforeIndex = i;
					isFirst = false;
				} else if (!"0".equals(list.get(i).toString())) {
					beforeIndex = i;
					isFirst = true;
				} else if (!isFirst && (i - beforeIndex + 1) == subLen) {
					nullIndexList.add(beforeIndex);
					isFirst = true;
				}
			}
			if (j == 0) {
				tmpNullIndexList = new ArrayList(nullIndexList);
			} else {
				tmpNullIndexList.retainAll(nullIndexList);
				tmpNullIndexList = new ArrayList(tmpNullIndexList);
			}
			nullIndexList.clear();
			nullIndexList = null;
		}
		for (Integer it : tmpNullIndexList) {
			System.out.print(it + ",");
		}
		System.out.println();
		list = null;
		nullIndexList = null;
		return tmpNullIndexList;
	}

	/**
	 * 主要思路:优先把第一行跨多列的数据先合并,再合并第2行子数据,暂只支持2行N列 如果要修改该功能,建议重写一个更简单,如果看不懂我写的
	 * 
	 * @param sheet
	 * @startR 从第几行开始(下标从0开始)
	 * @param headList
	 * @param headStyle
	 */
	private void createSheetTitle(Sheet sheet, int startR, List headList,
			CellStyle headStyle) {
		Row row_head_0 = null;
		Row row_head_1 = null;
		Cell cell = null;
		// 保存未拆分时的值
		String attr = null;
		// 保存第一次拆分时的值
		String[] tmp = null;
		// 拆分后第一行的值
		String[] tmp2 = null;
		// 拆分后第2行的值
		String[] tmp3 = null;
		// 第一次匹配时的值
		String preAttr = null;
		// 下一次匹配时的值
		String lastAttr = null;
		int preIdx = 0;
		int start_row = startR;// 起始行
		int start_col = 0;// 起始列
		row_head_0 = sheet.createRow(start_row + 0);
		row_head_1 = sheet.createRow(start_row + 1);
		CellRangeAddress range = new CellRangeAddress(0, 0, 0, 0);
		for (int i = 0; i < headList.size(); i++) {
			attr = String.valueOf(headList.get(i));
			// 以$分割数据
			tmp = attr.split("\\$");
			if (tmp.length == 1) {
				cell = row_head_0.createCell(start_col + i);
				// #分割的是行 列信息
				cell.setCellValue(tmp[0].split("\\#")[0]);
				cell.setCellStyle(headStyle);
				cell = row_head_1.createCell(start_col + i);
				cell.setCellStyle(headStyle);
				// 创建cell主要是指定样式,防止跨列时少样式
				for (int k = start_col + i + 1; k <= start_col + i; k++) {
					row_head_0.createCell(k).setCellStyle(headStyle);
					row_head_1.createCell(k).setCellStyle(headStyle);
				}
				range.setFirstRow(start_row + 0);
				range.setLastRow(start_row + 1);
				range.setFirstColumn(start_col + i);
				range.setLastColumn(start_col + i);
				sheet.addMergedRegion(range);
				if ("xsd".equalsIgnoreCase(tmp[0].split("\\#")[0])) {
					sheet.setColumnWidth(i, 50 * 256); // 256基本单位
				} else if (tmp[0].split("\\#")[0].getBytes().length > 16) {
					sheet.setColumnWidth(i, 25 * 256); // 256基本单位
				}
				preIdx = i + 1;
			} else if (tmp.length == 2) {
				preAttr = tmp[0];
				tmp2 = tmp[0].split("\\#");
				tmp3 = tmp[1].split("\\#");
				int tmpI = Integer.parseInt(tmp2[2]);
				int tmpI2 = Integer.parseInt(tmp3[2]);
				if (!preAttr.equals(lastAttr)) {
					lastAttr = tmp[0];
					cell = row_head_0.createCell(start_col + i);
					cell.setCellValue(tmp2[0]);
					cell.setCellStyle(headStyle);
					// 创建cell主要是指定样式,防止跨列时少样式
					for (int k = start_col + preIdx + 1; k <= start_col
							+ preIdx + tmpI - 1; k++) {
						row_head_0.createCell(k).setCellStyle(headStyle);
					}
					range.setFirstRow(start_row + 0);
					range.setLastRow(start_row + 0);
					range.setFirstColumn(start_col + preIdx);
					range.setLastColumn(start_col + preIdx + tmpI - 1);
					sheet.addMergedRegion(range);
				}
				cell = row_head_1.createCell(start_col + i);
				cell.setCellValue(tmp3[0]);
				cell.setCellStyle(headStyle);
				// 第二行跨列
				if (tmpI2 != 1) {
					// 创建cell主要是指定样式,防止跨列时少样式
					for (int k = start_col + preIdx + 1; k <= start_col
							+ preIdx + tmpI2 - 1; k++) {
						row_head_1.createCell(k).setCellStyle(headStyle);
					}
					range.setFirstRow(start_row + 1);
					range.setLastRow(start_row + 1);
					range.setFirstColumn(start_col + preIdx);
					range.setLastColumn(start_col + preIdx + tmpI2 - 1);
					sheet.getRow(start_row + 1)
							.createCell(start_col + preIdx + tmpI2 - 1)
							.setCellStyle(headStyle);
					sheet.addMergedRegion(range);
					start_col = start_col + tmpI2 - 1;
				}
				preIdx++;
			}
		}
	}

	// 创建样式库
	private Map<String, CellStyle> createStyles(Workbook wb) {
		Map<String, CellStyle> stylesMap = new HashMap<String, CellStyle>();
		CellStyle style = null;
		Font sheetFont = wb.createFont();
		sheetFont.setColor(IndexedColors.WHITE.getIndex());
		sheetFont.setFontName("楷体");
		sheetFont.setFontHeightInPoints((short) 10);
		sheetFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
		style = wb.createCellStyle();
		style.setFont(sheetFont);
		style.setFillForegroundColor(IndexedColors.AQUA.getIndex());
		style.setFillPattern(CellStyle.SOLID_FOREGROUND);
		style.setAlignment(CellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
		style.setBorderTop(CellStyle.BORDER_DOTTED);
		style.setTopBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderLeft(CellStyle.BORDER_DOTTED);
		style.setLeftBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderRight(CellStyle.BORDER_DOTTED);
		style.setRightBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderBottom(CellStyle.BORDER_DOTTED);
		style.setBottomBorderColor(IndexedColors.WHITE.getIndex());
		stylesMap.put("sheet_title", style);

		sheetFont = wb.createFont();
		sheetFont.setColor(IndexedColors.WHITE.getIndex());
		sheetFont.setFontName("楷体");
		sheetFont.setFontHeightInPoints((short) 10);
		sheetFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
		style = wb.createCellStyle();
		style.setFont(sheetFont);
		style.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.getIndex());
		style.setFillPattern(CellStyle.SOLID_FOREGROUND);
		style.setAlignment(CellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
		style.setBorderTop(CellStyle.BORDER_DOTTED);
		style.setTopBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderLeft(CellStyle.BORDER_DOTTED);
		style.setLeftBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderRight(CellStyle.BORDER_DOTTED);
		style.setRightBorderColor(IndexedColors.WHITE.getIndex());
		style.setBorderBottom(CellStyle.BORDER_DOTTED);
		style.setBottomBorderColor(IndexedColors.WHITE.getIndex());
		stylesMap.put("sheet_title_style", style);

		style = wb.createCellStyle();
		style.setAlignment(CellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
		stylesMap.put("cell_center", style);

		style = wb.createCellStyle();
		DataFormat format = wb.createDataFormat();
		style.setDataFormat(format.getFormat("0"));
		style.setAlignment(CellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
		stylesMap.put("cell_long", style);
		return stylesMap;
	}

	public void writeExcel(Workbook wb, String fileName) {
		if (wb != null) {
			try {
				FileOutputStream fileOutStream = new FileOutputStream(fileName);
				wb.write(fileOutStream);
				if (fileOutStream != null) {
					fileOutStream.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public List<String> generateExcelHead(int subTotal) {
		List<String> header = new ArrayList<String>();
		header = new ArrayList<String>();
		// 表头_行数_列数$
		header.add("编号#2#1$");
		header.add("MSN#2#1$");
		header.add("一级标题#2#1$");
		header.add("二级标题#2#1$");
		header.add("品牌名#2#1$");
		header.add("型号#2#1$");
		header.add("颜色#2#1$");
		header.add("性质#2#1$");
		header.add("状态#2#1$");

		for (int i = 1; i < subTotal; i++) {
			header.add("下游合作商_" + i + "#1#3$数量#1#1$");
			header.add("下游合作商_" + i + "#1#3$金额#1#1$");
			header.add("下游合作商_" + i + "#1#3$小计#1#1$");
		}
		header.add("总数量#2#1$");
		header.add("总金额#2#1$");
		header.add("总计#2#1$");
		return header;
	}

	public void createExcelHeader(Workbook wb, Sheet sheet,
			Map<String, CellStyle> styles, List<String> header)
			throws Exception {
		CellStyle titleStyle = null;
		titleStyle = styles.get("sheet_title");
		// 为某一位sheet填充数据
		createSheetTitle(sheet, header, titleStyle);
		titleStyle = null;
		header = null;
	}
}

    待解决问题:  

    (1)多个Excel合并为一个Excel

   

    本文系原创,转载请注明出处,谢谢

    全文完。

 

  

 

  • 大小: 371.4 KB
0
2
分享到:
评论
5 楼 18335864773 2017-06-13  
用pageoffice生成excel吧。poi生成excel代码复杂,速度也慢。POI使用的xml处理对象本身就消耗内存,它要把整个文档都加载到内存,加上其他开销,比实际Word、Excel文档还大,遇到打开较大的Word、Excel文档时,JVM很容易内存溢出。用PageOffice提取Word、Excel文档中的内容,40MB大小的文档没问题,100MB大小的文档也无压力。
4 楼 53873039oycg 2014-04-19  
sffylet 写道
请教个问题
在使用POI 导出excel文件后,该文件的sharedStrings.xml内容丢失,导致再用该文件导入时
SharedStringsTable sst = r.getSharedStringsTable(); 无法获取
必须将导出文件打开保存一下才能生成sharedStrings.xml内容,不知道是什么原因

不好意思,这个不知道是什么原因引起的。
3 楼 sffylet 2014-04-19  
请教个问题
在使用POI 导出excel文件后,该文件的sharedStrings.xml内容丢失,导致再用该文件导入时
SharedStringsTable sst = r.getSharedStringsTable(); 无法获取
必须将导出文件打开保存一下才能生成sharedStrings.xml内容,不知道是什么原因
2 楼 53873039oycg 2014-03-26  
freezingsky 写道
看你思路的意思,也就是说,在插入到excel之前,把不必要的数据从List里先删除。

没有删除,只是在写的时候判断是否在nullList里面,有,则跳过,删除的数据是表头list里面的数据,其实也可以跳过处理。欢迎提出更好的方法,谢谢。
1 楼 freezingsky 2014-03-26  
看你思路的意思,也就是说,在插入到excel之前,把不必要的数据从List里先删除。

相关推荐

    poi导出excel2007

    ### 使用Apache POI导出Excel 2007并避免内存溢出问题 #### 背景介绍 在处理大量数据时,使用Java导出Excel文件可能会遇到内存溢出的问题,尤其是在导出Excel 2007(.xlsx格式)时更为常见。这是因为传统的`...

    SpringBoot +Mybatis +POI导入、导出Excel文件

    总的来说,"SpringBoot + Mybatis + POI导入、导出Excel文件"的项目是一个实用的工具,可以帮助开发者快速实现数据交换功能,提高工作效率。通过理解SpringBoot的自动配置、Mybatis的SQL映射以及POI的Excel操作,...

    SpringBootMybatis+poi+Thymeleaf实现excel文件数据导入到数据库以及从数据库将数据导出成excel.zip

    在本项目中,"SpringBootMybatis+poi+Thymeleaf实现excel文件数据导入到数据库以及从数据库将数据导出成excel.zip",我们主要关注的是如何利用Java技术栈来处理Excel文件,并与数据库进行交互。以下是相关知识点的...

    java解决大批量数据导出Excel产生内存溢出的方案

    - 使用如JExcelApi、OpenCSV等其他第三方库,它们可能提供了更优化的数据导出方案,尤其是针对大数据量。 7. **优化Excel文件格式**: - 如果可能,可以考虑使用CSV格式代替Excel,因为CSV文件对内存的需求较低,...

    导出数据库的表结构到Excel

    标题提到的"导出数据库的表结构到Excel"就是一个这样的解决方案,它提供了一种方法将数据库中的表结构信息转换成Excel表格,便于分享、审查或进一步处理。 这个源码包和Release包可能包含了一个应用程序或者一组...

    java导出Excel(s2sh)

    ### Java 导出 Excel 在 S2SH 项目中的实现 #### 概述 在 Java 开发过程中,常常需要处理各种格式的数据文件,其中 Excel 文件因其便捷性和通用性被广泛使用。Struts2、Spring 和 Hibernate(简称 S2SH)作为经典...

    java导出30万数据量的excel(采用生成多个excel,最后打包zip)

    在Java开发中,处理大数据量的Excel导出是一项常见的任务,尤其当数据量达到数十万条时,单个Excel文件可能会遇到性能瓶颈或格式限制。本项目针对这一问题提出了一种解决方案,即分块生成多个Excel文件,然后将它们...

    导出Excel多个单元格合并及图片插入

    ### 导出Excel多个单元格合并及图片插入 #### 问题描述 在安全生产项目中,为了更好地管理和展示巡检记录,通常需要将这些记录导出为Excel文件,并且每个巡检项都应附带相应的抓图。这不仅要求能够有效地处理数据...

    ExtJS实现Excel导出

    ExtJS,作为一种强大的前端框架,能够帮助开发者构建复杂的Web应用程序,其在实现Excel导出方面的解决方案也备受关注。 #### 极致解析:ExtJS中的Excel导出机制 **1. 概念理解** ExtJS是一种基于客户端的AJAX应用...

    Java_批量导出大数据量Excel方法.zip

    在Java开发中,批量导出大数据量到...通过以上方法,开发者可以构建一个高效且健壮的Java批量导出大数据量到Excel的解决方案。具体实现细节可能在提供的excelproj和ExpXLS文件中有所体现,建议解压后仔细研究源代码。

    Java实现数据库数据导出到excel,内有数据连接jar包

    综上所述,这个Java项目提供了从数据库到Excel的数据导出功能,使用了JDBC进行数据库连接,借助Apache POI处理Excel文件,是学习和实践这一技术的好例子。通过理解这些知识点,开发者可以构建自己的数据导出工具,...

    Java中Excel转图片工具包(纯java)

    "Java中Excel转图片工具包(纯java)"就是这样一个解决方案,它实现了将Excel文件通过PDF中间格式转化为图片的功能。 首先,让我们了解一下这个工具包的工作原理。Excel文件本身并不直接支持转换为图片格式,但可以...

    我的boss的excel导出解决方案20170316

    - **方案名称**:我的boss的Excel导出解决方案20170316 - **适用范围**:根据描述,这是一个针对个人使用的解决方案,并不适用于所有场景,因此在实际应用中需要评估其通用性和适用性。 #### 二、方案核心功能 - **...

    使用xls或xlsx模板(jxls语法)导出Excel并下载的Demo

    而当我们需要在Web应用程序中实现动态生成和导出Excel文件时,一种高效的方法是利用模板和特定的库,如jxls。本文将深入探讨如何使用jxls库,结合xls或xlsx模板,来实现Excel文件的导出和下载。 首先,了解jxls。...

    Excel 导出 struts2 spring hibernate

    在导入导出Excel时,它会用于读取或写入数据库记录。 接下来,我们将讨论Excel数据的导入导出过程: - **导出**:在JSP+SSH环境下,导出通常在Action类中触发。首先,需要使用Apache POI库创建一个Workbook对象,...

    J2EE项目开发Excel导入导出操作组件源代码(附带说明文档).rar

    本组件专注于解决这一问题,提供了一套完整的J2EE项目开发中进行Excel导入导出的解决方案。以下是关于这个组件的详细知识点: 1. **Excel文件格式**: - Excel文件主要基于两种格式:`.xls`(老版本,Excel 97-...

    javaweb Excel生成器

    JavaWeb Excel生成器通过提供一个通用的解决方案,消除了针对每种报表定制导出代码的繁琐工作。 生成Excel文件的核心技术主要涉及以下几点: 1. **Apache POI库**:Apache POI是Java中广泛使用的API,用于读取和...

    J2EE项目开发Excel导入导出操作组件源代码(附带说明文档)

    总之,这个J2EE项目开发的Excel导入导出组件利用了Java的Apache POI库,实现了高效且灵活的Excel数据处理。开发者可以通过学习和使用这个组件,快速地在自己的项目中实现Excel数据的导入导出功能,提升开发效率,...

    excel 导入导出

    使用Apache POI,你可以打开一个现有的Excel文件,然后遍历其行和列来获取数据。读取数据后,可能需要进行数据验证、转换和清理,以确保数据符合系统的输入要求。最后,这些数据可能通过JDBC或者其他的持久化框架...

Global site tag (gtag.js) - Google Analytics