无法使用apache POI在工作簿中创建新的Excel工作表

时间:2015-06-04 15:14:57

标签: java excel apache-poi

我正在尝试在单个excel文件中复制多个文件。该excel文件中的每个工作表都将包含一个文件的内容。我需要复制大约6个文件。因此,生成的文件应包含6张。但是当我运行我的代码时,只为单个文件生成了1张表。我试过调试它,但无法弄清楚原因。

这是我的代码。

 public static void main(String[] args) throws IOException {

    // TODO Auto-generated method stub
    CreateSingleExcelFile cef = new CreateSingleExcelFile();
    cef.fileIterator();
 }

 public void fileIterator() throws IOException{

    File dir = new File("path for files to copy");
    File[] dir_listing = dir.listFiles();
    HSSFWorkbook my_wb = new HSSFWorkbook();                        
    //creating an output stream to copy all files in combined.xls
    BufferedOutputStream bos= new BufferedOutputStream(new FileOutputStream("path of resultant excel sheet"));
    //traversing through a list of files
    for(File file: dir_listing){
        //file: file to be copied.
        add_in_excel(my_wb,bos,file);
        System.out.println("In file :" + file.getName());
    }
    bos.close();
    System.out.println("Files are copied");
}


 private void add_in_excel(HSSFWorkbook copy_wb, BufferedOutputStream bos,File file) throws IOException {
    // TODO Auto-generated method stub
    //creating a new sheet in the copy workbook
    HSSFSheet mySheet =  copy_wb.createSheet(file.getName());

    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
    HSSFWorkbook workbook = new HSSFWorkbook(bis);
    CellStyle cs = copy_wb.createCellStyle();
    cs.setWrapText(true);   

    HSSFSheet sheet = null;
    HSSFRow row = null;
    HSSFCell cell = null;               
    HSSFRow myRow = null;
    HSSFCell myCell = null;
    int sheets = workbook.getNumberOfSheets();          
    int fRow = 3;
    int lRow = 0;
    int count_row=0;

    //traversing through sheets in the 'file'
    for (int iSheet = 0; iSheet < sheets; iSheet++) {                   
        sheet = workbook.getSheetAt(iSheet);                
        if (sheet != null) {                                      
            lRow = sheet.getLastRowNum();
            for (int iRow = fRow; iRow <= lRow; iRow++) {
                row = sheet.getRow(iRow);
                //creating row in the new sheet
                myRow = mySheet.createRow(count_row++);
                if (row != null) {                           
                    for (int iCell = 0; iCell < 4; iCell++) {  
                        //creating a column in the new sheet
                        cell = row.getCell(iCell);
                        myCell = myRow.createCell(iCell);                                
                        myCell.setCellStyle(cs);
                        //setting cell type and adding data in each cell
                        if (cell != null ) {                                
                            myCell.setCellType(cell.getCellType());
                            switch (cell.getCellType()) {
                            case HSSFCell.CELL_TYPE_BLANK:                                      
                               myCell.setCellValue("");
                                break;

                            case HSSFCell.CELL_TYPE_BOOLEAN:
                                myCell.setCellValue(cell.getBooleanCellValue());
                                break;

                            case HSSFCell.CELL_TYPE_ERROR:
                                myCell.setCellErrorValue(cell.getErrorCellValue());
                                break;

                            case HSSFCell.CELL_TYPE_FORMULA:
                                myCell.setCellFormula(cell.getCellFormula());
                                break;

                            case HSSFCell.CELL_TYPE_NUMERIC:
                                if(HSSFDateUtil.isCellDateFormatted(cell))
                                    myCell.setCellValue(cell.getDateCellValue());
                                else
                                    myCell.setCellValue(cell.getNumericCellValue());
                                break;

                            case HSSFCell.CELL_TYPE_STRING:
                                myCell.setCellValue(cell.getStringCellValue());
                                break;
                            default:
                                myCell.setCellFormula(cell.getCellFormula());
                            }                                   
                        }
                    }
                }
            }
        }
    }
    bis.close();           
    copy_wb.write(bos);        
}

2 个答案:

答案 0 :(得分:2)

由于你没有提到任何异常或堆栈跟踪,我将采取疯狂猜测 - 对于目录中的每个新excel文件,你正在做

HSSFWorkbook workbook = new HSSFWorkbook(bis);

在阅读每张纸(所有行和单元格)的最后,您将继续前进到下一张纸,依此类推,直到所有纸张都已创建并位于内存中。然后通过

将工作簿本身写入输出流

copy_wb.write(bos);

[我知道你知道这件事但是如果将来有人来,这将使他们更容易理解正在发生的事情而不花时间]

我在想第一次你写workbook.write(outputstream)的内容。但是你没有关闭流,你已经写完了整本工作簿。下次你想将 另一个工作簿 写入同一个流时,我真的不知道会发生什么。不应该将工作表添加到当前工作簿(而不是将多个工作簿写入同一输出流)?

我建议创建目标工作簿(如果它不存在)并编写源工作簿的工作表(而不是工作簿本身)。这可能是一个解决方法,但除非我可以调试多个工作簿与同一输出流的交易,否则我无法真正建议解决当前问题。

答案 1 :(得分:1)

我已将此问题简化为主要问题:

import org.apache.poi.hssf.usermodel.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.BufferedOutputStream;

class CreateSingleExcelFile {

 public static void main(String[] args) throws IOException {
  CreateSingleExcelFile cef = new CreateSingleExcelFile();
  cef.fileIterator();
 }

//This is what you actual doing:
 public void fileIterator() throws IOException{
  HSSFWorkbook my_wb = new HSSFWorkbook();                        
  BufferedOutputStream bos= new BufferedOutputStream(new FileOutputStream("copiedWB.xls"));
  for(int i = 0; i < 3; i++){
   add_in_excel(my_wb, bos,"file" + i);
   System.out.println("In file :" + "file" + i);
  }
  bos.close(); //closing the BufferedOutputStream. The resulting file contains bytes for 3 complete XLS files. 
 }

 private void add_in_excel(HSSFWorkbook copy_wb, BufferedOutputStream bos, String file) throws IOException {
  HSSFSheet mySheet =  copy_wb.createSheet(file);
  copy_wb.write(bos); //write the copy_wb with one new added sheet into the BufferedOutputStream without closing it. But writing a XLS file is complex. So this will not work properly. It will append bytes for a complete XLS workbook onto the stream.
 }
}

您将copy_wb添加一个新添加的工作表写入BufferedOutputStream而不关闭该流。但是编写XLS文件很复杂。所以这不会正常工作。它将为完整的XLS工作簿附加字节,其中首先是1,然后是2,最后是3张到流上。但每次都是一个完整的XLS工作簿文件。

添加所有工作表后,关闭BufferedOutputStream。流和结果文件包含3个完整XLS文件的字节。第一张有1张,第二张有2张,第三张有3张。如果用Excel打开,只会读取第一个。

这样可行,但不建议使用。

//This will work, but is not recommend
 public void fileIterator() throws IOException{
  HSSFWorkbook my_wb = new HSSFWorkbook();                        
  for(int i = 0; i < 3; i++){
   BufferedOutputStream bos= new BufferedOutputStream(new FileOutputStream("copiedWB.xls")); // creating a new BufferedOutputStream for each call of add_in_excel
   add_in_excel(my_wb, bos,"file" + i);
   System.out.println("In file :" + "file" + i);
  }
 }

 private void add_in_excel(HSSFWorkbook copy_wb, BufferedOutputStream bos, String file) throws IOException {
  HSSFSheet mySheet =  copy_wb.createSheet(file);
  copy_wb.write(bos);
  bos.close(); //write the copy_wb with one new added sheet into the BufferedOutputStream and close it.
 }

add_in_excel的每次调用创建一个新的BufferedOutputStream。将带有一个新添加的工作表的copy_wb写入BufferedOutputStream并关闭它。因此,每个writeclose创建一个新的完整XLS文件,其中包含一个表单。由于它具有相同的名称,因此将覆盖现有文件。

但是为什么每次添加新工作表时都要编写完整的工作簿?

所以这就是我要做的事情:

 public void fileIterator() throws IOException{
  HSSFWorkbook my_wb = new HSSFWorkbook();                        
  BufferedOutputStream bos= new BufferedOutputStream(new FileOutputStream("copiedWB.xls")); //create the BufferedOutputStream only for the fileIterator method
  for(int i = 0; i < 3; i++){
   add_in_excel(my_wb, "file" + i);
   System.out.println("In file :" + "file" + i);
  }
  my_wb.write(bos);
  bos.close();  //write into and close the BufferedOutputStream only once after you have added all sheets.
 }

 private void add_in_excel(HSSFWorkbook copy_wb, String file) throws IOException {
  HSSFSheet mySheet =  copy_wb.createSheet(file);
 }

仅为fileIterator方法创建BufferedOutputStream。不要将其传递给add_in_excel。在添加完所有工作表后,只写入并关闭BufferedOutputStream一次。