OSDN Git Service

Foreachのパフォーマンス改善
authornoboru saitoh <msnobosan@gmal.com>
Fri, 12 Sep 2014 18:22:29 +0000 (03:22 +0900)
committernoboru saitoh <msnobosan@gmal.com>
Fri, 12 Sep 2014 18:22:29 +0000 (03:22 +0900)
Jaxcel/src/org/hanei/jaxcel/report/TLParser.java
Jaxcel/src/org/hanei/jaxcel/util/ExcelUtil.java

index 5139ec3..7a0b586 100644 (file)
@@ -672,8 +672,8 @@ public class TLParser {
        private void parseForeach() {
                log.trace("parseForeach start");
 
-               Row row, toRow;
-               Cell cell, toCell;
+               Row fromRow, toRow;
+               Cell fromCell, toCell;
                Object evalObject;
                Object listObject;
                Object[] mapKeys = null;
@@ -819,7 +819,7 @@ public class TLParser {
                // シートに収まる範囲にリサイズ
                fromRange = ExcelUtil.getIntersectRange(sheet, fromRange);
 
-               // 繰返しコピー回数1以上なら
+               // 繰返しコピー回数1以上なら、コピー先範囲シフト・クリア等実施
                if(startIdx != endIdx) {
                        // コピー先範囲の範囲特定
                        int copyCount = startIdx < endIdx ? endIdx - startIdx : startIdx - endIdx;
@@ -887,118 +887,93 @@ public class TLParser {
                        }
                }
 
-               // コピー元範囲を繰返しコピー
-               // 範囲行でループ
-               for(int r = fromRange.getFirstRow(); r <= fromRange.getLastRow(); r++) {
-                       row = sheet.getRow(r);
-                       // コピー元行がnullで繰返し方向横(列)の場合
-                       if(row == null && COL.equalsIgnoreCase(direction)) {
-                               // コピー先行もnullとなるのでセルの処理はせず終了
-                               log.debug("continue. direction: col from row [{}] is null", (r + 1));
-                               continue;
-                       }
-
-                       // 範囲列でループ
-                       for(int c = fromRange.getFirstColumn(); c <= fromRange.getLastColumn(); c++) {
-                               // コピー元行がnullの場合セルもnull
-                               if(row == null) {
-                                       cell = null;
-                               } else {
-                                       cell = row.getCell(c);
+               // 繰返し回数でループしコピー
+               boolean copyFlg = true;
+               for(int i = startIdx, cpCount = 0; (startIdx <= endIdx && i <= endIdx || startIdx > endIdx && i >= endIdx); i = (startIdx <= endIdx ? i + 1 : i - 1), cpCount++) {
+                       // 範囲行でループ
+                       for(int r = fromRange.getFirstRow(); r <= fromRange.getLastRow(); r++) {
+                               // 繰返し方向縦(行)の場合、コピー先の範囲チェック
+                               if(ROW.equalsIgnoreCase(direction) && (r + rowSpan * cpCount < 0 || r + rowSpan * cpCount > ExcelUtil.getMaxRowIndex(sheet))) {
+                                       // コピー先行がシート範囲外
+                                       log.warn("to row outside sheet");
+                                       // 繰返しコピーフラグfalse
+                                       copyFlg = false;
+                                       break;
                                }
 
-                               // 繰返し回数でループ
-                               for(int i = startIdx, cpCount = 0; (startIdx <= endIdx && i <= endIdx || startIdx > endIdx && i >= endIdx); i = (startIdx <= endIdx ? i + 1 : i - 1), cpCount++) {
-                                       // 繰返し方向横(列)(行がデフォルト)
-                                       if(COL.equalsIgnoreCase(direction)) {
-                                               // 範囲チェック
-                                               if(c + colSpan * cpCount < 0 || c + colSpan * cpCount > ExcelUtil.getMaxColumnIndex(sheet)) {
-                                                       log.warn("to cell outside sheet");
-                                                       break;
-                                               }
-                                               toRow = row;
-                                               toCell = row.getCell(c + colSpan * cpCount);
-                                               // コピー元セルがnullならコピー先セルもnull
-                                               if(cell == null) {
-                                                       if(toCell != null) {
-                                                               toRow.removeCell(toCell);
-                                                               log.debug("continue. from cell [{}] is null. to cell [{}] remove", (new CellReference(r, c)).formatAsString(), (new CellReference(r, c + colSpan * cpCount)).formatAsString());
-                                                       }
-                                                       else {
-                                                               log.debug("continue. from cell [{}] and to cell [{}] is null", (new CellReference(r, c)).formatAsString(), (new CellReference(r, c + colSpan * cpCount)).formatAsString());
-                                                       }
-                                                       continue;
-                                               }
-                                               else {
-                                                       if(toCell == null) toCell = row.createCell(c + colSpan * cpCount);
-                                                       // block falseなら列情報(幅)もコピー
-                                                       if(!block) {
-                                                               sheet.setColumnWidth(toCell.getColumnIndex(), sheet.getColumnWidth(cell.getColumnIndex()));
-                                                       }
-                                               }
+                               // コピー元行
+                               fromRow = sheet.getRow(r);
+                               // コピー先行
+                               toRow = ROW.equalsIgnoreCase(direction) ? sheet.getRow(r + rowSpan * cpCount) : fromRow;
+
+                               // コピー元行がnullならコピー先行もnull。continue
+                               if(fromRow == null) {
+                                       if(toRow != null) {
+                                               log.debug("continue. from row [{}] is null. to row [{}] remove", (r + 1), (toRow.getRowNum() + 1));
+                                               sheet.removeRow(toRow);
                                        }
-                                       // 繰返し方向縦(行)の場合
                                        else {
-                                               // 範囲チェック
-                                               if(r + rowSpan * cpCount < 0 || r + rowSpan * cpCount > ExcelUtil.getMaxRowIndex(sheet)) {
-                                                       log.warn("to row outside sheet");
-                                                       break;
+                                               log.debug("continue. from row [{}] and to row [{}] is null", (r + 1), ((ROW.equalsIgnoreCase(direction) ? (r + rowSpan * cpCount) : r) + 1));
+                                       }
+                                       continue;
+                               } 
+                               
+                               // コピー先行がnullなら生成
+                               if(toRow == null) toRow = sheet.createRow(r + rowSpan * cpCount);
+                               
+                               // コピー元行・コピー先行 行番号が異なり、block falseなら行情報(高さ)もコピー
+                               if(fromRow.getRowNum() != toRow.getRowNum() && !block) toRow.setHeight(fromRow.getHeight());
+
+                               // 範囲列でループ
+                               for(int c = fromRange.getFirstColumn(); c <= fromRange.getLastColumn(); c++) {
+                                       // 繰返し方向横(列)の場合、コピー先の範囲チェック
+                                       if(COL.equalsIgnoreCase(direction) && (c + colSpan * cpCount < 0 || c + colSpan * cpCount > ExcelUtil.getMaxColumnIndex(sheet))) {
+                                               // コピー先列がシート範囲外
+                                               log.warn("to cell outside sheet");
+                                               break;
+                                       }
+
+                                       // コピー元セル
+                                       fromCell = fromRow.getCell(c);
+                                       // コピー先セル
+                                       toCell = toRow.getCell(COL.equalsIgnoreCase(direction) ? c + colSpan * cpCount : c);
+                                       
+                                       // コピー元セルがnullならコピー先セルもnull
+                                       if(fromCell == null) {
+                                               if(toCell != null) {
+                                                       log.debug("continue. from cell [{}] is null. to cell [{}] remove", (new CellReference(fromRow.getRowNum(), c)).formatAsString(), (new CellReference(toCell.getRowIndex(), toCell.getColumnIndex())).formatAsString());
+                                                       toRow.removeCell(toCell);
                                                }
-                                               // 繰返し先の行がなければ生成
-                                               toRow = sheet.getRow(r + rowSpan * cpCount);
-                                               toCell = null;
-                                               // コピー元行がnullならコピー先行もnull
-                                               if(row == null) {
-                                                       if(toRow != null) {
-                                                               sheet.removeRow(toRow);
-                                                               log.debug("continue. from row [{}] is null. to row [{}] remove", (r + 1));
-                                                       }
-                                                       else {
-                                                               log.debug("continue. from and to row is null");
-                                                       }
-                                                       continue;
-                                               } 
                                                else {
-                                                       if(toRow == null) toRow = sheet.createRow(r + rowSpan * cpCount);
-                                                       // block falseなら行情報(高さ)もコピー
-                                                       if(!block) {
-                                                               toRow.setHeight(row.getHeight());
-                                                       }
-                                                       toCell = toRow.getCell(c);
-                                                       // コピー元セルがnullならコピー先セルもnull
-                                                       if(cell == null) {
-                                                               if(toCell != null) {
-                                                                       toRow.removeCell(toCell);
-                                                                       log.debug("continue. from cell is null. to cell remove");
-                                                               }
-                                                               else {
-                                                                       log.debug("continue. from cell [{}] and to cell [{}] is null", (new CellReference(r, c)).formatAsString(), (new CellReference(r + rowSpan * cpCount, c)).formatAsString());
-                                                               }
-                                                               continue;
-                                                       }
-                                                       else {
-                                                               if(toCell == null) toCell = toRow.createCell(c);
-                                                       }
+                                                       log.debug("continue. from cell [{}] and to cell [{}] is null", (new CellReference(fromRow.getRowNum(), c)).formatAsString(), (new CellReference(toRow.getRowNum(), COL.equalsIgnoreCase(direction) ? c + colSpan * cpCount : c)).formatAsString());
                                                }
+                                               continue;
                                        }
 
+                                       // コピー先セルがnullなら生成
+                                       if(toCell == null) toCell = toRow.createCell(COL.equalsIgnoreCase(direction) ? c + colSpan * cpCount : c);
+
+                                       // コピー元列・コピー先列 列番号が異なり、block falseなら列情報(幅)もコピー  ( 繰返しループ1回目のみ)
+                                       if(cpCount == 0 && fromCell.getColumnIndex() != toCell.getColumnIndex() && !block)
+                                               sheet.setColumnWidth(toCell.getColumnIndex(), sheet.getColumnWidth(fromCell.getColumnIndex()));
+
                                        // スタイルコピーなら
                                        if(cpCount > 0 && COPY.equalsIgnoreCase(style)) {
                                                // スタイルのコピー
-                                               toCell.setCellStyle(cell.getCellStyle());
+                                               toCell.setCellStyle(fromCell.getCellStyle());
                                        }
                                        // 値のコピー
-                                       switch(cell.getCellType()) {
+                                       switch(fromCell.getCellType()) {
                                        case Cell.CELL_TYPE_BLANK:
                                                toCell.setCellType(Cell.CELL_TYPE_BLANK);
                                                break;
                                        case Cell.CELL_TYPE_BOOLEAN:
                                                toCell.setCellType(Cell.CELL_TYPE_BOOLEAN);
-                                               toCell.setCellValue(cell.getBooleanCellValue());
+                                               toCell.setCellValue(fromCell.getBooleanCellValue());
                                                break;
                                        case Cell.CELL_TYPE_ERROR:
                                                toCell.setCellType(Cell.CELL_TYPE_ERROR);
-                                               toCell.setCellErrorValue(cell.getErrorCellValue());
+                                               toCell.setCellErrorValue(fromCell.getErrorCellValue());
                                                break;
                                        case Cell.CELL_TYPE_FORMULA:
                                                toCell.setCellType(Cell.CELL_TYPE_FORMULA);
@@ -1006,27 +981,169 @@ public class TLParser {
                                                toCell.setCellFormula(
                                                                ExcelUtil.getMoveFormula(
                                                                                sheet, 
-                                                                               cell.getCellFormula().replace(
-                                                                                               (i == startIdx ? object : list + "[" + (mapKeys == null ? (startIdx - 1) : "'" + mapKeys[startIdx - 1] + "'") + "]"), list + "[" + (mapKeys == null ? (i - 1) : "'" + mapKeys[i - 1] + "'") + "]"), 
-                                                                               toCell.getRowIndex() - cell.getRowIndex(), 
-                                                                               toCell.getColumnIndex() - cell.getColumnIndex()
+                                                                               fromCell.getCellFormula().replace(
+                                                                                               (cpCount == 0 ? object : list + "[" + (mapKeys == null ? (startIdx - 1) : "'" + mapKeys[startIdx - 1] + "'") + "]"), list + "[" + (mapKeys == null ? (i - 1) : "'" + mapKeys[i - 1] + "'") + "]"), 
+                                                                               toCell.getRowIndex() - fromCell.getRowIndex(), 
+                                                                               toCell.getColumnIndex() - fromCell.getColumnIndex()
                                                                )
                                                );
                                                log.debug("to cell Formula: {}", toCell.getCellFormula());
                                                break;
                                        case Cell.CELL_TYPE_NUMERIC:
                                                toCell.setCellType(Cell.CELL_TYPE_NUMERIC);
-                                               toCell.setCellValue(cell.getNumericCellValue());
+                                               toCell.setCellValue(fromCell.getNumericCellValue());
                                                break;
                                        case Cell.CELL_TYPE_STRING:
                                                toCell.setCellType(Cell.CELL_TYPE_STRING);
-                                               toCell.setCellValue(cell.getStringCellValue().replace((i == startIdx ? object : list + "[" + (mapKeys == null ? (startIdx - 1) : "'" + mapKeys[startIdx - 1] + "'") + "]"), list + "[" + (mapKeys == null ? (i - 1) : "'" + mapKeys[i - 1] + "'") + "]"));
+                                               toCell.setCellValue(fromCell.getStringCellValue().replace((cpCount == 0 ? object : list + "[" + (mapKeys == null ? (startIdx - 1) : "'" + mapKeys[startIdx - 1] + "'") + "]"), list + "[" + (mapKeys == null ? (i - 1) : "'" + mapKeys[i - 1] + "'") + "]"));
                                                log.debug("to cell string: {}", toCell.getStringCellValue());
                                                break;
                                        }
                                }
                        }
+                       // 繰返しコピーフラグfalseならbreak
+                       if(!copyFlg) break;
                }
+//             // コピー元範囲を繰返しコピー
+//             // 範囲行でループ
+//             for(int r = fromRange.getFirstRow(); r <= fromRange.getLastRow(); r++) {
+//                     row = sheet.getRow(r);
+//                     // コピー元行がnullで繰返し方向横(列)の場合
+//                     if(row == null && COL.equalsIgnoreCase(direction)) {
+//                             // コピー先行もnullとなるのでセルの処理はせず終了
+//                             log.debug("continue. direction: col from row [{}] is null", (r + 1));
+//                             continue;
+//                     }
+//
+//                     // 範囲列でループ
+//                     for(int c = fromRange.getFirstColumn(); c <= fromRange.getLastColumn(); c++) {
+//                             // コピー元行がnullの場合セルもnull
+//                             if(row == null) {
+//                                     cell = null;
+//                             } else {
+//                                     cell = row.getCell(c);
+//                             }
+//
+//                             // 繰返し回数でループ
+//                             for(int i = startIdx, cpCount = 0; (startIdx <= endIdx && i <= endIdx || startIdx > endIdx && i >= endIdx); i = (startIdx <= endIdx ? i + 1 : i - 1), cpCount++) {
+//                                     // 繰返し方向横(列)(行がデフォルト)
+//                                     if(COL.equalsIgnoreCase(direction)) {
+//                                             // 範囲チェック
+//                                             if(c + colSpan * cpCount < 0 || c + colSpan * cpCount > ExcelUtil.getMaxColumnIndex(sheet)) {
+//                                                     log.warn("to cell outside sheet");
+//                                                     break;
+//                                             }
+//                                             toRow = row;
+//                                             toCell = row.getCell(c + colSpan * cpCount);
+//                                             // コピー元セルがnullならコピー先セルもnull
+//                                             if(cell == null) {
+//                                                     if(toCell != null) {
+//                                                             toRow.removeCell(toCell);
+//                                                             log.debug("continue. from cell [{}] is null. to cell [{}] remove", (new CellReference(r, c)).formatAsString(), (new CellReference(r, c + colSpan * cpCount)).formatAsString());
+//                                                     }
+//                                                     else {
+//                                                             log.debug("continue. from cell [{}] and to cell [{}] is null", (new CellReference(r, c)).formatAsString(), (new CellReference(r, c + colSpan * cpCount)).formatAsString());
+//                                                     }
+//                                                     continue;
+//                                             }
+//                                             else {
+//                                                     if(toCell == null) toCell = row.createCell(c + colSpan * cpCount);
+//                                                     // block falseなら列情報(幅)もコピー
+//                                                     if(!block) {
+//                                                             sheet.setColumnWidth(toCell.getColumnIndex(), sheet.getColumnWidth(cell.getColumnIndex()));
+//                                                     }
+//                                             }
+//                                     }
+//                                     // 繰返し方向縦(行)の場合
+//                                     else {
+//                                             // 範囲チェック
+//                                             if(r + rowSpan * cpCount < 0 || r + rowSpan * cpCount > ExcelUtil.getMaxRowIndex(sheet)) {
+//                                                     log.warn("to row outside sheet");
+//                                                     break;
+//                                             }
+//                                             // 繰返し先の行がなければ生成
+//                                             toRow = sheet.getRow(r + rowSpan * cpCount);
+//                                             toCell = null;
+//                                             // コピー元行がnullならコピー先行もnull
+//                                             if(row == null) {
+//                                                     if(toRow != null) {
+//                                                             sheet.removeRow(toRow);
+//                                                             log.debug("continue. from row [{}] is null. to row [{}] remove", (r + 1));
+//                                                     }
+//                                                     else {
+//                                                             log.debug("continue. from and to row is null");
+//                                                     }
+//                                                     continue;
+//                                             } 
+//                                             else {
+//                                                     if(toRow == null) toRow = sheet.createRow(r + rowSpan * cpCount);
+//                                                     // block falseなら行情報(高さ)もコピー
+//                                                     if(!block) {
+//                                                             toRow.setHeight(row.getHeight());
+//                                                     }
+//                                                     toCell = toRow.getCell(c);
+//                                                     // コピー元セルがnullならコピー先セルもnull
+//                                                     if(cell == null) {
+//                                                             if(toCell != null) {
+//                                                                     toRow.removeCell(toCell);
+//                                                                     log.debug("continue. from cell is null. to cell remove");
+//                                                             }
+//                                                             else {
+//                                                                     log.debug("continue. from cell [{}] and to cell [{}] is null", (new CellReference(r, c)).formatAsString(), (new CellReference(r + rowSpan * cpCount, c)).formatAsString());
+//                                                             }
+//                                                             continue;
+//                                                     }
+//                                                     else {
+//                                                             if(toCell == null) toCell = toRow.createCell(c);
+//                                                     }
+//                                             }
+//                                     }
+//
+//                                     // スタイルコピーなら
+//                                     if(cpCount > 0 && COPY.equalsIgnoreCase(style)) {
+//                                             // スタイルのコピー
+//                                             toCell.setCellStyle(cell.getCellStyle());
+//                                     }
+//                                     // 値のコピー
+//                                     switch(cell.getCellType()) {
+//                                     case Cell.CELL_TYPE_BLANK:
+//                                             toCell.setCellType(Cell.CELL_TYPE_BLANK);
+//                                             break;
+//                                     case Cell.CELL_TYPE_BOOLEAN:
+//                                             toCell.setCellType(Cell.CELL_TYPE_BOOLEAN);
+//                                             toCell.setCellValue(cell.getBooleanCellValue());
+//                                             break;
+//                                     case Cell.CELL_TYPE_ERROR:
+//                                             toCell.setCellType(Cell.CELL_TYPE_ERROR);
+//                                             toCell.setCellErrorValue(cell.getErrorCellValue());
+//                                             break;
+//                                     case Cell.CELL_TYPE_FORMULA:
+//                                             toCell.setCellType(Cell.CELL_TYPE_FORMULA);
+//                                             // 数式のパース・移動先に合わせる
+//                                             toCell.setCellFormula(
+//                                                             ExcelUtil.getMoveFormula(
+//                                                                             sheet, 
+//                                                                             cell.getCellFormula().replace(
+//                                                                                             (i == startIdx ? object : list + "[" + (mapKeys == null ? (startIdx - 1) : "'" + mapKeys[startIdx - 1] + "'") + "]"), list + "[" + (mapKeys == null ? (i - 1) : "'" + mapKeys[i - 1] + "'") + "]"), 
+//                                                                             toCell.getRowIndex() - cell.getRowIndex(), 
+//                                                                             toCell.getColumnIndex() - cell.getColumnIndex()
+//                                                             )
+//                                             );
+//                                             log.debug("to cell Formula: {}", toCell.getCellFormula());
+//                                             break;
+//                                     case Cell.CELL_TYPE_NUMERIC:
+//                                             toCell.setCellType(Cell.CELL_TYPE_NUMERIC);
+//                                             toCell.setCellValue(cell.getNumericCellValue());
+//                                             break;
+//                                     case Cell.CELL_TYPE_STRING:
+//                                             toCell.setCellType(Cell.CELL_TYPE_STRING);
+//                                             toCell.setCellValue(cell.getStringCellValue().replace((i == startIdx ? object : list + "[" + (mapKeys == null ? (startIdx - 1) : "'" + mapKeys[startIdx - 1] + "'") + "]"), list + "[" + (mapKeys == null ? (i - 1) : "'" + mapKeys[i - 1] + "'") + "]"));
+//                                             log.debug("to cell string: {}", toCell.getStringCellValue());
+//                                             break;
+//                                     }
+//                             }
+//                     }
+//             }
                // スタイルコピーなら
                if(COPY.equalsIgnoreCase(style)) {
                        // 行列加算用
@@ -1055,8 +1172,10 @@ public class TLParser {
                                                                tmpBfRange.getLastRow() + (addRow * cpCount),
                                                                tmpBfRange.getFirstColumn() + (addCol * cpCount),
                                                                tmpBfRange.getLastColumn() + (addCol * cpCount));
-                                               sheet.addMergedRegion(tmpAfRange);
-                                               log.debug("mergedRegion copy. from: [{}] to: [{}]", tmpBfRange.formatAsString(), tmpAfRange.formatAsString());
+                                               if(ExcelUtil.validateRange(sheet, tmpAfRange)) {
+                                                       sheet.addMergedRegion(tmpAfRange);
+                                                       log.debug("mergedRegion copy. from: [{}] to: [{}]", tmpBfRange.formatAsString(), tmpAfRange.formatAsString());
+                                               }
                                        }
                                }
                        }
@@ -1121,12 +1240,12 @@ public class TLParser {
                                CTMarker from, to; 
                                try {
                                        // DocumentPartでループ
-                                       for(POIXMLDocumentPart dr : ((XSSFSheet)sheet).getRelations()) {
-                                               if(dr == null) continue;
-                                               log.debug("DocumentPart class: {}", dr.getClass().getName());
+                                       for(POIXMLDocumentPart part : ((XSSFSheet)sheet).getRelations()) {
+                                               if(part == null) continue;
+                                               log.debug("DocumentPart class: {}", part.getClass().getName());
                                                // DocumentPartがDrawingオブジェクトの場合
-                                               if(dr instanceof XSSFDrawing) {
-                                                       ctDrawing = ((XSSFDrawing) dr).getCTDrawing();
+                                               if(part instanceof XSSFDrawing) {
+                                                       ctDrawing = ((XSSFDrawing) part).getCTDrawing();
                                                        if(ctDrawing != null) {
                                                                // アンカーでループ
                                                                int alSize = ctDrawing.getTwoCellAnchorList().size();
@@ -1149,7 +1268,6 @@ public class TLParser {
                                                                        case CellRangeUtil.INSIDE:
                                                                        case CellRangeUtil.OVERLAP:
                                                                                // 繰返し回数でループ
-                                                                               ;       // コピー実施回数のクリア
                                                                                for(int j = startIdx, cpCount = 1; (startIdx <= endIdx && j <= endIdx || startIdx > endIdx && j >= endIdx); j = (startIdx <= endIdx ? j + 1 : j - 1), cpCount++) {
                                                                                        // 初回はコピーしない(コピー元だから)
                                                                                        if(j == startIdx) continue;
index 80958f8..fdedd0c 100644 (file)
@@ -414,8 +414,9 @@ public class ExcelUtil {
                if(!validateRange(sheet, range)) {
                        _range = getIntersectRange(sheet, range);
                        if(_range == null) {
-                               log.error("range is illegal: [{}]", range.formatAsString());
-                               throw new JaxcelInputException("range is illegal");
+                               log.warn("range is illegal: [{}]", range.formatAsString());
+                               log.trace("shift end");
+                               return;
                        }
                        else {
                                log.info("resize range: [{}]", _range.formatAsString());