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 함수 자체가 완벽하지 않고 일부 열 너비가 내부 데이터에 정확히 맞지 않습니다.그래서 나에게 맞는 해결책을 찾았습니다.
- 비정상적인 계산을 피하려면 autoSizeColumn() 함수에 이 값을 지정합니다.
sheet.autoSizeColumn(<columnIndex>);
- 현재 컬럼은 라이브러리별로 자동 조정되지만 테이블이 올바르게 표시되도록 현재 컬럼 너비에 조금 더 추가하는 경향이 있습니다.
// 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));
- 전체 기능은 다음과 같습니다.
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
'programing' 카테고리의 다른 글
코드에서 동적 리소스 스타일을 할당하려면 어떻게 해야 합니까? (0) | 2023.04.15 |
---|---|
Javascript의 PMT 함수 (0) | 2023.04.15 |
WPF 팝업 UI가 검은색으로 표시됨 (0) | 2023.04.15 |
서명 중 오류가 발생했습니다. (0) | 2023.04.10 |
문서 폴더의 파일 목록을 가져오는 중 (0) | 2023.04.10 |