[Apache POI] 라이브러리를 사용 해서 대용량의 엑셀 파일을 만들려고 하고 있습니다.
https://blog.naver.com/tommybee/222056850634
대략 700000 건 정도 되는 데이터 였는 데요.
다음과 같이 메서드를 작성 하였죠.
private static final String localheadersformat[] = new String[]
{
"팀 ",
"조 ",
"차량번호 ",
"성명 ",
"업무 ",
"ID ",
"컬럼 A ",
};
public static void printXlxsFile(String fileName, String[] localgpsheadersformat, final String dateStart, final String dateEnd) {
String excelFilePath = "데이터_${start}_${end}.xlsx"
.replace("${start}", dateStart)
.replace("${end}", dateEnd);
XSSFWorkbook workbook = null;
XSSFSheet sheet = null;
final String headerNames[][] = new String[][] {
localheadersformat,
{}
};
final int numberOfColumns = headerNames[0].length;
// logger.debug("numberOfColumns:{}", numberOfColumns);
try {
workbook = new XSSFWorkbook();
sheet = workbook.createSheet(excelFilePath);
Row headerRow = sheet.createRow(0);
String columnName = null;
// exclude the first column which is the ID field
for (int i = 0; i < numberOfColumns; i++) {
columnName = headerNames[0][i];
CellStyleUtils.createHeaderCell(workbook, headerRow, i, HorizontalAlignment.CENTER, VerticalAlignment.TOP, columnName);
columnName = null;
}
} catch (Exception e) {
System.out.println("File IO error:");
e.printStackTrace();
}
String TEAM_NM = null;
... 생략 ...
BufferedReader bReader = null;
BufferedOutputStream outputStream = null;
CellStyle cellStyle = null;
try {
int rowCount = 1;
int cellCount = 0;
bReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
String line = null;
final String delim = "$";
while((line = bReader.readLine()) != null)
{
StringTokenizer stTok = new StringTokenizer(line, delim);
stTok.setEmptyTokenAsNull(true);
... 생략 ...
Row row = sheet.createRow(rowCount++);
cellCount = 0;
CellStyleUtils.createCommonCell(workbook, row, cellCount++, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM,
TEAM_NM);
... 생략 ...
row = null;
line = null;
}
outputStream = new BufferedOutputStream(new FileOutputStream(excelFilePath));
workbook.write(outputStream);
} catch (Exception e) {
System.out.println("File IO error:");
e.printStackTrace();
} finally {
try {
if (workbook != null)
workbook.close();
if (bReader != null)
bReader.close();
if (outputStream != null)
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return;
}
CellStyleUtils 클래스는 부치 유틸리티 클래스 인데 코드는 다음과 같았습니다.
static void createCommonCell(Workbook wb, Row row, int column, HorizontalAlignment halign,
VerticalAlignment valign, String value) {
// Create a new font and alter it.
Font font = wb.createFont();
// font.setFontHeightInPoints((short)24);
font.setFontName("굴림");
// font.setItalic(true);
// font.setStrikeout(true);
Cell cell = row.createCell(column);
cell.setCellValue(value);
// Style the cell with borders all around.
CellStyle style = wb.createCellStyle();
// style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
// style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderLeft(BorderStyle.THIN);
style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderTop(BorderStyle.THIN);
style.setTopBorderColor(IndexedColors.BLACK.getIndex());
style.setAlignment(halign);
style.setVerticalAlignment(valign);
style.setFont(font);
cell.setCellStyle(style);
}
별 문제 없는 코드이긴 합니다만, 만들려고 하는 데이터가 몇건인가가 중요한 문제가 되었습니다.
우선, 저는 환하게 반기는 오류가 있었습니다.
The maximum number of Cell Styles was exceeded.
내용을 입력하세요.
저에게는 새로운 사실이군요. 스타일을 64000개 이상은 못쓴다는 것을 확인 하는 날이 될 줄이야...
이 부분을 넘어가기 위해서 스타일을 만드는 메서드를 다음과 같이 따로 뽑아 냈습니다.
static CellStyle adjustCellStyle(Workbook wb,HorizontalAlignment halign, VerticalAlignment valign)
{
// Create a new font and alter it.
Font font = wb.createFont();
// font.setFontHeightInPoints((short)24);
font.setFontName("굴림");
// font.setItalic(true);
// font.setStrikeout(true);
// Style the cell with borders all around.
CellStyle style = wb.createCellStyle();
// style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
// style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderLeft(BorderStyle.THIN);
style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderTop(BorderStyle.THIN);
style.setTopBorderColor(IndexedColors.BLACK.getIndex());
style.setAlignment(halign);
style.setVerticalAlignment(valign);
style.setFont(font);
return style;
}
그런 다음엔 다음과 같이 최초 메서드를 수정 하였습니다.
public static void printXlxsFile(String fileName, String[] localgpsheadersformat, final String dateStart, final String dateEnd) {
String excelFilePath = "데어터_${start}_${end}.xlsx"
.replace("${start}", dateStart)
.replace("${end}", dateEnd);
XSSFWorkbook workbook = null;
XSSFSheet sheet = null;
final String headerNames[][] = new String[][] {
localheadersformat,
{}
};
final int numberOfColumns = headerNames[0].length;
// logger.debug("numberOfColumns:{}", numberOfColumns);
try {
workbook = new XSSFWorkbook();
sheet = workbook.createSheet(excelFilePath);
Row headerRow = sheet.createRow(0);
String columnName = null;
for (int i = 0; i < numberOfColumns; i++) {
columnName = headerNames[0][i];
CellStyleUtils.createHeaderCell(workbook, headerRow, i, HorizontalAlignment.CENTER, VerticalAlignment.TOP, columnName);
columnName = null;
}
} catch (Exception e) {
System.out.println("File IO error:");
e.printStackTrace();
}
String TEAM_NM = null;
... 생략 ...
BufferedReader bReader = null;
BufferedOutputStream outputStream = null;
CellStyle cellStyle = null;
try {
int rowCount = 1;
int cellCount = 0;
bReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
String line = null;
final String delim = "$";
cellStyle = CellStyleUtils.adjustCellStyle(workbook,HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
while((line = bReader.readLine()) != null)
{
StringTokenizer stTok = new StringTokenizer(line, delim);
stTok.setEmptyTokenAsNull(true);
... 생략 ...
Row row = sheet.createRow(rowCount++);
cellCount = 0;
CellStyleUtils.createCommonCell(cellStyle, row, cellCount++, TEAM_NM == null? "":TEAM_NM .trim());
... 생략 ...
row = null;
line = null;
}
outputStream = new BufferedOutputStream(new FileOutputStream(excelFilePath));
workbook.write(outputStream);
} catch (Exception e) {
System.out.println("File IO error:");
e.printStackTrace();
} finally {
try {
if (workbook != null)
workbook.close();
if (bReader != null)
bReader.close();
if (outputStream != null)
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return;
}
이렇게 되면 createCommonCell 메서드는 몇개 들어가 있지 않게 되는 군요...
static void createCommonCell(CellStyle style, Row row, int column, String value) {
Cell cell = row.createCell(column);
cell.setCellValue(value);
cell.setCellStyle(style);
}
그래서 위의 문제를 해결 하였습니다.
다 해결 되었을까요??? ㅋㅋㅋ
그 다음 문제가 Java heap space 오류니까 위 문제를 해결 해 봐야 안되는 문제 였다는 것입니다
해결책을 말씀드리자면, 데이터를 잘라서 각각의 엑셀 파일을 만들었습니다. 그 이외의 방법은 생각하지 않기로 했습니다.
결론은 700000 건의 데이터의 크기가 800메가 정도 되었는 데, 일반적인 컴터에서는 이 파일을 열기가 힘들다 였습니다.
이상.
'프로그래밍 > TroubleShooting' 카테고리의 다른 글
SSLHandshakeException 관련 오류 (1) | 2024.01.25 |
---|---|
[Internet Explorer] keep-alive, time-out 값 변경 방법 (0) | 2022.12.04 |
Notepad++ 에서 개행문자 치환 (1) | 2022.10.18 |
[mybatis] Expected one result (or null) to be returned by selectOne(), but found (0) | 2022.10.07 |