OSDN Git Service

#34479 対応中
[jaxcel/jaxcel.git] / Jaxcel / src / org / hanei / jaxcel / report / TLParser.java
index dd55731..41e67b3 100644 (file)
@@ -20,6 +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;
 
@@ -39,7 +43,7 @@ import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.xssf.usermodel.XSSFDrawing;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 import org.hanei.jaxcel.exception.JaxcelInputException;
-import org.hanei.jaxcel.util.JaxcelUtil;
+import org.hanei.jaxcel.util.ExcelUtil;
 import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTDrawing;
 import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
 import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor;
@@ -49,8 +53,9 @@ import org.slf4j.Logger;
 /**
  * Excelテンプレートシートの指示子(Template Language)、EL式(Expression Language)の検索、パースを行う
  * 
+ * @since 1.00.00
  * @author Noboru Saito
- *
+ * @deprecated 
  */
 public class TLParser {
 
@@ -81,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;
@@ -144,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"
        };
@@ -561,7 +584,7 @@ public class TLParser {
                                reParseFlg = false;
                        }
                        // 置換後の値がBool型
-                       else if(StringUtils.equalsIgnoreCase(newCellVal, "ture") || StringUtils.equalsIgnoreCase(newCellVal, "false")) {
+                       else if(StringUtils.equalsIgnoreCase(newCellVal, "true") || StringUtils.equalsIgnoreCase(newCellVal, "false")) {
                                // もともと文字列セルならBoolセルに変更し値をセット
                                if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
                                        cell.setCellType(Cell.CELL_TYPE_BLANK);
@@ -590,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");
@@ -655,8 +712,9 @@ public class TLParser {
                                }
                        }
                }
-               // newCellValが空白なら
+               // newCellValが空白
                else {
+                       cell.setCellType(Cell.CELL_TYPE_BLANK);
                        // 再パースフラグクリア
                        reParseFlg = false;
                }
@@ -670,10 +728,11 @@ 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;
                int listSize;
                ArrayList<CellRangeAddress> rangeList = new ArrayList<>(); 
                CellRangeAddress fromRange, toRange, tmpBfRange, tmpAfRange;
@@ -687,6 +746,11 @@ public class TLParser {
                }
                log.debug("list class: {}", listObject.getClass().getName());
 
+               // listObject Mapならキー取得
+               if(listObject instanceof Map) {
+                       mapKeys = ((Map<?, ?>)listObject).keySet().toArray();
+               }
+
                // listのサイズ取得
                evalObject = elMgr.evaluate("size(" + list + ")");
                // evalした結果がintでなければリスト不可なオブジェクトと判断
@@ -802,16 +866,16 @@ public class TLParser {
                        }
                        // 繰返し方向縦(行)の場合
                        else {
-                               fromRange = new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, 0, JaxcelUtil.getLastColNum(sheet));
+                               fromRange = new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, 0, ExcelUtil.getLastColNum(sheet));
                        }
                }
                else {
                        fromRange = new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, startColIdx, startColIdx + colSpan - 1);
                }
                // シートに収まる範囲にリサイズ
-               fromRange = JaxcelUtil.getIntersectRange(sheet, fromRange);
+               fromRange = ExcelUtil.getIntersectRange(sheet, fromRange);
 
-               // 繰返しコピー回数1以上なら
+               // 繰返しコピー回数1以上なら、コピー先範囲シフト・クリア等実施
                if(startIdx != endIdx) {
                        // コピー先範囲の範囲特定
                        int copyCount = startIdx < endIdx ? endIdx - startIdx : startIdx - endIdx;
@@ -841,18 +905,18 @@ public class TLParser {
                                if(COL.equalsIgnoreCase(direction)) {
                                        distance *= colSpan;
                                        // 繰返し範囲以降をずらす
-                                       JaxcelUtil.shift(sheet, new CellRangeAddress(fromRange.getFirstRow(), fromRange.getLastRow(), fromRange.getLastColumn() + 1, fromRange.getLastColumn() + 1), COL, distance, block);
+                                       ExcelUtil.shift(sheet, new CellRangeAddress(fromRange.getFirstRow(), fromRange.getLastRow(), fromRange.getLastColumn() + 1, fromRange.getLastColumn() + 1), COL, distance, block);
                                }
                                // 繰返し方向縦(行)の場合
                                else {
                                        distance *= rowSpan;
                                        // 繰返し範囲以降をずらす
-                                       JaxcelUtil.shift(sheet, new CellRangeAddress(fromRange.getLastRow() + 1, fromRange.getLastRow() + 1, fromRange.getFirstColumn(), fromRange.getLastColumn()), ROW, distance, block);
+                                       ExcelUtil.shift(sheet, new CellRangeAddress(fromRange.getLastRow() + 1, fromRange.getLastRow() + 1, fromRange.getFirstColumn(), fromRange.getLastColumn()), ROW, distance, block);
                                }
                        }
                        // shift:falseの場合、コピー先範囲をクリア
                        else {
-                               JaxcelUtil.clearRange(sheet, toRange, COPY.equalsIgnoreCase(style), true);
+                               ExcelUtil.clearRange(sheet, toRange, COPY.equalsIgnoreCase(style), COPY.equalsIgnoreCase(style));
                        }
                        // style:copyの場合、コピー元範囲の結合保持・解除
                        if(COPY.equalsIgnoreCase(style)) {
@@ -879,150 +943,263 @@ public class TLParser {
                        }
                }
 
-               // コピー元範囲を繰返しコピー
-               int cpCount = 0;
-               boolean contFlag;
-               // 範囲行でループ
-               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;
                                }
 
-                               // 繰返し回数でループ
-                               cpCount = 0;    // コピー実施回数のクリア
-                               for(int i = startIdx; (startIdx <= endIdx && i <= endIdx || startIdx > endIdx && i >= endIdx); i = (startIdx <= endIdx ? i + 1 : i - 1)) {
-                                       contFlag = false;
-                                       
-                                       // 繰返し方向横(列)(行がデフォルト)
-                                       if(COL.equalsIgnoreCase(direction)) {
-                                               // 範囲チェック
-                                               if(c + colSpan * cpCount < 0 || c + colSpan * cpCount > JaxcelUtil.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());
-                                                       }
-                                                       contFlag = true;
-                                               }
-                                               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 > JaxcelUtil.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");
-                                                       }
-                                                       contFlag = true;
-                                               } 
                                                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());
-                                                               }
-                                                               contFlag = true;
-                                                       }
-                                                       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;
                                        }
-                                       if(!contFlag) {
-                                               // スタイルコピーなら
-                                               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(
-                                                                       JaxcelUtil.getMoveFormula(
-                                                                                       sheet, 
-                                                                                       cell.getCellFormula().replace((i == startIdx ? object : list + "[" + (startIdx - 1) + "]"), list + "[" + (i - 1) + "]"), 
-                                                                                       toCell.getRowIndex() - cell.getRowIndex(), 
-                                                                                       toCell.getColumnIndex() - cell.getColumnIndex()
-                                                                       )
-                                                       );
-                                                       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 + "[" + (startIdx - 1) + "]"), list + "[" + (i - 1) + "]"));
-                                                       break;
-                                               }
+
+                                       // コピー先セルが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(fromCell.getCellStyle());
+                                       }
+                                       // 値のコピー
+                                       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(fromCell.getBooleanCellValue());
+                                               break;
+                                       case Cell.CELL_TYPE_ERROR:
+                                               toCell.setCellType(Cell.CELL_TYPE_ERROR);
+                                               toCell.setCellErrorValue(fromCell.getErrorCellValue());
+                                               break;
+                                       case Cell.CELL_TYPE_FORMULA:
+                                               toCell.setCellType(Cell.CELL_TYPE_FORMULA);
+                                               // 数式のパース・移動先に合わせる
+                                               toCell.setCellFormula(
+                                                               ExcelUtil.getMoveFormula(
+                                                                               sheet, 
+                                                                               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(fromCell.getNumericCellValue());
+                                               break;
+                                       case Cell.CELL_TYPE_STRING:
+                                               toCell.setCellType(Cell.CELL_TYPE_STRING);
+                                               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;
                                        }
-                                       cpCount++;
                                }
                        }
+                       // 繰返しコピーフラグ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)) {
                        // 行列加算用
@@ -1042,8 +1219,7 @@ public class TLParser {
                                for(int c = 0; c < rangeList.size(); c++) {
                                        tmpBfRange = rangeList.get(c);
                                        // 繰返し回数でループ
-                                       cpCount = 1;    // コピー実施回数のクリア
-                                       for(int i = startIdx; (startIdx <= endIdx && i <= endIdx || startIdx > endIdx && i >= endIdx); i = (startIdx <= endIdx ? i + 1 : i - 1)) {
+                                       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;
                                                // コピー先レンジ
@@ -1052,9 +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());
-                                               cpCount++;
+                                               if(ExcelUtil.validateRange(sheet, tmpAfRange)) {
+                                                       sheet.addMergedRegion(tmpAfRange);
+                                                       log.debug("mergedRegion copy. from: [{}] to: [{}]", tmpBfRange.formatAsString(), tmpAfRange.formatAsString());
+                                               }
                                        }
                                }
                        }
@@ -1119,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();
@@ -1147,11 +1324,10 @@ public class TLParser {
                                                                        case CellRangeUtil.INSIDE:
                                                                        case CellRangeUtil.OVERLAP:
                                                                                // 繰返し回数でループ
-                                                                               cpCount = 1;    // コピー実施回数のクリア
-                                                                               for(int j = startIdx; (startIdx <= endIdx && j <= endIdx || startIdx > endIdx && j >= endIdx); j = (startIdx <= endIdx ? j + 1 : j - 1)) {
+                                                                               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();
@@ -1164,7 +1340,6 @@ public class TLParser {
                                                                                                tmpAfRange = new CellRangeAddress(from.getRow(), to.getRow(), from.getCol(), to.getCol());
                                                                                                log.debug("object copy from: [{}] to: [{}]", tmpBfRange.formatAsString(), tmpAfRange.formatAsString());
                                                                                        }
-                                                                                       cpCount++;
                                                                                }
                                                                        }
                                                                }
@@ -1219,17 +1394,17 @@ public class TLParser {
                        switch(delete) {
                        // クリア
                        case CLEAR:
-                               JaxcelUtil.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;
                        // 左詰め
                        case LEFT:
                                // IF範囲以降をずらす
-                               JaxcelUtil.shift(sheet, new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, startColIdx + colSpan, startColIdx + colSpan), COL, -colSpan, block);
+                               ExcelUtil.shift(sheet, new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, startColIdx + colSpan, startColIdx + colSpan), COL, -colSpan, block);
                                break;
                        // 上詰め
                        case UP:
                                // IF範囲以降をずらす
-                               JaxcelUtil.shift(sheet, new CellRangeAddress(startRowIdx + rowSpan, startRowIdx + rowSpan, startColIdx, startColIdx + colSpan - 1), ROW, -rowSpan, block);
+                               ExcelUtil.shift(sheet, new CellRangeAddress(startRowIdx + rowSpan, startRowIdx + rowSpan, startColIdx, startColIdx + colSpan - 1), ROW, -rowSpan, block);
                        }
                }
                log.trace("parseIf end");
@@ -1270,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("$", "\\$"));
        }
        
        /**