OSDN Git Service

#34479 対応中
[jaxcel/jaxcel.git] / Jaxcel / src / org / hanei / jaxcel / report / TLParser.java
index 5139ec3..41e67b3 100644 (file)
@@ -20,7 +20,10 @@ package org.hanei.jaxcel.report;
 
 import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.Date;
+import java.util.Locale;
 import java.util.Map;
+import java.util.TimeZone;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -50,8 +53,9 @@ import org.slf4j.Logger;
 /**
  * Excelテンプレートシートの指示子(Template Language)、EL式(Expression Language)の検索、パースを行う
  * 
+ * @since 1.00.00
  * @author Noboru Saito
- *
+ * @deprecated 
  */
 public class TLParser {
 
@@ -82,6 +86,7 @@ public class TLParser {
        private static final int PARSE_MAX = 10;
        
        private static final short FORMAT_GENERAL = 0;
+       private static final short FORMAT_TEXT = 49;
 
        private Sheet sheet = null;
        private JaxcelContext context = null;
@@ -145,15 +150,32 @@ public class TLParser {
         * 日付形式書式パターン
         */
        private final String[] DATE_FORMATS = {
-                       "yyyy-MM-dd", 
-                       "yyyy/MM/dd", 
-                       "yyyy-MM-dd HH:mm:ss.SSS", 
+                       "yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
+                       "yyyy-MM-dd'T'HH:mm:ss.SSXXX",
+                       "yyyy-MM-dd'T'HH:mm:ss.SXXX",
+                       "yyyy-MM-dd'T'HH:mm:ss.SSSXX",
+                       "yyyy-MM-dd'T'HH:mm:ss.SSXX",
+                       "yyyy-MM-dd'T'HH:mm:ss.SXX",
+                       "yyyy-MM-dd'T'HH:mm:ss.SXXX",
+                       "yyyy-MM-dd'T'HH:mm:ss.SXX",
+                       "yyyy-MM-dd'T'HH:mm:ss.SX",
+                       "yyyy-MM-dd'T'HH:mm:ssXXX",
+                       "yyyy-MM-dd'T'HH:mm:ssXX",
+                       "yyyy-MM-dd'T'HH:mm:ssX",
+                       "yyyy-MM-dd'T'HH:mm:ss.S",
+                       "yyyy-MM-dd'T'HH:mm:ss",
+                       "yyyy-MM-dd'T'HH:mm",
+                       "yyyy-MM-dd HH:mm:ss.S",
                        "yyyy-MM-dd HH:mm:ss",
                        "yyyy-MM-dd HH:mm",
-                       "yyyy/MM/dd HH:mm:ss.SSS", 
+                       "yyyy-MM-dd", 
+                       "yyyy/MM/dd HH:mm:ss.S", 
                        "yyyy/MM/dd HH:mm:ss",
                        "yyyy/MM/dd HH:mm",
-                       "HH:mm:ss.SSS", 
+                       "yyyy/MM/dd"
+       };
+       private final String[] TIME_FORMATS = {
+                       "HH:mm:ss.S", 
                        "HH:mm:ss",
                        "HH:mm"
        };
@@ -591,54 +613,88 @@ public class TLParser {
                        }
                        // 置換後の値が上記以外
                        else {
-                               try {
-                                       // 置換後の値が日付・時刻型
-                                       if(DateUtils.parseDateStrictly(newCellVal, DATE_FORMATS) != null) {
-                                               // もともと文字列セルなら数値セルに変更し値をセット
-                                               if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
-                                                       cell.setCellType(Cell.CELL_TYPE_BLANK);
-                                                       cell.setCellType(Cell.CELL_TYPE_NUMERIC);
-                                                       // 書式未設定なら文字列のまま挿入
-                                                       if(FORMAT_GENERAL == cell.getCellStyle().getDataFormat()) {
-                                                               cell.setCellValue(newCellVal);
-                                                               log.debug("set value type: String");
-                                                       }
-                                                       else {
-                                                               cell.setCellValue(DateUtils.parseDateStrictly(newCellVal, DATE_FORMATS));
-                                                               log.debug("set value type: Date");
-                                                       }
+                               Date tmpDate = null;
+                               int valType = -1;
+                               for(int i = 0; i < 3; i++) {
+                                       switch(i) {
+                                       case 0:
+                                               try {
+                                                       // 置換後の値が日付・日付時刻型
+                                                       tmpDate = DateUtils.parseDateStrictly(newCellVal, Locale.getDefault(), DATE_FORMATS);
+                                                       valType = i;
+                                               } catch (ParseException e1) {}
+                                               break;
+                                       case 1:
+                                               try {
+                                                       // 置換後の値が時刻型
+                                                       tmpDate = DateUtils.parseDateStrictly(newCellVal, TIME_FORMATS);
+                                                       valType = i;
+                                               } catch (ParseException e1) {}
+                                               break;
+                                       default:
+                                               // 置換後の値が上記以外(文字列)
+                                               valType = i;
+                                               break;
+                                       }
+                                       if(valType >= 0) break;
+                               }
+                               
+                               switch(valType) {
+                               case 0:
+                               case 1:
+                                       // 置換後の値が日付・日付時刻・時刻型
+                                       // もともと文字列セルなら数値セルに変更し値をセット
+                                       if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
+                                               cell.setCellType(Cell.CELL_TYPE_BLANK);
+                                               cell.setCellType(Cell.CELL_TYPE_NUMERIC);
+                                               // 書式文字列なら文字列のまま挿入
+                                               if(FORMAT_GENERAL == cell.getCellStyle().getDataFormat() || FORMAT_TEXT == cell.getCellStyle().getDataFormat()) {
+                                                       cell.setCellValue(newCellVal);
+                                                       log.debug("set value type: String");
                                                }
-                                               // もともと計算式セルの場合は計算式として値をセット
                                                else {
-                                                       // まずはそのまま
-                                                       try {
-                                                               cell.setCellFormula(newCellVal);
-                                                               log.debug("set value type: Formula");
-                                                       }
-                                                       // エラー発生で数値としてセット
-                                                       catch(FormulaParseException e) {
-                                                               log.warn("formula set error: {}", e.getMessage(), e);
-                                                               cell.setCellType(Cell.CELL_TYPE_BLANK);
-                                                               cell.setCellType(Cell.CELL_TYPE_NUMERIC);
-                                                               cell.setCellValue(DateUtils.parseDateStrictly(newCellVal, DATE_FORMATS));
+                                                       switch(valType) {
+                                                       case 0:
+                                                               // 置換後の値が日付・日付時刻型ならDateでセット
+                                                               cell.setCellValue(tmpDate);
                                                                log.debug("set value type: Date");
+                                                               break;
+                                                       case 1:
+                                                               // 置換後の値が時刻型ならDoubleでセット(デフォルトタイムゾーン分加算)
+                                                               cell.setCellValue((tmpDate.getTime() + TimeZone.getDefault().getRawOffset()) / (1000.0 * 60 * 60 * 24));
+                                                               log.debug("set value type: double");
+                                                               break;
                                                        }
                                                }
-                                               // 再パースフラグクリア
-                                               reParseFlg = false;
                                        }
+                                       // もともと計算式セルの場合は計算式として値をセット
                                        else {
-                                               // 元のセルタイプのまま値をセット
-                                               throw new ParseException("", 0);
+                                               // まずはそのまま
+                                               try {
+                                                       cell.setCellFormula(newCellVal);
+                                                       log.debug("set value type: Formula");
+                                               }
+                                               // エラー発生で数値としてセット
+                                               catch(FormulaParseException e) {
+                                                       log.warn("formula set error: {}", e.getMessage(), e);
+                                                       cell.setCellType(Cell.CELL_TYPE_BLANK);
+                                                       cell.setCellType(Cell.CELL_TYPE_NUMERIC);
+                                                       cell.setCellValue(tmpDate);
+                                                       log.debug("set value type: Date");
+                                               }
                                        }
-                               }
-                               catch(ParseException e) {
+                                       // 再パースフラグクリア
+                                       reParseFlg = false;
+                                       break;
+                               default:
+                                       // 置換後の値が日付・日付時刻・時刻型以外(文字列と判断)
                                        // 元のセルタイプのまま値をセット
                                        if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
                                                cell.setCellValue(newCellVal);
                                                log.debug("set value type: String");
                                        } 
                                        else {
+                                               // 式
                                                try {
                                                        cell.setCellFormula(newCellVal);
                                                        log.debug("set value type: Formula");
@@ -672,8 +728,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 +875,7 @@ public class TLParser {
                // シートに収まる範囲にリサイズ
                fromRange = ExcelUtil.getIntersectRange(sheet, fromRange);
 
-               // 繰返しコピー回数1以上なら
+               // 繰返しコピー回数1以上なら、コピー先範囲シフト・クリア等実施
                if(startIdx != endIdx) {
                        // コピー先範囲の範囲特定
                        int copyCount = startIdx < endIdx ? endIdx - startIdx : startIdx - endIdx;
@@ -860,7 +916,7 @@ public class TLParser {
                        }
                        // shift:falseの場合、コピー先範囲をクリア
                        else {
-                               ExcelUtil.clearRange(sheet, toRange, COPY.equalsIgnoreCase(style), true);
+                               ExcelUtil.clearRange(sheet, toRange, COPY.equalsIgnoreCase(style), COPY.equalsIgnoreCase(style));
                        }
                        // style:copyの場合、コピー元範囲の結合保持・解除
                        if(COPY.equalsIgnoreCase(style)) {
@@ -887,118 +943,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 +1037,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)) {
                        // 行列加算用
@@ -1046,7 +1219,7 @@ public class TLParser {
                                for(int c = 0; c < rangeList.size(); c++) {
                                        tmpBfRange = rangeList.get(c);
                                        // 繰返し回数でループ
-                                       for(int i = startIdx, cpCount = 1; (startIdx <= endIdx && i <= endIdx || startIdx > endIdx && i >= endIdx); i = (startIdx <= endIdx ? i + 1 : i - 1), cpCount++) {
+                                       for(int i = startIdx, cpCount = 0; (startIdx <= endIdx && i <= endIdx || startIdx > endIdx && i >= endIdx); i = (startIdx <= endIdx ? i + 1 : i - 1), cpCount++) {
                                                // 初回はコピーしない(コピー元だから)
                                                if(i == startIdx) continue;
                                                // コピー先レンジ
@@ -1055,8 +1228,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 +1296,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,11 +1324,10 @@ 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++) {
+                                                                               for(int j = startIdx, cpCount = 0; (startIdx <= endIdx && j <= endIdx || startIdx > endIdx && j >= endIdx); j = (startIdx <= endIdx ? j + 1 : j - 1), cpCount++) {
                                                                                        // 初回はコピーしない(コピー元だから)
                                                                                        if(j == startIdx) continue;
-                                                                                       // TODO これでオブジェクト(アンカー)のコピーができる!!
+                                                                                       // オブジェクト(アンカー)のコピー
                                                                                        cpAnchor = ctDrawing.addNewTwoCellAnchor();
                                                                                        cpAnchor.set(fAnchor.copy());
                                                                                        from = cpAnchor.getFrom();
@@ -1220,7 +1394,6 @@ public class TLParser {
                        switch(delete) {
                        // クリア
                        case CLEAR:
-//                             ExcelUtil.clearRange(sheet, (new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, startColIdx, startColIdx + colSpan - 1)), true, true);
                                ExcelUtil.clearRange(sheet, (new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, startColIdx, startColIdx + colSpan - 1)), false, false);
                                break;
                        // 左詰め
@@ -1272,7 +1445,7 @@ public class TLParser {
         * @return      置換後の文字列
         */
        private String replaceFirst(String replacement) {
-               return mtAll.replaceFirst(replacement == null ? "" : replacement);
+               return mtAll.replaceFirst(replacement == null ? "" : replacement.replace("\\", "\\\\").replace("$", "\\$"));
        }
        
        /**