001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.hayabusa.taglib;
017
018import org.opengion.hayabusa.common.HybsSystem;
019import org.opengion.hayabusa.common.HybsSystemException;
020import org.opengion.fukurou.system.HybsConst;                                           // 6.4.5.2 (2016/05/06)
021import org.opengion.fukurou.util.StringUtil;
022import org.opengion.fukurou.util.ToString;
023import org.opengion.fukurou.util.FileUtil;                                                      // 6.4.5.2 (2016/05/06)
024import org.opengion.fukurou.model.POIUtil;
025// import org.opengion.fukurou.model.JacobUtil;                                         // 6.9.0.0 (2018/01/31) 廃止
026import org.opengion.fukurou.model.ExcelModel;
027
028import static org.opengion.fukurou.util.StringUtil.nval ;
029import static org.opengion.fukurou.system.HybsConst.BUFFER_LARGE;       // 6.1.0.0 (2014/12/26) refactoring
030
031import java.util.Map;
032import java.util.LinkedHashMap;
033import java.util.Arrays;
034import java.io.File;
035import java.util.List ;                                                                                         // 6.4.5.2 (2016/05/06)
036
037/**
038 * ExcelFileTag は、各種パラメータを指定して、Excelファイルの操作をおこなうタグです。
039 *
040 * 主に、ExcelModel、POIUtil 、JacobUtil の各機能をJSP上で使用できるようにしました。
041 * 入力の file1 を加工して、file2 を出力するというのが、基本パターンになります。
042 * file1 と、file2 を同じ値に指定した場合は、上書き保存されます。
043 *
044 * 6.9.0.0 (2018/01/31)
045 *   JacobUtil 廃止に伴い、toPrint、saveAs を廃止します。
046 *
047 * X ※ (saveAs,toPrint)属性は、JACOB(Java COM Bridge)の使用が前提です。
048 * X    これは、JavaからのCOMオートメーションコンポーネント呼び出しを可能とする 
049 * X    JAVA-COMブリッジです。COMライブラリのネイティブな呼び出しにJNIを使います。
050 * X    JACOBは、32bitおよび64bitのJVMをサポートするX86およびx64環境で動作します。 
051 * X    http://sourceforge.jp/projects/sfnet_jacob-project/  (日本語プロジェクト)
052 * X    http://sourceforge.net/projects/jacob-project/       (本家)
053 *
054 * X    設定:
055 * X       jacob-1.18-M2.zip をダウンロードし、
056 * X         ①jacob-1.18-M2-x64.dll または、jacob-1.18-M2-x86.dll を、
057 * X           Windowsのシステムディレクトリにコピーします。 (例:C:\Windows\System32)
058 * X         ②jacob.jar を、クラスパスに登録します。
059 * X           ここでは、名称を、jacob-1.18-M2.jar に変更し、jre\lib\ext にコピーしています。
060 *
061 * @og.formSample
062 * ●形式:<og:excelFile action="…" fileURL="…" >・・・</og:file>
063 * ●body:なし
064 *
065 * ●Tag定義:
066 *   <og:excelFile
067 *       fileURL            【TAG】操作するファイルのディレクトリを指定します (初期値:FILE_URL[=filetemp/])
068 *       file1            ○【TAG】入力ファイル名を指定します(必須)
069 *       file2              【TAG】出力ファイル名を指定します
070 *       sheetName          【TAG】EXCELファイルを読み込むときのシート名を設定します(初期値:指定なし)
071 *       sheetNos           【TAG】EXCELファイルを読み込むときのシート番号を複数設定できます(初期値:0)
072 *       sheetConstKeys     【TAG】EXCELファイルを読み込むときの固定値となるカラム名(CSV形式)
073 *       sheetConstAdrs     【TAG】EXCELファイルを読み込むときの固定値となるアドレス(行-列,行-列,・・・)
074 *       useActiveWorkbook  【TAG】EXCEL出力時に、セルの有効範囲を設定するかどうかを指定します(初期値:false)
075 *       addTitleSheet      【TAG】EXCEL出力時に、存在するSheet名一覧を作成する場合に、そのSheet名を指定します。
076 *       addImageFile       【TAG】画像ファイルを挿入します(画像ファイル名 シート番号 行 列)
077 *       valueType          【TAG】sheetConstXXX,readXXXX のパラメータに登録する方法を指定します(CSV,LIST,MAP)
078 *       readText           【TAG】ファイルを読み込んで、内容を 引数の変数にセットします。
079 *       readSheet          【TAG】ファイルを読み込んで、シート一覧を 引数の変数にセットします。
080 *       readName           【TAG】ファイルを読み込んで、名前一覧を 引数の変数にセットします。
081 *       readStyle          【TAG】ファイルを読み込んで、スタイル名を 引数の変数にセットします。
082 *       useConverter       【TAG】file1 のシート、セル、オブジェクトのテキストを変換します。
083 *       convFile           【TAG】useConverter=true 時に、変換対応表をファイルから読み取ります。
084 *       convMap            【TAG】useConverter=true 時に、変換対応表をMapから読み取ります。
085 *       scope              【TAG】キャッシュする場合のスコープ(request,session)を指定します(初期値:request)
086 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null) 5.7.7.2 (2014/06/20)
087 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null) 5.7.7.2 (2014/06/20)
088 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない) 5.7.7.2 (2014/06/20)
089 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない) 5.7.7.2 (2014/06/20)
090 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
091 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
092 *   />
093 *
094 * 【廃止】6.9.0.0 (2018/01/31) 物理削除
095 * X ※  saveAs             【廃止】file1 を指定のファイルの拡張子に合わせた変換を行って保存します(xls,xlsx,pdf)。
096 * X ※  toPrint            【廃止】file1 を指定のプリンタに印刷します。
097 *
098 * ●使用例
099 *    ・EXCEL を読み取って、シート名の一覧の目次を、先頭シートに追加します。
100 *        <og:excelFile  file1="input.xls" file2="input.xls" addTitleSheet="Title" />
101 *
102 * @og.group その他部品
103 * @og.rev 6.2.6.0 (2015/06/19) 新規作成
104 *
105 * @version  6.2
106 * @author       Kazuhiko Hasegawa
107 * @since    JDK8.0,
108 */
109public class ExcelFileTag extends CommonTagSupport {
110        /** このプログラムのVERSION文字列を設定します。   {@value} */
111        private static final String VERSION = "6.9.0.0 (2018/01/31)" ;
112        private static final long serialVersionUID = 690020180131L ;
113
114        /** sheetConstXXX,readXXXX のパラメータに登録する方法を指定します(CSV/LIST/MAP) */
115        private enum TypeEnum { CSV , LIST , MAP ; }
116
117        private TypeEnum valueType                      = TypeEnum.CSV ;        // sheetConstXXX,readXXXX のパラメータに登録する方法を指定します(CSV/LIST/MAP)
118
119        private String  fileURL                         = HybsSystem.sys( "FILE_URL" );
120        private String  file1                           ;
121        private String  file2                           ;
122
123        private String  sheetName                       ;               // EXCELファイルを読み込むときのシート名を設定します(初期値:指定なし)
124        private String  sheetNos                        ;               // EXCELファイルを読み込むときのシート番号を複数設定できます(初期値:0)
125        private String  sheetConstKeys          ;               // EXCELファイルを読み込むときの固定値となるカラム名(CSV形式)
126        private String  sheetConstAdrs          ;               // EXCELファイルを読み込むときの固定値となるアドレス(行-列,行-列,・・・)
127        private boolean useActiveWorkbook       ;               // EXCEL出力時に、セルの有効範囲を設定するかどうかを指定します(初期値:false)
128        private String  addTitleSheet           ;               // EXCEL出力時に、存在するSheet名一覧を作成する場合に、そのSheet名を指定します。
129        private String  addImageFile            ;               // 画像ファイルを挿入します(画像ファイル名 シート番号 行 列)
130        private String  readText                        ;               // ファイルを読み込んで、内容を 引数の変数にセットします。
131        private String  readSheet                       ;               // ファイルを読み込んで、シート一覧を 引数の変数にセットします。
132        private String  readName                        ;               // ファイルを読み込んで、名前一覧を 引数の変数にセットします。
133        private String  readStyle                       ;               // ファイルを読み込んで、スタイル名を 引数の変数にセットします。
134
135        private boolean useConverter            ;               // file1 のシート、セル、オブジェクトのテキストを変換します。
136        private String  convFile                        ;               // useConverter=true 時に、変換対応表をファイルから読み取ります。
137        private String  convMap                         ;               // useConverter=true 時に、変換対応表をMapから読み取ります。
138
139//      private String  saveAs                          ;               // file1 を指定のファイルの拡張子に合わせた変換を行って保存します(xls,xlsx,pdf)。            6.9.0.0 (2018/01/31) 廃止
140//      private String  toPrint                         ;               // file1 を指定のプリンタに印刷します。                6.9.0.0 (2018/01/31) 廃止
141
142        private String  scope                           = "request";    // "request","session"
143
144        /**
145         * デフォルトコンストラクター
146         *
147         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
148         */
149        public ExcelFileTag() { super(); }              // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
150
151        /**
152         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
153         *
154         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
155         * @og.rev 6.3.1.0 (2015/06/28) readText の取得方法を変更する。
156         * @og.rev 6.9.0.0 (2018/01/31) JacobUtil 廃止に伴い、toPrint、saveAs を廃止します。
157         *
158         * @return      後続処理の指示
159         */
160        @Override
161        public int doEndTag() {
162                debugPrint();           // 4.0.0 (2005/02/28)
163                if( useTag() ) {
164                        super.setScope( scope );                // デフォルトscope が "request" なので、再設定している。
165
166                        final String directory = HybsSystem.url2dir( fileURL );
167                        final File inFile = new File( StringUtil.urlAppend( directory,file1 ) );
168
169                        // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
170//                      if( toPrint == null ) {
171//                              if( saveAs == null ) {
172                                        final ExcelModel excel = new ExcelModel( inFile );
173                                        if( addTitleSheet != null ) { excel.setAddTitleSheet( addTitleSheet );  }
174                                        if( addImageFile  != null ) { putImageFile( excel );                                    }
175
176                                        // 6.3.1.0 (2015/06/28) readText の取得方法を変更する。
177                //                      if( readText    != null ) { setObject(      readText    , POIUtil.extractor( inFile )   ); }
178                                        if( readText    != null ) { setObject(      readText    , getExcelText( excel )                 ); }
179                                        if( readSheet   != null ) { setAttriObject( readSheet   , excel.getSheetNames()                 ); }
180                                        if( readName    != null ) { setAttriObject( readName    , excel.getNames()                              ); }
181                                        if( readStyle   != null ) { setAttriObject( readStyle   , excel.getStyleNames()                 ); }
182
183                                        if( sheetConstKeys != null && sheetConstAdrs != null ) { sheetConstSet( excel ); }
184
185                                        if( useConverter                ) { textConverter( excel );                     }
186                                        if( useActiveWorkbook   ) { excel.activeWorkbook( true );       }       // 引数のtrueは、「空セルを削除する」の指定
187
188                                        if( file2 != null ) {
189                                                final File outFile = new File( StringUtil.urlAppend( directory,file2 ) );
190                                                excel.saveFile( outFile );
191                                        }
192//                              }
193//                              else {
194//                                      if( file2 != null ) {
195//                                              final String errMsg = "file2とsaveAsは、同時に指定する事はできません。" + CR
196//                                                                              + "  file2=[" + file2 + "] , saveAs=[" + saveAs + "]";
197//                                              throw new HybsSystemException( errMsg );
198//                                      }
199//
200//                                      final File outFile = new File( StringUtil.urlAppend( directory,saveAs ) );
201//                                      JacobUtil.saveAs( inFile,outFile );
202//                              }
203//                      }
204//                      else {
205//                              JacobUtil.toPrint( inFile,toPrint );
206//                      }
207                }
208                return EVAL_PAGE ;
209        }
210
211        /**
212         * タグリブオブジェクトをリリースします。
213         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
214         *
215         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
216         * @og.rev 6.9.0.0 (2018/01/31) JacobUtil 廃止に伴い、toPrint、saveAs を廃止します。
217         *
218         */
219        @Override
220        protected void release2() {
221                super.release2();
222                valueType                       = TypeEnum.CSV; // sheetConstXXX,readXXXX のパラメータに登録する方法を指定します(CSV/LIST/MAP)
223                fileURL                         = HybsSystem.sys( "FILE_URL" );
224                file1                           = null;
225                file2                           = null;
226                sheetName                       = null;                 // EXCELファイルを読み込むときのシート名を設定します(初期値:指定なし)
227                sheetNos                        = null;                 // EXCELファイルを読み込むときのシート番号を複数設定できます(初期値:0)
228                sheetConstKeys          = null;                 // EXCELファイルを読み込むときの固定値となるカラム名(CSV形式)
229                sheetConstAdrs          = null;                 // EXCELファイルを読み込むときの固定値となるアドレス(行-列,行-列,・・・)
230                useActiveWorkbook       = false;                // EXCEL出力時に、セルの有効範囲を設定するかどうかを指定します(初期値:false)
231                addTitleSheet           = null;                 // EXCEL出力時に、存在するSheet名一覧を作成する場合に、そのSheet名を指定します。
232                addImageFile            = null;                 // 画像ファイルを挿入します(画像ファイル名 シート番号 行 列)
233                readText                        = null;                 // ファイルを読み込んで、内容を 引数の変数にセットします。
234                readSheet                       = null;                 // ファイルを読み込んで、シート一覧を 引数の変数にセットします。
235                readName                        = null;                 // ファイルを読み込んで、名前一覧を 引数の変数にセットします。
236                readStyle                       = null;                 // ファイルを読み込んで、スタイル名を 引数の変数にセットします。
237                useConverter            = false;                // file1 のシート、セル、オブジェクトのテキストを変換します。
238                convFile                        = null;                 // useConverter=true 時に、変換対応表をファイルから読み取ります。
239                convMap                         = null;                 // useConverter=true 時に、変換対応表をMapから読み取ります。
240//              saveAs                          = null;                 // file1 を指定のファイルの拡張子に合わせた変換を行って保存します(xls,xlsx,pdf)。
241//              toPrint                         = null;                 // file1 を指定のプリンタに印刷します。
242                scope                           = "request";    // "request","session"
243        }
244
245        /**
246         * addImageFile属性の実際の処理を行います。
247         *
248         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
249         *
250         * @param       excel ExcelModelオブジェクト
251         */
252        private void putImageFile( final ExcelModel excel ) {
253                final String[] org = addImageFile.split( " " );         // 連続するスペースは個別に "" に分割される。
254
255                final String[] vals = Arrays.copyOf( org , 10 );        // 10個の配列を用意します。
256
257                final String imgFile = nval( vals[0] , null );                                  // 挿入するイメージファイル名
258                final int    shtNo       = nval( vals[1] , 0 );                                         // シート番号
259                final int    row1        = nval( vals[2] , 0 );                                         // 挿入する行(開始)
260                final int    col1        = nval( vals[3] , 0 );                                         // 挿入する列(開始)
261                final int    row2        = nval( vals[4] , row1 );                                      // 挿入する行(終了-含まず)
262                final int    col2        = nval( vals[5] , col1 );                                      // 挿入する列(終了-含まず)
263                final int    dx1         = nval( vals[6] , 0 );                                         // 開始セルのX軸座標(マージン)
264                final int    dy1         = nval( vals[7] , 0 );                                         // 開始セルのY軸座標(マージン)
265                final int    dx2         = nval( vals[8] , 0 );                                         // 終了セルのX軸座標(マージン)
266                final int    dy2         = nval( vals[9] , 0 );                                         // 終了セルのY軸座標(マージン)
267
268                excel.addImageFile( imgFile,shtNo,row1,col1,row2,col2,dx1,dy1,dx2,dy2 );
269        }
270
271        /**
272         * テキスト情報を取得します。
273         *
274         * EXCELファイルのテキスト情報として、シート名、セル値、オブジェクト文字列を取得します。
275         * POIUtil.extractor( File ) でもテキストを取得できますが、細かい点で、調整できません。
276         *
277         * @og.rev 6.3.1.0 (2015/06/28) 新規作成
278         * @og.rev 6.3.9.0 (2015/11/06) Java 8 ラムダ式に変更
279         *
280         * @param       excel ExcelModelオブジェクト
281         * @return      テキスト情報
282         */
283        private String getExcelText( final ExcelModel excel ) {
284                final StringBuilder buf = new StringBuilder( BUFFER_LARGE );
285
286                // 6.3.9.0 (2015/11/06) Java 8 ラムダ式に変更
287                excel.textConverter(
288                        (val,cmnt) -> {
289                                if( val != null ) { buf.append( val ).append( CR ); }
290                                return null;
291                        }
292                );
293
294                return buf.toString();
295        }
296
297        /**
298         * sheetConstKeys,sheetConstAdrs属性の実際の処理を行います。
299         *
300         * EXCELファイルを読み込むときの固定値となるカラム名(CSV形式)と
301         * アドレス(行-列,行-列,・・・) から、値を取得します。
302         * 取得した結果は、valueType 属性で指定した方法でセーブします。
303         * アドレスは、1シートに1箇所ですが、シートが複数存在する場合は、
304         * 複数の値が求められます。その値の設定方法は、valueType属性で指定します。
305         *
306         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
307         *
308         * @param       excel ExcelModelオブジェクト
309         */
310        private void sheetConstSet( final ExcelModel excel ) {
311                final Map<String,String> kvMap = getCSVParameter( sheetConstKeys , sheetConstAdrs );
312
313                final int size = kvMap.size();
314                final String[] keys = new String[size];
315                final int[] rows = new int[size];
316                final int[] cols = new int[size];
317
318                // 行-列 文字列を、分解します。
319                int no = 0;
320                for( final Map.Entry<String,String> entry : kvMap.entrySet() ) {
321                        keys[no] = entry.getKey();
322                        final String val = entry.getValue();
323                        final int[] rci = POIUtil.kigo2rowCol( val );           // A1,B5 などの形式
324                        rows[no] = rci[0];
325                        cols[no] = rci[1];
326
327                        no++ ;
328                }
329                // size と、no は、同じ値のはず。
330
331                // EXCELからデータを抜き出します。
332                final int shtSize = excel.getNumberOfSheets();
333                final String[][] kvAry = new String[size][shtSize];
334                for( int shtNo=0; shtNo<shtSize; shtNo++ ) {
335                        final String shtNm = excel.getSheetName( shtNo );                       // シート名の取得と同時に、内部状態の Sheetオブジェクトを設定する。
336                        for( int i=0; i<size; i++ ) {
337                                if( rows[i] < 0 ) {
338                                        kvAry[i][shtNo] = shtNm;                                        // rowNo が -1 の場合は、シート名を設定
339                                }
340                                else {
341                                        kvAry[i][shtNo] = excel.getValue( rows[i],cols[i] );    // 配列の配置がループと会わないが、後でセットするため。
342                                }
343                        }
344                }
345
346                // キーと、各シートから集めた値を設定します。
347                for( int i=0; i<size; i++ ) {
348                        setAttriObject( keys[i] , kvAry[i] ) ;
349                }
350        }
351
352        /**
353         * シート、セル、オブジェクトのテキストを変換します。
354         *
355         * convFile : 変換対応表をファイルから読み取ります。
356         * convMap  : 変換対応表をMapから読み取ります。
357         *
358         * このメソッドは、useConverter=true の時のみ、呼ばれます。
359         * また、convFileとconvMapの両方とも、定義されていない場合は、
360         * 何もしません。
361         * 両方とも定義されていた場合は、if文の関係で、convFileが優先されます。
362         *
363         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
364         * @og.rev 6.4.2.1 (2016/02/05) HybsSystem.url2dir に引数追加。
365         * @og.rev 6.4.5.1 (2016/04/28) FileStringのコンストラクター変更
366         * @og.rev 6.4.5.2 (2016/05/06) fukurou.util.FileString から、fukurou.util.FileUtil に移動。
367         *
368         * @param       excel ExcelModelオブジェクト
369         */
370        @SuppressWarnings(value={"unchecked"})
371        private void textConverter( final ExcelModel excel ) {
372                Map<String,String> changeMap = null;
373
374                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
375                if( convFile == null ) {
376                        if( convMap != null ) {
377                                changeMap = (Map<String,String>)getObject( convMap );   // 警告: [unchecked] 無検査キャスト
378                        }
379                }
380                else {
381                        final String inFile = HybsSystem.url2dir( fileURL , convFile );                 // 6.4.2.1 (2016/02/05)
382
383                        // 6.4.5.1 (2016/04/28) FileStringのコンストラクター変更
384                        final List<String> list = FileUtil.getLineList( inFile , HybsConst.UTF_8 );     // 6.4.5.2 (2016/05/06)
385
386                        changeMap = new LinkedHashMap<>();
387                        for( final String line : list ) {
388                                final int indx = line.indexOf( '\t' );
389                                if( indx <= 0 ) { continue ; }                                  // TAB が先頭や、存在しない行は読み飛ばす。
390                                final String key = line.substring( 0,indx );
391                                final String cng = line.substring( indx+1 );
392                                changeMap.put( key,cng );
393                        }
394                }
395
396                // convFile も、convMap も定義されていない場合、changeMap は、null のまま。
397                if( changeMap != null ) {
398                        excel.textConverter( changeMap );
399                }
400        }
401
402        /**
403         * 【TAG】操作するファイルのディレクトリを指定します
404         *              (初期値:FILE_URL[={@og.value SystemData#FILE_URL}])。
405         *
406         * @og.tag
407         * この属性で指定されるディレクトリのファイルを操作します。
408         * 指定方法は、通常の fileURL 属性と同様に、先頭が、'/' (UNIX) または、2文字目が、
409         * ":" (Windows)の場合は、指定のURLそのままのディレクトリに、そうでない場合は、
410         * (初期値:システム定数のFILE_URL[={@og.value SystemData#FILE_URL}])。
411         *
412         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
413         * @og.rev 6.4.2.1 (2016/02/05) URLの最後に、"/" を追加する処理を廃止。
414         *
415         * @param       url ファイルURL
416         * @see         org.opengion.hayabusa.common.SystemData#FILE_URL
417         */
418        public void setFileURL( final String url ) {
419                final String furl = nval( getRequestParameter( url ),null );
420                if( furl != null ) {
421                        fileURL = StringUtil.urlAppend( fileURL,furl );
422                }
423        }
424
425        /**
426         * 【TAG】基準となるファイル名を指定します(コマンドの左辺のファイル名です)。
427         *
428         * @og.tag
429         * コマンドの左辺のファイル名です。
430         *
431         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
432         *
433         * @param       fname ファイル名1
434         */
435        public void setFile1( final String fname ) {
436                file1 = nval( getRequestParameter( fname ),file1 );
437        }
438
439        /**
440         * 【TAG】内部 Workbook オブジェクトをファイルに書き出します。
441         *
442         * @og.tag
443         * この属性を指定しない場合は、ファイルに出力されません。
444         * また、file1 と同じファイルを指定することは可能です。その場合は、
445         * 元のファイルが上書き保存されます。
446         * Excelの形式は、ここで指定する出力ファイルの拡張子ではなく、file1で
447         * 指定したファイルの拡張子で決まります。
448         * 異なる形式の拡張子を持つファイルを指定した場合、強制的に、オープンした 
449         * Workbook の形式の拡張子を追加します。
450         *
451         * 拡張子は、Excel 2007以降の形式(.xlsx)か、Excel 2003以前の形式(.xls) が指定できます。
452         * 拡張子が未設定の場合は、オープンした Workbook の形式に合わせた拡張子を付与します。
453         *
454         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
455         *
456         * @param       fname ファイル名2
457         */
458        public void setFile2( final String fname ) {
459                file2 = nval( getRequestParameter( fname ),file2 );
460        }
461
462        /**
463         * 【TAG】EXCELファイルを読み込むときのシート名を設定します(初期値:指定なし)。
464         *
465         * @og.tag
466         * EXCELファイルを読み込む時に、シート名を指定します。
467         * sheetNos と sheetName が同時に指定された場合は、sheetNos が優先されます。
468         * エラーにはならないのでご注意ください。
469         * 初期値は、指定なしです。
470         *
471         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
472         *
473         * @param   sheet EXCELファイルのシート名
474         * @see         #setSheetNos( String ) 
475         */
476        public void setSheetName( final String sheet ) {
477                sheetName = nval( getRequestParameter( sheet ),sheetName );
478        }
479
480        /**
481         * 【TAG】EXCELファイルを読み込むときのシート番号を指定します(初期値:0)。
482         *
483         * @og.tag
484         * EXCEL読み込み時に複数シートをマージして取り込みます。
485         * シート番号は、0 から始まる数字で表します。
486         * 
487         * シート番号の指定は、CSV形式で、複数指定できます。また、N-M の様にハイフンで繋げることで、
488         * N 番から、M 番のシート範囲を一括指定可能です。また、"*" による、全シート指定が可能です。
489         * これらの組み合わせも可能です。( 0,1,3,5-8,10-* )
490         * ただし、"*" に関しては例外的に、一文字だけで、すべてのシートを表すか、N-* を最後に指定するかの
491         * どちらかです。途中には、"*" は、現れません。
492         * シート番号は、重複(1,1,2,2)、逆転(3,2,1) での指定が可能です。これは、その指定順で、読み込まれます。
493         * sheetNos と sheetName が同時に指定された場合は、sheetNos が優先されます。
494         * エラーにはならないのでご注意ください。
495         * 
496         * 初期値は、0(第一シート) です。
497         *
498         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
499         *
500         * @param   sheet EXCELファイルのシート番号(0から始まる)
501         * @see         #setSheetName( String ) 
502         */
503        public void setSheetNos( final String sheet ) {
504                sheetNos = nval( getRequestParameter( sheet ),sheetNos );
505                if( sheetNos != null && sheetNos.length() > 0 ) {
506                        boolean errFlag = false;
507                        for( int i=0; i<sheetNos.length(); i++ ) {
508                                final char ch = sheetNos.charAt(i);
509                                if( ch == '-' || ch == ',' ) { continue; }
510                                if( ch == '*' && ( i==0 || i==sheetNos.length()-1 ) ) { continue; }
511                                if( ch < '0' || ch > '9' ) { errFlag = true; break; }
512                        }
513                        if( errFlag ) {
514                                final String errMsg = "sheetNos の指定を見直してください。sheetNos=[" + sheetNos + "]";
515                                throw new HybsSystemException( errMsg );
516                        }
517                }
518        }
519
520        /**
521         * 【TAG】EXCELファイルを読み込むときのシート単位の固定値を設定するためのキーをCSV形式で指定します。
522         *
523         * @og.tag
524         * カラム名は、CSV形式で指定します。
525         * これにより、シートの一か所に書かれている情報を、固定値として取得することができます。
526         * sheetConstAdrs 属性で指定したセル位置から取得した値を、sheetConstKeys で指定したキーに
527         * 設定します。
528         * 値の設定方法は、valueType 属性で指定します。
529         *
530         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
531         *
532         * @param   constKeys 固定値となるキー(CSV形式)
533         * @see         #setSheetConstAdrs( String ) 
534         */
535        public void setSheetConstKeys( final String constKeys ) {
536                sheetConstKeys = constKeys;
537        }
538
539        /**
540         * 【TAG】EXCELファイルを読み込むときのシート単位の固定値を設定するためのキーに対応するアドレスをCSV形式で指定します。
541         *
542         * @og.tag
543         * アドレスは、EXCEL上の行-列形式か、EXCEL表記に準拠した、A1,A2,B1形式が使用できます。
544         * また、特殊な文字として、"SHEET" という記号が使用できます。
545         *   ①行-列形式
546         *     行列は、EXCELオブジェクトに準拠するため、0から始まる整数です。
547         *     0-0 ⇒ A1 , 1-0 ⇒ A2 , 0-1 ⇒ B1 になります。
548         *   ②EXCEL表記
549         *     EXCEL表記に準拠した、A1,A2,B1 の記述も処理できるように対応します。
550         *     なお、A1,A2,B1 の記述は、必ず、英字1文字+数字 にしてください。(A~Zまで)
551         *   ③EXCELシート名をキーに割り当てるために、"SHEET" という記号に対応します。
552         *     readSheet 属性で、同等のことが出来まが、統一的に処理できるようにします。
553         *
554         * 例えば、sheetConstKeys="CLM,LANG,NAME" とし、sheetConstAdrs="0-0,A2,SHEET" とすると、
555         * NAMEカラムには、シート名を読み込むことができます。
556         * これは、内部処理の簡素化のためです。
557         *
558         * ちなみに、EXCELのセルに、シート名を表示させる場合の関数は、下記の様になります。
559         * =RIGHT(CELL("filename",$A$1),LEN(CELL("filename",$A$1))-FIND("]",CELL("filename",$A$1)))
560         *
561         * これにより、シートの一か所に書かれている情報を、固定値として取得することができます。
562         * sheetConstAdrs 属性で指定したセル位置から取得した値を、sheetConstKeys で指定したキーに
563         * 設定します。
564         * 値の設定方法は、valueType 属性で指定します。
565         *
566         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
567         *
568         * @param   constAdrs 固定値となるアドレス (行-列,行-列,・・・)
569         * @see         #setSheetConstKeys( String ) 
570         */
571        public void setSheetConstAdrs( final String constAdrs ) {
572                sheetConstAdrs = constAdrs;
573        }
574
575        /**
576         * 【TAG】EXCEL出力時に、セルの有効範囲を設定するかどうかを指定します(初期値:false)。
577         *
578         * @og.tag
579         * セルの有効範囲というのは、EXCELでの 空行、空列の存在しない範囲を指します(初期値:false)。
580         * 通常、空行でも、データとして残っている場合は、EXCELのセルオブジェクトは存在します。
581         * ここで、useActiveWorkbook="true" とすると、空行、空列を削除します。
582         * 初期値は、false:しない です。
583         *
584         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
585         *
586         * @param       useActWB 有効範囲の設定 [true:する/false:しない]
587         */
588        public void setUseActiveWorkbook( final String useActWB ) {
589                useActiveWorkbook = nval( getRequestParameter( useActWB ),useActiveWorkbook );
590        }
591
592        /**
593         * 【TAG】EXCEL出力時に、Sheet一覧を作成する場合のSheet名を指定します。
594         *
595         * @og.tag
596         * これは、Workbook に含まれる Sheet 一覧を作成する場合に、ここに指定した
597         * シート名で、目次を作成します。
598         *
599         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
600         *
601         * @param       sheetName タイトルシート名
602         */
603        public void setAddTitleSheet( final String sheetName ) {
604                addTitleSheet = nval( getRequestParameter( sheetName ),addTitleSheet );
605        }
606
607        /**
608         * 【TAG】指定のシートの行・列の箇所に、イメージファイルを挿入します。
609         *
610         * @og.tag
611         * ここでは、セル範囲ではなく、指定の行列の箇所に、アンカーを設定して、画像ファイルを
612         * 挿入します。一応、リサイズして、元の大きさ近くに戻しますが、縦横比が変わってしまいます。
613         * 正確に挿入する場合は、セル範囲の指定と、マージンを指定しなければなりませんが、
614         * 微調整が必要です。
615         * 引数は、スペース区切りで、下記の順番で指定します。
616         *
617         *    imgFile   挿入するイメージファイル名
618         *    shtNo     シート番号
619         *    row1      挿入する行(開始)
620         *    col1      挿入する列(開始)
621         *   [row2]     挿入する行(終了-含まず)      (未指定時は、row1)
622         *   [col2]     挿入する列(終了-含まず)      (未指定時は、col1)
623         *   [dx1 ]     開始セルのX軸座標(マージン)  (未指定時は、0)
624         *   [dy1 ]     開始セルのY軸座標(マージン)  (未指定時は、0)
625         *   [dx2 ]     終了セルのX軸座標(マージン)  (未指定時は、0)
626         *   [dy2 ]     終了セルのY軸座標(マージン)  (未指定時は、0)
627         *
628         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
629         *
630         * @param       imgFile (画像ファイル名 シート番号 開始行 開始列 [終了行 終了列 開始セルのX軸マージン 開始セルのY軸マージン 終了セルのX軸マージン 終了セルのY軸マージン])
631         */
632        public void setAddImageFile( final String imgFile ) {
633                addImageFile = nval( getRequestParameter( imgFile ),addImageFile );
634        }
635
636        /**
637         * 【TAG】sheetConstXXX,readXXXX のパラメータに登録する方法を指定します(CSV/LIST/MAP)。
638         *
639         * @og.tag
640         * キーに対して、値は複数存在する場合があります。
641         * その値を、設定する場合の、3つの方法を指定できます。
642         *
643         *   CSV : キーに対して、値をCSV形式でセットします。valueタグや、{&#064;XXX} で、取り出せます。
644         *         キーが複数ある場合は、個別に指定する必要があります。
645         *   LIST: キーに対して、値をListオブジェクトにセーブします。
646         *         キーが複数ある場合は、個別に指定する必要があります。
647         *   MAP : キー自体を、Mapオブジェクトに設定します。値は、CSV形式の文字列です。
648         *
649         * 初期値は、CSV です。
650         *
651         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
652         *
653         * @param       type 保管方法(CSV/LIST/MAP)
654         */
655        public void setValueType( final String type ) {
656                final String tp = nval( getRequestParameter( type ),null );
657                if( tp != null ) {
658                        valueType = TypeEnum.valueOf( tp );
659                }
660        }
661
662        /**
663         * 【TAG】ファイルを読み込んで、内容を引数の変数にセットします。
664         *
665         * @og.tag
666         * EXCELのセルと、テキストボックスオブジェクトの値を取得します。
667         * 引数に、キーとなるパラメータを指定します。
668         * テキストは、一つのキーに設定されます。
669         * valueType 属性の指定とは無関係にパラメータに登録されます。
670         *
671         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
672         *
673         * @param       read 書き込む変数名
674         */
675        public void setReadText( final String read ) {
676                readText = nval( getRequestParameter( read ),readText );
677        }
678
679        /**
680         * 【TAG】ファイルを読み込んで、シート一覧を引数の変数にセットします。
681         *
682         * @og.tag
683         * EXCELのシート一覧を取得します。
684         * 引数に、キーとなるパラメータを指定します。
685         * 値の設定方法は、valueType 属性で指定します。
686         *
687         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
688         *
689         * @param       read 書き込む変数名
690         */
691        public void setReadSheet( final String read ) {
692                readSheet = nval( getRequestParameter( read ),readSheet );
693        }
694
695        /**
696         * 【TAG】ファイルを読み込んで、名前一覧を 引数の変数にセットします。
697         *
698         * @og.tag
699         * EXCELの名前一覧を取得します。
700         * 名前一覧に、不正な値や、他のファイルのリンク等が設定されていると、
701         * EXCELを開くのに時間がかかる場合があります。EXCEL帳票などでは、問題になります。
702         * そこで、この名前が不正かどうか判別するのに、名前一覧を使用します。
703         * 引数に、キーとなるパラメータを指定します。
704         * 値の設定方法は、valueType 属性で指定します。
705         *
706         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
707         *
708         * @param       read 書き込む変数名
709         */
710        public void setReadName( final String read ) {
711                readName = nval( getRequestParameter( read ),readName );
712        }
713
714        /**
715         * 【TAG】ファイルを読み込んで、スタイル名を 引数の変数にセットします。
716         *
717         * @og.tag
718         * EXCELのスタイル名を取得します。
719         * スタイル名に、不正な値が設定されていると、EXCELを開くのに
720         * 時間がかかる場合があります。EXCEL帳票などでは、問題になります。
721         * そこで、このスタイル名が不正かどうか判別するのに、使用します。
722         * 引数に、キーとなるパラメータを指定します。
723         * 値の設定方法は、valueType 属性で指定します。
724         *
725         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
726         *
727         * @param       read 書き込む変数名
728         */
729        public void setReadStyle( final String read ) {
730                readStyle = nval( getRequestParameter( read ),readStyle );
731        }
732
733        /**
734         * 【TAG】シート名、セル、オブジェクトのテキストを変換するかどうか指定します(初期値:false)。
735         *
736         * @og.tag
737         * この属性では、テキスト変換を行うかどうかを指定します。例え、convFile属性や
738         * convMap属性が指定されていても、この属性を true にしないと、変換は行われません。
739         * また、convFile属性と、convMap属性がどちらも指定されていない場合も、実行されません。
740         * 初期値は、false:行わない です。
741         *
742         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
743         *
744         * @param       useConv コンバータ処理を行うかどうか [true:行う/false:行わない]
745         */
746        public void setUseConverter( final String useConv ) {
747                useConverter = nval( getRequestParameter( useConv ),useConverter );
748        }
749
750        /**
751         * 【TAG】useConverter=true 時に、変換対応表をファイルから読み取ります。
752         *
753         * @og.tag
754         * この属性は、useConverter=true を指定しないと、無視されます。
755         * テキスト変換を行う変換対応表を、ファイルで指定します。
756         * このテキストファイルは、変換元と変換先の文字列をタブ区切りで定義された、UTF-8ファイルです。
757         *
758         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
759         *
760         * @param       cfile コンバータ処理の変換対応表ファイル
761         */
762        public void setConvFile( final String cfile ) {
763                convFile = nval( getRequestParameter( cfile ),convFile );
764        }
765
766        /**
767         * 【TAG】useConverter=true 時に、変換対応表をMapから読み取ります。
768         *
769         * @og.tag
770         * この属性は、useConverter=true を指定しないと、無視されます。
771         * テキスト変換を行う変換対応表を、Mapオブジェクトで指定します。
772         * メモリ上のMapオブジェクトの取得キーを、指定します。
773         * スコープは、scope 属性を使います。
774         *
775         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
776         *
777         * @param       cmap コンバータ処理の変換対応表Mapの取得キー
778         */
779        public void setConvMap( final String cmap ) {
780                convMap = nval( getRequestParameter( cmap ),convMap );
781        }
782
783//      /**
784//       * 【TAG】file1 を指定のファイルの拡張子に合わせた変換を行って保存します(xls,xlsx,pdf)。
785//       *
786//       * @og.tag
787//       * この属性は、JACOB(Java COM Bridge)の使用が前提です。
788//       * file2と同時に指定する事はできません。
789//       * file2 属性と異なり、拡張子が異なるケースで、使用します。
790//       * また、xslx拡張子の場合でも、EXCELのバージョンや、設定によっては、POIでは
791//       * 読み取ることが出来ない場合があり、JACOBで変換することで、読み取ることが
792//       * できる形式に変換できます。
793//       * また、拡張子に、pdf を指定すると、PDFファイルに変換できます。
794//       * ※ この属性は単独でしか使用できません。(fileURL,file1 以外)
795//       *
796//       * @og.rev 6.2.6.0 (2015/06/19) 新規作成
797//       * @og.rev 6.9.0.0 (2018/01/31) JacobUtil 廃止に伴い、toPrint、saveAs を廃止します。
798//       *
799//       * @param       name セーブするファイル名
800//       */
801//      public void setSaveAs( final String name ) {
802//              saveAs = nval( getRequestParameter( name ),saveAs );
803//      }
804
805//      /**
806//       * 【TAG】file1 を指定のプリンタに印刷します。
807//       *
808//       * @og.tag
809//       * この属性は、JACOB(Java COM Bridge)の使用が前提です。
810//       * サーバーから使用できるプリンタ名を指定してEXCELを印刷します。
811//       * ※ この属性は単独でしか使用できません。(fileURL,file1 以外)
812//       *
813//       * @og.rev 6.2.6.0 (2015/06/19) 新規作成
814//       * @og.rev 6.9.0.0 (2018/01/31) JacobUtil 廃止に伴い、toPrint、saveAs を廃止します。
815//       *
816//       * @param       printer プリンタ名
817//       */
818//      public void setToPrint( final String printer ) {
819//              toPrint = nval( getRequestParameter( printer ),toPrint );
820//      }
821
822        /**
823         * 【TAG】キャッシュする場合のスコープ(request,session)を指定します(初期値:request)。
824         *
825         * @og.tag
826         * "request","session" が指定できます。
827         * 初期値は、 "request" です。
828         *
829         * @param       scp     スコープ
830         */
831        @Override
832        public void setScope( final String scp ) {
833                scope = nval( getRequestParameter( scp ),scope );
834        }
835
836        /**
837         * 指定のキーに、パラメータを登録します。
838         *
839         * キーに対して、値は複数存在する場合があります。
840         * その値を、設定する方法は、valueType属性 で指定します。
841         * 登録する場合の スコープも、scope属性 で指定します。
842         *
843         * @og.rev 6.2.6.0 (2015/06/19) 新規作成
844         * @og.rev 6.3.9.0 (2015/11/06) switch 文の2つの case のために同じコードを使用している(findbugs)
845         *
846         * @param       key  登録するキー
847         * @param       data 登録するデータ配列
848         */
849        private void setAttriObject( final String key,final String[] data ) {
850                // 6.3.9.0 (2015/11/06) switch 文の2つの case のために同じコードを使用している(findbugs)
851                if( valueType == TypeEnum.LIST ) {
852                        setObject( key , Arrays.asList ( data ) );
853                }
854                else {
855                        setObject( key , StringUtil.array2csv( data ) );
856                }
857        }
858
859        /**
860         * このオブジェクトの文字列表現を返します。
861         * 基本的にデバッグ目的に使用します。
862         *
863         * @return このクラスの文字列表現
864         * @og.rtnNotNull
865         */
866        @Override
867        public String toString() {
868                return ToString.title( this.getClass().getName() )
869                                .println( "VERSION"                             ,VERSION                        )
870                                .println( "fileURL"                             ,fileURL                        )
871                                .println( "file1"                               ,file1                          )
872                                .println( "file2"                               ,file2                          )
873                                .println( "sheetName"                   ,sheetName                      )
874                                .println( "sheetNos"                    ,sheetNos                       )
875                                .println( "sheetConstKeys"              ,sheetConstKeys         )
876                                .println( "sheetConstAdrs"              ,sheetConstAdrs         )
877                                .println( "useActiveWorkbook"   ,useActiveWorkbook      )
878                                .println( "addTitleSheet"               ,addTitleSheet          )
879                                .println( "addImageFile"                ,addImageFile           )
880                                .println( "valueType"                   ,valueType                      )
881                                .println( "readText"                    ,readText                       )
882                                .println( "readSheet"                   ,readSheet                      )
883                                .println( "readName"                    ,readName                       )
884                                .println( "readStyle"                   ,readStyle                      )
885                                .println( "useConverter"                ,useConverter           )
886                                .println( "convFile"                    ,convFile                       )
887                                .println( "convMap"                             ,convMap                        )
888//                              .println( "saveAs"                              ,saveAs                         )       // 6.9.0.0 (2018/01/31) JacobUtil 廃止に伴い、toPrint、saveAs を廃止します。
889//                              .println( "toPrint"                             ,toPrint                        )       // 6.9.0.0 (2018/01/31) JacobUtil 廃止に伴い、toPrint、saveAs を廃止します。
890                                .println( "Other..."    ,getAttributes().getAttribute() )
891                                .fixForm().toString() ;
892        }
893}