Как преобразовать область в Excel do c в таблицу, используя Apache POI? - PullRequest
1 голос
/ 20 апреля 2020

Я написал приложение, которое извлекает данные из базы данных и создает из этих данных Excel do c, используя классы XSSF в библиотеке Apache POI. Я импортировал poi, poi-oo xml и poi-oo xml -schemas, все версии 4.1.0.

Файл записывается нормально, и при открытии файла ошибок нет, пока Я раскомментирую код создания таблицы, который вставлю ниже:

CellReference topLeft = new CellReference(sheet.getRow(3).getCell(0));
CellReference bottomRight = new CellReference(sheet.getRow(nextRow-1).getCell(3));
AreaReference tableArea = workbook.getCreationHelper().createAreaReference(topLeft, bottomRight);
XSSFTable dataTable = sheet.createTable(tableArea);

Я добавил несколько дополнительных полей, чтобы исключить некоторые потенциальные проблемы:

int test = dataTable.getEndRowIndex(); //Returns 968, as expected
tableArea = dataTable.getArea(); //The area remains A4 to D968, as expected
int testColumns = dataTable.getColumnCount(); //Returns 4, as expected
int testRows = dataTable.getRowCount(); //Returns 968, as expected

Когда я пытаюсь открыв книгу после раскомментирования приведенного выше кода, я получаю следующую ошибку:

"Мы обнаружили проблему с некоторым содержимым в файле" filename.xlsx ". Хотите, чтобы мы попытались восстановить столько, сколько мы можем? Если вы доверяете источнику этой книги, нажмите «Да». «

После нажатия« Да »данные отображаются без таблицы и отображается следующая ошибка:« Удаленная часть: /xl/tables/table1.*1020 » * часть с XML ошибка. (Таблица) Ошибка загрузки. Строка 2, столбец 94. "

Это сбивает с толку, поскольку все признаки показывают, что в таблице должно быть только 4 столбца ... подсказка, что может происходить и как это исправить?

1 Ответ

3 голосов
/ 20 апреля 2020

У вашего XSSFTable нет имен. По крайней мере, отображаемое имя должно быть установлено с помощью XSSFTable.setDisplayName .

Так что dataTable.setDisplayName("Table1"); должно решить вашу проблему.

Как обнаружить?

Сначала создайте простой завершенный пример. Затем, после открытия результата с помощью Excel, обратите внимание, в какой строке / столбце /xl/tables/table1.xml содержится ошибка. Затем откройте /xl/tables/table1.xml после расстегивания молнии *.xlsx. Теперь вы должны найти, что ошибочный XML:

<table id="1" ref="A4:D..." xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><tableColumns count="4">

И ошибка сразу после <table id="1" ref="A4:D..." xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">. Таким образом, первый тег кажется неполным.

Теперь сравните это с XML Excel, который создает сам. Вы обнаружите, что для Excel table элементов всегда будет установлено name="TableN" displayName="TableN".

Полный пример:

import java.io.FileOutputStream;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;

import java.util.GregorianCalendar;

class CreateExcelTable {

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

  Object[][] data = new Object[][] {
   new Object[] {"Text", "Date", "Number", "Boolean"},
   new Object[] {"Text 1", new GregorianCalendar(2020, 0, 1), 1234d, true},
   new Object[] {"Text 2", new GregorianCalendar(2020, 1, 15), 5678d, true},
   new Object[] {"Text 3", new GregorianCalendar(2020, 2, 1), 90.1234, false},
   new Object[] {"Text 4", new GregorianCalendar(2020, 3, 15), 567.89, false}
  };

  try (XSSFWorkbook workbook = new XSSFWorkbook();
       FileOutputStream fileout = new FileOutputStream("Excel.xlsx") ) {

   XSSFCellStyle dateCellStyle = workbook.createCellStyle();
   dateCellStyle.setDataFormat(14);

   XSSFSheet sheet = workbook.createSheet();
   XSSFRow row = sheet.createRow(0);
   XSSFCell cell = row.createCell(0);
   cell.setCellValue("Lorem ipsum");
   row = sheet.createRow(1);
   cell = row.createCell(0);
   cell.setCellValue("semit dolor");

   int nextRow = 3;
   int nextCol = 0;
   for (Object[] dataRow : data) {
    row = sheet.createRow(nextRow++);
    nextCol = 0;
    for (Object value : dataRow) {
     cell = row.createCell(nextCol++);
     if (value instanceof String) cell.setCellValue((String)value);
     else if (value instanceof GregorianCalendar) {
      cell.setCellValue((GregorianCalendar)value);
      cell.setCellStyle(dateCellStyle);
     }
     else if (value instanceof Double) cell.setCellValue((Double)value);
     else if (value instanceof Boolean) cell.setCellValue((Boolean)value);
    }
   }

   CellReference topLeft = new CellReference(sheet.getRow(3).getCell(0));
   CellReference bottomRight = new CellReference(sheet.getRow(nextRow-1).getCell(3));
   AreaReference tableArea = workbook.getCreationHelper().createAreaReference(topLeft, bottomRight);
   XSSFTable dataTable = sheet.createTable(tableArea);
   //dataTable.setName("Table1");
   dataTable.setDisplayName("Table1");

/* 
   //this styles the table as Excel would do per default
   dataTable.getCTTable().addNewTableStyleInfo();
   XSSFTableStyleInfo style = (XSSFTableStyleInfo)dataTable.getStyle();
   style.setName("TableStyleMedium2");
   style.setShowColumnStripes(false);
   style.setShowRowStripes(true);

   dataTable.getCTTable().addNewAutoFilter().setRef(tableArea.formatAsString());
*/

   workbook.write(fileout);
  }

 }
}
...