programing

Apache POI의 컬럼 크기를 자동화하는 방법은 무엇입니까?

newsource 2023. 4. 15. 08:55

Apache POI의 컬럼 크기를 자동화하는 방법은 무엇입니까?

스프레드시트의 열을 자동 크기 조정하려면 다음 코드를 사용합니다.

for (int i = 0; i < columns.size(); i++) {
   sheet.autoSizeColumn(i, true);
   sheet.setColumnWidth(i, sheet.getColumnWidth(i) + 600);
}

문제는 행이 3000개 이상인 대형 스프레드시트의 경우 각 열의 크기를 자동화하는 데 10분 이상 걸린다는 것입니다.작은 문서에는 매우 빠르게 처리됩니다.오토사이징을 빠르게 할 수 있는 방법이 있을까요?

"CHANGE: "CHANGE: "CHANGE: " 。

병합 영역을 회피할 수 있기 때문에 다른 셀을 통해 반복하여 최종적으로 다음과 같이 가장 큰 셀로 자동 사이징할 수 있습니다.

int width = ((int)(maxNumCharacters * 1.14388)) * 256;
sheet.setColumnWidth(i, width);

여기서 1.14388은 "Serif" 글꼴과 256 글꼴 단위의 최대 문자 너비입니다.

오토사이징의 퍼포먼스는 10분에서6초로 향상되었습니다.

autoSizeColumn 함수 자체가 완벽하지 않고 일부 열 너비가 내부 데이터에 정확히 맞지 않습니다.그래서 나에게 맞는 해결책을 찾았습니다.

  1. 비정상적인 계산을 피하려면 autoSizeColumn() 함수에 이 값을 지정합니다.
   sheet.autoSizeColumn(<columnIndex>);
  1. 현재 컬럼은 라이브러리별로 자동 조정되지만 테이블이 올바르게 표시되도록 현재 컬럼 너비에 조금 더 추가하는 경향이 있습니다.
   // get autosized column width
   int currentColumnWidth = sheet.getColumnWidth(<columnIndex>);

   // add custom value to the current width and apply it to column
   sheet.setColumnWidth(<columnIndex>, (currentColumnWidth + 2500));
  1. 전체 기능은 다음과 같습니다.
   public void autoSizeColumns(Workbook workbook) {
        int numberOfSheets = workbook.getNumberOfSheets();
        for (int i = 0; i < numberOfSheets; i++) {
            Sheet sheet = workbook.getSheetAt(i);
            if (sheet.getPhysicalNumberOfRows() > 0) {
                Row row = sheet.getRow(sheet.getFirstRowNum());
                Iterator<Cell> cellIterator = row.cellIterator();
                while (cellIterator.hasNext()) {
                    Cell cell = cellIterator.next();
                    int columnIndex = cell.getColumnIndex();
                    sheet.autoSizeColumn(columnIndex);
                    int currentColumnWidth = sheet.getColumnWidth(columnIndex);
                    sheet.setColumnWidth(columnIndex, (currentColumnWidth + 2500));
                }
            }
        }
    }

P.S. Ondrej Kvasnovsky 함수에 감사드립니다.

autosizeColumn()이치노Apache POI를 사용하다

이 과정은 큰 시트에서 상대적으로 느릴 수 있습니다.

셀의 폭을 수동으로 계산하고 설정하는 것이 훨씬 빠릅니다.제 경우는 시간을 25,000ms에서 1~5ms로 단축했습니다.

(Vladimir Shcherbukhin의 답변에 근거하고 있었습니다).

Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
final int[] maxNumCharactersInColumns = new int[headers.length]; // maximum number of characters in columns. Necessary to calculate the cell width in most efficient way. sheet.autoSizeColumn(...) is very slow.

Row headersRow = sheet.createRow(0);
CellStyle headerStyle = createHeadersStyle(workbook); // createHeadersStyle() is my own function. Create headers style if you want

for (int i = 0; i < headers.length; i++) { // create headers
        Cell headerCell = headersRow.createCell(i, CELL_TYPE_STRING);
        headerCell.setCellValue(headers[i]);
        headerCell.setCellStyle(headerStyle);

        int length = headers[i].length();
        if (maxNumCharactersInColumns[i] < length) { // adjust the columns width
            maxNumCharactersInColumns[i] = length + 2; // you can add +2 if you have filtering enabled on your headers
        }
}

int rowIndex = 1;
    for (List<Object> rowValues : rows) {
        Row row = sheet.createRow(rowIndex);

        int columnIndex = 0;
        for (Object value : rowValues) {
            Cell cell = createRowCell(row, value, columnIndex); // createRowCell() is my own function.

            int length;
            if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
                String cellValue = cell.getStringCellValue();

                // this is quite important part. In some excel spreadsheet you can have a values with line-breaks. It'll be cool to handle that scenario :)
                String[] arr = cellValue.split("\n"); // if cell contains complex value with line breaks, calculate only the longest line
                length = Arrays.stream(arr).map(String::length).max(Integer::compareTo).get();
            } else {
                length = value != null ? value.toString().length() : 0;
            }

            if (maxNumCharactersInColumns[columnIndex] < length) { // if the current cell value is the longest one, save it to an array
                maxNumCharactersInColumns[columnIndex] = length;
            }

            columnIndex++;
        }
        rowIndex++;
    }

    for (int i = 0; i < headers.length; i++) {
        int width = (int) (maxNumCharactersInColumns[i] * 1.45f) * 256; // 1.45f <- you can change this value
        sheet.setColumnWidth(i, Math.min(width, MAX_CELL_WIDTH)); // <- set calculated cell width
    }

    sheet.setAutoFilter(new CellRangeAddress(0, 0, 0, headers.length - 1));

    ByteArrayOutputStream output = new ByteArrayOutputStream();
    workbook.write(output);
    workbook.close();

유감스럽게도 저는 아직 평판이 좋지 않아서 답변에 코멘트를 추가할 수 없습니다.여기 몇 가지 주석이 있습니다.

  • 「」를 사용하고 Row row = sheet.getRow(sheet.getFirstRowNum());shure, 이 행에는 마지막 열에 적어도 값이 포함되어 있습니다.그렇지 않으면 cellIterator가 너무 일찍 종료됩니다. 즉, 후속 행의 값이 이 열에 있는 경우 이 열은 자동으로 크기가 조정되지 않습니다.안 되다, 안 되다, 안 되다 하면 안 요.row에 헤더(컬럼 이름)를 나타냅니다.또는 알려진 헤더 행을 명시적으로 사용합니다.
    int indexOfHeaderRow = ...;
    ...
    Row row = sheet.getRow(indexOfHeaderRow);

  • sheet.setColumnWidth(i, Math.min(width, MAX_CELL_WIDTH)); // <- set calculated cellwidth
    MAX_CELL_WIDW의 내용에 대한 정보가 없기 때문에 이 행에 대해서는 설명하지 않습니다.체적적전그래서 대신 이렇게 썼어요.
    sheet.setColumnWidth(i, Math.max(width, 2048));
    폭은 입니까?2048 심은 2048 심입니까?이 값은 비어 있는 열의 폭이 극도로 좁아지는 것을 방지합니다.

언급URL : https://stackoverflow.com/questions/18983203/how-to-speed-up-autosizing-columns-in-apache-poi