簡體   English   中英

無法使用apache POI在工作簿中創建新的Excel工作表

[英]Cannot create new excel sheet in a workbook using 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);        
}

既然您沒有提到任何異常或堆棧跟蹤,那么我將大膽猜測-對於目錄中的每個新excel文件,您都在做

HSSFWorkbook workbook = new HSSFWorkbook(bis);

在讀取每張紙(所有行和單元格)結束時,您將繼續到下一張紙,依此類推,直到創建了所有紙並將其存儲在內存中。 然后您通過以下方式將工作簿本身寫到輸出流中

copy_wb.write(bos);

[我知道這一點,但是如果將來有人來,這將使他們更容易理解正在發生的事情而無需花費時間]

我在想您第一次說到workbook.write(outputstream)內容被寫入。 但是您尚未關閉流程,並且已經寫完了整個工作簿。 下次您想在同一流中編寫另一個工作簿時 ,我真的不知道會發生什么。 不應該在當前工作簿中添加工作表(而不是將多個工作簿寫入同一輸出流)嗎?

我建議創建目標工作簿(如果不存在)並編寫源工作簿的工作表(而不是工作簿本身)。 這可能是一種變通方法,但是除非我可以將多個工作簿的調試工作放到同一個輸出流中,否則我無法真正建議解決當前問題的方法。

我已將其簡化為主要問題:

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一次。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM