简体   繁体   English

Apache POI XSSFWorkbook setSheetOrder 未排序

[英]Apache POI XSSFWorkbook setSheetOrder not sorting

I'm using Apache POI (4.1.1) to modify an existing workbook.我正在使用 Apache POI (4.1.1) 修改现有工作簿。 The workbook contains four sheets.该工作簿包含四张纸。 I'm using the second sheet as a template by cloning it, then writing data to the new cloned sheets.我通过克隆第二个工作表作为模板,然后将数据写入新的克隆工作表。 It's cloned around six times or so.它被克隆了大约六次。 At the end of this process I remove the template sheet, then I try to set a sheet order to all the sheets: the existing sheets (minus the template) and then the sheets I cloned.在此过程结束时,我删除了模板工作表,然后尝试为所有工作表设置工作表顺序:现有工作表(减去模板),然后是我克隆的工作表。 I'm using XSSFWorkbook::setSheetOrder to do this, and I see it change the index in debug, but when my Excel file actually writes out, the sheets are not in order.我正在使用 XSSFWorkbook::setSheetOrder 来执行此操作,并且我看到它在调试中更改了索引,但是当我的 Excel 文件实际写出时,工作表没有按顺序排列。

Here is the relevant code:这是相关的代码:

        // wb is an XSSFWorkbook
        wb.removeSheetAt(wb.getSheetIndex("Original Sheet 2")); // Remove the template sheet
        wb.setSheetOrder("Original Sheet 1", 0);
        for (ReportPresenter presenter : dataMap.values()) {
            String sheetTitle = makeSheetTitleFromPresenter(presenter);
            int oldIndex = wb.getSheetIndex(wb.getSheet(sheetTitle));
            wb.setSheetOrder(sheetTitle, presenter.getAnalysisNumber());
            int newIndex = wb.getSheetIndex(wb.getSheet(sheetTitle));
            System.out.println(oldIndex + " -> " + newIndex);
        }
        wb.setSheetOrder("Original Sheet 3", dataMap.size() + 1);
        wb.setSheetOrder("Original Sheet 4", dataMap.size() + 2);

I included the debug println above to show here how I know that the index is actually being changed to the order I want with the setSheetOrder method.我在上面包含了调试 println 以在这里展示我如何知道索引实际上正在使用 setSheetOrder 方法更改为我想要的顺序。 However, when I open the Excel file that is generated by this code, my sheets all exist but they are not in the order I have specified.但是,当我打开此代码生成的 Excel 文件时,我的工作表都存在,但它们没有按照我指定的顺序排列。

I would really appreciate some ideas!我真的很感激一些想法! Thank you.谢谢你。

Cannot reproducing that behavior.无法重现该行为。 Please show a Minimal, Reproducible Example which shows that behavior.请展示一个最小的、可重现的示例,以显示该行为。

I will provide a such which shows that it works properly:我将提供一个这样的,它表明它可以正常工作:

Start with Execl.xlsx like this:像这样从Execl.xlsx开始:

在此处输入图片说明

Then following code:然后如下代码:

import java.io.FileOutputStream;
import java.io.FileInputStream;

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

public class ExcelSetSheetOrder {

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

  java.util.Map<Integer, ReportPresenter> dataMap = new java.util.HashMap<Integer, ReportPresenter>();
  dataMap.put(1, new ReportPresenter("New Sheet 1", 1));
  dataMap.put(2, new ReportPresenter("New Sheet 2", 2));
  dataMap.put(3, new ReportPresenter("New Sheet 3", 3));
  dataMap.put(4, new ReportPresenter("New Sheet 4", 4));
  dataMap.put(5, new ReportPresenter("New Sheet 5", 5));
  dataMap.put(6, new ReportPresenter("New Sheet 6", 6));

  try (XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("./Excel.xlsx"))) {

   workbook.cloneSheet(workbook.getSheetIndex("Original Sheet 2"), dataMap.get(1).getSheetTitle());
   workbook.cloneSheet(workbook.getSheetIndex("Original Sheet 2"), dataMap.get(2).getSheetTitle());
   workbook.cloneSheet(workbook.getSheetIndex("Original Sheet 2"), dataMap.get(3).getSheetTitle());
   workbook.cloneSheet(workbook.getSheetIndex("Original Sheet 2"), dataMap.get(4).getSheetTitle());
   workbook.cloneSheet(workbook.getSheetIndex("Original Sheet 2"), dataMap.get(5).getSheetTitle());
   workbook.cloneSheet(workbook.getSheetIndex("Original Sheet 2"), dataMap.get(6).getSheetTitle());

   workbook.removeSheetAt(workbook.getSheetIndex("Original Sheet 2")); // Remove the template sheet
   workbook.setSheetOrder("Original Sheet 1", 0);
   for (ReportPresenter presenter : dataMap.values()) {
    String sheetTitle = presenter.getSheetTitle();
    int oldIndex = workbook.getSheetIndex(workbook.getSheet(sheetTitle));
    workbook.setSheetOrder(sheetTitle, presenter.getAnalysisNumber());
    int newIndex = workbook.getSheetIndex(workbook.getSheet(sheetTitle));
    System.out.println(oldIndex + " -> " + newIndex);
   }
   workbook.setSheetOrder("Original Sheet 3", dataMap.size() + 1);
   workbook.setSheetOrder("Original Sheet 4", dataMap.size() + 2);

   String filePath = "./ExcelNew.xlsx";
   try (FileOutputStream fileOut = new FileOutputStream(filePath)) {
    workbook.write(fileOut);
   }
  }
 }

 static class ReportPresenter {
  String sheetTitle = "";
  int analysisNumber = -1;

  public ReportPresenter(String sheetTitle, int analysisNumber) {
   this.sheetTitle = sheetTitle;
   this.analysisNumber = analysisNumber;
  }

  public int getAnalysisNumber() {
   return this.analysisNumber;
  }
  public String getSheetTitle() {
   return this.sheetTitle;
  }
 }
}

prints the following on console:在控制台上打印以下内容:

axel@arichter:~/Dokumente/JAVA/poi/poi-4.1.1$ javac -Xlint:deprecation -Xlint:unchecked -cp .:./*:./lib/*:./ooxml-lib/* ExcelSetSheetOrder.java 
axel@arichter:~/Dokumente/JAVA/poi/poi-4.1.1$ java -cp .:./*:./lib/*:./ooxml-lib/* ExcelSetSheetOrder 
3 -> 1
4 -> 2
5 -> 3
6 -> 4
7 -> 5
8 -> 6

and leads to this result ExcelNew.xlsx :并导致此结果ExcelNew.xlsx

在此处输入图片说明

As it turns out, I had a misunderstanding of how XSSFWorkbook::setSheetOrder works.事实证明,我对 XSSFWorkbook::setSheetOrder 的工作方式有误解。

I was assuming (wrongly) that setting the order of a sheet would keep the sheet in that position, kind of like slotting the sheets into their index into an array.我假设(错误地)设置工作表的顺序会使工作表保持在那个位置,有点像将工作表插入到数组的索引中。 However, subsequent calls to setSheetOrder will modify the sheet order of other sheets if your latest call implicitly modifies the order in front of the sheet used in your last call.但是,如果您最近的调用隐式修改了上次调用中使用的工作表前面的顺序,则对 setSheetOrder 的后续调用将修改其他工作表的工作表顺序。

For example, if you have sheets ordered like this:例如,如果您有这样订购的工作表:

[StaticX, StaticY, Cloned3, Cloned4, Cloned1, Cloned2] and you call setSheetOrder("Cloned3", 3) [StaticX, StaticY, Cloned3, Cloned4, Cloned1, Cloned2] 然后你调用 setSheetOrder("Cloned3", 3)

the order becomes订单变成

[StaticX, StaticY, Cloned4, Cloned3, Cloned1, Cloned2] which is desired. [StaticX, StaticY, Cloned4, Cloned3, Cloned1, Cloned2] 这是需要的。

However, a subsequent call to setSheetOrder("Cloned1", 1) will now make the order但是,对 setSheetOrder("Cloned1", 1) 的后续调用现在将使订单

[StaticX, Cloned1, StaticY, Cloned4, Cloned3, Cloned2] which has moved Cloned3 out of position 3. [StaticX, Cloned1, StaticY, Cloned4, Cloned3, Cloned2] 已将 Cloned3 移出位置 3。

In my debug prints I was thinking it was working because I was just checking the order that the last call set, which is of course correct every time, but when I started printing out the order of all sheets after every setting of the sheet order, the problem became evident.在我的调试打印中,我认为它正在工作,因为我只是检查最后一次调用设置的顺序,这当然每次都是正确的,但是当我在每次设置工作表顺序后开始打印所有工作表的顺序时,问题变得很明显。

To fix this, I just put all my sheetnames into an array in the order I wanted them, and set the sheet order from first to last in order, which works great.为了解决这个问题,我只是按照我想要的顺序将我所有的工作表名称放入一个数组中,并按顺序设置工作表的顺序,这很好用。

Thanks so much to Axel for providing that minimal example.非常感谢 Axel 提供了这个最小的例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM