当前位置: 首页 > 知识库问答 >
问题:

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

连俊智
2023-03-14

我正试图在一个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个答案

邬友樵
2023-03-14

由于您没有提到任何异常或stacktraces,我将进行疯狂猜测--对于目录中的每个新excel文件,您都在做

HSSFWorkbook workbook=新建HSSFWorkbook(双);

在读取每一个工作表(所有行和单元格)结束时,您将移到下一个工作表,依此类推,直到所有工作表都被创建并在内存中为止。然后通过以下方式将工作簿本身写入输出流

copy_wb.write(bos);

[我知道这件事你知道,但万一将来有人来了,这会让他们更容易理解发生了什么,而不用花时间]

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

我建议创建目标工作簿(如果它不存在)并编写源工作簿的工作表(而不是工作簿本身)。这可能是一个解决办法,但除非我能够调试多个工作簿对同一个输出流的处理,否则我不能为当前的问题提供一个修复方案。

关飞翼
2023-03-14

我把这归结为主要问题:

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

 类似资料:
  • 我无法使用 apache poi eclipse 在我创建的 java excel 中创建工作表

  • 所以在问这个之前,我搜索并发现了一些与我在这里想要做的相似的事情。 基本上我有工作簿AlphaMaster。这个工作簿是一个模板,我想用它来创建每周的新工作簿。 在本工作簿中,有名为“周一至周六”的工作表,以及带有相应日期的周一、周二等其他工作表。 我创建了一个在打开工作簿时加载的表单。我想要的是当我单击表单运行时,它将: > 将代码保存模板作为新工作簿运行 根据userform1的输入重命名工作

  • 我正在尝试使用一个包含多行数据的Excel工作表,并使用行中的一个值作为新工作簿名称为每一行创建单独的工作簿。这些工作簿将保存为逗号分隔的工作簿,以便它们可以上传到机器的控制器中。我可以手动打开一个新工作簿并从基本工作簿中获取单元格的外部引用,但对如何编写循环以使其自动在行中移动并创建新工作簿以及如何使用其中一个值作为新工作簿的名称感到困惑。 基本工作簿的结构是从A到J的行,其中A列包含我要将新工

  • ...需要很长时间(~30秒),并且该文件只有72行10列(365KB)。 这不是问题,只是看起来有点过分。我在想我是做错了什么,还是没有做我应该做的事情。实例化具有相同数据(但只有25KB)的xls文件只需1或2秒。如果这是正常的,那么有人可以告诉我。 编辑: 因此,我不知道这是App Engine的问题,还是POI不喜欢返回的InputStream的味道。顺便说一句,我不能用而不是尝试初始化,

  • 问题内容: 我有几个要转储为excel工作簿(xls / xlsx)中新工作表的csv文件。我该如何实现? Google搜索并找到“ pyXLwriter”,但该项目似乎已停止。当我尝试“ pyXLwriter”时,我想知道是否有其他选择/建议/模块? 非常感谢。 [编辑] 这是我的解决方案:(任何人都有更精简的pythonic解决方案?请发表评论。thx) 问题答案: 不知道 您 所说的“更精简

  • 请在下面找到代码片段 当我们创建excel文件时,这意味着我们正在创建工作簿。从那里,我们访问表格,然后是行和列。 我不明白为什么我们写写当我们已经有一个'Workbook'我们应该有一些方法来获取我们已经创建的工作簿,就像我们为行(getRow),工作表(getSheet),细胞(getcell)所做的那样。 你能帮我理解POI吗?