OSDN Git Service

d82b9c7e52064e7970fe89bb2383bb0f82de4b56
[jaxcel/jaxcel.git] / Jaxcel / src / org / hanei / jaxcel / report / TLParser.java
1 /**
2  * Copyright 2014 Hanei Management Co.,Ltd. 
3  * 
4  * This file is part of Jaxcel
5  * 
6  *  Jaxcel is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU Lesser General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  Jaxcel is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 package org.hanei.jaxcel.report;
20
21 import java.text.ParseException;
22 import java.util.ArrayList;
23 import java.util.Map;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26
27
28 import org.apache.commons.lang3.BooleanUtils;
29 import org.apache.commons.lang3.StringUtils;
30 import org.apache.commons.lang3.math.NumberUtils;
31 import org.apache.commons.lang3.time.DateUtils;
32 import org.apache.poi.POIXMLDocumentPart;
33 import org.apache.poi.hssf.record.cf.CellRangeUtil;
34 import org.apache.poi.ss.formula.FormulaParseException;
35 import org.apache.poi.ss.usermodel.Cell;
36 import org.apache.poi.ss.usermodel.Row;
37 import org.apache.poi.ss.usermodel.Sheet;
38 import org.apache.poi.ss.util.CellRangeAddress;
39 import org.apache.poi.ss.util.CellReference;
40 import org.apache.poi.xssf.usermodel.XSSFDrawing;
41 import org.apache.poi.xssf.usermodel.XSSFSheet;
42 import org.hanei.jaxcel.exception.JaxcelInputException;
43 import org.hanei.jaxcel.util.ExcelUtil;
44 import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTDrawing;
45 import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
46 import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor;
47 import org.slf4j.LoggerFactory;
48 import org.slf4j.Logger;
49
50 /**
51  * Excelテンプレートシートの指示子(Template Language)、EL式(Expression Language)の検索、パースを行う
52  * 
53  * @author Noboru Saito
54  *
55  */
56 public class TLParser {
57
58         private static final Logger log = LoggerFactory.getLogger(TLParser.class);
59
60         private static final String EL = "el";
61         private static final String TL_IF = "if";
62         private static final String TL_FOREACH = "foreach";
63         private static final String TLP_EXPR = "${";
64         private static final String TLP_DELETE = "delete";
65         private static final String TLP_DIRECTION = "direction";
66         private static final String TLP_SHIFT = "shift";
67         private static final String TLP_BLOCK = "block";
68         private static final String TLP_STYLE = "style";
69         private static final String TLP_START = "start";
70         private static final String TLP_END = "end";
71         private static final String TLP_ROWS = "rows";
72         private static final String TLP_COLS = "cols";
73         
74         private static final String LEFT = "left";
75         private static final String UP = "up";
76         private static final String CLEAR = "clear";
77         private static final String ROW = "row";
78         private static final String COL = "col";
79         private static final String COPY = "copy";
80         private static final int SPAN_DEF = 1;
81         private static final int IDX_BASE = 1;
82         private static final int PARSE_MAX = 10;
83         
84         private static final short FORMAT_GENERAL = 0;
85
86         private Sheet sheet = null;
87         private JaxcelContext context = null;
88         private ELManager elMgr = null;
89         private Cell cell = null;
90         private int startRowIdx;
91         private int startColIdx;
92
93         private String type;            // TL式のタイプ
94         private String expression;      // EL式
95         private String delete;          // delete
96         private int rowSpan;            // row
97         private int colSpan;            // column
98         private String direction;       // direction
99         private boolean shift;          // shift
100         private boolean block;          // block
101         private String style;           // style
102         private String start;           // start
103         private String end;                     // end
104         private String list;            // list
105         private String object;          // object
106         private String matchString;     // マッチした文字列保持用
107         private boolean reParseFlg;     // 同一セル再パース要否フラグ
108         private int parseCount;         // 同一セルパース回数
109
110         /**
111          *  ${expression}
112          */
113         private final String  rgEl = "\\$\\{([^\\{\\}]+)\\}";
114         private final Pattern ptEl = Pattern.compile(rgEl);
115         private Matcher mtEl;
116
117     /**
118      *  #if(${expression} delete:"up|left|clear" block:"true|false" rows:"number" cols:"number")
119      */
120         private final String  rgIf = "#if\\(\\s*(\\$\\{[^\\{\\}]+\\})(?:\\s+(?:(delete\\s*:\\s*\"[^\"]*\")|(block\\s*:\\s*\"[^\"]*\")|(rows\\s*:\\s*\"\\d+\")|(cols\\s*:\\s*\"\\d+\"))){0,4}\\s*\\)";
121         private final Pattern ptIf = Pattern.compile(rgIf);
122         private Matcher mtIf;
123         
124     /**
125      *  #foreach(${object in list} direction:"row|col" style:"copy|^copy" shift:"true|false" block:"true|false" start:"number" end:"number" rows:"number" cols:"number")
126      */
127         private final String  rgForeach = "#foreach\\(\\s*(\\$\\{\\s*\\S+\\s+in\\s+\\S+\\s*\\})(?:\\s+(?:(direction\\s*:\\s*\"[^\"]*\")|(style\\s*:\\s*\"[^\"]*\")|(shift\\s*:\\s*\"[^\"]*\")|(block\\s*:\\s*\"[^\"]*\")|(start\\s*:\\s*\"[^\"]*\")|(end\\s*:\\s*\"[^\"]*\")|(rows\\s*:\\s*\"\\d+\")|(cols\\s*:\\s*\"\\d+\"))){0,8}\\s*\\)";
128         private final Pattern ptForeach = Pattern.compile(rgForeach);
129         private Matcher mtForeach;
130
131         /**
132          *  attribute
133          */
134         private final String rgAttrEL = "\\$\\{([^\\{\\}]*)\\}";
135         private final String rgAttr = "\\s*:\\s*\"([^\"]*)\"";
136         private final String $1 = "$1";
137
138         /**
139          *  指示子・EL式一括
140          */
141         private final Pattern ptAll = Pattern.compile(rgIf + "|" + rgForeach + "|" + rgEl);
142         private Matcher mtAll = null;
143
144         /**
145          * 日付形式書式パターン
146          */
147         private final String[] DATE_FORMATS = {
148                         "yyyy-MM-dd", 
149                         "yyyy/MM/dd", 
150                         "yyyy-MM-dd HH:mm:ss.SSS", 
151                         "yyyy-MM-dd HH:mm:ss",
152                         "yyyy-MM-dd HH:mm",
153                         "yyyy/MM/dd HH:mm:ss.SSS", 
154                         "yyyy/MM/dd HH:mm:ss",
155                         "yyyy/MM/dd HH:mm",
156                         "HH:mm:ss.SSS", 
157                         "HH:mm:ss",
158                         "HH:mm"
159         };
160
161         /**
162          * コンストラクタ
163          * 
164          * @param context       Jaxlsコンテキストオブジェクト
165          */
166         public TLParser(JaxcelContext context) {
167                 this.context = context;
168                 if(this.context != null) {
169                         sheet = this.context.getCurrentSheet();
170                         elMgr = this.context.getElManager();
171                 }
172         }
173         
174         /**
175          * EL式、If句、Foreach句のパース
176          * 
177          * @param cell  対象セル
178          * 
179          * @throws JaxcelInputException 入力例外発生時
180          */
181         public void parse(Cell cell) {
182                 log.trace("parse start");
183
184                 // チェック
185                 if(elMgr == null) {
186                         log.error("ELManager is null");
187                         log.trace("parse end");
188                         throw new JaxcelInputException("ELManager is null");
189                 }
190                 if(cell == null) {
191                         // 再パースフラグクリア
192                         this.cell = null;
193                         reParseFlg = false;             
194                         parseCount = 0;
195                         log.debug("cell is null");
196                         log.trace("parse end");
197                         return;
198                 }
199                 
200                 // 新規対象セルの場合、保持
201                 if(this.cell == null) {
202                         log.debug("start new cell parse");
203                         this.cell = cell;
204                         // 再パースフラグ・カウントクリア
205                         reParseFlg = false;
206                         parseCount = 0;
207                 }
208                 else if(!this.cell.equals(cell)) {
209                         log.debug("start new cell parse");
210                         this.cell = cell;
211                         // 再パースフラグ・カウントクリア
212                         reParseFlg = false;
213                         parseCount = 0;
214                 }
215                 // 新規対象セルでない場合
216                 else {
217                         log.debug("start repeat cell parse");
218                         // 再パースカウント加算
219                         parseCount++;
220                 }
221
222                 // 再パース回数チェック
223                 if(parseCount >= PARSE_MAX) {
224                         log.warn("parse repeat count over");
225                         // 再パースフラグクリア
226                         reParseFlg = false;
227                         log.trace("parse end");
228                         return;
229                 }
230                 
231                 // 指示子,EL式検索
232                 if(find()) {
233                         // 検索ヒット
234
235                         // EL式
236                         if(isEL()) {
237                                 evaluate();
238                         }
239                         // EL式以外
240                         else {
241                                 // 指示子の消去
242                                 switch (cell.getCellType()) {
243                                 case Cell.CELL_TYPE_STRING:
244                                         cell.setCellValue(replaceFirst(""));
245                                         break;
246                                 case Cell.CELL_TYPE_FORMULA:
247                                         // まずはそのまま
248                                         try {
249                                                 cell.setCellFormula(replaceFirst(""));
250                                         }
251                                         catch(FormulaParseException e) {
252                                                 log.debug("formula set error: {}", e.getMessage(), e);
253                                                 cell.setCellType(Cell.CELL_TYPE_BLANK);
254                                                 cell.setCellType(Cell.CELL_TYPE_STRING);
255                                                 cell.setCellValue(replaceFirst(""));
256                                                 log.debug("set value type: String");
257                                         }
258                                 }
259                                 if(isIf()) {
260                                         parseIf();
261                                 }
262                                 else if(isForeach()) {
263                                         parseForeach();
264                                 }
265                                 // EL式以外は再パースフラグセット
266                                 reParseFlg = true;
267                         }
268                 }
269                 else {
270                         // 検索ヒットせず
271                         log.debug("not found TL");
272                         // 再パースフラグクリア
273                         reParseFlg = false;
274                 }
275                 
276                 log.trace("parse end: reParseFlg: {} parseCount: {}", reParseFlg, parseCount);
277         }
278
279         /**
280          * テンプレート指示子の検索、データ保持
281          * 
282          * @param cell  検索対象セル
283          * 
284          * @return 検索結果
285          */
286         private boolean find() {
287                 log.trace("matchTL start");
288                 
289                 boolean findFlg = false;
290
291                 // 初期化
292                 type = null;            // TL式のタイプ
293                 expression = null;      // EL式
294                 rowSpan = SPAN_DEF;     // rows
295                 colSpan = SPAN_DEF;     // cols
296                 delete = LEFT;          // delete
297                 list = null;            // list
298                 object = null;          // object
299                 direction = ROW;        // direction
300                 shift = true;           // shift
301                 block = true;           // block
302                 style = COPY;           // style
303                 start = null;           // start
304                 end = null;                     // end
305                 matchString = null;
306                 String cellVal = null;
307                 
308                 // セルインデックス保持
309                 startRowIdx = cell.getRowIndex();
310                 startColIdx = cell.getColumnIndex();
311
312                 // セルタイプにより分岐
313                 // 文字列・計算式の場合は値保持。以外は終了
314                 switch(cell.getCellType()){
315                 case Cell.CELL_TYPE_STRING:
316                         cellVal = cell.getStringCellValue();
317                         log.debug("cell[{}] cellType: string  value: {}", (new CellReference(cell)).formatAsString(), cellVal);
318                         break;
319                 case Cell.CELL_TYPE_FORMULA:
320                         cellVal = cell.getCellFormula();
321                         log.debug("cell[{}] cellType: formula  value: {}", (new CellReference(cell)).formatAsString(), cellVal);
322                         break;
323                 default:
324                         log.debug("cell type is not string or formula");
325                         log.trace("matchTL end");
326                         return findFlg;
327                 }
328
329                 // 指示子(TL)の検索
330                 mtAll = ptAll.matcher(cellVal);
331                 // 指示子ヒット
332                 if(mtAll.find()) {
333                         matchString = mtAll.group();
334                         log.debug("match: {}", matchString);
335
336                         // IF文であるか
337                         if((mtIf = ptIf.matcher(matchString)).find()) {
338                                 log.debug("type: {}", TL_IF);
339
340                                 // タイプ保持
341                                 type = TL_IF;
342                                 findFlg = true;
343
344                                 // データ保持
345                                 for(int i = 1; i <= mtIf.groupCount(); i++) {
346                                         if(mtIf.group(i) == null) continue;
347                                         // ${...}  式
348                                         if(mtIf.group(i).startsWith(TLP_EXPR)) {
349                                                 expression = mtIf.group(i).replaceAll(rgAttrEL, $1).trim();
350                                                 log.debug("expression: {}", expression);
351                                         }
352                                         // delete:"up|left|clear"  削除動作 デフォルト left
353                                         else if(mtIf.group(i).startsWith(TLP_DELETE)) {
354                                                 delete = mtIf.group(i).replaceAll(TLP_DELETE + rgAttr, $1).trim();
355                                                 log.debug("{}: {}", TLP_DELETE, delete);
356                                                 if(!UP.equalsIgnoreCase(delete) && !LEFT.equalsIgnoreCase(delete) && !CLEAR.equalsIgnoreCase(delete)) {
357                                                         log.debug("{} is illegal argument. set default: {}", TLP_DELETE, LEFT);
358                                                         delete = LEFT;
359                                                 }
360                                         }
361                                         // blick:"true|false"  ブロック範囲で削除操作をするかの指定 デフォルト true
362                                         else if(mtIf.group(i).startsWith(TLP_BLOCK)) {
363                                                 block = BooleanUtils.toBoolean(mtIf.group(i).replaceAll(TLP_BLOCK + rgAttr, $1).trim());
364                                                 log.debug("{}: {}", TLP_BLOCK, block);
365                                         }
366                                         // rows:"number"  範囲 デフォルト 1
367                                         else if(mtIf.group(i).startsWith(TLP_ROWS)) {
368                                                 rowSpan = NumberUtils.toInt(mtIf.group(i).replaceAll(TLP_ROWS + rgAttr, $1).trim());
369                                                 log.debug("{}: {}", TLP_ROWS, rowSpan);
370                                                 if(rowSpan <= 0) {
371                                                         log.warn("{} is illegal argument. set default: {}", TLP_ROWS, SPAN_DEF);
372                                                         rowSpan = SPAN_DEF;
373                                                 }
374                                         }
375                                         // cols:"number"  範囲 デフォルト 1
376                                         else if(mtIf.group(i).startsWith(TLP_COLS)) {
377                                                 colSpan = NumberUtils.toInt(mtIf.group(i).replaceAll(TLP_COLS + rgAttr, $1).trim());
378                                                 log.debug("{}: {}", TLP_COLS, colSpan);
379                                                 if(colSpan <= 0) {
380                                                         log.warn("{} is illegal argument. set default: {}", TLP_COLS, SPAN_DEF);
381                                                         colSpan = SPAN_DEF;
382                                                 }
383                                         }
384                                 }
385                         }
386                         // Foreach文であるか
387                         else if((mtForeach = ptForeach.matcher(matchString)).find()) {
388                                 log.debug("type: {}", TL_FOREACH);
389
390                                 // タイプ保持
391                                 type = TL_FOREACH;
392                                 findFlg = true;
393                                 
394                                 // データ保持
395                                 String[] tmp;
396                                 for(int i = 1; i <= mtForeach.groupCount(); i++) {
397                                         if(mtForeach.group(i) == null) continue;
398                                         // ${objct in list}
399                                         if(mtForeach.group(i).startsWith(TLP_EXPR)) {
400                                                 expression = mtForeach.group(i).replaceAll(rgAttrEL, $1).trim();
401                                                 log.debug("expression: {}", expression);
402                                                 tmp = expression.split("\\s+");
403                                                 if(tmp != null && tmp.length == 3) {
404                                                         object = tmp[0];
405                                                         list = tmp[2];
406                                                         if(log.isDebugEnabled()) {
407                                                                 log.debug("object: {}", object);
408                                                                 log.debug("list: {}", list);
409                                                         }
410                                                 }
411                                                 else {
412                                                         log.warn("format error: ex) object in list");
413                                                 }
414                                         }
415                                     // direction:"row|col"  繰返し方向 デフォルト row
416                                         else if(mtForeach.group(i).startsWith(TLP_DIRECTION)) {
417                                                 direction = mtForeach.group(i).replaceAll(TLP_DIRECTION + rgAttr, $1);
418                                                 log.debug("{}: {}", TLP_DIRECTION, direction);
419                                                 if(!ROW.equalsIgnoreCase(direction) && !COL.equalsIgnoreCase(direction)) {
420                                                         log.warn("{} is illegal argument. set default: {}", TLP_DIRECTION, ROW);
421                                                         direction = ROW;
422                                                 }
423                                         }
424                                         // shift:"true|false"  foreachレンジより後のセルに対するシフト指定 デフォルト false
425                                         else if(mtForeach.group(i).startsWith(TLP_SHIFT)) {
426                                                 shift = BooleanUtils.toBoolean(mtForeach.group(i).replaceAll(TLP_SHIFT + rgAttr, $1).trim());
427                                                 log.debug("{}: {}", TLP_SHIFT, shift);
428                                         }
429                                         // blick:"true|false"  foreachレンジをブロック範囲で繰り返すかの指定 デフォルト true
430                                         else if(mtForeach.group(i).startsWith(TLP_BLOCK)) {
431                                                 block = BooleanUtils.toBoolean(mtForeach.group(i).replaceAll(TLP_BLOCK + rgAttr, $1).trim());
432                                                 log.debug("{}: {}", TLP_BLOCK, block);
433                                         }
434                                         // style:"copy|^copy"  foreachレンジのセルスタイルのコピー指定 デフォルト copy
435                                         else if(mtForeach.group(i).startsWith(TLP_STYLE)) {
436                                                 style = mtForeach.group(i).replaceAll(TLP_STYLE + rgAttr, $1).trim();
437                                                 log.debug("{}: {}", TLP_STYLE, style);
438                                         }
439                                     // start:"numberExpression"
440                                         else if(mtForeach.group(i).startsWith(TLP_START)) {
441                                                 start = mtForeach.group(i).replaceAll(TLP_START + rgAttr, $1);
442                                                 log.debug("{}: {}", TLP_START, start);
443                                         }
444                                     // end:"numberExpression"
445                                         else if(mtForeach.group(i).startsWith(TLP_END)) {
446                                                 end = mtForeach.group(i).replaceAll(TLP_END + rgAttr, $1);
447                                                 log.debug("{}: {}", TLP_END, end);
448                                         }
449                                         // rows:"number"  範囲 デフォルト 1
450                                         else if(mtForeach.group(i).startsWith(TLP_ROWS)) {
451                                                 rowSpan = NumberUtils.toInt(mtForeach.group(i).replaceAll(TLP_ROWS + rgAttr, $1).trim());
452                                                 log.debug("{}: {}", TLP_ROWS, rowSpan);
453                                                 if(rowSpan <= 0) {
454                                                         log.warn("{} is illegal argument. set default: {}", TLP_ROWS, SPAN_DEF);
455                                                         rowSpan = SPAN_DEF;
456                                                 }
457                                         }
458                                         // cols:"number"  範囲 デフォルト 1
459                                         else if(mtForeach.group(i).startsWith(TLP_COLS)) {
460                                                 colSpan = NumberUtils.toInt(mtForeach.group(i).replaceAll(TLP_COLS + rgAttr, $1).trim());
461                                                 log.debug("{}: {}", TLP_COLS, colSpan);
462                                                 if(colSpan <= 0) {
463                                                         log.warn("{} is illegal argument. set default: {}", TLP_COLS, SPAN_DEF);
464                                                         colSpan = SPAN_DEF;
465                                                 }
466                                         }
467                                 }
468                         }
469                         // オブジェクト(EL)のヒット
470                         else if((mtEl = ptEl.matcher(matchString)).find()) {
471                                 log.debug("type: {}", EL);
472
473                                 // タイプ保持
474                                 type = EL;
475                                 findFlg = true;
476
477                                 // ${...}
478                                 expression = mtEl.group(1).trim();
479                                 log.debug("expression: {}", expression);
480                         }
481                         // 不明
482                         else {
483                                 log.warn("TL type: ???");
484                                 // 再パースフラグクリア
485                                 reParseFlg = false;
486                         }
487                 }
488                 else {
489                         log.debug("unmatch");
490                 }
491                 
492                 log.trace("matchTL end: {}", findFlg);
493                 return findFlg;
494         }
495
496         /**
497          * EL式の評価
498          */
499         private void evaluate() {
500                 log.trace("evaluate start");
501
502                 Object elResult;                // パース結果保持用
503                 String newCellVal;              // セル値
504
505                 // evaluate
506                 elResult = elMgr.evaluate(expression);
507                 if(elResult == null) {
508                         log.debug("evaluate result is null");
509                 }
510                 else {
511                         log.debug("evaluate result: {}", elResult.toString());
512                 }
513                 // マッチ1件目をevaluate結果で置換 
514                 newCellVal = replaceFirst(elResult == null ? "" : elResult.toString());
515                 log.debug("replace value: {}", newCellVal);
516                 
517                 // newCellValが空白でないなら
518                 if(!"".equals(newCellVal.trim())) {
519                         // 置換後の値の形式チェック
520                         // 置換後の値が数値型
521                         if(NumberUtils.isNumber(newCellVal)) {
522                                 // もともと文字列セルなら数値セルに変更し値をセット
523                                 if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
524                                         cell.setCellType(Cell.CELL_TYPE_BLANK);
525                                         cell.setCellType(Cell.CELL_TYPE_NUMERIC);
526                                         // まずは整数変換
527                                         try {
528                                                 cell.setCellValue(Integer.parseInt(newCellVal));
529                                                 log.debug("set value type: Integer");
530                                         }
531                                         // エラー発生で実数変換
532                                         catch(NumberFormatException e) {
533                                                 cell.setCellValue(NumberUtils.toDouble(newCellVal));
534                                                 log.debug("set value type: Double");
535                                         }
536                                 }
537                                 // もともと計算式セルの場合は計算式として値をセット
538                                 else {
539                                         // まずはそのまま
540                                         try {
541                                                 cell.setCellFormula(newCellVal);
542                                                 log.debug("set value type: Formula");
543                                         }
544                                         // エラー発生で数値としてセット
545                                         catch(FormulaParseException e) {
546                                                 log.warn("formula set error: {}", e.getMessage(), e);
547                                                 cell.setCellType(Cell.CELL_TYPE_BLANK);
548                                                 cell.setCellType(Cell.CELL_TYPE_NUMERIC);
549                                                 // まずは整数変換
550                                                 try {
551                                                         cell.setCellValue(Integer.parseInt(newCellVal));
552                                                         log.debug("set value type: Integer");
553                                                 }
554                                                 // エラー発生で実数変換
555                                                 catch(NumberFormatException e2) {
556                                                         cell.setCellValue(NumberUtils.toDouble(newCellVal));
557                                                         log.debug("set value type: Double");
558                                                 }
559                                         }
560                                 }
561                                 // 再パースフラグクリア
562                                 reParseFlg = false;
563                         }
564                         // 置換後の値がBool型
565                         else if(StringUtils.equalsIgnoreCase(newCellVal, "ture") || StringUtils.equalsIgnoreCase(newCellVal, "false")) {
566                                 // もともと文字列セルならBoolセルに変更し値をセット
567                                 if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
568                                         cell.setCellType(Cell.CELL_TYPE_BLANK);
569                                         cell.setCellType(Cell.CELL_TYPE_BOOLEAN);
570                                         cell.setCellValue(BooleanUtils.toBoolean(newCellVal));
571                                         log.debug("set value type: Boolean");
572                                 }
573                                 // もともと計算式セルの場合は計算式として値をセット
574                                 else {
575                                         // まずはそのまま
576                                         try {
577                                                 cell.setCellFormula(newCellVal);
578                                                 log.debug("set value type: Formula");
579                                         }
580                                         // エラー発生でBoolとしてセット
581                                         catch(FormulaParseException e) {
582                                                 log.warn("formula set error: {}", e.getMessage(), e);
583                                                 cell.setCellType(Cell.CELL_TYPE_BLANK);
584                                                 cell.setCellType(Cell.CELL_TYPE_BOOLEAN);
585                                                 cell.setCellValue(BooleanUtils.toBoolean(newCellVal));
586                                                 log.debug("set value type: Boolean");
587                                         }
588                                 }
589                                 // 再パースフラグクリア
590                                 reParseFlg = false;
591                         }
592                         // 置換後の値が上記以外
593                         else {
594                                 try {
595                                         // 置換後の値が日付・時刻型
596                                         if(DateUtils.parseDateStrictly(newCellVal, DATE_FORMATS) != null) {
597                                                 // もともと文字列セルなら数値セルに変更し値をセット
598                                                 if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
599                                                         cell.setCellType(Cell.CELL_TYPE_BLANK);
600                                                         cell.setCellType(Cell.CELL_TYPE_NUMERIC);
601                                                         // 書式未設定なら文字列のまま挿入
602                                                         if(FORMAT_GENERAL == cell.getCellStyle().getDataFormat()) {
603                                                                 cell.setCellValue(newCellVal);
604                                                                 log.debug("set value type: String");
605                                                         }
606                                                         else {
607                                                                 cell.setCellValue(DateUtils.parseDateStrictly(newCellVal, DATE_FORMATS));
608                                                                 log.debug("set value type: Date");
609                                                         }
610                                                 }
611                                                 // もともと計算式セルの場合は計算式として値をセット
612                                                 else {
613                                                         // まずはそのまま
614                                                         try {
615                                                                 cell.setCellFormula(newCellVal);
616                                                                 log.debug("set value type: Formula");
617                                                         }
618                                                         // エラー発生で数値としてセット
619                                                         catch(FormulaParseException e) {
620                                                                 log.warn("formula set error: {}", e.getMessage(), e);
621                                                                 cell.setCellType(Cell.CELL_TYPE_BLANK);
622                                                                 cell.setCellType(Cell.CELL_TYPE_NUMERIC);
623                                                                 cell.setCellValue(DateUtils.parseDateStrictly(newCellVal, DATE_FORMATS));
624                                                                 log.debug("set value type: Date");
625                                                         }
626                                                 }
627                                                 // 再パースフラグクリア
628                                                 reParseFlg = false;
629                                         }
630                                         else {
631                                                 // 元のセルタイプのまま値をセット
632                                                 throw new ParseException("", 0);
633                                         }
634                                 }
635                                 catch(ParseException e) {
636                                         // 元のセルタイプのまま値をセット
637                                         if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
638                                                 cell.setCellValue(newCellVal);
639                                                 log.debug("set value type: String");
640                                         } 
641                                         else {
642                                                 try {
643                                                         cell.setCellFormula(newCellVal);
644                                                         log.debug("set value type: Formula");
645                                                 }
646                                                 catch(FormulaParseException e2) {
647                                                         log.warn("formula set error: {}", e2.getMessage(), e2);
648                                                         cell.setCellType(Cell.CELL_TYPE_BLANK);
649                                                         cell.setCellType(Cell.CELL_TYPE_STRING);
650                                                         cell.setCellValue(newCellVal);
651                                                         log.debug("set value type: String");
652                                                 }
653                                         }
654                                         // 再パースフラグON
655                                         reParseFlg = true;
656                                 }
657                         }
658                 }
659                 // newCellValが空白
660                 else {
661                         cell.setCellType(Cell.CELL_TYPE_BLANK);
662                         // 再パースフラグクリア
663                         reParseFlg = false;
664                 }
665
666                 log.trace("evaluate end");
667         }
668
669         /**
670          * Foreach句のパース
671          */
672         private void parseForeach() {
673                 log.trace("parseForeach start");
674
675                 Row row, toRow;
676                 Cell cell, toCell;
677                 Object evalObject;
678                 Object listObject;
679                 Object[] mapKeys = null;
680                 int listSize;
681                 ArrayList<CellRangeAddress> rangeList = new ArrayList<>(); 
682                 CellRangeAddress fromRange, toRange, tmpBfRange, tmpAfRange;
683
684                 // リスト
685                 listObject = elMgr.evaluate(list);
686                 if(listObject == null) {
687                         log.debug("list is null eval response.");
688                         log.trace("parseForeach end");
689                         return; 
690                 }
691                 log.debug("list class: {}", listObject.getClass().getName());
692
693                 // listObject Mapならキー取得
694                 if(listObject instanceof Map) {
695                         mapKeys = ((Map<?, ?>)listObject).keySet().toArray();
696                 }
697
698                 // listのサイズ取得
699                 evalObject = elMgr.evaluate("size(" + list + ")");
700                 // evalした結果がintでなければリスト不可なオブジェクトと判断
701                 if(evalObject == null) {
702                         log.error("list size unknown");
703                         log.trace("parseForeach end");
704                         return; 
705                 }
706                 else if(!(evalObject instanceof Integer)) {
707                         log.error("list size is not Integer instance");
708                         log.trace("parseForeach end");
709                         return; 
710                 }
711                 listSize = (int) evalObject;
712                 log.debug("list size: {}", listSize);
713
714                 // start インデックス
715                 int startIdx;
716                 if(start != null) {
717                         log.debug("start: {}", start);
718                         // size(list) 等 式の可能性もあるのでevalする
719                         evalObject = elMgr.evaluate(start);
720                         if(evalObject != null) {
721                                 // evalした結果がintでなければデフォルト
722                                 if(!(evalObject instanceof Integer)) {
723                                         log.warn("start is not Integer instance. start set default: {}", IDX_BASE);
724                                         startIdx = IDX_BASE;
725                                 }
726                                 else {
727                                         startIdx = (int) evalObject;
728                                         // startIdxの補正
729                                         if(startIdx == 0) {
730                                                 // startIdxが0の場合、1に補正
731                                                 startIdx = IDX_BASE;
732                                         }
733                                         else if(startIdx < 0) {
734                                                 // startIdxがマイナス値の場合、listのサイズからの逆順とする
735                                                 // -1 の場合リストのサイズ
736                                                 startIdx = listSize + startIdx + IDX_BASE;
737                                         }
738                                         else if(startIdx > listSize) {
739                                                 // startIdxがリストのサイズより大きい場合、リストのサイズに切り詰める
740                                                 startIdx = listSize;
741                                         }
742                                 }
743                         }
744                         // evalした結果がnullの場合はデフォルト
745                         else {
746                                 log.debug("start is null eval response. start set default: {}", IDX_BASE);
747                                 startIdx = IDX_BASE;
748                         }
749                 }
750                 else {
751                         log.debug("start is null. start set default: {}", IDX_BASE);
752                         startIdx = IDX_BASE;
753                 }
754                 log.debug("startIdx: {}", startIdx);
755
756                 // end インデックス
757                 int endIdx;
758                 if(end != null) {
759                         log.debug("end: {}", end);
760                         // size(list) 等 式の可能性もあるのでevalする
761                         evalObject = elMgr.evaluate(end);
762                         if(evalObject != null) {
763                                 // evalした結果がintでなければリストサイズ
764                                 if(!(evalObject instanceof Integer)) {
765                                         log.warn("end is not Integer instance. end set list size: {}", listSize);
766                                         endIdx = listSize;
767                                 }
768                                 else {
769                                         endIdx = (int) evalObject;
770                                         // endIdxの補正
771                                         if(endIdx == 0) {
772                                                 // endIdxが0の場合、リストサイズ
773                                                 endIdx = listSize;
774                                         }
775                                         else if(endIdx < 0) {
776                                                 // endIdxがマイナス値の場合、listのサイズからの逆順とする
777                                                 // -1 の場合リストのサイズ
778                                                 endIdx = listSize + endIdx + IDX_BASE;
779                                         }
780                                         else if(endIdx > listSize) {
781                                                 // endIdxがリストのサイズより大きい場合、リストのサイズに切り詰める
782                                                 endIdx = listSize;
783                                         }
784                                 }
785                         }
786                         // evalした結果がnullの場合はリストサイズ
787                         else {
788                                 log.debug("end is null eval response. end set list size: {}", listSize);
789                                 endIdx = listSize;
790                         }
791                 }
792                 else {
793                         log.debug("end is null. end set list size: {}", listSize);
794                         endIdx = listSize;
795                 }
796                 
797                 if(log.isDebugEnabled()) {
798                         log.debug("endIdx: {}", endIdx);
799                         log.debug("direction: {}", direction);
800                         log.debug("shift: {}", shift);
801                         log.debug("block: {}", block);
802                         log.debug("style: {}", style);
803                 }
804                 
805                 // コピー元範囲 block:falseの場合、行・列全体に範囲を広げる
806                 if(!block) {
807                         // 繰返し方向横(列)(行がデフォルト)
808                         if(COL.equalsIgnoreCase(direction)) {
809                                 fromRange = new CellRangeAddress(sheet.getFirstRowNum(), sheet.getLastRowNum(), startColIdx, startColIdx + colSpan - 1);
810                         }
811                         // 繰返し方向縦(行)の場合
812                         else {
813                                 fromRange = new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, 0, ExcelUtil.getLastColNum(sheet));
814                         }
815                 }
816                 else {
817                         fromRange = new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, startColIdx, startColIdx + colSpan - 1);
818                 }
819                 // シートに収まる範囲にリサイズ
820                 fromRange = ExcelUtil.getIntersectRange(sheet, fromRange);
821
822                 // 繰返しコピー回数1以上なら
823                 if(startIdx != endIdx) {
824                         // コピー先範囲の範囲特定
825                         int copyCount = startIdx < endIdx ? endIdx - startIdx : startIdx - endIdx;
826                         // 繰返し方向横(列)(行がデフォルト)
827                         if(COL.equalsIgnoreCase(direction)) {
828                                 toRange = new CellRangeAddress(
829                                                 fromRange.getFirstRow(), 
830                                                 fromRange.getLastRow(), 
831                                                 fromRange.getLastColumn() + 1, 
832                                                 fromRange.getLastColumn() + (fromRange.getLastColumn() - fromRange.getFirstColumn() + 1) * copyCount);
833                         }
834                         // 繰返し方向縦(行)の場合
835                         else {
836                                 toRange = new CellRangeAddress(
837                                                 fromRange.getLastRow() + 1, 
838                                                 fromRange.getLastRow() + (fromRange.getLastRow() - fromRange.getFirstRow() + 1) * copyCount, 
839                                                 fromRange.getFirstColumn(), 
840                                                 fromRange.getLastColumn());
841                         }
842
843                         // shift:trueの場合、コピー先範囲の後続範囲をシフト
844                         if(shift) {
845                                 // 移動量
846                                 int distance = (startIdx > endIdx ? startIdx - endIdx : endIdx - startIdx);
847
848                                 // 繰返し方向横(列)(行がデフォルト)
849                                 if(COL.equalsIgnoreCase(direction)) {
850                                         distance *= colSpan;
851                                         // 繰返し範囲以降をずらす
852                                         ExcelUtil.shift(sheet, new CellRangeAddress(fromRange.getFirstRow(), fromRange.getLastRow(), fromRange.getLastColumn() + 1, fromRange.getLastColumn() + 1), COL, distance, block);
853                                 }
854                                 // 繰返し方向縦(行)の場合
855                                 else {
856                                         distance *= rowSpan;
857                                         // 繰返し範囲以降をずらす
858                                         ExcelUtil.shift(sheet, new CellRangeAddress(fromRange.getLastRow() + 1, fromRange.getLastRow() + 1, fromRange.getFirstColumn(), fromRange.getLastColumn()), ROW, distance, block);
859                                 }
860                         }
861                         // shift:falseの場合、コピー先範囲をクリア
862                         else {
863                                 ExcelUtil.clearRange(sheet, toRange, COPY.equalsIgnoreCase(style), true);
864                         }
865                         // style:copyの場合、コピー元範囲の結合保持・解除
866                         if(COPY.equalsIgnoreCase(style)) {
867                                 // コピー元範囲の結合状態チェック・保持。コピー先範囲の結合解除
868                                 CellRangeAddress tmpRange;
869                                 for(int i = 0; i < sheet.getNumMergedRegions(); i++) {
870                                         tmpRange = sheet.getMergedRegion(i);
871                                         // コピー元範囲の結合状態保持・解除
872                                         switch(CellRangeUtil.intersect(fromRange, tmpRange)) {
873                                         case CellRangeUtil.INSIDE:
874                                                 rangeList.add(tmpRange);
875                                                 log.debug("from range inside mergedRegion. save: {}", tmpRange.formatAsString());
876                                                 break;
877                                         case CellRangeUtil.ENCLOSES:
878                                                 log.warn("from range encloses mergedRegion. remove: {}", tmpRange.formatAsString());
879                                                 sheet.removeMergedRegion(i);
880                                                 break;
881                                         case CellRangeUtil.OVERLAP:
882                                                 log.warn("from range overlap mergedRegion. remove: {}", tmpRange.formatAsString());
883                                                 sheet.removeMergedRegion(i);
884                                                 break;
885                                         }
886                                 }
887                         }
888                 }
889
890                 // コピー元範囲を繰返しコピー
891                 // 範囲行でループ
892                 for(int r = fromRange.getFirstRow(); r <= fromRange.getLastRow(); r++) {
893                         row = sheet.getRow(r);
894                         // コピー元行がnullで繰返し方向横(列)の場合
895                         if(row == null && COL.equalsIgnoreCase(direction)) {
896                                 // コピー先行もnullとなるのでセルの処理はせず終了
897                                 log.debug("continue. direction: col from row [{}] is null", (r + 1));
898                                 continue;
899                         }
900
901                         // 範囲列でループ
902                         for(int c = fromRange.getFirstColumn(); c <= fromRange.getLastColumn(); c++) {
903                                 // コピー元行がnullの場合セルもnull
904                                 if(row == null) {
905                                         cell = null;
906                                 } else {
907                                         cell = row.getCell(c);
908                                 }
909
910                                 // 繰返し回数でループ
911                                 for(int i = startIdx, cpCount = 0; (startIdx <= endIdx && i <= endIdx || startIdx > endIdx && i >= endIdx); i = (startIdx <= endIdx ? i + 1 : i - 1), cpCount++) {
912                                         // 繰返し方向横(列)(行がデフォルト)
913                                         if(COL.equalsIgnoreCase(direction)) {
914                                                 // 範囲チェック
915                                                 if(c + colSpan * cpCount < 0 || c + colSpan * cpCount > ExcelUtil.getMaxColumnIndex(sheet)) {
916                                                         log.warn("to cell outside sheet");
917                                                         break;
918                                                 }
919                                                 toRow = row;
920                                                 toCell = row.getCell(c + colSpan * cpCount);
921                                                 // コピー元セルがnullならコピー先セルもnull
922                                                 if(cell == null) {
923                                                         if(toCell != null) {
924                                                                 toRow.removeCell(toCell);
925                                                                 log.debug("continue. from cell [{}] is null. to cell [{}] remove", (new CellReference(r, c)).formatAsString(), (new CellReference(r, c + colSpan * cpCount)).formatAsString());
926                                                         }
927                                                         else {
928                                                                 log.debug("continue. from cell [{}] and to cell [{}] is null", (new CellReference(r, c)).formatAsString(), (new CellReference(r, c + colSpan * cpCount)).formatAsString());
929                                                         }
930                                                         continue;
931                                                 }
932                                                 else {
933                                                         if(toCell == null) toCell = row.createCell(c + colSpan * cpCount);
934                                                         // block falseなら列情報(幅)もコピー
935                                                         if(!block) {
936                                                                 sheet.setColumnWidth(toCell.getColumnIndex(), sheet.getColumnWidth(cell.getColumnIndex()));
937                                                         }
938                                                 }
939                                         }
940                                         // 繰返し方向縦(行)の場合
941                                         else {
942                                                 // 範囲チェック
943                                                 if(r + rowSpan * cpCount < 0 || r + rowSpan * cpCount > ExcelUtil.getMaxRowIndex(sheet)) {
944                                                         log.warn("to row outside sheet");
945                                                         break;
946                                                 }
947                                                 // 繰返し先の行がなければ生成
948                                                 toRow = sheet.getRow(r + rowSpan * cpCount);
949                                                 toCell = null;
950                                                 // コピー元行がnullならコピー先行もnull
951                                                 if(row == null) {
952                                                         if(toRow != null) {
953                                                                 sheet.removeRow(toRow);
954                                                                 log.debug("continue. from row [{}] is null. to row [{}] remove", (r + 1));
955                                                         }
956                                                         else {
957                                                                 log.debug("continue. from and to row is null");
958                                                         }
959                                                         continue;
960                                                 } 
961                                                 else {
962                                                         if(toRow == null) toRow = sheet.createRow(r + rowSpan * cpCount);
963                                                         // block falseなら行情報(高さ)もコピー
964                                                         if(!block) {
965                                                                 toRow.setHeight(row.getHeight());
966                                                         }
967                                                         toCell = toRow.getCell(c);
968                                                         // コピー元セルがnullならコピー先セルもnull
969                                                         if(cell == null) {
970                                                                 if(toCell != null) {
971                                                                         toRow.removeCell(toCell);
972                                                                         log.debug("continue. from cell is null. to cell remove");
973                                                                 }
974                                                                 else {
975                                                                         log.debug("continue. from cell [{}] and to cell [{}] is null", (new CellReference(r, c)).formatAsString(), (new CellReference(r + rowSpan * cpCount, c)).formatAsString());
976                                                                 }
977                                                                 continue;
978                                                         }
979                                                         else {
980                                                                 if(toCell == null) toCell = toRow.createCell(c);
981                                                         }
982                                                 }
983                                         }
984
985                                         // スタイルコピーなら
986                                         if(cpCount > 0 && COPY.equalsIgnoreCase(style)) {
987                                                 // スタイルのコピー
988                                                 toCell.setCellStyle(cell.getCellStyle());
989                                         }
990                                         // 値のコピー
991                                         switch(cell.getCellType()) {
992                                         case Cell.CELL_TYPE_BLANK:
993                                                 toCell.setCellType(Cell.CELL_TYPE_BLANK);
994                                                 break;
995                                         case Cell.CELL_TYPE_BOOLEAN:
996                                                 toCell.setCellType(Cell.CELL_TYPE_BOOLEAN);
997                                                 toCell.setCellValue(cell.getBooleanCellValue());
998                                                 break;
999                                         case Cell.CELL_TYPE_ERROR:
1000                                                 toCell.setCellType(Cell.CELL_TYPE_ERROR);
1001                                                 toCell.setCellErrorValue(cell.getErrorCellValue());
1002                                                 break;
1003                                         case Cell.CELL_TYPE_FORMULA:
1004                                                 toCell.setCellType(Cell.CELL_TYPE_FORMULA);
1005                                                 // 数式のパース・移動先に合わせる
1006                                                 toCell.setCellFormula(
1007                                                                 ExcelUtil.getMoveFormula(
1008                                                                                 sheet, 
1009                                                                                 cell.getCellFormula().replace(
1010                                                                                                 (i == startIdx ? object : list + "[" + (mapKeys == null ? (startIdx - 1) : "'" + mapKeys[startIdx - 1] + "'") + "]"), list + "[" + (mapKeys == null ? (i - 1) : "'" + mapKeys[i - 1] + "'") + "]"), 
1011                                                                                 toCell.getRowIndex() - cell.getRowIndex(), 
1012                                                                                 toCell.getColumnIndex() - cell.getColumnIndex()
1013                                                                 )
1014                                                 );
1015                                                 log.debug("to cell Formula: {}", toCell.getCellFormula());
1016                                                 break;
1017                                         case Cell.CELL_TYPE_NUMERIC:
1018                                                 toCell.setCellType(Cell.CELL_TYPE_NUMERIC);
1019                                                 toCell.setCellValue(cell.getNumericCellValue());
1020                                                 break;
1021                                         case Cell.CELL_TYPE_STRING:
1022                                                 toCell.setCellType(Cell.CELL_TYPE_STRING);
1023                                                 toCell.setCellValue(cell.getStringCellValue().replace((i == startIdx ? object : list + "[" + (mapKeys == null ? (startIdx - 1) : "'" + mapKeys[startIdx - 1] + "'") + "]"), list + "[" + (mapKeys == null ? (i - 1) : "'" + mapKeys[i - 1] + "'") + "]"));
1024                                                 log.debug("to cell string: {}", toCell.getStringCellValue());
1025                                                 break;
1026                                         }
1027                                 }
1028                         }
1029                 }
1030                 // スタイルコピーなら
1031                 if(COPY.equalsIgnoreCase(style)) {
1032                         // 行列加算用
1033                         int addRow = 0;
1034                         int addCol = 0;
1035                         if(COL.equalsIgnoreCase(direction)) {
1036                                 addCol = colSpan;
1037                         }
1038                         else {
1039                                 addRow = rowSpan;
1040                         }
1041                         
1042                         // コピー元範囲の結合保持なら
1043                         if(!rangeList.isEmpty()) {
1044                                 // 結合をコピー
1045                                 // 結合保持数でループ
1046                                 for(int c = 0; c < rangeList.size(); c++) {
1047                                         tmpBfRange = rangeList.get(c);
1048                                         // 繰返し回数でループ
1049                                         for(int i = startIdx, cpCount = 1; (startIdx <= endIdx && i <= endIdx || startIdx > endIdx && i >= endIdx); i = (startIdx <= endIdx ? i + 1 : i - 1), cpCount++) {
1050                                                 // 初回はコピーしない(コピー元だから)
1051                                                 if(i == startIdx) continue;
1052                                                 // コピー先レンジ
1053                                                 tmpAfRange = new CellRangeAddress(
1054                                                                 tmpBfRange.getFirstRow() + (addRow * cpCount),
1055                                                                 tmpBfRange.getLastRow() + (addRow * cpCount),
1056                                                                 tmpBfRange.getFirstColumn() + (addCol * cpCount),
1057                                                                 tmpBfRange.getLastColumn() + (addCol * cpCount));
1058                                                 sheet.addMergedRegion(tmpAfRange);
1059                                                 log.debug("mergedRegion copy. from: [{}] to: [{}]", tmpBfRange.formatAsString(), tmpAfRange.formatAsString());
1060                                         }
1061                                 }
1062                         }
1063 /**
1064                         // オブジェクトのコピー
1065                         xls形式非対応                      
1066                         if(sheet instanceof HSSFSheet) {
1067                                 CellRangeAddress cpRange;
1068                                 HSSFShape cpShape;
1069                                 HSSFPatriarch patriarch = ((HSSFSheet)sheet).getDrawingPatriarch();
1070                                 if(patriarch != null) {
1071                                         List<HSSFShape> shapes = ((HSSFSheet)sheet).getDrawingPatriarch().getChildren();
1072                                         if(shapes != null) {
1073                                                 HSSFClientAnchor fAnchor, tAnchor;
1074                                                 HSSFShape tShape;
1075                                                 int r1, r2;
1076                                                 short c1, c2;
1077                                                 for (int i = 0; i < shapes.size(); i++) {
1078                                                         fAnchor = (HSSFClientAnchor)shapes.get(i).getAnchor();
1079                                                         if(fAnchor != null) {
1080                                                                 r1 = fAnchor.getRow1();
1081                                                                 c1 = fAnchor.getCol1();
1082                                                                 r2 = fAnchor.getRow2();
1083                                                                 c2 = fAnchor.getCol2();
1084                                                                 tmpRange = new CellRangeAddress(r1, r2, c1, c2);
1085                                                                 switch(CellRangeUtil.intersect(fRange, tmpRange)) {
1086                                                                 case CellRangeUtil.INSIDE:
1087                                                                 case CellRangeUtil.OVERLAP:
1088                                                                         // 繰返し方向縦(行)でない場合
1089                                                                         if(!ROW.equalsIgnoreCase(direction)) {
1090                                                                                 tAnchor = new HSSFClientAnchor(
1091                                                                                                 fAnchor.getDx1(), fAnchor.getDy1(),
1092                                                                                                 fAnchor.getDx2(), fAnchor.getDy2(),
1093                                                                                                 (short) (c1 + (colSpan * cpCount)), r1,
1094                                                                                                 (short) (c2 + (colSpan * cpCount)), r2);
1095                                                                                 cpRange = new CellRangeAddress(r1, r2, c1 + (colSpan * cpCount), c2 + (colSpan * cpCount));
1096                                                                         }
1097                                                                         // 繰返し方向縦(行)の場合
1098                                                                         else {
1099                                                                                 tAnchor = new HSSFClientAnchor(
1100                                                                                                 fAnchor.getDx1(), fAnchor.getDy1(),
1101                                                                                                 fAnchor.getDx2(), fAnchor.getDy2(),
1102                                                                                                 c1, r1 + (rowSpan * cpCount),
1103                                                                                                 c2, r2 + (rowSpan * cpCount));
1104                                                                                 cpRange = new CellRangeAddress(r1 + (rowSpan * cpCount), r2 + (rowSpan * cpCount), c1, c2);
1105                                                                         }
1106                                                                         if(log.isDebugEnabled()) log.debug("object copy from: " + tmpRange.formatAsString() + " to: "  + cpRange.formatAsString());
1107                                                                         HSSFShape = new 
1108                                                                         patriarch.addShape(new shapes.get(i),)
1109                                                                 }
1110                                                         }
1111                                                 }
1112                                         }
1113                                 }
1114                         }
1115 */
1116                         // オブジェクトのコピー Excel2007以降 ooxml形式のみ対応
1117                         if(sheet instanceof XSSFSheet) {
1118                                 int r1, c1, r2, c2;
1119                                 CTDrawing ctDrawing;
1120                                 CTTwoCellAnchor fAnchor, cpAnchor;
1121                                 CTMarker from, to; 
1122                                 try {
1123                                         // DocumentPartでループ
1124                                         for(POIXMLDocumentPart dr : ((XSSFSheet)sheet).getRelations()) {
1125                                                 if(dr == null) continue;
1126                                                 log.debug("DocumentPart class: {}", dr.getClass().getName());
1127                                                 // DocumentPartがDrawingオブジェクトの場合
1128                                                 if(dr instanceof XSSFDrawing) {
1129                                                         ctDrawing = ((XSSFDrawing) dr).getCTDrawing();
1130                                                         if(ctDrawing != null) {
1131                                                                 // アンカーでループ
1132                                                                 int alSize = ctDrawing.getTwoCellAnchorList().size();
1133                                                                 for (int i = 0; i < alSize; i++) {
1134                                                                         fAnchor = ctDrawing.getTwoCellAnchorList().get(i);
1135                                                                         // GraphicFrameをもつグラフ、スマートアートは簡単にはコピーできないので非対応
1136                                                                         if(fAnchor.isSetGraphicFrame()) continue;
1137                                                                         
1138                                                                         // アンカーの位置情報
1139                                                                         from = fAnchor.getFrom();
1140                                                                         r1 = from.getRow();
1141                                                                         c1 = from.getCol();
1142                                                                         to = fAnchor.getTo();
1143                                                                         r2 = to.getRow();
1144                                                                         c2 = to.getCol();
1145                                                                         tmpBfRange = new CellRangeAddress(r1, r2, c1, c2);
1146                                                                         
1147                                                                         // コピー元レンジに含まれている、掛かっているならコピー
1148                                                                         switch(CellRangeUtil.intersect(fromRange, tmpBfRange)) {
1149                                                                         case CellRangeUtil.INSIDE:
1150                                                                         case CellRangeUtil.OVERLAP:
1151                                                                                 // 繰返し回数でループ
1152                                                                                 ;       // コピー実施回数のクリア
1153                                                                                 for(int j = startIdx, cpCount = 1; (startIdx <= endIdx && j <= endIdx || startIdx > endIdx && j >= endIdx); j = (startIdx <= endIdx ? j + 1 : j - 1), cpCount++) {
1154                                                                                         // 初回はコピーしない(コピー元だから)
1155                                                                                         if(j == startIdx) continue;
1156                                                                                         // TODO これでオブジェクト(アンカー)のコピーができる!!
1157                                                                                         cpAnchor = ctDrawing.addNewTwoCellAnchor();
1158                                                                                         cpAnchor.set(fAnchor.copy());
1159                                                                                         from = cpAnchor.getFrom();
1160                                                                                         from.setRow(from.getRow() + (addRow * cpCount));
1161                                                                                         from.setCol(from.getCol() + (addCol * cpCount));
1162                                                                                         to = cpAnchor.getTo();
1163                                                                                         to.setRow(to.getRow() + (addRow * cpCount));
1164                                                                                         to.setCol(to.getCol() + (addCol * cpCount));
1165                                                                                         if(log.isDebugEnabled()) {
1166                                                                                                 tmpAfRange = new CellRangeAddress(from.getRow(), to.getRow(), from.getCol(), to.getCol());
1167                                                                                                 log.debug("object copy from: [{}] to: [{}]", tmpBfRange.formatAsString(), tmpAfRange.formatAsString());
1168                                                                                         }
1169                                                                                 }
1170                                                                         }
1171                                                                 }
1172                                                         }
1173                                                 }
1174                                         }
1175                                 }
1176                                 catch(Exception e) {
1177                                         log.error("object copy error: " + e.getMessage(), e);
1178                                 }
1179                         }
1180                 }
1181                 log.trace("parseForeach end");
1182         }
1183         
1184         /**
1185          * If句のパース
1186          */
1187         private void parseIf() {
1188                 log.trace("parseIf start");
1189
1190                 // 判定
1191                 boolean result;
1192                 Object elResult = elMgr.evaluate(expression);
1193                 if(elResult == null) {
1194                         log.debug("evaluate result is null");
1195                         result = false;
1196                 }
1197                 else if(elResult instanceof Boolean) {
1198                         result = (boolean) elResult;
1199                 }
1200                 else {
1201                         result = true;
1202                 }
1203                 log.debug("evaluate result: {}", result);
1204
1205                 // 判定falseの場合、範囲の操作
1206                 if(!result) {
1207                         if(delete == null) {
1208                                 log.debug("{} is null set default: {}", TLP_DELETE, LEFT);
1209                                 delete = LEFT;
1210                         }
1211                         else if(!LEFT.equalsIgnoreCase(delete) && !UP.equalsIgnoreCase(delete) && !CLEAR.equalsIgnoreCase(delete)) {
1212                                 log.warn("{} is illegal argument. set default: {}", TLP_DELETE, LEFT);
1213                                 delete = LEFT;
1214                         }
1215                         else {
1216                                 log.debug("delete: {}", delete);
1217                                 delete = delete.toLowerCase().trim();
1218                         }
1219                         
1220                         switch(delete) {
1221                         // クリア
1222                         case CLEAR:
1223                                 ExcelUtil.clearRange(sheet, (new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, startColIdx, startColIdx + colSpan - 1)), true, true);
1224                                 break;
1225                         // 左詰め
1226                         case LEFT:
1227                                 // IF範囲以降をずらす
1228                                 ExcelUtil.shift(sheet, new CellRangeAddress(startRowIdx, startRowIdx + rowSpan - 1, startColIdx + colSpan, startColIdx + colSpan), COL, -colSpan, block);
1229                                 break;
1230                         // 上詰め
1231                         case UP:
1232                                 // IF範囲以降をずらす
1233                                 ExcelUtil.shift(sheet, new CellRangeAddress(startRowIdx + rowSpan, startRowIdx + rowSpan, startColIdx, startColIdx + colSpan - 1), ROW, -rowSpan, block);
1234                         }
1235                 }
1236                 log.trace("parseIf end");
1237         }
1238         
1239         /**
1240          * マッチした結果がEL式であるかを返却
1241          * 
1242          * @return      マッチした結果がEL式であればtrue。以外の場合false
1243          */
1244         private boolean isEL() {
1245                 return EL.equalsIgnoreCase(type);
1246         }
1247
1248         /**
1249          * マッチした結果がIf句であるかを返却
1250          * 
1251          * @return      マッチした結果がIf句であればtrue。以外の場合false
1252          */
1253         private boolean isIf() {
1254                 return TL_IF.equalsIgnoreCase(type);
1255         }
1256
1257         /**
1258          * マッチした結果がForeach句であるかを返却
1259          * 
1260          * @return      マッチした結果がForeach句であればtrue。以外の場合false
1261          */
1262         private boolean isForeach() {
1263                 return TL_FOREACH.equalsIgnoreCase(type);
1264         }
1265         
1266         /**
1267          * 指示子全体検索結果から1つ目の指示子を置換
1268          * 
1269          * @param replacement   置換文字列
1270          * 
1271          * @return      置換後の文字列
1272          */
1273         private String replaceFirst(String replacement) {
1274                 return mtAll.replaceFirst(replacement == null ? "" : replacement);
1275         }
1276         
1277         /**
1278          * 同一セルの再パース要否を返却
1279          * 
1280          * @return 再パース必要であればはtrue。不要であればfalse
1281          */
1282         public boolean isReParseCell() {
1283                 return reParseFlg;
1284         }
1285 }