Java使用Apache的POI读写Excel,使用HSSFWorkbook、XSSFWorkbook和SXSSFWorkbook对Excel做拆分合并操作

一、使用Apache的POI操作Excel需要的jar包

注意:POI的jar不同版本要求jdk版本不同,根据自己jdk版本选择不同版本。我用的jdk1.6,下载的3.17版本的POI。
其中commons-collections4是poi的依赖jar包,poi-ooxml-schemas和xmlbeans是poi-ooxml的依赖jar包,如果使用maven自动下载只在pom文件中添加poi和poi-ooxml就可以,如果自己下载jar包添加到项目中则5个都需要下载并添加。

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.17</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.17</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>3.17</version>
</dependency>
<dependency>
    <groupId>org.apache.xmlbeans</groupId>
    <artifactId>xmlbeans</artifactId>
    <version>3.1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.1</version>
</dependency>

二、实现Excel的读写

操作xls后缀的Excel用HSSFWorkbook,操作xlsx后缀的Excel用XSSFWorkbook或者SXSSFWorkbook。SXSSFWorkbook可以指定多少条数据保存在内存中,其余数据保存在磁盘中,防止写入数据太大导致内存溢出。关于两种Excel区别和三个类的具体区别可另行百度。
注意:使用XSSFWorkbook读取xlsx类型Excel时,会将Excel所有内容一次性加载放到内存中包括空行也会读取出来,如果数据量巨大或者有巨多空行时会比较耗时。此次写入只判断了读取到的是否是空行,没有研究怎么快速读取大数据量的xlsx。
1、读取Excel
方法中调用的其他方法可在HandleFile类完整内容中寻找

	/**
	 * 将Excel的标题行内容放入list中,获取所有内容可循环所有行,每一行在循环所有列
	 * @param path
	 * @param filename
	 * @param fileType
	 */
	public void readExcel(String path, String filename, String fileType) {
		Workbook wb = null;
		try {
			wb = getWorkbook(wb,path,filename,fileType);
			Sheet sheet = wb.getSheetAt(0);// 获取第一个sheet页
			int countrow = sheet.getPhysicalNumberOfRows();// 获取sheet页的总行数
			if (countrow==0) { throw new Exception("Excel读取到的总行数为0"); }
			Row row0 = sheet.getRow(0);// 获取第0行的标题行
			List<String> titleList = new ArrayList<String>(); //保存标题
			for (int k = 0; k < row0.getPhysicalNumberOfCells(); k++) {// 循环所有列,放入list中
				Cell cell = row0.getCell(k);
				titleList.add(getString(cell));
			}
		} catch (Exception e) {
			addMsg("Excel在读取内容时出错:"+e+"\r\n***********************************************************************************************************************************************************");
		} finally {
			if (wb!=null) { try{wb.close(); }catch(Exception e) {}}
		}
	}

2、写入Excel
方法中调用的其他方法可在HandleFile类完整内容中寻找

	/**
	 * 将list中的内容写入Excel的一行中
	 * @param path	文件路径
	 * @param fileName	写入Excel的文件名带后缀
	 * @param fileType	写入Excel的文件类型,xls、xlsx
	 * @param titleList	要写入Excel的list数据
	 */
	public void writeRxcel(String path, String fileName, String fileType, List<String> titleList) {
		Workbook wb = null; Sheet sheet = null;
		try {
			File file = new File(path+fileName);
			if (file.exists()) {// 追加
				wb = getWorkbook(wb, path, fileName, fileType);
				sheet = wb.getSheetAt(0);
			} else {// 新创建并写入
				file.createNewFile();// 创建文件
				wb = createWorkbook(wb, fileType);
				sheet = wb.createSheet();
			}
			
			int numRow = sheet.getPhysicalNumberOfRows();// 当前sheet页有多少行
			Row row = sheet.createRow(numRow);// 在下一行创建row对象
			for (int k = 0; k < titleList.size(); k++) {
				row.createCell(k, CellType.STRING).setCellValue(titleList.get(k));
			}
			
			FileOutputStream fout = new FileOutputStream(file);
			wb.write(fout);
            fout.close();
		} catch (Exception e) {
			//e.printStackTrace();
			addMsg("写入Excel时出错:"+e+"\r\n***********************************************************************************************************************************************************");
		}
	}

三、Excel的拆分

将Excel按某一列不同的值拆分成不同的Excel,相同的值保存在相同的Excel中。将新生成的Excel和拆分的Excel打包在一个zip中。
方法中调用的其他方法可在HandleFile类完整内容中寻找

	/**
	 * 将Excel按某一列不同的值拆分成不同的Excel,相同的值保存在相同的Excel中。将新生成的Excel和拆分的Excel打包在一个zip中
	 * @param path	文件所在路径
	 * @param filename	文件名带后缀,文件名中带着_日期,例如拆分Excel_20220829.xlsx
	 * @param fileType	文件类型
	 * @param fileZip	创建的压缩文件名
	 * @return
	 */
	public String handlingExcel(String path, String filename, String fileType, String fileZip) {
		long sj1 = System.currentTimeMillis(); String re = "OK"; Workbook wb = null;
		try {
			//获取文件名中的日期
			String strDate = filename.substring(filename.lastIndexOf("_")+1, filename.lastIndexOf("."));
			int splitNum = -1;
			Map<Object,List<Object>> map = new HashMap<Object,List<Object>>();
			wb = getWorkbook(wb,path,filename,fileType);
			Sheet sheet = wb.getSheetAt(0);
			int countrow = sheet.getPhysicalNumberOfRows();// 总行数
			if (countrow==0) { throw new Exception("Excel读取到的总行数为0"); }
			Row row0 = sheet.getRow(0);//第0行是标题
			List<Object> titleList = new ArrayList<Object>();// 保存Excel的标题行所有标题
			for (int k = 0; k < row0.getPhysicalNumberOfCells(); k++) {// 循环所有列,放入list中
				Cell cell = row0.getCell(k);
				titleList.add(getString(cell));
				if ("AAB301".equals(getString(cell))) {// 要按哪一列进行拆分的那一列的标题名
					splitNum = k;
				}
			}
			if (splitNum<0) { splitNum=1; } // 没有匹配的标题名默认用第二列作为拆分,也可在此抛出异常
			
			List<Object> rowList = new ArrayList<Object>(); List<Object> cellList = new ArrayList<Object>();
			for (int i = 1; i < countrow; i++) {//数据从第1行开始
				Row row = sheet.getRow(i);
				if (isEmptyRow(row)) { continue; }// 判断是否是空行
				Cell titleCell = row.getCell(splitNum);
				String aab301 = getString(titleCell);
				rowList = new ArrayList<Object>(); cellList = new ArrayList<Object>();// 每次都先清除列数据list中的数据,用clear方法会导致其他引用list的地方也变成空
				for(int j = 0; j < row.getPhysicalNumberOfCells(); j++) {// 循环所有列,放入list中
					Cell cell = row.getCell(j);
					cellList.add(getString(cell));
				}
				
				/**
				 * map中key保存的是要拆分的列中不同的值,value保存的是rowList数据对应Excel中的行数据。
				 * rowList中保存的是cellList相当于保存了拆分列等于key的所有行,cellList保存的是一行中所有列的数据。
				 */
				if (map.containsKey(aab301+"_"+strDate)) {
					rowList = map.get(aab301+"_"+strDate);
					rowList.add(cellList);
					map.put(aab301+"_"+strDate, rowList);
					if (rowList.size() >= 100) {// 每一百条写入一次Excel
						writeExcel(path,aab301+"_"+strDate+"."+fileType,fileType,rowList,titleList);
						//清空map中的list
						map.put(aab301+"_"+strDate, new ArrayList<Object>());
					}
				} else {
					rowList.add(cellList);
					map.put(aab301+"_"+strDate, rowList);
				}
			}
			
			// 循环map,将不足100条的也写入Excel中
			Set<Map.Entry<Object, List<Object>>> entries = map.entrySet();
			Iterator<Map.Entry<Object, List<Object>>> iterators = entries.iterator();
			while (iterators.hasNext()) {
				Map.Entry<Object, List<Object>> next = iterators.next();
				writeExcel(path,String.valueOf(next.getKey())+"."+fileType,fileType,next.getValue(),titleList);
			}
			
			// 创建压缩文件
			zip(path, path+fileZip);
		} catch (Exception e) {
			re = e.toString();
			//e.printStackTrace();
			addMsg("拆分Excel在读取内容时出错:"+e+"\r\n***********************************************************************************************************************************************************");
		} finally {
			if (wb!=null) { try{wb.close(); }catch(Exception e) {}}
		}
		addMsg("拆分Excel结束,用时:"+((System.currentTimeMillis() - sj1)+"ms")+"\r\n***********************************************************************************************************************************************************");
		return re;
	}

四、Excel的合并

方法中调用的其他方法可在HandleFile类完整内容中寻找

	/**
	 * 将多个Excel合并成一个Excel
	 * @param path	压缩文件路径
	 * @param filename	压缩文件zip文件名带后缀
	 * @param fileDownLoad	要生成的Excel文件名带后缀
	 * @return
	 */
	public String handlingZip(String path, String filename, String fileDownLoad) {
		long sj1=System.currentTimeMillis(); String re = "OK";
		try {
			//解压文件
			unzip(path+filename, path);
			
			List<File> files = new ArrayList<File>();
			getAllFiles(files,path);
			mergeFile(path,fileDownLoad,files);
		} catch (Exception e) {
			addMsg("合并Excel时出错:"+e+"\r\n");
		}
		addMsg("合并Excel结束,用时:"+((System.currentTimeMillis() - sj1)+"ms")+"\r\n***********************************************************************************************************************************************************");
		return re;
	}

五、测试用的类HandleFile

其中压缩文件用到的jar包

<dependency>
    <groupId>org.apache.ant</groupId>
    <artifactId>ant</artifactId>
    <version>1.8.2</version>
</dependency>

HandleFile类完整内容


import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
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.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Expand;
import org.apache.tools.ant.taskdefs.Zip;

public class HandleFile {
	public static StringBuffer strMsg = new StringBuffer();
	
	public void addMsg(String s){ strMsg.append(getTime()+","+s+"\n"); if (strMsg.length()>200000) strMsg.delete(0,100000); }
	
	public String getTime() { return getTime(System.currentTimeMillis(), "yyyyMMddHHmmss"); }
	
	public String getTime(long time, String format) { if (time <= 0) { return ""; } else { return new SimpleDateFormat(format).format(new Date(time)); } }
	
	/**
	 * 将Excel的标题行内容放入list中
	 * @param path
	 * @param filename
	 * @param fileType
	 */
	public void readExcel(String path, String filename, String fileType) {
		Workbook wb = null;
		try {
			wb = getWorkbook(wb,path,filename,fileType);
			Sheet sheet = wb.getSheetAt(0);// 获取第一个sheet页
			int countrow = sheet.getPhysicalNumberOfRows();// 获取sheet页的总行数
			if (countrow==0) { throw new Exception("Excel读取到的总行数为0"); }
			Row row0 = sheet.getRow(0);// 获取第0行的标题行
			List<String> titleList = new ArrayList<String>(); //保存标题
			for (int k = 0; k < row0.getPhysicalNumberOfCells(); k++) {// 循环所有列,放入list中
				Cell cell = row0.getCell(k);
				titleList.add(getString(cell));
			}
		} catch (Exception e) {
			addMsg("拆分Excel在读取内容时出错:"+e+"\r\n***********************************************************************************************************************************************************");
		} finally {
			if (wb!=null) { try{wb.close(); }catch(Exception e) {}}
		}
	}
	
	/**
	 * 将list中的内容写入Excel的一行中
	 * @param path	文件路径
	 * @param fileName	写入Excel的文件名带后缀
	 * @param fileType	写入Excel的文件类型,xls、xlsx
	 * @param titleList	要写入Excel的list数据
	 */
	public void writeRxcel(String path, String fileName, String fileType, List<String> titleList) {
		Workbook wb = null; Sheet sheet = null;
		try {
			File file = new File(path+fileName);
			if (file.exists()) {// 追加
				wb = getWorkbook(wb, path, fileName, fileType);
				sheet = wb.getSheetAt(0);
			} else {// 新创建并写入
				file.createNewFile();// 创建文件
				wb = createWorkbook(wb, fileType);
				sheet = wb.createSheet();
			}
			
			int numRow = sheet.getPhysicalNumberOfRows();// 当前sheet页有多少行
			Row row = sheet.createRow(numRow);// 在下一行创建row对象
			for (int k = 0; k < titleList.size(); k++) {
				row.createCell(k, CellType.STRING).setCellValue(titleList.get(k));
			}
			
			FileOutputStream fout = new FileOutputStream(file);
			wb.write(fout);
            fout.close();
		} catch (Exception e) {
			//e.printStackTrace();
			addMsg("写入Excel时出错:"+e+"\r\n***********************************************************************************************************************************************************");
		}
	}
	
	/**
	 * 将Excel按某一列不同的值拆分成不同的Excel,相同的值保存在相同的Excel中。将新生成的Excel和拆分的Excel打包在一个zip中
	 * @param path	文件所在路径
	 * @param filename	文件名带后缀,文件名中带着_日期,例如拆分Excel_20220829.xlsx
	 * @param fileType	文件类型
	 * @param fileZip	创建的压缩文件名
	 * @return
	 */
	public String handlingExcel(String path, String filename, String fileType, String fileZip) {
		long sj1=System.currentTimeMillis(); String re = "OK"; Workbook wb = null;
		try {
			String strDate = filename.substring(filename.lastIndexOf("_")+1, filename.lastIndexOf("."));
			int splitNum = -1;
			Map<Object,List<Object>> map = new HashMap<Object,List<Object>>();
			wb = getWorkbook(wb,path,filename,fileType);
			Sheet sheet = wb.getSheetAt(0);
			int countrow = sheet.getPhysicalNumberOfRows();// 总行数
			if (countrow==0) { throw new Exception("Excel读取到的总行数为0"); }
			Row row0 = sheet.getRow(0);//第0行是标题
			List<Object> titleList = new ArrayList<Object>();
			for (int k = 0; k < row0.getPhysicalNumberOfCells(); k++) {// 循环所有列,放入list中
				Cell cell = row0.getCell(k);
				titleList.add(getString(cell));
				if ("AAB301".equals(getString(cell))) {// 要按哪一列进行拆分的那一列的标题名
					splitNum = k;
				}
			}
			if (splitNum<0) { splitNum=1; }
			
			List<Object> rowList = new ArrayList<Object>(); List<Object> cellList = new ArrayList<Object>();
			for (int i = 1; i < countrow; i++) {//数据从第1行开始
				Row row = sheet.getRow(i);
				if (isEmptyRow(row)) { continue; }
				Cell titleCell = row.getCell(splitNum);
				String aab301 = getString(titleCell);
				rowList = new ArrayList<Object>(); cellList = new ArrayList<Object>();// 每次都先清除列数据list中的数据,用clear方法会导致其他引用list的地方也变成空
				for(int j = 0; j < row.getPhysicalNumberOfCells(); j++) {// 循环所有列,放入list中
					Cell cell = row.getCell(j);
					cellList.add(getString(cell));
				}
				
				if (map.containsKey(aab301+"_"+strDate)) {
					rowList = map.get(aab301+"_"+strDate);
					rowList.add(cellList);
					map.put(aab301+"_"+strDate, rowList);
					if (rowList.size() >= 100) {// 每一百条写入一次Excel
						writeExcel(path,aab301+"_"+strDate+"."+fileType,fileType,rowList,titleList);
						//清空map中的list
						map.put(aab301+"_"+strDate, new ArrayList<Object>());
					}
				} else {
					rowList.add(cellList);
					map.put(aab301+"_"+strDate, rowList);
				}
			}
			
			// 循环map,将不足100条的也写入Excel中
			Set<Map.Entry<Object, List<Object>>> entries = map.entrySet();
			Iterator<Map.Entry<Object, List<Object>>> iterators = entries.iterator();
			while (iterators.hasNext()) {
				Map.Entry<Object, List<Object>> next = iterators.next();
				writeExcel(path,String.valueOf(next.getKey())+"."+fileType,fileType,next.getValue(),titleList);
			}
			
			// 创建压缩文件
			zip(path, path+fileZip);
		} catch (Exception e) {
			re = e.toString();
			//e.printStackTrace();
			addMsg("拆分Excel在读取内容时出错:"+e+"\r\n***********************************************************************************************************************************************************");
		} finally {
			if (wb!=null) { try{wb.close(); }catch(Exception e) {}}
		}
		addMsg("拆分Excel结束,用时:"+((System.currentTimeMillis() - sj1)+"ms")+"\r\n***********************************************************************************************************************************************************");
		return re;
	}
	
	public Workbook createWorkbook(Workbook wb, String fileType) {
		try {
			if ("xls".equals(fileType)) {
				wb = new HSSFWorkbook();
			} else if ("xlsx".equals(fileType)) {
				wb = new SXSSFWorkbook(100);
			}
		} catch (Exception e) {
			//e.printStackTrace();
			addMsg("写入Excel创建Workbook时出错:"+e+"\r\n***********************************************************************************************************************************************************");
		}
		return wb;
	}
	
	/**
	 * 获取Workbook对象
	 * @param wb
	 * @param path	文件路径
	 * @param fileName	文件名称带后缀
	 * @param fileType	文件类型,xls、xlsx
	 * @return
	 */
	public Workbook getWorkbook(Workbook wb, String path, String fileName, String fileType) {
		FileInputStream in = null;
		try {
			File file = new File(path+fileName);
			in = new FileInputStream(file);
			if ("xls".equals(fileType)) {
				wb = new HSSFWorkbook(in);
			} else if ("xlsx".equals(fileType)) {
				wb = new XSSFWorkbook(in);// XSSFWorkbook所有数据写在内存中,当数据量太大时容易导致内存溢出。
			}
		} catch (Exception e) {
			//e.printStackTrace();
			addMsg("获取Workbook时出错:"+e+"\r\n");
		} finally {
			if (in != null) { try { in.close(); } catch (Exception e) {} }
		}
		return wb;
	}
	
	public static String getString(Cell cell) {
		if (cell == null) {
			return ""; 
		} else if (cell.getCellTypeEnum() == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell)) {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
			double value = cell.getNumericCellValue();  
            Date date = DateUtil.getJavaDate(value);  
            return sdf.format(date);
		} else {
			cell.setCellType(CellType.STRING);
			return cell.getStringCellValue();
        }
    }
	
	/**
	 * 将list中的内容写入到Excel中
	 * @param path	文件路径
	 * @param fileName	写入Excel的文件名带后缀
	 * @param fileType	文件类型
	 * @param rowList	写入Excel的行数据的list,rowList中每一个值保存的是一个list,里面的list是一个行数据,保存的是列的值
	 * @param titleList	写入Excel的标题
	 */
	public void writeExcel(String path, String fileName, String fileType, List<Object> rowList, List<Object> titleList) {
		Workbook wb = null; Sheet sheet = null; List<Object> cellList = null;
		try {
			File file = new File(path+fileName);
			if (file.exists()) {// 追加
				wb = getWorkbook(wb, path, fileName, fileType);
				sheet = wb.getSheetAt(0);
			} else {// 新创建并写入
				file.createNewFile();// 创建文件
				wb = createWorkbook(wb, fileType);
				sheet = wb.createSheet();
				Row row = sheet.createRow(0);
				for (int k = 0; k < titleList.size(); k++) {
					row.createCell(k, CellType.STRING).setCellValue(String.valueOf(titleList.get(k)));
				}
			}
			int rowNum = sheet.getPhysicalNumberOfRows();// sheet已有行数
			for (int i = 0; i < rowList.size(); i++) {// 循环将行数据list写入sheet页
				Row row = sheet.createRow(rowNum++);
				cellList = objToList(rowList.get(i));
				for(int j = 0; j < cellList.size(); j++) {
					row.createCell(j, CellType.STRING).setCellValue(String.valueOf(cellList.get(j)));
				}
			}
			FileOutputStream fout = new FileOutputStream(file);
			wb.write(fout);
            fout.close();
		} catch (Exception e) {
			//e.printStackTrace();
			addMsg("写入Excel时出错:"+e+"\r\n***********************************************************************************************************************************************************");
		}
	}
	
	/**
	 * 将object转成list对象
	 * @param obj
	 * @return
	 */
	public List<Object> objToList(Object obj) {
		List<Object> result = new ArrayList<Object>();
    	if (obj instanceof ArrayList<?>) {
	        for (Object o : (List<?>) obj) {
	            result.add(o);
	        }
        }
        return result;
	}
	
	/**
	 * 将路径下的文件都压缩
	 * @param dir	要压缩的路径,将路径下的所有文件压缩在一起
	 * @param zipfile	压缩后的文件路径加文件名带后缀
	 */
	public void zip(String dir, String zipfile) {
		Zip zip = new Zip();
		zip.setProject(new Project());
		zip.setEncoding("GBK");
		zip.setBasedir(new File(dir));
		zip.setDestFile(new File(zipfile));
		zip.execute();
	}
	
	/**
	 * 将多个Excel合并成一个Excel
	 * @param path	压缩文件路径
	 * @param filename	压缩文件zip文件名带后缀
	 * @param fileDownLoad	要生成的Excel文件名带后缀
	 * @return
	 */
	public String handlingZip(String path, String filename, String fileDownLoad) {
		long sj1=System.currentTimeMillis(); String re = "OK";
		try {
			//解压文件
			unzip(path+filename, path);
			
			List<File> files = new ArrayList<File>();
			getAllFiles(files,path);
			mergeFile(path,fileDownLoad,files);
		} catch (Exception e) {
			addMsg("合并Excel时出错:"+e+"\r\n");
		}
		addMsg("合并Excel结束,用时:"+((System.currentTimeMillis() - sj1)+"ms")+"\r\n***********************************************************************************************************************************************************");
		return re;
	}
	
	/**将压缩文件解压
	 * @param zipfile	压缩文件路径加文件名 带后缀
	 * @param dir	解压后保存的路径
	 */
	public void unzip(String zipfile, String dir) {
		Expand exp = new Expand();
		exp.setProject(new Project());
		exp.setEncoding("GBK");
		exp.setSrc(new File(zipfile));
		exp.setDest(new File(dir));
		exp.execute();
	}
	
	/**
	 * 获取文件夹下所有的文件
	 * @param files	保存所有文件的list
	 * @param path	要获取文件的文件夹路径
	 */
	public void getAllFiles(List<File> files,String path) {
		File file = new File(path);
		File[] childrenFiles = file.listFiles();//获取路径下的所有文件
		if (childrenFiles.length == 0) { return; }
		for (File childFile : childrenFiles) {// 遍历所有文件
			// 如果是文件,添加到list集合
			if (childFile.isFile()) {
                files.add(childFile);
            } else if(childFile.isDirectory()) { // 如果是文件夹,遍历文件夹下的文件
            	getAllFiles(files,childFile.getPath());
            }
		}
	}
	
	/**
	 * 将所有xls和xlsx文件写入到新的文件中
	 * @param path	新的写入文件的路径
	 * @param fileZip	新的写入文件的文件名带着后缀
	 * @param files	所有要写入新文件中的文件
	 */
	public void mergeFile(String path, String fileZip, List<File> files) {
		Workbook wb = null; Workbook wbSrc = null; Sheet sheetWrite = null; Row row0 = null; BufferedOutputStream outputStream = null;
		List<String> list = new ArrayList<String>();// 要写入文件的标题
		List<String> titleList = null;// 读取文件的标题
		try {
			wb = new SXSSFWorkbook(getXSSFWorkbook(path+fileZip), 100);
			sheetWrite = wb.getSheetAt(0);
			row0 = sheetWrite.createRow(0);
			
			File fileSrc = null;
			for (int i = 0; i < files.size(); i++) {
				fileSrc = files.get(i);
				String fileSrcType = fileSrc.getName().substring(fileSrc.getName().lastIndexOf(".")+1);
				if("xls".equals(fileSrcType) || "xlsx".equals(fileSrcType)) {
					titleList = new ArrayList<String>();
					wbSrc = getWorkbook(wbSrc,fileSrc.getPath(),"",fileSrc.getName().substring(fileSrc.getName().lastIndexOf(".")+1,fileSrc.getName().length()));
					Sheet sheetSrc = wbSrc.getSheetAt(0);
					int numRow = sheetSrc.getPhysicalNumberOfRows();
					if (numRow == 0) { break; }// 总行数
					Row rowTitle = sheetSrc.getRow(0);// 标题行
					for (int k = 0; k < rowTitle.getPhysicalNumberOfCells(); k++) {// 循环所有列,放入list中
						Cell cellTitle = rowTitle.getCell(k);
						titleList.add(getString(cellTitle));
					}
					
					if (list.size() == 0) {
						// 写入标题
						for (int n = 0; n < titleList.size(); n++) {
							row0.createCell(n, CellType.STRING).setCellValue(titleList.get(n));
							list.add(titleList.get(n));
						}
					}
					
					// 遍历所有数据行,写入新文件
					boolean isMatch = true;
					Row rowWrite = null; Row rowSrc = null;
					for (int ii = 1; ii < sheetSrc.getPhysicalNumberOfRows(); ii++) {
						rowSrc = sheetSrc.getRow(ii);
						if (isEmptyRow(rowSrc)) { continue; }
						rowWrite = sheetWrite.createRow(sheetWrite.getPhysicalNumberOfRows());
						for (int j = 0; j < titleList.size(); j++) {
							isMatch = false;
							for (int jj = 0; jj < list.size(); jj++) {
								if (titleList.get(j).equals(list.get(jj))) {
									rowWrite.createCell(jj, CellType.STRING).setCellValue(getString(rowSrc.getCell(j)));
									isMatch = true;
									break;
								}
							}
							if (!isMatch) {// 读取文件的标题在写入文件中不存在,在写入文件标题后的列坐标创建新列
								list.add(titleList.get(j));
								rowWrite.createCell(list.size()-1, CellType.STRING).setCellValue(getString(rowSrc.getCell(j)));
							}
						}
					}
					if (wbSrc!=null) { try{wbSrc.close(); }catch(Exception e) {}}
				}
			}
			
			outputStream = new BufferedOutputStream(new FileOutputStream(path+fileZip));
			wb.write(outputStream);
			outputStream.flush();
			if (outputStream!=null) { try{outputStream.close(); }catch(Exception e) {}}
		} catch (Exception e) {
			//e.printStackTrace();
			addMsg("合并Excel在写入新文件时出错:"+e+"\r\n");
		} finally {
			if (wb!=null) { try{wb.close(); }catch(Exception e) {}}
			if (wbSrc!=null) { try{wbSrc.close(); }catch(Exception e) {}}
			if (outputStream!=null) { try{outputStream.close(); }catch(Exception e) {}}
		}
		// 更新标题
		updateTitle(path, fileZip, list);
	}
	
	public XSSFWorkbook getXSSFWorkbook(String filePath) {
		XSSFWorkbook workbook =  null;
		BufferedOutputStream outputStream = null;
		try {
			File fileXlsxPath = new File(filePath);
			outputStream = new BufferedOutputStream(new FileOutputStream(fileXlsxPath));
			workbook = new XSSFWorkbook();
			workbook.createSheet("Sheet1");
			workbook.write(outputStream);
		} catch (Exception e) {
			//e.printStackTrace();
		} finally {
			if (outputStream!=null) { try{outputStream.close(); }catch(Exception e) {}}
		}
		return workbook;
	}
	
	/**
	 * 判断row是否是空行
	 * @param row
	 * @return
	 */
	public boolean isEmptyRow(Row row) {
        if(row == null || row.toString().isEmpty()){
            return  true;
        }else{
            Iterator<Cell> it = row.iterator();
            boolean isEmpty = true;
            while (it.hasNext()){
                Cell cell = it.next();
                if(cell.getCellTypeEnum() != CellType.BLANK){
                    isEmpty = false;
                    break;
                }
            }
            return isEmpty;
        }
    }

	public void updateTitle(String path, String fileZip,List<String> list) {
		Workbook wb = null; BufferedOutputStream outputStream = null;
		try {
			wb = getWorkbook(wb, path, fileZip, fileZip.substring(fileZip.lastIndexOf(".")+1, fileZip.length()));
			Row row = wb.getSheetAt(0).getRow(0);// 标题行
			for (int i = row.getPhysicalNumberOfCells(); i < list.size(); i++) {
				row.createCell(i, CellType.STRING).setCellValue(list.get(i));
			}
			outputStream = new BufferedOutputStream(new FileOutputStream(path+fileZip));
			wb.write(outputStream);
			outputStream.flush();
			if (outputStream!=null) { try{outputStream.close(); }catch(Exception e) {}}
		} catch (Exception e) {
			addMsg("更新Excel标题时出错:"+e+"\r\n");
		} finally {
			if (wb!=null) { try{wb.close(); }catch(Exception e) {}}
		}
	}
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值