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     */
016    package org.opengion.hayabusa.report;
017    
018    import org.opengion.hayabusa.common.HybsSystem;
019    import org.opengion.hayabusa.common.HybsSystemException;
020    import org.opengion.fukurou.util.LogWriter;
021    
022    import org.opengion.fukurou.util.QrcodeImage;
023    import org.opengion.fukurou.util.ReplaceString;
024    
025    import java.io.IOException;
026    import java.util.Map ;
027    import java.util.HashMap ;
028    import java.util.regex.Pattern;
029    import java.util.regex.Matcher ;
030    
031    /**
032     * DBTableReport インターフェース を実?たHTMLをパースするクラスです?
033     * AbstractDBTableReport を継承して?す?で?writeReport() のみオーバ?ライドして??
034     * 固定長?ファイルの出力機?を実現して?す?
035     *
036     * @og.group 帳票シス?
037     *
038     * @version  4.0
039     * @author   Kazuhiko Hasegawa
040     * @since    JDK5.0,
041     */
042    public class DBTableReport_HTML extends AbstractDBTableReport {
043            private static final String TR_IN        = "<tr" ;
044            private static final String TR_OUT       = "</tr>" ;
045            private static final String TD_OUT       = "</td>" ;                      // 3.5.5.9 (2004/06/07)
046            private static final String PAGE_BREAK   = "page-break" ;
047            private static final String PAGE_END_CUT = "PAGE_END_CUT" ;             // 3.6.0.0 (2004/09/17)
048            private static final String END_TAG      = "</table></body></html>";
049            private static final String CUT_TAG1     = "<span";
050            private static final String CUT_TAG2     = "</span>";
051            private static final String SPACE_ST     = "<span style=\"mso-spacerun: yes\">";  // 3.6.0.0 (2004/09/17)
052            private static final String SPACE        = "&nbsp;";                                                                // 3.6.0.0 (2004/09/17)
053            private static final String SPACE_ED     = " </span>";                                                    // 3.6.0.0 (2004/09/17)
054            private static final String FRAMESET     = "Excel Workbook Frameset" ;
055    
056            private static final String CR         = System.getProperty("line.separator");
057    
058            // <td xxx="yyy">zzzz</td> 形式とマッチし?zzzz< 部?前方参?します?
059            private static final Pattern PTN1 = Pattern.compile("<td[^>]*(>.*?<)/td>");
060            // >aaaa<span bb="cc">dddd</span>eeee< 形式に?文字以上?スペ?スを含?ータと
061            // マッチし、aaaa,dddd,eeee を前方参?します?
062            private static final Pattern PTN2 = Pattern.compile("[^>]*>([^<]*?  ++[^<]*?)<");
063            // aa   bb    cc    形式とマッチし、各連続スペ?ス部?前方参?します?
064            private static final Pattern PTN3 = Pattern.compile("(  +)");
065    
066            private boolean  fileEnd        = false;                // ファイルの読み取り制御
067    
068            // 3.6.1.0 (2005/01/05) QRコー??次?ーコー?用の出力ファイル管?
069            private Map<String,String> qrFileMap = null;
070            // <v:shape ??? alt="{@QRCODE.XXXX}" ???>
071            //   <v:imagedata src="yyy" ???>???</v:shape>形式とマッチし?
072            // xxx 部?、yyy 部?前方参?します?
073            private static final Pattern IMGPTN1 = Pattern.compile("<v:shape [^>]*alt=\"\\{@QRCODE.([^\\}]*)\\}\"[^>]*>[^<]*<v:imagedata [^>]*src=\"([^\"]*)\"[^>]*>");
074            // <img ??? src="yyy" ??? alt="{@QRCODE.XXXX}" ??? > 形式とマッチし?
075            // yyy 部?、xxx 部?前方参?します?
076            private static final Pattern IMGPTN2 = Pattern.compile("<img [^>]*src=\"([^\"]*)\"[^>]*alt=\"\\{@QRCODE.([^\\}]*)\\}\"[^>]*>");
077    
078            // 4.0.0 (2007/06/08) pageEndCut = true  時? LINE_COPY 機?の実?
079            private static final String LINE_COPY = "LINE_COPY" ;           // 4.0.0 (2007/06/08)
080            private String lineCopy = null;
081    
082            /**
083             * 入力文字? を読み取って、?力します?
084             * tr タグを目印に??trタグ?ずつ取り出します?
085             * 読み取りを終?る?合?、null を返します?
086             * ?ブクラスで実?てください?
087             *
088             * @og.rev 3.0.0.1 (2003/02/14) ?もValueセ?して???に次ペ?ジ要求があった?合?、フォーマットがおかしい
089             * @og.rev 3.6.0.0 (2004/09/24) フォーマットエラーの判?formatErr)を?親クラスに移動します?
090             *
091             * @return      出力文字?
092             */
093            @Override
094            protected String readLine() {
095                    if( fileEnd ) { return null; }
096    
097                    // pageEndCut 時に、データがオーバ?して??のみ、lineCopy があれ?返す?
098                    if( pageEndCut && !rowOver && lineCopy != null ) {
099                            lineCopyCnt ++ ;        // 雛形は、_0 のみが毎回返される為の、加?
100                            return lineCopy ;
101                    }
102    
103                    final StringBuilder buf ;
104                    try {
105                            String line = reader.readLine();
106                            if( line == null ) {
107                                    if( rowOver ) {
108                                            return null;
109                                    }
110                                    else {
111                                            initReader();
112                                            initWriter();
113                                            line = reader.readLine();
114                                            if( line == null ) { return null; }
115                                    }
116                            }
117                            if( line.indexOf( FRAMESET )  >= 0 ) {
118                                    String errMsg = "HTML ファイルエラー :" + line + HybsSystem.CR
119                                                                    + "Excelファイル形式がフレー?なって?す?(?シートには未対?" ;
120                                    throw new HybsSystemException( errMsg );
121                            }
122                            if( line.indexOf( TR_IN )  >= 0 ) {
123                                    buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
124                                    buf.append( line );
125                                    int trLebel = 1;                        // 行を表?<tr> のレベル
126                                    while( trLebel != 0 ) {
127                                            line = reader.readLine();
128                                            // 4.0.0 (2005/08/31) null 参?はずし対?
129                                            if( line != null ) {
130                                                    if( line.indexOf( TR_IN  ) >= 0 ) { trLebel++ ; }
131                                                    if( line.indexOf( TR_OUT ) >= 0 ) { trLebel-- ; }
132                                                    buf.append( CR ).append( line );
133                                            }
134                                            else {
135                                                    String errMsg = "HTML ファイルエラー :" + buf.toString() + HybsSystem.CR
136                                                                            + "?TR)の整合?が取れる前に、ファイルが終?ました? ;
137                                                    throw new HybsSystemException( errMsg );
138                                            }
139                                    }
140                            }
141                            else {
142                                    return line;
143                            }
144                    } catch(IOException ex) {
145                            String errMsg = "HTML ファイル 読取時にエラーが発生しました? + reader;
146                            throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び?更
147                    }
148    
149                    String rtnLine = buf.toString() ;
150    
151                    // lineCopy ??の取得?
152                    if( pageEndCut && !rowOver ) {
153                            // LINE_COPY は削除します?で、表示上見えるよ?しておいてください?
154                            int adrs = rtnLine.indexOf( LINE_COPY );
155                            if( adrs >= 0 ) {
156                                    lineCopy = rtnLine.substring( 0,adrs )
157                                                            + rtnLine.substring( adrs + LINE_COPY.length() ) ;
158                                    rtnLine = lineCopy ;
159                            }
160                    }
161    
162                    return rtnLine ;
163            }
164    
165            /**
166             * 入力文字? を加工して、?力します?
167             * {&#064;XXXX} をテーブルモ?より読み取り、?をセ?します?
168             * ?ブクラスで実?てください?
169             *
170             * @og.rev 3.0.0.1 (2003/02/14) ?もValueセ?して???に次ペ?ジ要求があった?合?、フォーマットがおかしい
171             * @og.rev 3.0.0.2 (2003/02/20) {&#064;XXXX}?が、EXCELに表示しきれな??合に挿入されるタグの削除処??変更?
172             * @og.rev 3.5.0.0 (2003/09/17) {&#064;XXXX}??スペ?スを?&amp;nbsp;と置き換えます?
173             * @og.rev 3.5.0.0 (2003/09/17) {&#064;XXXX}?がアンバランス時にHybsSystemExceptionを発行する?
174             * @og.rev 3.5.5.9 (2004/06/07) {&#064;XXXX}の連続???アドレス計算方法が?違って?したので修正します?
175             * @og.rev 3.6.0.0 (2004/09/17) pageEndCut ?true の場合?、PAGE_END_CUT ??のある行を削除します?
176             * @og.rev 3.6.0.0 (2004/09/24) フォーマットエラーの判?formatErr)を?親クラスに移動します?
177             * @og.rev 3.6.1.0 (2005/01/05) QRコー??次?ーコー?の機?追?
178             * @og.rev 3.8.1.2 (2005/12/19) PAGE_END_CUTの判定にdataOver フラグを使用?
179             *
180             * @param       inLine  入力文字?
181             *
182             * @return      出力文字?
183             */
184            @Override
185            protected String changeData( final String inLine ) {
186                    // rowOver で、かつ ペ?ジブレークか?ージエンドカ?の場合?処???
187                    if( rowOver && ( inLine.indexOf( PAGE_BREAK ) >= 0 ) ) {
188                            fileEnd = true;
189                            return END_TAG;
190                    }
191    
192                    String chLine = changeHeaderFooterData( inLine ) ;
193    
194                    // 3.6.1.0 (2005/01/05) QRコー??次?ーコー?の機?追?
195                    if( chLine.indexOf( "{@QRCODE." ) >= 0 ) {
196                            chLine = qrcodeReplace( chLine );
197                    }
198    
199                    int st = chLine.indexOf( "{@" );
200                    // 3.8.1.2 (2005/12/19) {@XXXX}の存在しな?も PAGE_END_CUTの判定を行う?
201    
202                    StringBuilder buf = new StringBuilder( chLine );
203    
204                    boolean spaceInFlag = false;    // {@XXXX} 変数の??タにスペ?スを含?ど?チェ?
205                    while( st >= 0 ) {
206                            int end = buf.indexOf( "}",st+2 );
207    
208                            // EXCELに表示しきれな?字?、CUT_TAG1,CUT_TAG2 が挿入されてしま??
209                            // 削除する?がある?
210                            int cutSt1 = buf.indexOf( CUT_TAG1,st+2 );
211                            if( cutSt1 >= 0 && cutSt1 < end ) {
212                                    int cutEnd1 = buf.indexOf( ">",cutSt1 );
213    
214                                    int cutSt2 = buf.indexOf( CUT_TAG2,end );
215                                    if( cutSt2 >= 0 ) {
216                                            buf.delete( cutSt2, cutSt2 + CUT_TAG2.length() );
217                                    }
218                                    buf.delete( cutSt1, cutEnd1+1 );
219                                    // 途中をカ?した為、も??計算しなおし?
220                                    end = buf.indexOf( "}",st+2 );          // 3.5.5.9 (2004/06/07)
221                            }
222    
223                            // 3.5.5.9 (2004/06/07)
224                            // 関数等を使用すると、{@XXXX} ??を直接?した??タが?力される?
225                            // こ??されたデータは、HTML 表示に使用されるだけ?ため、削除します?
226                            // 削除方法?、{@XXX</td> を想定して?為?{@ から </td> の間です?
227                            int td_out = buf.indexOf( TD_OUT,st+2 );
228                            if( td_out >= 0 && td_out < end ) {
229                                    buf.delete( st, td_out );
230                                    // {@XXXX} パラメータが消えた?で、次の計算を行います?
231                                    st = buf.indexOf( "{@",st+4 );          // 3.5.5.9 (2004/06/07)
232                                    continue ;
233                            }
234    
235                            // 途中をカ?した為、も??計算しなおし?
236                            // フォーマットがおかしい場合?処?
237                            if( end < 0 ) {
238                                    String errMsg = "こ??プレートファイルの {@XXXX} が?フォーマットエラーです?"
239                                                                    + HybsSystem.CR
240                                                                    + chLine.substring( st ) ;
241                                    throw new HybsSystemException( errMsg );
242                            }
243    
244                            String key = buf.substring( st+2,end );
245    
246                            String val = getValue( key );
247                            if( val.indexOf( "  " ) >= 0 ) { spaceInFlag = true; }
248    
249                            // {@XXXX} ?実際の値と置き換える?
250                            buf.replace( st,end+1,val );
251    
252                            // {@ の 存在チェ??
253                            st = buf.indexOf( "{@",st-1 );          // 3.5.5.9 (2004/06/07)
254                    }
255    
256                    // 3.6.0.0 (2004/09/17) pageEndCut ?true の場合?、PAGE_END_CUT ??のある行を削除します?
257                    // ここで判定する?は、PAGE_END_CUT ?そのも?が??されて?可能性があるため?
258                    String rtn = buf.toString();
259                    if( dataOver && pageEndCut ) {          // 3.8.1.2 (2005/12/19)
260                            String temp = rtn.replaceAll( CUT_TAG1 + "[^>]*>" ,"" );
261                            if( temp.indexOf( PAGE_END_CUT ) >= 0 ) {
262                                    rtn = "" ;
263                            }
264                    }
265                    else {
266                            // 3.6.0.0 (2004/09/17) スペ?ス置き換え??td XXX>YYY</td> の YYYの?のみとする?
267                            if( spaceInFlag ) {
268                                    rtn = spaceReplace( rtn ) ;
269                            }
270                    }
271                    return rtn ;
272            }
273    
274            /**
275             * ?殊???
276             * EXCEL の ヘッ??/フッター部??、\{\&#064;XXXX\} と、エスケープ文字が付加され?
277             * ので、この??を見つけたら?{&#064;XXXX} に、戻して処?るよ?する?
278             *
279             * @param       inLine  入力文字?
280             *
281             * @return      出力文字?
282             */
283            private String changeHeaderFooterData( final String inLine ) {
284                    int st = inLine.indexOf( "\\{\\@" );
285                    if( st < 0 ) { return inLine; }
286    
287                    StringBuilder buf = new StringBuilder( inLine );
288    
289                    while( st >= 0 ) {
290                            buf.deleteCharAt( st );                 // 初めの '\'
291                            buf.deleteCharAt( st+1 );               // ?文字削除して?為?1 番目を削除
292                            int end = buf.indexOf( "\\}",st+2 );
293                            // フォーマットがおかしい場合?処?
294                            if( end < 0 ) {
295                                    String errMsg = "こ??プレート? HeaderFooter 部?? {@XXXX} が?書式エラーです?"
296                                                                    + HybsSystem.CR
297                                                                    + inLine ;
298                                    throw new HybsSystemException( errMsg );
299                            }
300                            buf.deleteCharAt( end );                // 初めの '\'
301                            st = buf.indexOf( "\\{\\@",end + 1 );
302                    }
303                    return buf.toString();
304            }
305    
306            /**
307             * 入力文字? を読み取って、?力します?
308             * ?ブクラスで実?てください?
309             *
310             * @param line 入力文字?
311             */
312            @Override
313            protected void println( final String line ) {
314                    writer.println( line );
315            }
316    
317            /**
318             * {&#064;XXXX}?変換後?スペ?スを?&amp;nbsp;と置き換えます?
319             *
320             * ただし?式などを使用すると、td タグの属???に{&#064;XXXX}?が含ま?
321             * これに、EXCELのスペ?スである?lt;span style="mso-spacerun:
322             * yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
323             * と置き換えると、属?リスト中のタグと?入れ子状態が発生する為?
324             * これは、置き換えません?
325             * &lt;td XXX&gt;YYY&lt;/td&gt; の YYYの? を置き換えることになります?
326             *
327             * ここでは?去の互換性を最大限確保する為に、特殊な方法で、??ます?
328             * 前後?スペ?スを取り除???で、かつ?つ以上?連続したスペ?ス?
329             * 存在する場合?み、trim して??続スペ?スを?&amp;nbsp;と置き換えます?
330             * ??間に連続スペ?スがな??合?、前後?スペ?スも削除せずに?
331             * ????をそのまま返します?
332             * 前後?スペ?スを変換してしま?、数字型の場合に、EXCELでの計算式がエラーになります?
333             *
334             * @og.rev 3.5.0.0 (2003/09/17) 新規追?
335             * @og.rev 3.5.5.0 (2004/03/12) 連続スペ?スの処?EXCELの方式に合わせる
336             * @og.rev 3.6.0.0 (2004/09/17) スペ?ス置き換え??td XXX>YYY</td> の YYYの?のみとする?
337             * @og.rev 3.6.1.0 (2005/01/05) 置換ロジ?修正(ReplaceString クラスを使用)
338             *
339             * @param       target ????
340             *
341             * @return      置換えた文字?
342             */
343            private String spaceReplace( final String target ) {
344                    ReplaceString repData = new ReplaceString();
345    
346                    Matcher match1 = PTN1.matcher( target ) ;
347                    while( match1.find() ) {
348                            int st1 = match1.start(1);
349                            String grp1 = match1.group(1);
350                            Matcher match2 = PTN2.matcher( grp1 ) ;
351                            while( match2.find() ) {
352                                    int st2 = match2.start(1);
353                                    String grp2 = match2.group(1);
354                                    Matcher match3 = PTN3.matcher( grp2 ) ;
355                                    while( match3.find() ) {
356    
357                                            int st = st1 + st2 + match3.start(1);
358                                            int ed = st1 + st2 + match3.end(1);
359    
360                                            repData.add( st,ed,makeSpace( ed-st ) );
361                                    }
362                            }
363                    }
364    
365                    String rtn = repData.replaceAll( target );
366    
367                    return rtn ;
368            }
369    
370            /**
371             * ??個数のスペ?ス?を表す?EXCEL の記号を作?します?
372             *
373             * EXCELでは、スペ?ス??以上を?lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;
374             * 形式に置き換えます?これは、EXCELがHTML変換する時?ルールです?
375             *
376             * ここでは、スペ?スの個数-1 の &amp;nbsp; を持つ、上記???を作?します?
377             * ???は、本物のスペ?ス記号を割り当てます?
378             *
379             * @og.rev 3.6.0.0 (2004/09/17) 新規追?
380             *
381             * @param       cnt スペ?スの個数
382             *
383             * @return      置換えた文字?
384             */
385            private String makeSpace( final int cnt ) {
386                    StringBuilder buf = new StringBuilder( 40 + cnt * 6 );
387                    buf.append( SPACE_ST );
388                    for( int i=1; i<cnt; i++ ) {
389                            buf.append( SPACE );
390                    }
391                    buf.append( SPACE_ED );
392    
393                    return buf.toString();
394            }
395    
396            /**
397             * {&#064;QRCODE.XXXX} を含???の alt 属??src 属?にセ?します?
398             *
399             * QRコード?画像を入れ替えるため、alt属?に設定してある キー??を?に?
400             * ?次?ーコード画像を作?し?そ?ファイル名を、src 属?に設定することで?
401             * 動的に画像ファイルのリンクを作?します?
402             * 現在のEXCELでは、バージョンによって?種類?画像表示方法が存在するようで?
403             * ?画像に付き??の変更が?です?こ???は、変換方法が異なる為?
404             * 全く別の処?行う?があります?
405             *
406             * <v:shape ??? alt="{&#064;QRCODE.XXXX}" ???>
407             *   <v:imagedata src="yyy" ???>???</v:shape>形式とマッチし?
408             * xxx 部?、yyy 部?前方参?します?
409             *
410             * <img ??? src="yyy" ??? alt="{&#064;QRCODE.XXXX}" ??? > 形式とマッチし?
411             * yyy 部?、xxx 部?前方参?します?
412             *
413             * 画像?エンコード?、alt属?に設定した?{&#064;QRCODE.XXXX} ??の
414             * XXXX 部??カラ?ータ(通常、{&#064;XXXX} で取得できる値)を使用します?
415             * ??タが存在しな??合?、src="yyy" 部を削除することで対応します?
416             * なお?後続???関係で、alt="{&#064;QRCODE.XXXX}" ??は、削除します?
417             *
418             * @og.rev 3.6.1.0 (2005/01/05) 新規追?
419             *
420             * @param       target ????
421             *
422             * @return      置換えた文字?
423             */
424            private String qrcodeReplace( final String target ) {
425                    ReplaceString repData = new ReplaceString();
426    
427                    Matcher match1 = IMGPTN1.matcher( target ) ;
428                    while( match1.find() ) {
429                            String altV = match1.group(1);
430    
431                            int stAlt = match1.start(1) - 9 ;       // {@QRCODE. まで遡?
432                            int edAlt = match1.end(1)   + 1 ;       // } を含める
433                            repData.add( stAlt,edAlt,"" );          // {@QRCODE.XXXX} の部?除
434    
435                            int st = match1.start(2);
436                            int ed = match1.end(2);
437    
438                            String msg = getValue( altV );  // QRコード変換する??の取?
439                            if( msg != null && msg.length() > 0 ) {
440                                    String newStr = makeQrImage( altV,msg );        // 画像ファイルのファイル?
441                                    repData.add( st,ed,newStr );
442                            }
443                            else {
444                                    repData.add( st-5,ed+1,"" );            // src="yyy" 部??み削除
445                            }
446                    }
447    
448                    Matcher match2 = IMGPTN2.matcher( target ) ;
449                    while( match2.find() ) {
450                            int st = match2.start(1);
451                            int ed = match2.end(1);
452    
453                            String altV = match2.group(2);
454                            int stAlt = match2.start(2) - 9 ;       // {@QRCODE. まで遡?
455                            int edAlt = match2.end(2)   + 1 ;       // } を含める
456                            repData.add( stAlt,edAlt,"" );          // {@QRCODE.XXXX} の部?除
457    
458                            String msg = getValue( altV );  // QRコード変換する??の取?
459                            if( msg != null && msg.length() > 0 ) {
460                                    String newStr = makeQrImage( altV,msg );        // 画像ファイルのファイル?
461                                    repData.add( st,ed,newStr );
462                            }
463                            else {
464                                    repData.add( st-5,ed+1,"" );            // src="yyy" 部??み削除
465                            }
466                    }
467    
468                    String rtn = repData.replaceAll( target ) ;
469    
470                    return rtn ;
471            }
472    
473            /**
474             * ??カラ?と、QRコード変換する??より、画像を作?します?
475             *
476             * 返り値は、作?した画像ファイルのファイル名です?
477             * これは、データが存在しな??合に、src="" を返す?があるため?
478             * (でな?、画像へのリンクが表示されてしま??)
479             * src="./帳票ID.files/image00x.png" と?画像ファイルのアドレス部?
480             *  {&#064;QRCODE_カラ?} 形式に変更しておく?があります?
481             *
482             * @og.rev 3.6.1.0 (2005/01/05) 新規追?
483             *
484             * @param       key カラ?
485             * @param       msg QRコード変換する??
486             *
487             * @return      画像ファイルのファイル?
488             */
489            private String makeQrImage( final String key, final String msg ) {
490                    if( msg == null || msg.length() == 0 ) { return "" ; }
491    
492                    String realClmName = null ;
493                    int sp = key.lastIndexOf( '_' );
494                    if( sp >= 0 ) {
495                            try {
496                                    int row = Integer.parseInt( key.substring( sp+1 ) );
497                                    int realRow = getRealRow( row );
498                                    realClmName = key.substring( 0,sp ) + "_" + realRow ;
499                            }
500                            catch (NumberFormatException e) {       // 4.0.0 (2005/01/31)
501                                    String errMsg = "警告:QRCODE名?ヘッ??に'_'カラ?が使用";
502                                    LogWriter.log( errMsg );
503                            }
504                    }
505                    else {
506                            realClmName = key ;
507                    }
508    
509                    if( qrFileMap == null ) { qrFileMap = new HashMap<String,String>(); }
510                    if( qrFileMap.containsKey( realClmName ) ) {    // Map にすでに存在して??
511                            return qrFileMap.get( realClmName );
512                    }
513    
514                    // 帳票?? を?に、画像ファイルの保存フォル?求めます?
515                    String filename    = "./" + listId + ".files/" + realClmName + ".png";
516                    String fullAddress = htmlDir + filename ;
517    
518                    QrcodeImage qrImage = new QrcodeImage();
519                    qrImage.init( msg,fullAddress );
520                    qrImage.saveImage();
521    
522                    qrFileMap.put( realClmName,filename );
523                    return filename;
524            }
525    }