Apache POI XSSFWorkbook setSheetOrder не сортируется - PullRequest
0 голосов
/ 28 марта 2020

Я использую Apache POI (4.1.1) для изменения существующей книги. Рабочая тетрадь содержит четыре листа. Я использую второй лист в качестве шаблона, клонируя его, а затем записывая данные на новые клонированные листы. Клонируется примерно шесть раз или около того. В конце этого процесса я удаляю лист шаблона, затем пытаюсь установить порядок листов для всех листов: существующие листы (без шаблона) и затем клонированные листы. Я использую XSSFWorkbook :: setSheetOrder, чтобы сделать это, и я вижу, как это изменяет индекс в отладке, но когда мой файл Excel фактически записывает, листы не в порядке.

Вот соответствующий код:

        // 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);

Я включил отладочную печать выше, чтобы показать, откуда я знаю, что индекс на самом деле изменяется в порядке, который я хочу с помощью метода setSheetOrder. Однако, когда я открываю файл Excel, сгенерированный этим кодом, все мои листы существуют, но они не в указанном мной порядке.

Я был бы очень признателен за некоторые идеи! Спасибо.

Ответы [ 2 ]

1 голос
/ 28 марта 2020

Невозможно воспроизвести это поведение. Пожалуйста, покажите Минимальный воспроизводимый пример , который показывает это поведение.

Я приведу такой, который показывает, что он работает правильно:

Начните с Execl.xlsx, например так:

enter image description here

Затем следующий код:

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;
  }
 }
}

печатает на консоли следующее:

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

и приводит к этому результату ExcelNew.xlsx:

enter image description here

0 голосов
/ 28 марта 2020

Как оказалось, у меня было неправильное понимание того, как работает XSSFWorkbook :: setSheetOrder.

Я предполагал (ошибочно), что установка порядка листа будет держать лист в этом положении, что-то вроде распределяя листы по их индексу в массив. Однако последующие вызовы setSheetOrder изменят порядок листов других листов, если ваш последний вызов неявно изменяет порядок перед листом, использованным в вашем последнем вызове.

Например, если у вас есть листы, упорядоченные следующим образом:

[StaticX, StaticY, Cloned3, Cloned4, Cloned1, Cloned2] и вы вызываете setSheetOrder ("Cloned3", 3)

, порядок становится

[StaticX, StaticY, Cloned4, Cloned3, Cloned1, Cloned2], что необходимо.

Однако, последующий вызов setSheetOrder ("Cloned1", 1) теперь будет иметь порядок

[StaticX, Cloned1, StaticY, Cloned4, Cloned3, Cloned2], который переместил Cloned3 из позиции 3.

В моих отладочных отпечатках я думал, что это работает, потому что я просто проверял порядок, который установил последний вызов, который, конечно, корректен каждый раз время, но когда я начал распечатывать порядок всех листов после каждой настройки порядка листов, проблема стала очевидной.

Чтобы это исправить, я просто положил все Укажите имена листов в массиве в том порядке, в котором я их хотел, и установите порядок листов от первого к последнему в порядке, что прекрасно работает.

Большое спасибо Акселю за предоставленный этот минимальный пример.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...