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.fukurou.model; 017 018import java.util.List; 019import java.util.ArrayList; 020import java.util.Map; // 6.1.0.0 (2014/12/26) ConstData を Mapで管理 021import java.util.HashMap; // 6.1.0.0 (2014/12/26) ConstData を Mapで管理 022import java.util.Arrays; // 6.2.0.0 (2015/02/27) 023import java.io.File; // 6.2.0.0 (2015/02/27) 024 025import org.opengion.fukurou.system.OgRuntimeException; // 6.4.2.0 (2016/01/29) 026import org.opengion.fukurou.util.StringUtil; // 6.2.0.0 (2015/02/27) 027import org.opengion.fukurou.util.FileInfo; // 6.2.0.0 (2015/02/27) 028 029/** 030 * EXCELやテキストファイルを、イベント方式に準拠して、読み込み処理を行います。 031 * TableModelHelperイベントは、openGion形式のファイル読み取りに準拠した方法をサポートします。 032 * ※ openGion形式のEXCEL/テキストファイルとは、#NAME 列に、カラム名があり、#で始まる 033 * レコードは、コメントとして判断し、読み飛ばす処理の事です。 034 * 035 * このイベントクラスは、サブクラスを作成し、EXCEL関連の EventReader_XLS、EventReader_XLSX 036 * クラスや、EventReader_TEXT などのテキスト関連のクラスで、eventReader メソッドの引数に指定します。 037 * EventReader_XLS と、EventReader_XLSX は、対象のEXCEL形式が異なりますが、実際は、 038 * POIUtil#eventReader( String , TableModelHelper ) を使用すれば、拡張子に応じて使用するクラスを 039 * 選択します。 040 * 041 * @og.rev 6.0.3.0 (2014/11/13) 新規作成 042 * @og.rev 6.2.0.0 (2015/02/27) パッケージ変更(util → model),クラス名変更(ExcelReaderEvent → TableModelHelper) 043 * @og.group ファイル入力 044 * 045 * @version 6.0 046 * @author Kazuhiko Hasegawa 047 * @since JDK7.0, 048 */ 049public class TableModelHelper { 050 private int nowRowNo = -1; // 現在の行番号 051 private boolean isColSkip ; // カラムスキップ中かどうか(true:スキップ中) 052 private boolean isNowName ; // カラム名配列の収集中かどうか(true:収集中) 053 private boolean isReadBreak ; // 読み取り処理を途中で中止するかどうか(true:中止) 054 private String nullBreakClm; // データがnullまたはゼロ文字列の場合に、Sheet読み取りを停止 055 private String nullSkipClm ; // 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加 056 057 private int skipRowCnt ; // 読み飛ばす行数(読み飛ばし中でも ContDataは取得する) 058 private int nBrkClmNo = -1; // nullBreakClmの列番号 059 private int nSkpClmNo = -1; // 6.2.3.0 (2015/05/01) nullSkipClmの列番号 060 061 private int clmSize = -1 ; // カラムサイズ(-1は未設定) 062 private String[] names ; // カラム名配列 063 private int[] colms ; // カラム番号配列 7.3.1.3 (2021/03/09) colList をテンポラリにするため 064 private String[] vals ; // 値の文字列配列(1行分) 065 private boolean useVals ; // 値配列に設定されたか? 066 067 private List<Integer> colList ; // カラム番号:name が null かゼロ文字列の場合は、飛ばします。 068 private List<String> nmsList ; // カラム番号に対応したカラム名配列(#NAMEの場合のみ使用) 069 070 private ConstData cnstData ; 071 072 private boolean useDebug ; // 6.2.0.0 (2015/02/27) デバッグ情報の出力するかどうか。新規追加 073 074 /** 075 * デフォルトコンストラクター 076 * 077 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 078 */ 079 public TableModelHelper() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 080 081 /** 082 * ファイルの読み取り開始時にイベントが発生します。 083 * 084 * 新しいファイルの読み取り開始毎に、1回呼ばれます。 085 * 戻り値が、true の場合は、そのファイルの読み取りを継続します。 086 * false の場合は、そのファイルの読み取りは行われません。 087 * 初期実装では、固定値設定処理を行っていますので、オーバーライドする場合は、 088 * super.startFile(String,int) してください。 089 * 初期実装では、true を返します。 090 * 091 * @og.rev 6.2.0.0 (2015/02/27) 新規作成 092 * 093 * @param file 読み取りファイル 094 * @return 読取継続するか [true:継続/false:読取らない] 095 */ 096 public boolean startFile( final File file ) { 097 if( useDebug ) { System.out.println( "startFile=[" + file + "]" ); } 098 // ファイル属性を設定する。 099 if( cnstData != null ) { cnstData.putConstFile( file ); } 100 return true; 101 } 102 103 /** 104 * ファイルの読み取り終了時にイベントが発生します。 105 * 106 * 初期実装では、固定値設定処理を行っていますので、オーバーライドする場合は、 107 * super.endFile(File) してください。 108 * 109 * @og.rev 6.0.3.0 (2014/11/13) 新規作成 110 * @og.rev 6.1.0.0 (2014/12/26) シートブレイク処理追加 111 * 112 * @param file 読み取りファイル 113 */ 114 public void endFile( final File file ) { 115 if( useDebug ) { System.out.println( "endFile=[" + file + "]" ); } 116 isReadBreak = false; // 読み取り再開 117 endRow(); // 行終了処理 118 if( cnstData != null ) { cnstData.clearValsMap( ConstData.END_FILE ); } 119 } 120 121 /** 122 * シートの読み取り開始時にイベントが発生します。 123 * 124 * ※ EXCEL関係以外の読み取りでは、このイベントは発生しません。 125 * 126 * 新しいシートの読み取り開始毎に、1回呼ばれます。 127 * 戻り値が、true の場合は、そのシートの読み取りを継続します。 128 * false の場合は、そのシートの読み取りは行わず、次のシートまで 129 * イベントは発行されません。 130 * 初期実装では、固定値設定処理を行っていますので、オーバーライドする場合は、 131 * super.startSheet(String,int) してください。 132 * 初期実装では、true を返します。 133 * 134 * @og.rev 6.0.3.0 (2014/11/13) 新規作成 135 * 136 * @param shtNm シート名 137 * @param shtNo シート番号(0~) 138 * @return 読取継続するか [true:継続/false:読取らない] 139 */ 140 public boolean startSheet( final String shtNm,final int shtNo ) { 141 if( useDebug ) { System.out.println( "startSheet=[" + shtNm + "], No=[" + shtNo + "]" ); } 142 // シート名を設定する。 143 if( cnstData != null ) { cnstData.putConstSheet( shtNm ); } 144 return true; 145 } 146 147 /** 148 * シートの読み取り終了時にイベントが発生します。 149 * 150 * ※ EXCEL関係以外の読み取りでは、このイベントは発生しません。 151 * 152 * #columnNames( String[] ) や、#values( String[] ,int ) などは、行の処理が完了した時点で 153 * イベントが呼ばれるため、一番最後のレコードの終了条件が判りません。 154 * そこで、このイベントを呼ぶことで、シートの終了(=最終行の終了)処理を行うことができます。 155 * 156 * 引数のシート番号は、参考情報で、#startSheet( String,int ) で呼ばれたシート番号と 157 * 比較できるようにしています。 158 * 初期実装では、固定値設定処理を行っていますので、オーバーライドする場合は、 159 * super.endSheet(int) してください。 160 * 161 * @og.rev 6.0.3.0 (2014/11/13) 新規作成 162 * @og.rev 6.1.0.0 (2014/12/26) シートブレイク処理追加 163 * 164 * @param shtNo シート番号(0~) 165 */ 166 public void endSheet( final int shtNo ) { 167 if( useDebug ) { System.out.println( "endSheet No=[" + shtNo + "]" ); } 168 isReadBreak = false; // 読み取り再開 169 endRow(); // 行終了処理 170 if( cnstData != null ) { cnstData.clearValsMap( ConstData.END_SHEET ); } 171 } 172 173 /** 174 * 読み取り状態の時に、rowNo にある行データを引数にイベントが発生します。 175 * 176 * ※ 主に、行データの読み込み処理で使用されるメソッドです。 177 * このメソッドは、EventReader#eventReader( String , TableModelHelper )メソッドの 178 * 処理の過程で、設定されます。 179 * このメソッドから、各種イベントが発行されます。 180 * 181 * 行データをセパレータで分解したのち、value( String ,int ,int ) メソッドを呼びます。 182 * ただし、行データが、null、空文字列、#で始まる場合は、呼ばれません。 183 * 184 * @og.rev 6.2.0.0 (2015/02/27) 新規作成 185 * @og.rev 6.2.1.0 (2015/03/13) 先頭に、'0 が含まれる場合のセミコロンや、前後のダブルクオートは削除 186 * @og.rev 6.2.5.0 (2015/06/05) デバック時に1行単位に出力するのを止めます。 187 * @og.rev 7.1.0.0 (2020/01/27) セパレータ分割時にデータ分割されない場合は、エンコードエラーの可能性が高い。 188 * @og.rev 7.3.1.3 (2021/03/09) #NAMEのオリジナルを取得できるようにします。 189 * @og.rev 8.4.0.0 (2022/12/23) 7.1.0.0 (2020/01/27) の対応は、ReadTableTag に移動。 190 * 191 * @param line 行データ 192 * @param rowNo 行番号(0~) 193 * @param sepa セパレータ 194 */ 195 protected void value( final String line,final int rowNo,final char sepa ) { 196 nowRowNo = rowNo; // 現在行の設定 197 198 // 値が存在する場合のみ、処理する。 199 if( line!=null && !line.isEmpty() ) { 200 // 6.2.5.0 (2015/06/05) デバック時に1行単位に出力するのを止めます。 201 // if( useDebug ) { System.out.println( "rowNo[" + rowNo + "], line=[" + line + "]" ); } 202 203 // 先頭カラムのコメント判断と、#NAME列判断 204 if( line.charAt(0)=='#' ) { 205 // 互換性の問題。#NAME は、大文字小文字両方対応できないといけない。( 5 == "#NAME".length() の事) 206 // 7.3.1.3 (2021/03/09) #NAME があれば処理する。 207// if( clmSize <= 0 && line.length() >= 5 && "#NAME".equalsIgnoreCase( line.substring( 0,5 ) ) ) { 208 if( line.length() >= 5 && "#NAME".equalsIgnoreCase( line.substring( 0,5 ) ) ) { 209 colList = new ArrayList<>() ; // 初期化 210 nmsList = new ArrayList<>() ; // 初期化 211 final String[] tmpNm = StringUtil.csv2Array( line,sepa ); 212 for( int colNo=1; colNo<tmpNm.length; colNo++ ) { // #NAME を無視(colNo=1~) 213 final String nm = tmpNm[colNo]; 214 // #NAME 設定も、null や、ゼロ文字列の場合は、登録しない。(一番上の if で対処) 215 if( nm != null && !nm.isEmpty() ) { 216 // 2.0.0 (2024/01/12) PMD 7.0.0 UnnecessaryBoxing 217// colList.add( Integer.valueOf( colNo ) ); 218 colList.add( colNo ); 219 nmsList.add( nm ); 220 } 221 } 222// originalNames( nmsList.toArray( new String[nmsList.size()] ) ); // 7.3.1.3 (2021/03/09) #NAMEのオリジナルを取得 223 originalNames( nmsList.toArray( new String[0] ) ); // 7.3.1.3 (2021/03/09) #NAMEのオリジナルを取得 // 8.5.4.2 (2024/01/12) PMD 7.0.0 OptimizableToArrayCall 対応 224 isNowName = true; 225 } 226 } 227 // clmSize > 0 は、#NAME が設定済みという意味 228 else if( clmSize > 0 && skipRowCnt <= rowNo ) { // skipRowCnt は、値セットだけ影響する。 229 final String[] tmpVals = StringUtil.csv2Array( line ,sepa ); 230 // if( cnstData != null ) { tmpVals = cnstData.getConstVals( tmpVals ); } 231 // int min = Math.min( clmSize,tmpVals.length ); 232 233 // // 8.4.0.0 (2022/12/23) 7.1.0.0 (2020/01/27) の対応は、ReadTableTag に移動。 234 // // 7.1.0.0 (2020/01/27) エンコードによってはエラーにならず1カラムのデータとして取れてしまう。 235 // // カラム数が1以上で、データ数が1の場合は、取り込みミスなので処理を終了する。 236 // if( clmSize > 1 && tmpVals.length == 1 ) { 237 // isReadBreak = true; // 処理の停止 238 // clmSize = 0; // #NAME列未設定と同じ(-1にしないのは、単に初期値と違うという事) 239 // return ; // 即抜ける 240 // } 241 242 for( int i=0; i<clmSize; i++ ) { 243// final int indx = colList.get( i ); // カラム番号の位置が 値配列の配列番号 244 final int indx = colms[i]; // 7.3.1.3 (2021/03/09) カラム番号の位置が 値配列の配列番号 245 if( indx >= 0 && indx < tmpVals.length ) { 246 vals[i] = StringUtil.csvOutQuote( tmpVals[indx] ); // 6.2.1.0 (2015/03/13) 247 } 248 } 249 useVals = true; 250 // values( vals , rowNo ); // イベント発行(現在行) 251 } 252 253 endRow(); // 行末処理実行。名前設定処理が走ります。 254 } 255 } 256 257 /** 258 * 読み取り状態の時に、rowNo,colNo にあるセルの値を引数にイベントが発生します。 259 * 260 * ※ 主に、EXCEL関係の読み取り処理で使用されるメソッドです。 261 * このメソッドは、EventReader#eventReader( String , TableModelHelper )メソッドの 262 * 処理の過程で、設定されます。 263 * このメソッドから、各種イベントが発行されます。 264 * 265 * 戻り値が、true の場合は、その行の読み取りを継続します。 266 * false の場合は、その行の読み取りは行わず、次の行まで 267 * イベントは発行されません。 268 * 269 * openGion での標準的な処理は、colNo==0 の時に、val の先頭が、# で 270 * 始まる場合は、その行はスキップします。 271 * ここでの return は、#isSkip( int ) と逆になりますので、ご注意ください。 272 * 初期実装では、#NAME処理、行スキップ、行終了処理等を実行します。 273 * オーバーライドする場合は、super.value(String,int,int) してください。 274 * 275 * @og.rev 6.0.3.0 (2014/11/13) 新規作成 276 * @og.rev 6.2.2.0 (2015/03/27) 先頭に、'0 が含まれる場合のセミコロンや、前後のダブルクオートは削除 277 * @og.rev 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加 278 * @og.rev 7.3.1.3 (2021/03/09) #NAMEのオリジナルを取得できるようにします。 279 * 280 * @param val 文字列値 281 * @param rowNo 行番号(0~) 282 * @param colNo 列番号(0~) 283 * @return 読み取りするかどうか(true:読み取りする/false:読み取りしない) 284 * @see #isSkip( int ) 285 */ 286 protected boolean value( final String val,final int rowNo,final int colNo ) { 287 // if( useDebug ) { System.out.println( "R[" + rowNo + "," + colNo + "]=" + val ); } 288 289 // 値が存在する場合のみ、処理する。 290 if( val!=null && val.length()>0 ) { 291 // 行番号が異なった場合は、行の終了処理を実行する。 292 if( nowRowNo != rowNo ) { 293 if( isNowName ) { // 7.3.1.3 (2021/03/09) #NAMEのオリジナルを取得 294// originalNames( nmsList.toArray( new String[nmsList.size()] ) ); 295 originalNames( nmsList.toArray( new String[0] ) ); // 8.5.4.2 (2024/01/12) PMD 7.0.0 OptimizableToArrayCall 対応 296 } 297 298 endRow(); // 行終了処理 299 nowRowNo = rowNo; // 現在行の設定 300 } 301 302 // 固定文字の設定なので、コメントもスキップも無関係 303 if( cnstData != null ) { cnstData.putConstValue( val,rowNo,colNo ); } 304 305 // 先頭カラムのコメント判断と、#NAME列判断 306 if( colNo==0 && val.charAt(0)=='#' ) { 307// if( "#NAME".equalsIgnoreCase( val ) && clmSize <= 0 ) { // clmSize <= 0 は、#NAME未設定という意味 308 // 7.3.1.3 (2021/03/09) #NAME があれば処理する 309 if( "#NAME".equalsIgnoreCase( val )) { 310 isNowName = true ; 311 colList = new ArrayList<>() ; // 初期化 312 nmsList = new ArrayList<>() ; // 初期化 313 } 314 isColSkip = !isNowName; // #NAME の場合は、false(SKIPしない) 315 } 316 // #NAME処理中 317 else if( isNowName ) { 318 // #NAME 設定も、null や、ゼロ文字列の場合は、登録しない。(一番上の if で対処) 319 // 2.0.0 (2024/01/12) PMD 7.0.0 UnnecessaryBoxing 320// colList.add( Integer.valueOf( colNo ) ); 321 colList.add( colNo ); 322 nmsList.add( val ); 323 } 324 // 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加 325 else if( nSkpClmNo >= 0 && StringUtil.isNull( vals[nSkpClmNo] ) ) { // nullSkipClm 処理 326 isColSkip = true; // Skip する 327 } 328 // clmSize > 0 は、#NAME が設定済みという意味 329 // 7.3.1.3 (2021/03/09) カラム番号の位置が 値配列の配列番号 330 else if( clmSize > 0 && skipRowCnt <= rowNo ) { // skipRowCnt は、値セットだけ影響する 331 for( int i=0; i<clmSize ; i++ ) { // カラム番号の位置が 値配列の配列番号 332 if( colms[i] == colNo ) { 333 vals[i] = StringUtil.csvOutQuote( val ); // 6.2.2.0 (2015/03/27) 334 useVals = true; 335 break; 336 } 337 } 338 } 339// else if( clmSize > 0 && skipRowCnt <= rowNo ) { // skipRowCnt は、値セットだけ影響する。 340// final int indx = colList.indexOf( Integer.valueOf( colNo ) ); // カラム番号の位置が 値配列の配列番号 341// if( indx >= 0 ) { 342// vals[indx] = StringUtil.csvOutQuote( val ); // 6.2.2.0 (2015/03/27) 343// useVals = true; 344// } 345// } 346 } 347 348 return !isColSkip; 349 } 350 351 /** 352 * rowNo を元に、この行をスキップするかどうか判定のイベントが発生します。 353 * 354 * ※ EXCEL関係の列毎にイベントが発生する場合の列処理をスキップするのが目的です。 355 * 行単位に読み込む場合や、行のループに入れても、意味はありません。 356 * 引数から、行のループに入れてしまいそうですが、行列のループに入れてください。 357 * 358 * ※ 主に、EXCEL関係の読み取り処理で使用されるメソッドです。 359 * このメソッドは、EventReader#eventReader( String , TableModelHelper )メソッドの 360 * 処理の過程で、設定されます。 361 * このメソッドから、各種イベントが発行されます。 362 * 363 * 戻り値が、true の場合は、その行の読み取りをスキップします。 364 * false の場合は、読み取り処理を継続します。 365 * スキップ中は、行に関するイベントは発行されません。 366 * 367 * 値(val)を求める前に、行情報を入手し、スキップ中の現在行と同じ場合に、スキップ(=true)と判定します。 368 * スキップ中かどうかは、#value( String,int,int ) で、判定します。 369 * 初期実装では、スキップ中 かつ 現在行と同じ行の場合、または、シートブレーク中の場合に、true を返します。 370 * 371 * @og.rev 6.0.3.0 (2014/11/13) 新規作成 372 * @og.rev 6.1.0.0 (2014/12/26) シートブレイク処理追加 373 * 374 * @param rowNo 行番号(0~) 375 * @return スキップするかどうか(true:スキップする/false:スキップしない) 376 * @see #value( String,int,int ) 377 */ 378 protected boolean isSkip( final int rowNo ) { 379 return isColSkip && nowRowNo == rowNo || isReadBreak ; 380 } 381 382 /** 383 * 行の終了時に実行されます。 384 * 385 * ここでは、rowNo がブレークするか、シート終了時に呼ぶことで、 386 * 一番最後の行の処理を行います。 387 * 388 * #NAME 処理中の場合(isNowName == true) は、カラム名配列を作成して、 389 * columnNames イベントを呼び出します。 390 * 値配列が設定されている場合(useVals == true) は、values イベントを 391 * 呼び出します。 392 * #NAME 処理が完了している場合は、値配列の初期化を行います。 393 * そのうえで、スキップの解除(isColSkip = false)と行データ 394 * 未設定(useVals = false)に、初期化します。 395 * 396 * @og.rev 6.0.3.0 (2014/11/13) 新規作成 397 * @og.rev 6.2.2.0 (2015/03/27) Overflow処理は、Tag側に戻す。 398 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 399 * @og.rev 7.3.1.3 (2021/03/09) #NAMEのオリジナルを取得できるようにします。 400 * 401 * @see #columnNames( String[] ) 402 * @see #values( String[],int ) 403 */ 404 private void endRow() { 405 if( isNowName ) { // #NAME 処理中の場合 406 if( clmSize > 0 ) { // 7.3.1.3 (2021/03/09) names,#NAME が設定済みという意味 407 isNowName = false; 408 return; 409 } 410 411 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 412 if( colList == null ) { 413 final String errMsg = "#value(String,int,char) または#value(String,int,int) を先に実行しておいてください。" ; 414 throw new OgRuntimeException( errMsg ); 415 } 416 417 clmSize = colList.size(); 418// names = nmsList.toArray( new String[clmSize] ); 419 names = nmsList.toArray( new String[0] ); // 8.5.4.2 (2024/01/12) PMD 7.0.0 OptimizableToArrayCall 対応 420 colms = colList.stream().mapToInt(i->i).toArray(); // 7.3.1.3 (2021/03/09) 421 422 if( nullBreakClm != null ) { 423 for( int i=0; i<clmSize; i++ ) { 424 if( nullBreakClm.equalsIgnoreCase( names[i] ) ) { 425 nBrkClmNo = i; 426 break; 427 } 428 } 429 } 430 // 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加 431 if( nullSkipClm != null ) { 432 for( int i=0; i<clmSize; i++ ) { 433 if( nullSkipClm.equalsIgnoreCase( names[i] ) ) { 434 nSkpClmNo = i; 435 break; 436 } 437 } 438 } 439 440 if( cnstData != null ) { cnstData.setColumns( names ); } 441 columnNames( names.clone() ); // イベント(setNames でも、#NAME でもイベントが発生する) 442 isNowName = false; 443 colList = null ; // 7.3.1.3 (2021/03/09) 不要 444 nmsList = null ; // 不要 445 } 446 else if( useVals ) { // 値配列が設定されている場合 447 if( nBrkClmNo >= 0 && StringUtil.isNull( vals[nBrkClmNo] ) ) { // nullBreakClm 処理 448 isReadBreak = true; // ReadBreak する 449 } 450 else { 451 if( cnstData != null ) { vals = cnstData.getConstVals( vals ); } 452 values( vals , nowRowNo ); // イベント発行(現在行) 453 } 454 } 455 456 if( clmSize > 0 ) { // clmSize > 0 は、#NAME が設定済みという意味 457 vals = new String[clmSize]; // 値配列の初期化 458 } 459 460 isColSkip = false; // スキップの解除 461 useVals = false; // 行データ未設定にする 462 } 463 464 /** 465 * シート数のイベントが発生します。 466 * 467 * ※ EXCEL関係以外の読み取りでは、このイベントは発生しません。 468 * 469 * 処理の開始前に、シート数のイベントが発生します。 470 * これを元に、処理するシート番号の選別が可能です。 471 * 472 * @og.rev 6.1.0.0 (2014/12/26) シートの数のイベント 473 * 474 * @param size シート数 475 */ 476 public void sheetSize( final int size ) { 477 if( useDebug ) { System.out.println( "sheetSize=[" + size + "]" ); } 478 } 479 480 /** 481 * カラム名配列がそろった段階で、イベントが発生します。 482 * 483 * openGion での標準的な処理は、colNo==0 の時に、val の先頭が、#NAME 484 * で始まるレコードを、名前配列として認識します。 485 * #value( String,int,int ) で、この #NAME だけは、継続処理されます。 486 * その上で、#NAME レコードが終了した時点で、カラム名配列が完成するので 487 * そこで初めて、このメソッドが呼ばれます。(EXCEL関係の場合) 488 * 489 * 外部から設定する、#setNames( String , boolean ) 時も同様に呼ばれます。 490 * 491 * @og.rev 6.0.3.0 (2014/11/13) 新規作成 492 * 493 * @param names カラム名配列 494 * @see #value( String,int,int ) 495 * @see #setNames( String , boolean ) 496 */ 497 public void columnNames( final String[] names ) { 498 if( useDebug ) { System.out.println( "columnNames=[" + Arrays.toString(names) + "]" ); } 499 } 500 501 /** 502 * #NAME のオリジナルカラム名配列がそろった段階で、イベントが発生します。 503 * 504 * #columnNames( String[] ) は、setNames指定時も、#NAME 指定時もイベントが発生します。 505 * このメソッドは、setNames の設定に関係なく、ファイルに書かれていた #NAME で始まるレコードを、 506 * 名前配列として識別して呼出します。 507 * 508 * #NAME が存在しない場合は、呼び出されません。 509 * 510 * @og.rev 7.3.1.3 (2021/03/09) #NAMEのオリジナルを取得できるようにします。 511 * 512 * @param names #NAME のオリジナルカラム名配列 513 * @see #columnNames( String[] ) 514 */ 515 public void originalNames( final String[] names ) { 516 if( useDebug ) { System.out.println( "originalNames=[" + Arrays.toString(names) + "]" ); } 517 } 518 519 /** 520 * row にあるセルのオブジェクト値がそろった段階で、イベントが発生します。 521 * 522 * 初期実装は、何もありません。 523 * 524 * @og.rev 6.0.3.0 (2014/11/13) 新規作成 525 * 526 * @param vals 文字列値の1行分の配列 527 * @param rowNo 行番号(0~) 528 */ 529 public void values( final String[] vals,final int rowNo ) { 530 if( useDebug ) { System.out.println( "values[" + rowNo + "]=[" + Arrays.toString(vals) + "]" ); } 531 } 532 533 /** 534 * 外部からCSV形式のカラム名文字列を設定します。 535 * 536 * ※ イベント処理実行前の初期化処理です。 537 * 538 * カラム名配列を、#NAME で始まるレコードではなく、外部から指定します。 539 * ここで設定した場合、#columnNames( String[] )イベントも発生します。 540 * null か、長さゼロのカラム名は、設定されません。 541 * 542 * @og.rev 6.1.0.0 (2014/12/26) カラム名配列設定の対応 543 * @og.rev 7.3.1.3 (2021/03/09) #NAMEのオリジナルを取得できるようにします。 544 * 545 * @param clms CSV形式のカラム名文字列 546 * @param useNumber 行番号情報 [true:使用している/false:していない] 547 * @see #columnNames( String[] ) 548 */ 549 public final void setNames( final String clms , final boolean useNumber ) { 550 if( clms != null && clms.length() > 0 ) { 551 if( useDebug ) { System.out.println( "setNames=[" + clms + "]" ); } 552 553 colList = new ArrayList<>() ; // 初期化 554 nmsList = new ArrayList<>() ; // 初期化 555 556 final String[] nms = StringUtil.csv2Array( clms ); 557 final int adrs = useNumber ? 1 : 0 ; // useNumber =true の場合は、1件目(No)は読み飛ばす。 558 for( int i=0; i<nms.length; i++ ) { 559 // null か、長さゼロのカラム名は、設定されません。 560 final String nm = nms[i]; 561 if( nm != null && nm.length() > 0 ) { 562 // 2.0.0 (2024/01/12) PMD 7.0.0 UnnecessaryBoxing 563// colList.add( Integer.valueOf( i+adrs ) ); 564 colList.add( i+adrs ); 565 nmsList.add( nm ); 566 } 567 } 568 isNowName = true; // 名前設定中 569 useVals = false; // データ未設定 570 endRow(); // 行末処理実行。名前設定処理が走ります。 571 } 572 } 573 574 /** 575 * カラム名配列が、設定されたかどうか、返します。 576 * 577 * カラム名配列は、#NAME で始まるレコードか、#setNames( String,boolean )メソッドを 578 * 使用して、外部から指定します。 579 * カラム名配列が未設定の場合は、データもセットできないので、処理の最後の判定に使います。 580 * 581 * @og.rev 6.1.0.0 (2014/12/26) カラム名配列設定の対応 582 * 583 * @return カラム名配列が、設定されたかどうか(true:設定済み/false:未設定) 584 * @see #setNames( String,boolean ) 585 */ 586 public boolean isNameSet() { 587 // clmSize > 0 は、#NAME が設定済みという意味 588 return clmSize > 0; 589 } 590 591 /** 592 * 以降のデータを読み飛ばすかどうかを指定します(初期値:false)。 593 * 594 * データを読み込む途中で、それ以降のデータを読み込む必要がなくなった場合に、 595 * true に設定すると、以降のデータを今のシート/ファイルが終了するまで、スキップします。 596 * 例えば、読み込むべき必須カラムで判定する、nullBreakClm 機能を実現できます。 597 * 初期値は、false:読み飛ばさない です。 598 * 599 * @og.rev 6.1.0.0 (2014/12/26) シートブレイク処理追加 600 * 601 * @param flag 以降のデータを読み飛ばすかどうか [true:読み飛ばす/false:読み飛ばさない] 602 * @see #isSkip( int ) 603 */ 604 public void setReadBreak( final boolean flag ) { 605 isReadBreak = flag ; 606 } 607 608 /** 609 * 先頭データの読み飛ばし件数を設定します。 610 * 611 * ※ イベント処理実行前の初期化処理です。 612 * 613 * データの読み始めの行を指定します。 614 * シート/ファイルの先頭行が、0行としてカウントしますので、設定値は、読み飛ばす 615 * 件数になります。(1と指定すると、1件読み飛ばし、2件目から読み込みます。) 616 * 読み飛ばしは、コメント行などは、無視しますので、実際の行数分読み飛ばします。 617 * #NAME属性や、columns 属性は、読み飛ばし中でも処理対象行になります。 618 * 619 * @og.rev 6.1.0.0 (2014/12/26) Excel関係改善 620 * 621 * @param count 読み始めの初期値(0なら、読み飛ばしなし) 622 */ 623 public void setSkipRowCount( final int count ) { 624 skipRowCnt = count; 625 } 626 627 /** 628 * ここに指定されたカラム列に NULL/ゼロ文字列 が現れた時点でSheetの読み取りを中止します。 629 * 630 * これは、指定のカラムは必須という事を条件に、そのレコードだけを読み取る処理を行います。 631 * 複数Sheetの場合は、次のSheetを読みます。 632 * Sheetが存在しない場合(通常のテキスト等)では、読み取り処理の終了になります。 633 * 634 * @og.rev 6.2.0.0 (2015/02/27) 新規追加 635 * 636 * @param clm カラム列 637 */ 638 public void setNullBreakClm( final String clm ) { 639 nullBreakClm = clm; 640 } 641 642 /** 643 * ここに指定されたカラム列に NULL が現れたレコードは読み飛ばします。 644 * 645 * 例えば、更新対象カラムで、null の場合は、何もしない、などのケースで使用できます。 646 * 複数カラムの場合は、AND条件やOR条件などが、考えられるため、 647 * カラムを一つにまとめて、指定してください。 648 * 649 * @og.rev 6.2.3.0 (2015/05/01) 行読み飛ばし nullSkipClm追加 650 * 651 * @param clm カラム列 652 */ 653 public void setNullSkipClm( final String clm ) { 654 nullSkipClm = clm; 655 } 656 657 /** 658 * 固定値となるカラム名(CSV形式)と、固定値となるアドレス(行-列,行-列...) or(A1,B3...)を設定します。 659 * 660 * ※ イベント処理実行前の初期化処理です。 661 * 662 * アドレスは、EXCEL上の行-列か、EXCEL列のA1,B3 などの形式を、CSV形式で指定します。 663 * 行列は、EXCELオブジェクトに準拠するため、0から始まる整数です。 664 * 0-0 ⇒ A1 , 1-0 ⇒ A2 , 0-1 ⇒ B1 になります。 665 * これにより、シートの一か所に書かれている情報を、DBTableModel のカラムに固定値として 666 * 設定することができます。 667 * 例として、DB定義書で、テーブル名をシートの全レコードに設定したい場合などに使います。 668 * 669 * 5.7.6.3 (2014/05/23) より、 670 * ①EXCEL表記に準拠した、A1,A2,B1 の記述も処理できるように対応します。 671 * なお、A1,A2,B1 の記述は、必ず、英字1文字+数字 にしてください。(A~Zまで) 672 * EXCEL2007形式で列数が拡張されていますが、列数は制限しています。 673 * ②処理中のEXCELシート名をカラムに割り当てるために、"SHEET" という記号に対応します。 674 * 6.2.0.0 (2015/02/27) より、 675 * ③EXCEL以外では、"FILE","NAME","SUFIX" が使えます。(EXCEL時にも使えます。) 676 * NAME は、ファイル名から拡張子を取り除いた文字列になります。(AAA/BBB/CCC.xls → CCC) 677 * 例えば、sheetConstKeys="CLM,LANG,NAME" とし、sheetConstAdrs="0-0,A2,SHEET" とすると、 678 * NAMEカラムには、シート名を読み込むことができます。 679 * これは、内部処理の簡素化のためです。 680 * 681 * ちなみに、EXCELのセルに、シート名を表示させる場合の関数は、下記の様になります。 682 * =RIGHT(CELL("filename",$A$1),LEN(CELL("filename",$A$1))-FIND("]",CELL("filename",$A$1))) 683 * 684 * @og.rev 5.5.8.2 (2012/11/09) 新規追加 685 * @og.rev 5.7.6.3 (2014/05/23) EXCEL表記(A2,B1等)の対応と、特殊記号(SHEET)の対応 686 * @og.rev 6.1.0.0 (2014/12/26) カラム名配列設定の対応 687 * 688 * @param constKeys 固定値となるカラム名(CSV形式) 689 * @param constAdrs 固定値となるアドレス(行-列,行-列...) or(A1,B3...) 690 */ 691 public void setConstData( final String constKeys,final String constAdrs ) { 692 if( constKeys != null && !constKeys.isEmpty() && constAdrs != null && !constAdrs.isEmpty() ) { 693 cnstData = new ConstData( constKeys,constAdrs ); 694 // setNames( String , boolean ) と、このメソッドの呼び出し順に影響がないようにするため。 695 if( names != null ) { cnstData.setColumns( names ); } 696 } 697 } 698 699 /** 700 * デバッグ情報を出力するかどうか[true:する/false:しない]を指定します。 701 * 702 * EXCELなどを読み取る場合、シートマージで読み取ると、エラー時の行番号が、連番になるため、 703 * どのシートなのか、判らなくなります。 704 * そこで、どうしてもわからなくなった場合に備えて、デバッグ情報を出力できるようにします。 705 * 通常は使用しませんので、設定を無視します。 706 * 初期値は、false:デバッグ情報を出力しない です。 707 * 708 * @og.rev 6.2.0.0 (2015/02/27) デバッグ情報の出力するかどうか。新規追加 709 * 710 * @param useDebug デバッグ出力するか [true:する/false:しない] 711 */ 712 public void setDebug( final boolean useDebug ) { 713 this.useDebug = useDebug; 714 } 715 716 /** 717 * デバッグ情報を出力するかどうか[true:する/false:しない]を取得します。 718 * 719 * EXCELなどを読み取る場合、シートマージで読み取ると、エラー時の行番号が、連番になるため、 720 * どのシートなのか、判らなくなります。 721 * そこで、どうしてもわからなくなった場合に備えて、デバッグ情報を出力できるようにします。 722 * 723 * @og.rev 6.2.0.0 (2015/02/27) デバッグ情報の出力するかどうか。新規追加 724 * 725 * @return デバッグ出力 [true:する/false:しない] 726 */ 727 protected boolean isDebug() { 728 return useDebug ; 729 } 730 731 /** 732 * EXCELファイルの所定の位置から、固定値を取り出す処理を管理します。 733 * 734 * この固定値の取出しは、内部処理に、非常に依存しているため、今は、 735 * TableModelHelper クラスに含めていますが、将来的には、分ける予定です。 736 * 737 * @og.rev 6.1.0.0 (2014/12/26) Excel関係改善 738 * @og.rev 6.2.0.0 (2015/02/27) 特殊記号(FILE,NAME,SUFIX)追加 739 * 740 * @version 6.0 741 * @author Kazuhiko Hasegawa 742 * @since JDK7.0, 743 */ 744 private static final class ConstData { 745 /** 内部情報のクリア方法の指定 {@value} */ 746 public static final int END_FILE = 1 ; 747 /** 内部情報のクリア方法の指定 {@value} */ 748 public static final int END_SHEET = 2 ; 749 750 // 6.2.0.0 (2015/02/27) 特殊記号処理 追加 (SHEET,FILE,NAME,SUFIX) 751 private static final String KEYS = ",SHEET,FILE,NAME,SUFIX,"; 752 753 // ①cnstMap は、cnstKey をキーに、拾ってきた値を持っています。(Sheet毎のトランザクション) 754 private final Map<String,String> cnstMap = new HashMap<>(); // 6.1.0.0 (2014/12/26) Mapで管理 755 // ②rowcolMap は、rowcol をキーに、アドレスを持っています。 756 private final Map<String,Integer> rowcolMap = new HashMap<>(); // 6.1.0.0 (2014/12/26) Mapで管理 757 // ③valsMap は、アドレス をキーに、拾ってきた値を持っています。(Sheet毎のトランザクション) 758 private final Map<Integer,String> valsMap = new HashMap<>(); // 6.1.0.0 (2014/12/26) Mapで管理 759 760 private final int maxRow ; // 6.4.9.1 (2016/08/05) final化。最大値持っておき、判定処理を早める。 761 762 // ※ rowcolMap を使用する為、必ず #setColumns( String... ) の実行後に行います。 763 private boolean isNameSet ; 764 private File tmpFile ; 765 private String tmpShtNm ; 766 767 /** 768 * 固定値となるカラム名(CSV形式)と、固定値となるアドレス(行-列,行-列...) or(A1,B3...)を設定します。 769 * 770 * アドレスは、EXCEL上の行-列か、EXCEL列のA1,B3 などの形式を、CSV形式で指定します。 771 * 行列は、EXCELオブジェクトに準拠するため、0から始まる整数です。 772 * 0-0 ⇒ A1 , 1-0 ⇒ A2 , 0-1 ⇒ B1 になります。 773 * これにより、シートの一か所に書かれている情報を、DBTableModel のカラムに固定値として 774 * 設定することができます。 775 * 例として、DB定義書で、テーブル名をシートの全レコードに設定したい場合などに使います。 776 * 777 * 5.7.6.3 (2014/05/23) より、 778 * ①EXCEL表記に準拠した、A1,A2,B1 の記述も処理できるように対応します。 779 * なお、A1,A2,B1 の記述は、必ず、英字1文字+数字 にしてください。(A~Zまで) 780 * EXCEL2007形式で列数が拡張されていますが、列数は制限しています。 781 * ②処理中のEXCELシート名をカラムに割り当てるために、"SHEET" という記号に対応します。 782 * 6.2.0.0 (2015/02/27) より、 783 * ③EXCEL以外では、"FILE","NAME","SUFIX" が使えます。 784 * NAME は、ファイル名から拡張子を取り除いた文字列になります。(AAA/BBB/CCC.xls → CCC) 785 * 例えば、sheetConstKeys="CLM,LANG,SHT" とし、sheetConstAdrs="0-0,A2,SHEET" とすると、 786 * SHTカラムには、シート名を読み込むことができます。 787 * これは、内部処理の簡素化のためです。 788 * 789 * ちなみに、EXCELのセルに、シート名を表示させる場合の関数は、下記の様になります。 790 * =RIGHT(CELL("filename",$A$1),LEN(CELL("filename",$A$1))-FIND("]",CELL("filename",$A$1))) 791 * 792 * @og.rev 5.5.8.2 (2012/11/09) 新規追加 793 * @og.rev 5.7.6.3 (2014/05/23) EXCEL表記(A2,B1等)の対応と、特殊記号(SHEET)の対応 794 * @og.rev 6.1.0.0 (2014/12/26) カラム名配列設定の対応 795 * @og.rev 6.2.0.0 (2015/02/27) 特殊記号(FILE,NAME,SUFIX)の追加対応 796 * @og.rev 6.4.9.1 (2016/08/05) maxRowをfinal化します。 797 * 798 * @param constKeys 固定値となるカラム名(CSV形式) 799 * @param constAdrs 固定値となるアドレス(行-列,行-列...) or(A1,B3...) 800 */ 801 /* default */ ConstData( final String constKeys,final String constAdrs ) { 802 final String[] cnstKeys = constKeys.split( "," ); 803 // 8.5.5.1 (2024/02/29) PMD 7.0.0 LocalVariableNamingConventions 804// final String[] row_col = constAdrs.split( "," ); 805 final String[] rowCols = constAdrs.split( "," ); 806 807// if( cnstKeys.length != row_col.length ) { 808 if( cnstKeys.length != rowCols.length ) { 809 final String errMsg = "キーに対するアドレスの個数が不一致です。Keys=[" + constKeys + "]" 810 + " , Adrs=[" + constAdrs + "]" ; 811 throw new OgRuntimeException( errMsg ); 812 } 813 814 int tmpRow = -1; // 6.4.9.1 (2016/08/05) 815 // 初期の カラムとアドレス(キーワード)の関連付け 816 for( int j=0; j<cnstKeys.length; j++ ) { 817 final String cnstKey = cnstKeys[j].trim(); // 前後の不要なスペースを削除 818 if( !cnstKey.isEmpty() ) { 819// String rowcol = row_col[j].trim(); // 前後の不要なスペースを削除 820 String rowcol = rowCols[j].trim(); // 前後の不要なスペースを削除 821 if( !rowcol.isEmpty() ) { 822 // 5.7.6.3 (2014/05/23) EXCEL表記(A2,B1等)の対応と、特殊記号(SHEET)の対応 823 final int sep = rowcol.indexOf( '-' ); 824 if( sep > 0 ) { 825 final int row = Integer.parseInt( rowcol.substring( 0,sep ) ); 826 // int col = Integer.parseInt( rowcol.substring( sep+1 ) ); 827 if( tmpRow < row ) { tmpRow = row; } // 6.4.9.1 (2016/08/05) 828 // rowcol = String.valueOf( (char)('A' + col) ) + String.valueOf( row + 1 ) ; // row-col 形式なので、不要 829 } 830 // 6.2.0.0 (2015/02/27) 特殊記号(SHEET,FILE,NAME,SUFIX)の追加対応 831 else if( !KEYS.contains( ',' + rowcol + ',' ) ) { 832 final int row = Integer.parseInt( rowcol.substring( 1 ) ) -1; // C6 の場合、rowは、6-1=5 833 final int col = rowcol.charAt(0) - 'A' ; // C6 の場合、colは、'C'-'A'=2 834 if( tmpRow < row ) { tmpRow = row; } // 6.4.9.1 (2016/08/05) 835 rowcol = row + "-" + col ; 836 } 837 cnstMap.put( cnstKey , rowcol ); // 6.1.0.0 (2014/12/26) cnstMap に行列情報を設定する 838 } 839 } 840 } 841 maxRow = tmpRow; 842 } 843 844 /** 845 * カラム名配列を元に、固定値カラムのアドレスを求めます。 846 * カラム名配列は、順番に、指定する必要があります。 847 * 848 * @og.rev 6.1.0.0 (2014/12/26) カラム名配列設定の対応 849 * 850 * @param names カラム列配列(可変長引数) 851 */ 852 /* default */ void setColumns( final String... names ) { 853 // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。 854 if( names != null && names.length > 0 ) { 855 // 5.5.8.2 (2012/11/09) 固定値取得用の cnstIndx の設定を行う。 856 for( int i=0; i<names.length; i++ ) { 857 final String rowcol = cnstMap.get( names[i] ); // cnstKey があれば、rowcol が取得できるはず 858 if( rowcol != null ) { 859 // 2.0.0 (2024/01/12) PMD 7.0.0 UnnecessaryBoxing 860// rowcolMap.put( rowcol , Integer.valueOf( i ) ); 861 rowcolMap.put( rowcol ,i ); 862 } 863 } 864 isNameSet = true; // 名前設定がされないと、FILEやSHEET キーワードが使えない。 865 866 if( tmpFile != null ) { putConstFile( tmpFile ); } 867 if( tmpShtNm != null ) { putConstSheet( tmpShtNm ); } 868 } 869 } 870 871 /** 872 * 読み取り時に、rowNo,colNo にあるセルの値を、固定値となるカラム名に関連付けます。 873 * 874 * イベントモデルでは、固定値の指定アドレス(rowNo,colNo)をピンポイントで取得することが 875 * できないため、イベント発生毎に、チェックする必要があります。 876 * そのため、固定値を使用すると、処理速度が低下します。 877 * 878 * @og.rev 6.1.0.0 (2014/12/26) Excel関係改善 879 * 880 * @param val 文字列値(null またはゼロ文字列は、不可) 881 * @param rowNo 行番号(0~) 882 * @param colNo 列番号(0~) 883 */ 884 /* default */ void putConstValue( final String val,final int rowNo,final int colNo ) { 885 if( rowNo <= maxRow ) { 886 final String rowcol = rowNo + "-" + colNo ; 887 final Integer adrs = rowcolMap.get( rowcol ); 888 if( adrs != null ) { 889 valsMap.put( adrs,val ); 890 } 891 } 892 } 893 894 /** 895 * ファイル系特殊記号(FILE,NAME,SUFIX)を指定します。 896 * 897 * ../AAA/BBB/CCC.XLS というファイルオブジェクトに対して、 898 * FILE : CCC.XLS ファイル名 899 * NAME : CCC 拡張子なしのファイル名 900 * SUFIX : xls ピリオド無しの拡張子(小文字に統一) 901 * 902 * これは、新しいファイルの読み取り開始時に、設定します。 903 * 904 * ※ rowcolMap を使用する為、必ず #setColumns( String... ) の実行後に行います。 905 * 906 * @og.rev 6.2.0.0 (2015/02/27) 新規作成 907 * 908 * @param filNm 指定ファイル 909 */ 910 /* default */ void putConstFile( final File filNm ) { 911 if( filNm != null ) { 912 tmpFile = filNm; // 名前設定がされるまで、一時保管する。(順番があるので呼ばれればセットしておく) 913 if( isNameSet ) { // 名前設定がされないと、FILEやSHEET キーワードが使えない。 914 final FileInfo info = new FileInfo( filNm ); 915 916 for( final String key : FileInfo.KEY_LIST ) { 917 final Integer adrs = rowcolMap.get( key ); 918 if( adrs != null ) { 919 final String val = info.getValue( key ); 920 if( val != null ) { 921 valsMap.put( adrs,val ); 922 } 923 } 924 } 925 } 926 } 927 } 928 929 /** 930 * シート名を外部から指定します。 931 * アドレス指定の特殊系として、"SHEET" 文字列を指定できます。 932 * これは、新しいシートの読み取り開始時に、設定します。 933 * 934 * ※ rowcolMap を使用する為、必ず #setColumns( String... ) の実行後に行います。 935 * 936 * @og.rev 6.1.0.0 (2014/12/26) Excel関係改善 937 * 938 * @param shtNm シート名 939 */ 940 /* default */ void putConstSheet( final String shtNm ) { 941 if( shtNm != null ) { 942 tmpShtNm = shtNm; // 名前設定がされるまで、一時保管する。 943 if( isNameSet ) { // 名前設定がされないと、FILEやSHEET キーワードが使えない。 944 final Integer adrs = rowcolMap.get( "SHEET" ); 945 if( adrs != null ) { 946 valsMap.put( adrs,shtNm ); 947 } 948 } 949 } 950 } 951 952 /** 953 * 内部の valsMap を初期化します。 954 * 固定値の読み取りは、シートごとに行います。 955 * 新しいシートにデータが設定されていない場合、前のシートの値が残ります。 956 * ここでは、シート呼出しごとに、毎回クリアします。 957 * 引数に応じて、クリアする範囲を限定します。 958 * END_FILE 時は、すべてクリア。END_SHEET 時は、ファイル情報は残します。 959 * 960 * @og.rev 6.1.0.0 (2014/12/26) Excel関係改善 961 * 962 * @param type 内部情報のクリア方法の指定(END_FILE or END_SHEET) 963 */ 964 /* default */ void clearValsMap( final int type ) { 965 valsMap.clear(); 966 if( type == END_SHEET ) { putConstFile( tmpFile ); } // 全削除後にファイル情報を再設定 967 } 968 969 /** 970 * 値配列のデータに、固定値を設定します。 971 * 引数の文字列配列に、固定値を設定しますので、配列オブジェクト自体を更新します。 972 * 973 * @og.rev 6.1.0.0 (2014/12/26) Excel関係改善 974 * @og.rev 6.4.3.4 (2016/03/11) forループを、forEach メソッドに置き換えます。 975 * 976 * @param vals 文字列値の1行分の配列 977 * @return 固定値を設定された1行分の文字列配列 978 */ 979 /* default */ String[] getConstVals( final String[] vals ) { 980 if( vals != null && vals.length > 0 ) { 981 // 6.4.3.4 (2016/03/11) forループを、forEach メソッドに置き換えます。 982 valsMap.forEach( (k,v) -> { 983 if( k < vals.length ) { vals[k] = v; } 984 } ); 985 } 986 return vals ; 987 } 988 } 989}