Всем привет, столкнулся с проблемой, при формирование эксель файла, процесс с каждой итерацией начинает тормозить, первые итерации проходят за 60-70мс, последующие увеличиваются на 10-20мс, к 50й итерации уже больше секунды.
каждая итерация состоит из добавления от 6 до 10 строк, с применениями стилей, форматирования, объединения. То есть формируется отчет.
общее число итераций может достигать до 800 итераций.
Может кто подскажет, кто-то может решал такую проблему? по другому не могу формировать отчет. Может как-то через многопоточность возможно? Но я к сожалению в ней пока сырой.
Вот кусок основного кода, кода много.
try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(fileCalc))) {
ZipSecureFile.setMinInflateRatio(-1.0d);
xssfWorkbook = new XSSFWorkbook(fis);
XSSFSheet sheet = xssfWorkbook.getSheetAt(0);
// Строка старта шапки
int rowStartHead = 0;
int numberTable = 1;
for (TotalModel totalModel: listTotalModel) {
if (totalModel != null) {
// Строка финиша шапки
int rowFinishHead = rowStartHead + 3;
for (int i = rowStartHead; i <= rowFinishHead; i++) {
XSSFRow rowHead = sheet.createRow(i);
Cell head0 = rowHead.createCell(0);
head0.setCellValue("№п/п");
head0.setCellStyle(cellStyleHead(sheet));
Cell head1 = rowHead.createCell(1);
head1.setCellValue("Станция отправления");
head1.setCellStyle(cellStyleHead(sheet));
Cell head2 = rowHead.createCell(2);
head2.setCellValue("Дорога отпр.");
head2.setCellStyle(cellStyleHead(sheet));
sheet.setColumnWidth(2, 2194);
Cell head3 = rowHead.createCell(3);
head3.setCellValue("Станция назначения");
head3.setCellStyle(cellStyleHead(sheet));
Cell head4 = rowHead.createCell(4);
head4.setCellValue("Дорога назн.");
head4.setCellStyle(cellStyleHead(sheet));
sheet.setColumnWidth(4, 2194);
Cell head5 = rowHead.createCell(5);
head5.setCellValue("Наименование груза");
head5.setCellStyle(cellStyleHead(sheet));
Cell head6 = rowHead.createCell(6);
head6.setCellValue("Расст., км");
head6.setCellStyle(cellStyleHead(sheet));
Cell head7 = rowHead.createCell(7);
head7.setCellValue("Время в пути, сут");
head7.setCellStyle(cellStyleHead(sheet));
Cell head8 = rowHead.createCell(8);
head8.setCellValue("Погр. / выгр.");
head8.setCellStyle(cellStyleHead(sheet));
Cell head9 = rowHead.createCell(9);
head9.setCellValue("Оборот, сут.");
head9.setCellStyle(cellStyleHead(sheet));
Cell head10 = rowHead.createCell(10);
head10.setCellValue("ВО");
head10.setCellStyle(cellStyleHead(sheet));
Cell head11 = rowHead.createCell(11);
if (i == rowFinishHead) {
head11.setCellValue("руб/ваг.");
} else {
head11.setCellValue("ДОХОД");
}
head11.setCellStyle(cellStyleHeadBottom(sheet));
Cell head12 = rowHead.createCell(12);
if (i == rowFinishHead - 1 || i == rowFinishHead - 2) {
head12.setCellValue("Тариф в собств. вагонах");
} else if (i == rowFinishHead) {
head12.setCellValue("руб/ваг.");
} else {
head12.setCellValue("РАСХОД");
}
head12.setCellStyle(cellStyleHeadBottom(sheet));
Cell head13 = rowHead.createCell(13);
if (i == rowFinishHead - 1 || i == rowFinishHead - 2) {
head13.setCellValue("За нахождение в пути");
} else if (i == rowFinishHead) {
head13.setCellValue("руб/ваг.");
} else {
head13.setCellValue("ПРИБЫЛЬ");
}
head13.setCellStyle(cellStyleHeadBottom(sheet));
Cell head14 = rowHead.createCell(14);
if (i == rowFinishHead - 1 || i == rowFinishHead - 2) {
head14.setCellValue("В сутки");
} else if (i == rowFinishHead) {
head14.setCellValue("руб/ваг/сут.");
} else {
head14.setCellValue("ПРИБЫЛЬ");
}
head14.setCellStyle(cellStyleHeadRight(sheet));
}
for (int i = 0; i < 11; i++) {
sheet.addMergedRegion(new CellRangeAddress(rowStartHead, rowFinishHead, i, i));
}
sheet.addMergedRegion(new CellRangeAddress(rowStartHead, rowFinishHead - 1, 11, 11));
sheet.addMergedRegion(new CellRangeAddress(rowStartHead, rowStartHead, 13, 14));
for (int i = 12; i < 15; i++) {
sheet.addMergedRegion(new CellRangeAddress(rowStartHead + 1, rowFinishHead - 1, i, i));
}
// Строка первого рейса
int rowFirstRoute = rowFinishHead + 1;
// Номер первой ячейки данных
int firstNumberCell = rowFirstRoute + 1;
boolean isMarker = false;
for (Route route : totalModel.getTotalList()) {
int num = rowFirstRoute + 1;
XSSFRow row = sheet.createRow(rowFirstRoute);
Cell number = row.createCell(0);
if (!isMarker) {
number.setCellValue(numberTable);
isMarker = true;
} else {
number.setCellValue("");
}
number.setCellStyle(cellStyleField(sheet));
Cell stationDeparture = row.createCell(1);
stationDeparture.setCellValue(route.getStationDeparture().getNameStation());
if (route.isFlagNeedCalc()) {
stationDeparture.setCellStyle(cellStyleFieldNeedCalc(sheet,false));
} else {
stationDeparture.setCellStyle(cellStyleField(sheet));
}
Cell roadDeparture = row.createCell(2);
roadDeparture.setCellValue(route.getStationDeparture().getRoad().getNameRoad());
if (route.isFlagNeedCalc()) {
roadDeparture.setCellStyle(cellStyleFieldNeedCalc(sheet,false));
} else {
roadDeparture.setCellStyle(cellStyleField(sheet));
}
Cell stationDestination = row.createCell(3);
stationDestination.setCellValue(route.getStationDestination().getNameStation());
if (route.isFlagNeedCalc()) {
stationDestination.setCellStyle(cellStyleFieldNeedCalc(sheet,false));
} else {
stationDestination.setCellStyle(cellStyleField(sheet));
}
Cell roadDestination = row.createCell(4);
roadDestination.setCellValue(route.getStationDestination().getRoad().getNameRoad());
if (route.isFlagNeedCalc()) {
roadDestination.setCellStyle(cellStyleFieldNeedCalc(sheet,false));
} else {
roadDestination.setCellStyle(cellStyleField(sheet));
}
Cell cargo = row.createCell(5);
if (route.getRate() != 0) {
cargo.setCellValue(route.getCargo().getNameCargo());
cargo.setCellStyle(cellStyleFieldCargo(sheet));
} else {
cargo.setCellValue("Порожняк");
cargo.setCellStyle(cellStyleFieldCargo(sheet));
}
Cell distance = row.createCell(6);
distance.setCellValue(route.getDistance());
distance.setCellStyle(cellStyleFieldFormat(sheet, true));
Cell countDays = row.createCell(7);
countDays.setCellValue(route.getCountDays());
countDays.setCellStyle(cellStyleField(sheet));
Cell daysLoadUnload = row.createCell(8);
daysLoadUnload.setCellValue(route.getCountDaysLoadAndUnload());
daysLoadUnload.setCellStyle(cellStyleField(sheet));
Cell fullCountDays = row.createCell(9);
fullCountDays.setCellFormula("SUM(H" + num + ":I" + num + ")");
fullCountDays.setCellStyle(cellStyleField(sheet));
Cell call9 = row.createCell(10);
call9.setCellValue("поваг");
call9.setCellStyle(cellStyleField(sheet));
sheet.autoSizeColumn(10);
Cell rate = row.createCell(11);
if (route.getRate() == 0) {
rate.setCellStyle(cellStyleFieldNull(sheet));
} else {
rate.setCellValue(route.getRate());
if (route.isFlagNeedCalc()) {
rate.setCellStyle(cellStyleFieldNeedCalc(sheet, false));
} else {
rate.setCellStyle(cellStyleFieldFormat(sheet, false));
}
}
Cell tariff = row.createCell(12);
if (route.getTariff() == 0) {
tariff.setCellStyle(cellStyleFieldNull(sheet));
} else {
tariff.setCellValue(route.getTariff());
tariff.setCellStyle(cellStyleFieldFormat(sheet, false));
}
Cell rateTariff = row.createCell(13);
rateTariff.setCellFormula("L" + num + "-M" + num);
rateTariff.setCellStyle(cellStyleFieldFormat(sheet, false));
sheet.setColumnWidth(13, 3182);
Cell cell13 = row.createCell(14);
cell13.setCellValue("");
cell13.setCellStyle(cellStyleFieldRightBold(sheet));
rowFirstRoute++;
}
// Номер последней ячейки данных
int lastNumberCell = rowFirstRoute;
int totalYieldNum = rowFirstRoute + 1;
XSSFRow row = sheet.createRow(rowFirstRoute);
Cell cell0 = row.createCell(0);
cell0.setCellStyle(cellStyleFieldTotal(sheet));
Cell cell1 = row.createCell(1);
cell1.setCellStyle(cellStyleFieldTotal(sheet));
Cell cell2 = row.createCell(2);
cell2.setCellStyle(cellStyleFieldTotal(sheet));
Cell cell3 = row.createCell(3);
cell3.setCellStyle(cellStyleFieldTotal(sheet));
Cell cell4 = row.createCell(4);
cell4.setCellStyle(cellStyleFieldTotal(sheet));
Cell cell5 = row.createCell(5);
cell5.setCellStyle(cellStyleFieldTotal(sheet));
sheet.addMergedRegion(new CellRangeAddress(rowFirstRoute, rowFirstRoute, 0, 5));
// Строка итоговых расчетов
Cell totalDistance = row.createCell(6);
totalDistance.setCellFormula("SUM(G" + firstNumberCell + ":G" + lastNumberCell + ")");
totalDistance.setCellStyle(cellStyleFieldTotalFormat(sheet, true));
Cell totalCountDays = row.createCell(7);
totalCountDays.setCellFormula("SUM(H" + firstNumberCell + ":H" + lastNumberCell + ")");
totalCountDays.setCellStyle(cellStyleFieldTotal(sheet));
Cell totalCountLoadUnloadDays = row.createCell(8);
totalCountLoadUnloadDays.setCellFormula("SUM(I" + firstNumberCell + ":I" + lastNumberCell + ")");
totalCountLoadUnloadDays.setCellStyle(cellStyleFieldTotal(sheet));
Cell totalFullCountDays = row.createCell(9);
totalFullCountDays.setCellFormula("SUM(J" + firstNumberCell + ":J" + lastNumberCell + ")");
totalFullCountDays.setCellStyle(cellStyleFieldTotal(sheet));
Cell cell10 = row.createCell(10);
cell10.setCellStyle(cellStyleFieldTotal(sheet));
Cell cell11 = row.createCell(11);
cell11.setCellStyle(cellStyleFieldTotal(sheet));
Cell cell12 = row.createCell(12);
cell12.setCellStyle(cellStyleFieldTotal(sheet));
Cell totalRateTariff = row.createCell(13);
totalRateTariff.setCellFormula("SUM(N" + firstNumberCell + ":N" + lastNumberCell + ")");
totalRateTariff.setCellStyle(cellStyleFieldTotalFormat(sheet,false));
Cell yield = row.createCell(14);
yield.setCellFormula("N" + totalYieldNum + "/J" + totalYieldNum);
yield.setCellStyle(cellStyleFieldTotalRight(sheet, false));
sheet.autoSizeColumn(14);
Cell cell15 = row.createCell(15);
cell15.setCellValue(totalModel.getYield());
Cell cell16 = row.createCell(16);
cell16.setCellFormula("P" + totalYieldNum + "-O" + totalYieldNum);
Cell cell17 = row.createCell(17);
cell17.setCellFormula("Q" + totalYieldNum + "*J" + totalYieldNum);
rowStartHead = lastNumberCell + 1;
numberTable++;
}
}
xssfWorkbook.write(outputStream);
outputStream.flush();
outputStream.close();
}
Попробуйте расчитать стиль cellStyleField(sheet) один раз и другие стили тоже и вынести это из цикла, потом подставляйте только значения.
Сейчас у вас конструкция такая:
for (TotalModel totalModel: listTotalModel) {
//заполнение шапки
for (int i = rowStartHead; i <= rowFinishHead; i++) {
...
<cell>.setCellStyle(cellStyleHead(sheet));
...
}
//заполнение данными
for (Route route : totalModel.getTotalList()) {
...
<cell>.setCellStyle(cellStyleField(sheet));
...
}
}
я предлагаю попробовать примерно такой подход:
style1 = ...
style2 = ...
header = buildHeader();
for (TotalModel totalModel: listTotalModel) {
setHeader(header );
setData(sheet);
setStyles(sheet);
}
private void buildHeader(XSSFSheet sheet){
...
}
private void setHeader(XSSFSheet sheet){
...
}
private void setData(XSSFSheet sheet){
...
}
private void setStyles(XSSFSheet sheet){
<range1>.setCellStyle(style1);
<range2>.setCellStyle(style2);
}
Так избавитесь от многочисленных заданий стилей на каждую ячейку, и будет проще разбираться в коде в будущем, когда попросят доработать отчет.
Продвижение своими сайтами как стратегия роста и независимости