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