POI пишет поврежденный .xlsx при добавлении большого количества ValidationData в лист - PullRequest
0 голосов
/ 03 июля 2019

Я хочу написать большой .xlsx файл (50K строк), используя POI в JAVA.Я ожидаю, что каждая строка будет содержать несколько раскрывающихся ячеек.Код работает нормально, когда число строк меньше 30 КБ, но записывает поврежденный файл, если количество строк превышает 35 КБ.

Я пробовал SXSSFWorkbook и XSSFWorkbook, но ни одна из них не работала для меня.

Вот код:

        SXSSFWorkbook workbook = new SXSSFWorkbook(100);
        SXSSFSheet sheet = workbook.createSheet();
        String[] optionsArray = new String[] {"1000.00","2000.00"};
        int no_of_rows = 35000;
        for(int i=0;i<=no_of_rows;i++) {
            SXSSFRow row1 = sheet.createRow(i);
            SXSSFCell r1c1 = row1.createCell(0);
            DataValidationConstraint  constraint1 = sheet.getDataValidationHelper().createExplicitListConstraint(optionsArray);
            CellRangeAddressList addressList1 = new CellRangeAddressList(i, i, 0, 0);
            DataValidation dataValidation1 = sheet.getDataValidationHelper().createValidation(constraint1, addressList1);
            sheet.addValidationData(dataValidation1);
            r1c1.setCellValue("1000.00");   

            SXSSFCell r1c2 = row1.createCell(1);
            DataValidationConstraint  constraint2 = sheet.getDataValidationHelper().createExplicitListConstraint(optionsArray);
            CellRangeAddressList addressList2 = new CellRangeAddressList(i, i, 1, 1);
            DataValidation dataValidation2 = sheet.getDataValidationHelper().createValidation(constraint2, addressList2);
            sheet.addValidationData(dataValidation2);
            r1c2.setCellValue("2000.00");
        }
        FileOutputStream fos =new FileOutputStream(new File("c:\\data\\testout.xlsx"));
        workbook.write(fos);
        workbook.close();
        fos.close();

Я ожидаю, что POI будет хорошо работать как минимум с 50К строк таких данных.

1 Ответ

0 голосов
/ 04 июля 2019

Не создавать DataValidation для каждой отдельной ячейки.Вместо этого создайте только две необходимые проверки данных, одну для A1:A50001, а другую для B1:B50001.Для этого CellRangeAddressList s может содержать целые диапазоны столбцов:

CellRangeAddressList addressList1 = new CellRangeAddressList(0, no_of_rows, 0, 0);

и

CellRangeAddressList addressList1 = new CellRangeAddressList(0, no_of_rows, 1, 1);

Ваш пример:

import java.io.File;
import java.io.FileOutputStream;
import org.apache.poi.ss.util.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.*;

class CreateSXSSFWorkbookDataValidations {

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

        SXSSFWorkbook workbook = new SXSSFWorkbook(100);
        SXSSFSheet sheet = workbook.createSheet();

        String[] optionsArray = new String[] {"1000.00","2000.00"};

        int no_of_rows = 50000;

        for(int i=0;i<=no_of_rows;i++) {
            SXSSFRow row1 = sheet.createRow(i);
            SXSSFCell r1c1 = row1.createCell(0);
            r1c1.setCellValue("1000.00");   
            SXSSFCell r1c2 = row1.createCell(1);
            r1c2.setCellValue("2000.00");
        }

        DataValidationConstraint constraint1 = sheet.getDataValidationHelper().createExplicitListConstraint(optionsArray);
        CellRangeAddressList addressList1 = new CellRangeAddressList(0, no_of_rows, 0, 0);
        DataValidation dataValidation1 = sheet.getDataValidationHelper().createValidation(constraint1, addressList1);
        sheet.addValidationData(dataValidation1);

        DataValidationConstraint constraint2 = sheet.getDataValidationHelper().createExplicitListConstraint(optionsArray);
        CellRangeAddressList addressList2 = new CellRangeAddressList(0, no_of_rows, 1, 1);
        DataValidation dataValidation2 = sheet.getDataValidationHelper().createValidation(constraint2, addressList2);
        sheet.addValidationData(dataValidation2);

        FileOutputStream fos = new FileOutputStream(new File("testout.xlsx"));
        workbook.write(fos);
        workbook.close();
        fos.close();


    }
}

Наличие разных уникальных данныхпроверка для каждой отдельной ячейки невозможна, когда количество различных проверок уникальных данных превышает предел.Это ограничение Excel, а не apache poi.

Это специальное ограничение для проверки данных не задокументировано в Спецификации и ограничения Excel .Но это может быть связано с ограничениями уникальных форматов ячеек / стилей ячеек (64 000) или с ограничением гиперссылок на листе (66 530).

...