将多个Excel文件合并成一个的源码(转)

源码是在poi-3.1-FINAL-20080629版本下编译通过。

 

本源码修正了获取sheet中数据行数的BUG,详情看getRows方法。

 

public class ExcelMergeUtil {  
	public static void merge(List sourceFiles, String destFile)throws Exception{
		InputStream[] inputs = new InputStream[sourceFiles.size()]; 
	    for(int i=0; i rootRecords = getRecords(inputs[0]); 
			Workbook workbook = Workbook.createWorkbook(rootRecords); 
			List sheets = getSheets(workbook, rootRecords);   
			if(sheets == null || sheets.size() == 0) {   
				throw new IllegalArgumentException("第一个文档格式错误,必须至少有一个sheet!");   
			}   
			
			//以第一个文档的最后一个sheet为根,以后的数据都追加在这个sheet后面   
			Sheet rootSheet = sheets.get(sheets.size() - 1);    
			int rootRows = getRows(rootRecords); //记录第一篇文档的行数,以后的行数在此基础上增加   
			rootSheet.setLoc(rootSheet.getDimsLoc());   
			map = new HashMap(1000);
			
			for(int i = 1; i < inputs.length; i++){ //从第二篇开始遍历   
				List records = getRecords(inputs[i]);   
				int rowsOfCurXls = 0;   
				//遍历当前文档的每一个record   
				for(Iterator it = records.iterator(); it.hasNext();){   
			        Record record = (Record) it.next();   
			        if(record.getSid() == RowRecord.sid){ //如果是RowRecord   
			        	RowRecord rowRecord = (RowRecord) record;   
			        	rowRecord.setRowNumber(rootRows + rowRecord.getRowNumber()); //调整行号   
			        	rootSheet.addRow(rowRecord); //追加Row   
			        	rowsOfCurXls++; //记录当前文档的行数   
			        }   
			        //SST记录,SST保存xls文件中唯一的String,各个String都是对应着SST记录的索引   
			        else if (record.getSid() == SSTRecord.sid){   
			        	SSTRecord sstRecord = (SSTRecord) record;   
			        	for (int j = 0; j < sstRecord.getNumUniqueStrings(); j++) {   
			        		int index = workbook.addSSTString(sstRecord.getString(j));   
			        		//记录原来的索引和现在的索引的对应关系   
			        		map.put(Integer.valueOf(j), Integer.valueOf(index));   
			        	}   
			        }
			        else if (record.getSid() == LabelSSTRecord.sid){   
			        	LabelSSTRecord label = (LabelSSTRecord) record;   
			        	//调整SST索引的对应关系   
			        	label.setSSTIndex( ((Integer)map.get(Integer.valueOf(label.getSSTIndex()))).intValue() );   
			        }   
			        
			        //追加ValueCell   
			        if(record instanceof CellValueRecordInterface){   
			        	CellValueRecordInterface cell = (CellValueRecordInterface) record;   
			        	int cellRow = cell.getRow() + rootRows;   
			        	cell.setRow(cellRow);   
			        	rootSheet.addValueRecord(cellRow, cell);   
			        }   
				}   
	      		rootRows += rowsOfCurXls;  
	    	}   
			
	    	byte[] data = getBytes(workbook, sheets.toArray(new Sheet[0]));  
	    	
	    	write(out, data); 
	    	
	    	System.out.println("合并完成");
		}finally{
			if(map!=null){
				map.clear();
				map = null;
			}
		}
	}   
  
	static void write(OutputStream out, byte[] data)throws Exception{   
		POIFSFileSystem fs = new POIFSFileSystem();     
		try{   
			fs.createDocument(new ByteArrayInputStream(data), "Workbook");   
			fs.writeFilesystem(out);   
			out.flush();   
		}finally{   
			try{   
				out.close();   
			}catch(IOException e){   
				e.printStackTrace();   
			}   
		}   
	}   
  
	/**
	 * 获取Sheet列表
	 */
  	static List getSheets(Workbook workbook, List records)throws Exception{   
  		int recOffset = workbook.getNumRecords();   
  		int sheetNum = 0;   
    
  		convertLabelRecords(records, recOffset, workbook);   
    
  		List sheets = new ArrayList();   
  		while(recOffset < records.size()){   
  			Sheet sheet = Sheet.createSheet(records, sheetNum++, recOffset);
  			recOffset = sheet.getEofLoc() + 1;   
  			if(recOffset == 1) break;  
  			sheets.add(sheet);   
  		}   
    	return sheets;   
  	} 

  	/**
  	 * 取得一个sheet中数据的行数
  	 */
  	static int getRows(List records) {   
  	    int row = 0;   
  	    for(Iterator it = records.iterator(); it.hasNext();){   
  	      Record record = (Record) it.next();
  	      if(record.getSid() == DimensionsRecord.sid){   
  	    	  DimensionsRecord dr = (DimensionsRecord)record;
  	    	  row = dr.getLastRow();
  	    	  break;
  	      }   
  	    }   
  	    return row;   
  	}  
     
  	/**
  	 * 获取Excel文档的记录集
   	*/
  	static List getRecords(InputStream input) {   
  		try{   
  			POIFSFileSystem poifs = new POIFSFileSystem(input); 
  			InputStream stream = poifs.getRoot().createDocumentInputStream("Workbook");   
  			return RecordFactory.createRecords(stream);
  		}catch(IOException e){   
  			System.out.println("ExcelMergeUtil.getRecords: " + e.toString());
  			e.printStackTrace();   
  		}   
  		return Collections.EMPTY_LIST;   
  	}   
  
  	static void convertLabelRecords(List records, int offset, Workbook workbook)throws Exception{   
  		for(int k = offset; k < records.size(); k++){   
  			Record rec = (Record) records.get(k);   
  
  			if (rec.getSid() == LabelRecord.sid) {   
  				LabelRecord oldrec = (LabelRecord) rec;   
  				
		        records.remove(k);     
		        int stringid = workbook.addSSTString(new UnicodeString(oldrec.getValue()));   

		        LabelSSTRecord newrec = new LabelSSTRecord(); 
		        newrec.setRow(oldrec.getRow());   
		        newrec.setColumn(oldrec.getColumn());   
		        newrec.setXFIndex(oldrec.getXFIndex());   
		        newrec.setSSTIndex(stringid);   
		        records.add(k, newrec);   
  			}
  		}   
  	}   
  
  	static byte[] getBytes(Workbook workbook, Sheet[] sheets) { 
  		int nSheets = sheets.length;   
     
  		for(int i = 0; i < nSheets; i++){   
  			sheets[i].preSerialize();   
  		}   
  		
  		int totalsize = workbook.getSize();   
    
  		int[] estimatedSheetSizes = new int[nSheets];   
  		for(int k = 0; k < nSheets; k++){   
  			workbook.setSheetBof(k, totalsize);   
  			int sheetSize = sheets[k].getSize();   
  			estimatedSheetSizes[k] = sheetSize;   
  			totalsize += sheetSize;
  		} 
  
  		byte[] retval = new byte[totalsize];   
  		int pos = workbook.serialize(0, retval);   
  
  		for(int k = 0; k < nSheets; k++){   
  			int serializedSize = sheets[k].serialize(pos, retval);   
  			if(serializedSize != estimatedSheetSizes[k]){   
  				throw new IllegalStateException("Actual serialized sheet size (" + serializedSize   
  						+ ") differs from pre-calculated size (" + estimatedSheetSizes[k] + ") for sheet (" + k   
  						+ ")"); 
  			}   
  			pos += serializedSize;   
  		}   
    	return retval;   
  	} 
  
} 

 

你可能感兴趣的:(Java)