    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.report2;
    017
    018import java.io.File;
    019import java.util.Map;
    020import java.util.HashMap;
    021import java.util.Locale;
    022
    023import org.opengion.fukurou.system.HybsConst;                                   // 8.0.1.0 (2021/10/29)
    024import org.opengion.fukurou.util.FileUtil;
    025import org.opengion.fukurou.util.StringUtil;
    026import org.opengion.hayabusa.common.HybsSystem;
    027import org.opengion.hayabusa.common.HybsSystemException;
    028import static org.opengion.fukurou.system.HybsConst.CR ;                // 6.1.0.0 (2014/12/26)
    029
    030import com.sun.star.beans.PropertyValue;
    031import com.sun.star.frame.XComponentLoader;
    032import com.sun.star.frame.XController;
    033import com.sun.star.frame.XDispatchHelper;
    034import com.sun.star.frame.XDispatchProvider;
    035import com.sun.star.frame.XModel;
    036import com.sun.star.frame.XStorable;
    037import com.sun.star.io.IOException;
    038import com.sun.star.lang.EventObject;
    039import com.sun.star.lang.IllegalArgumentException;
    040import com.sun.star.lang.XComponent;
    041import com.sun.star.uno.UnoRuntime;
    042import com.sun.star.util.CloseVetoException;
    043import com.sun.star.util.XCloseable;
    044import com.sun.star.view.PrintJobEvent;
    045import com.sun.star.view.PrintableState;
    046import com.sun.star.view.XPrintJobBroadcaster;
    047import com.sun.star.view.XPrintJobListener;
    048import com.sun.star.view.XPrintable;
    049
    050/**
    051 * OpenOfficeを利用して様々な形式のﾌｧｲﾙを読み込み､出力･印刷を行うための変換ｸﾗｽです｡
    052 *
    053 * 変換を行うことのできる入出力のﾌｫｰﾏｯﾄ以下の通りです｡
    054 *
    055 * [対応ﾌｫｰﾏｯﾄ]
    056 *  入力[Calc(ods)   ,Excel(xls)     ] ⇒ 出力[Calc(ods)   ,Excel(xls,xlsx)      ,PDF]
    057 *  入力[Writer(odt) ,Word(doc)      ] ⇒ 出力[Writer(odt) ,Word(doc,docx)       ,PDF]
    058 *  入力[Impress(odp),PowerPoint(ppt)] ⇒ 出力[Impress(odp),PowerPoint(ppt,pptx) ,PDF]
    059 *  入力[ * 上記の全て               ] ⇒ 印刷
    060 *
    061 * ※ xlsx,docx,pptx は､MS 2007形式の為､LibreOffice のみ利用できます｡
    062 *
    063 * 変換を行うには､以下の2通りの方法があります｡
    064 * (1)簡易的な変換ﾒｿｯﾄﾞを利用する場合
    065 *   {@link #convert(String, String)}を利用して､変換を行います｡
    066 *   この場合､出力形式は､出力ﾌｧｲﾙの拡張子に従って自動的に決定されます｡
    067 *   このため､印刷処理などを行う場合は､(2)の方法で出力して下さい｡
    068 * (2)段階的に書くﾒｿｯﾄﾞを呼び出して変換する場合
    069 *   ｵﾌﾞｼﾞｪｸﾄを生成した後､{@link #open()}､#(各種変換ﾒｿｯﾄﾞ)､{@link #clone()}を
    070 *   順番に呼び出して変換を行います｡
    071 *   この場合､出力形式は､それに対応するﾒｿｯﾄﾞを呼び出ることで決定されます｡
    072 *
    073 *   また､変換を行うための､各種ﾒｿｯﾄﾞは､例外としてThrowableを投げるように定義されています｡
    074 *   このｸﾗｽを利用する場合は､このThrowableをcatchし､catch句で､必ず{@link #close( boolean )}に､
    075 *   "true"(ｴﾗｰ発生時のｸﾛｰｽﾞ処理)を指定して､終了処理を行って下さい｡
    076 *   (これを行わない場合､OpenOfficeの不要なﾌﾟﾛｾｽが残ってしまう可能性があります)
    077 *
    078 * また､出力ﾌｧｲﾙが既に存在する場合､出力ﾌｧｲﾙは一旦削除された後､処理されます｡
    079 * なお､入力ﾌｧｲﾙと出力ﾌｧｲﾙが同じ場合､何も処理されません｡(例外も発行されません)
    080 *
    081 * 入力ﾌｧｲﾙを､CSV形式で複数指定した場合､複数の入力ﾌｧｲﾙをﾏｰｼﾞして出力します｡
    082 * ※1 現状は､ﾌｧｲﾙのﾏｰｼﾞは､入力ﾌｧｲﾙがExcelまたはCalcの場合のみ対応しています｡
    083 *
    084 * ※ DocConverter は､ｸﾗｳﾄﾞ対応されていません｡変換時はﾛｰｶﾙﾌｧｲﾙ間で行ってください｡
    085 *
    086 * @og.group 帳票ｼｽﾃﾑ
    087 *
    088 * @version  4.0
    089 * @author   Hiroki.Nakamura
    090 * @since    JDK1.6
    091 */
    092public class DocConverter_OOO {
    093        private static final String OFFICE_VER = HybsConst.getenv( "OPENOFFICE_VER","NULL" );   // 8.0.1.0 (2021/10/29) 環境変数から取得
    094
    095        private final boolean                   isOnline;                       // ｵﾝﾗｲﾝ処理かどうか(ｵﾝﾗｲﾝ処理の場合､ﾌﾟﾛｾｽはﾌｧｸﾄﾘｸﾗｽ経由で生成されます)
    096        private final String[]                  mergeFile;
    097
    098        private String                                  inputName;
    099        private String                                  origName;
    100
    101        private XComponent                              xComp;                          // 5.1.8.0 (2010/07/01) ﾒｿｯﾄﾞと重なる変数名の変更
    102        private SOfficeProcess                  soffice;
    103
    104        // 入力､出力の拡張子とこれに対応するﾌｨﾙﾀｰ名
    105        // \share\config\registry\instance\org\openoffice\office\TypeDetection.xml
    106        // share¥registry¥calc.xcd 形式のﾌｧｲﾙ <node oor:name="****" 部分？
    107
    108        /** staticｲﾆｼｬﾗｲｻﾞ後､読み取り専用にするので､ConcurrentHashMap を使用しません｡ */
    109        private static final Map<String,String> FILTER_MAP      = new HashMap<>();              // 6.4.1.1 (2016/01/16) filterMap → FILTER_MAP refactoring
    110        static {
    111                FILTER_MAP.put( "ods_ods", "calc8" );
    112                FILTER_MAP.put( "xls_ods", "calc8" );
    113                FILTER_MAP.put( "ods_xls", "MS Excel 97" );
    114                FILTER_MAP.put( "xls_xls", "MS Excel 97" );
    115                FILTER_MAP.put( "ods_pdf", "calc_pdf_Export" );
    116                FILTER_MAP.put( "xls_pdf", "calc_pdf_Export" );
    117                FILTER_MAP.put( "odt_odt", "writer8" );
    118                FILTER_MAP.put( "doc_odt", "writer8" );
    119                FILTER_MAP.put( "odt_doc", "MS Word 97" );
    120                FILTER_MAP.put( "doc_doc", "MS Word 97" );
    121                FILTER_MAP.put( "odt_pdf", "writer_pdf_Export" );
    122                FILTER_MAP.put( "doc_pdf", "writer_pdf_Export" );
    123                FILTER_MAP.put( "odp_odp", "impress8" );
    124                FILTER_MAP.put( "ppt_odp", "impress8" );
    125                FILTER_MAP.put( "odp_ppt", "MS PowerPoint 97" );
    126                FILTER_MAP.put( "ppt_ppt", "MS PowerPoint 97" );
    127                FILTER_MAP.put( "odp_pdf", "impress_pdf_Export" );
    128                FILTER_MAP.put( "ppt_pdf", "impress_pdf_Export" );
    129
    130                if( OFFICE_VER.contains( "LibreOffice" ) ) {                                            // 8.0.1.0 (2021/10/29) LibreOffice の時のみ使用可能
    131        //              FILTER_MAP.put( "ods_xlsx", "Calc MS Excel 2007 XML" );                 // 8.0.1.0 (2021/10/29)
    132        //              FILTER_MAP.put( "xls_xlsx", "Calc MS Excel 2007 XML" );                 // 8.0.1.0 (2021/10/29)
    133
    134                        FILTER_MAP.put( "ods_xlsx", "Calc Office Open XML" );                   // 8.0.1.0 (2021/10/29)
    135                        FILTER_MAP.put( "xls_xlsx", "Calc Office Open XML" );                   // 8.0.1.0 (2021/10/29)
    136
    137                        // share¥registry¥writer.xcd
    138                        FILTER_MAP.put( "odt_docx", "MS Word 2007 XML" );                               // 8.0.1.0 (2021/10/29)
    139                        FILTER_MAP.put( "doc_docx", "MS Word 2007 XML" );                               // 8.0.1.0 (2021/10/29)
    140                        // ※ writer_MS_Word_2007 は､failed: 0x81a(Error Area:Io Class:Parameter Code:26)
    141
    142                        // share¥registry¥impress.xcd
    143                        FILTER_MAP.put( "odp_pptx", "Impress MS PowerPoint 2007 XML" ); // 8.0.1.0 (2021/10/29)
    144                        FILTER_MAP.put( "ppt_pptx", "Impress MS PowerPoint 2007 XML" ); // 8.0.1.0 (2021/10/29)
    145                        // ※ MS PowerPoint 2007 XML は､failed: 0x81a(Error Area:Io Class:Parameter Code:26)
    146                        // ※ Office Open XML Presentation は､failed: 0x81a(Error Area:Io Class:Parameter Code:26)
    147                }
    148        };
    149
    150        /**
    151         * ｺﾝｽﾄﾗｸﾀです｡
    152         *
    153         * #DocConverter(input, true)と同じです｡
    154         *
    155         * @param input ﾌｧｲﾙ一覧(CSV形式)
    156         * @see #DocConverter_OOO(String[])
    157         */
    158        public DocConverter_OOO( final String input ) {
    159                this( StringUtil.csv2Array( input ), true );
    160        }
    161
    162        /**
    163         * ｺﾝｽﾄﾗｸﾀです｡
    164         *
    165         * #DocConverter(input, true)と同じです｡
    166         *
    167         * @param input ﾌｧｲﾙ一覧(配列)
    168         * @see #DocConverter_OOO(String[], boolean)
    169         */
    170        public DocConverter_OOO( final String input[] ) {
    171                this( input, true );
    172        }
    173
    174        /**
    175         * ｺﾝｽﾄﾗｸﾀです｡
    176         *
    177         * isOnline(isOl)がtrueに指定された場合､soffice.binのﾌﾟﾛｾｽをﾌｧｸﾄﾘｰｸﾗｽ経由で生成し､
    178         * ｷｬｯｼｭします｡
    179         * 但し､ｼｽﾃﾑﾘｿｰｽが読み込まれないような､ﾊﾞｯﾁﾌｧｲﾙから起動した場合は､この方法は
    180         * 利用できないため､isOnlineをfalseに指定する必要があります｡
    181         *
    182         * @param input ﾌｧｲﾙ一覧(配列)
    183         * @param isOl ｵﾝﾗｲﾝ(Web環境での使用)かどうか
    184         */
    185        public DocConverter_OOO( final String input[], final boolean isOl ) {
    186                if( input == null || input.length == 0 || input[0].isEmpty() ) {
    187                        throw new HybsSystemException( "入力ﾌｧｲﾙが指定されていません｡" );
    188                }
    189                origName = input[0];
    190                final File inFile = new File( origName );
    191                if( !inFile.exists() ) {
    192                        throw new HybsSystemException( "入力ﾌｧｲﾙが存在しません｡[file=" + input[0] + "]" );
    193                }
    194                isOnline  = isOl;
    195                inputName = origName;
    196//              origName  = input[0];
    197
    198                if( input.length == 1 ) {
    199                        mergeFile = null;
    200                }
    201                else {
    202                        if( !"xls".equals( getSuffix( origName ) ) && !"ods".equals( getSuffix( origName ) ) ) {
    203                                throw new HybsSystemException( "ﾌｧｲﾙのﾏｰｼﾞを行う場合､入力ﾌｧｲﾙは､ExcelまたはCacl形式である必要があります｡" );
    204                        }
    205
    206                        mergeFile = new String[input.length-1];
    207                        for( int i=0; i<mergeFile.length; i++ ) {
    208                                final String mrgFile = input[i+1];
    209                                if( mrgFile.isEmpty() || !( new File( mrgFile ) ).exists() ) {
    210                                        throw new HybsSystemException( "ﾏｰｼﾞﾌｧｲﾙが指定されていないか､または存在しません｡[file=" + mrgFile + "]" );
    211                                }
    212                                if( inputName.equals( mrgFile ) ) {
    213                                        throw new HybsSystemException( "ﾏｰｼﾞﾌｧｲﾙに入力ﾌｧｲﾙと同じﾌｧｲﾙが指定されてます｡[file=" + mrgFile + "]" );
    214                                }
    215                                if( !"xls".equals( getSuffix( mrgFile ) ) && !"ods".equals( getSuffix( mrgFile ) ) ) {
    216                                        throw new HybsSystemException( "ﾌｧｲﾙのﾏｰｼﾞを行う場合､ﾏｰｼﾞﾌｧｲﾙは､ExcelまたはCacl形式である必要があります｡" );
    217                                }
    218                                mergeFile[i] = mrgFile;
    219                        }
    220                }
    221        }
    222
    223        /**
    224         * SOficeのｺﾝﾎﾟｰﾈﾝﾄを起動します｡
    225         *
    226         * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    227         * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    228         *
    229         * @og.rev 5.1.7.0 (2010/06/01) ﾏｰｼﾞ処理対応
    230         *
    231         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    232         * @see #close()
    233         * @see #close(boolean)
    234         */
    235        public void open() throws Throwable {
    236                // ﾌﾟﾛｾｽの取得
    237                if( soffice == null ) {
    238                        if( isOnline ) {
    239                                soffice = ProcessFactory.newInstance();
    240                        }
    241                        else {
    242                                soffice = new SOfficeProcess( "docconverter.class" );
    243                                soffice.bootstrap();
    244                        }
    245
    246                        // ﾏｰｼﾞする場合は､ﾏｰｼﾞ対象のﾌｧｲﾙをﾃﾝﾎﾟﾗﾘにｺﾋﾟｰする(readOnly回避のため)
    247                        // ﾃﾝﾌﾟﾚｰﾄ(無題)として上げると､ｼｰﾄｺﾋﾟｰ先として特定できなくなるため
    248                        if( mergeFile != null ) {
    249                                final File origFile = new File( origName );
    250                                inputName = soffice.getTempPath() + System.currentTimeMillis() + "_" + origFile.getName();
    251                                FileUtil.copy( origFile, new File( inputName ) );
    252                        }
    253                }
    254
    255                // 5.1.7.0 (2010/06/01) ﾏｰｼﾞ処理対応
    256                xComp = getComponent( inputName, ( mergeFile == null ? true : false ), false );
    257
    258                if( mergeFile != null ) {
    259                        for( int i=0; i<mergeFile.length; i++ ) {
    260                                merge( mergeFile[i] );
    261                        }
    262                }
    263        }
    264
    265        /**
    266         * ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄを取得します｡
    267         *
    268         * @param       input                   ﾌｧｲﾙ名
    269         * @param       isHidden                隠し属性[true/false]
    270         * @param       isAsTemplate    OpenOffice上のTemplate属性[true/false]
    271         *
    272         * @return      ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄ
    273         */
    274        @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    275        private XComponent getComponent( final String input, final boolean isHidden, final boolean isAsTemplate ) {
    276                final PropertyValue[] calcProps = new PropertyValue[2];
    277                calcProps[0] = new PropertyValue();
    278                calcProps[0].Name = "Hidden";
    279                calcProps[0].Value = isHidden;
    280                calcProps[1] = new PropertyValue();
    281                calcProps[1].Name = "AsTemplate";
    282                calcProps[1].Value = isAsTemplate;
    283
    284                final String url = "file:///" + input.replace( '\\', '/' );
    285
    286                XComponent rtnDoc;
    287                final XComponentLoader cloader = (XComponentLoader) UnoRuntime.queryInterface( XComponentLoader.class, soffice.getDesktop() );
    288                try {
    289                        rtnDoc = cloader.loadComponentFromURL( url, "_blank", 0, calcProps );
    290                }
    291                catch( final IOException ex ) {
    292                        throw new HybsSystemException( "OpenOfficeの立ち上げ時にｴﾗｰが発生しました(入出力ｴﾗｰ)｡", ex );
    293                }
    294                catch( final IllegalArgumentException ex ) {
    295                        throw new HybsSystemException( "OpenOfficeの立ち上げ時にｴﾗｰが発生しました(ﾊﾟﾗﾒｰﾀｰ不正)｡", ex );
    296                }
    297                return rtnDoc;
    298        }
    299
    300        /**
    301         * ﾄﾞｷｭﾒﾝﾄ(xls,ods)のﾏｰｼﾞを行います｡
    302         *
    303         * @param mergeInputName ﾏｰｼﾞ対象のﾌｧｲﾙ名
    304         */
    305        @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    306        private void merge( final String mergeInputName ) {
    307                // ﾏｰｼﾞする副ﾌｧｲﾙは､ﾃﾝﾌﾟﾚｰﾄ(無題)として上げる(readOnly回避のため)
    308                final XComponent subDoc = getComponent( mergeInputName, false, true );
    309
    310                final XDispatchProvider dispatchProvider
    311                        = (XDispatchProvider)UnoRuntime.queryInterface( XDispatchProvider.class
    312                                ,((XController)UnoRuntime.queryInterface( XController.class
    313                                        ,((XModel)UnoRuntime.queryInterface( XModel.class
    314                                                ,subDoc
    315                                        )).getCurrentController()
    316                                )).getFrame()
    317                        );
    318
    319                final XDispatchHelper xDispatchHelper = soffice.getDispatcher();
    320                xDispatchHelper.executeDispatch(dispatchProvider, ".uno:TableSelectAll", "", 0, new PropertyValue[0]);
    321
    322                String title = new File( inputName ).getName() ;
    323                title = title.substring( 0, title.indexOf( '.' ) );
    324
    325                final PropertyValue[] moveProps = new PropertyValue[3];
    326                moveProps[0] = new PropertyValue();
    327                moveProps[0].Name = "DocName";
    328                moveProps[0].Value = title;
    329                moveProps[1] = new PropertyValue();
    330                moveProps[1].Name = "Index";
    331                moveProps[1].Value = 32767;
    332                moveProps[2] = new PropertyValue();
    333                moveProps[2].Name = "Copy";
    334                moveProps[2].Value = true;
    335                xDispatchHelper.executeDispatch(dispatchProvider, ".uno:Move", "", 0, moveProps);
    336
    337                closeComponent( subDoc );
    338        }
    339
    340        /**
    341         * Calcｺﾝﾎﾟｰﾈﾝﾄをｸﾛｰｽﾞします｡
    342         *
    343         * このｸﾛｰｽﾞ処理は､処理が正常終了した場合に呼び出しする必要があります｡
    344         * 例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    345         *
    346         * このﾒｿｯﾄﾞは#close(false)と同じです｡
    347         *
    348         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    349         * @see #close(boolean)
    350         */
    351        public void close() throws Throwable {
    352                close( false );
    353        }
    354
    355        /**
    356         * Calcｺﾝﾎﾟｰﾈﾝﾄをｸﾛｰｽﾞします｡
    357         *
    358         * 引数のisErrがtrueの場合､この変換ｵﾌﾞｼﾞｪｸﾄで生成されたﾌﾟﾛｾｽは強制的に破棄されます｡
    359         * falseの場合は､ﾌﾟﾛｾｽは､ﾌｧｸﾄﾘｸﾗｽを経由して､ｷｬｯｼｭに戻されます｡
    360         * (ﾊﾞｯﾁ処理の場合は､いずれの場合も､ﾌﾟﾛｾｽは強制的に破棄されます)
    361         *
    362         * 起動から変換､ｸﾛｰｽﾞまでの書く処理で例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    363         *
    364         * #close(false)は#close()と同じであるため､通常利用することはありません｡
    365         *
    366         * @og.rev 4.2.4.1 (2008/07/07 ) 終了処理を60回で終わるように修正
    367         * @og.rev 4.3.0.0 (2008/07/15 ) ↑は6秒しか待っていなかったので､60秒待つように修正
    368         *
    369         * @param       isErr   trueの場合､この変換ｵﾌﾞｼﾞｪｸﾄで生成されたﾌﾟﾛｾｽは強制的に破棄されます｡
    370         */
    371        @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    372        public void close( final boolean isErr ) {
    373                if( xComp != null ) {
    374                        closeComponent( xComp );
    375                }
    376
    377                if( soffice != null ) {
    378                        if( isOnline ) {
    379                                if( isErr ) {
    380                                        ProcessFactory.remove( soffice );
    381                                }
    382                                else {
    383                                        ProcessFactory.release( soffice );
    384                                }
    385                        }
    386                        else {
    387                                soffice.close();
    388                        }
    389                }
    390
    391                // ﾏｰｼﾞした場合は､ﾃﾝﾎﾟﾗﾘにｺﾋﾟｰしたﾌｧｲﾙを削除
    392                // 6.0.0.1 (2014/04/25) These nested if statements could be combined
    393                if( mergeFile != null && ! ( new File( inputName ) ).delete() ) {
    394                        System.err.println( "ﾃﾝﾎﾟﾗﾘにｺﾋﾟｰしたﾌｧｲﾙを削除できませんでした｡[" + inputName + "]" );
    395                }
    396        }
    397
    398        /**
    399         * ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄをｸﾛｰｽﾞします｡
    400         *
    401         * @param comp ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄ
    402         */
    403        @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    404        private void closeComponent( final XComponent comp ) {
    405                XCloseable closeable = null;
    406                for( int i=0;; ++i ) {
    407                        try {
    408                                closeable = (XCloseable) UnoRuntime.queryInterface( XCloseable.class, comp );
    409                                closeable.close( true );
    410                                break;
    411                        }
    412                        catch( final CloseVetoException ex ) {
    413                                // 4.2.4.1 (2008/07/07 )
    414                                // 4.3.4.4 (2009/01/01)
    415                                if( i == 600 ) { throw new HybsSystemException( "sofficeﾌﾟﾛｾｽに接続できません｡", ex ); }
    416                                try {
    417                                        Thread.sleep( 100 );
    418                                }
    419                                catch( final InterruptedException ex2 ) {
    420                        //              throw new HybsSystemException( ex2 );
    421                                }
    422                        }
    423                }
    424        }
    425
    426        /**
    427         * 印刷を行います｡
    428         *
    429         * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    430         * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    431         *
    432         * @og.rev 4.3.0.0 (2008/07/16) ｽﾌﾟｰﾙが終わるまでwaitし､さらにﾌﾟﾘﾝﾀ発行の状況を監視し､正常終了かどうかを判断
    433         * @og.rev 4.3.7.3 (2009/06/22) 存在しないﾌﾟﾘﾝﾀｰを指定した場合のｴﾗｰﾊﾝﾄﾞﾘﾝｸﾞを追加
    434         * @og.rev 5.1.2.0 (2010/01/01) CentOS等は､OS_INFOがLinux UNKNOWNとなるため､判定条件を変更
    435         *
    436         * @param       printer ﾌﾟﾘﾝﾀｰ名
    437         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    438         */
    439        public void print( final String printer ) throws Throwable {
    440                if( printer == null || printer.isEmpty() ) {
    441                        throw new HybsSystemException( "ﾌﾟﾘﾝﾀｰが指定されていません｡" );
    442                }
    443
    444        //      if( xComp == null ) { throw new HybsSystemException( "初めに､#open()を実行して下さい(1)" ); }
    445                @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    446                final XPrintable xprintable = (XPrintable) UnoRuntime.queryInterface( XPrintable.class, xComp );
    447                @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    448                final XPrintJobBroadcaster selection = (XPrintJobBroadcaster) UnoRuntime.queryInterface(XPrintJobBroadcaster.class, xprintable);
    449                final MyPrintJobListener listener = new MyPrintJobListener();
    450                selection.addPrintJobListener( listener );
    451
    452                final PropertyValue[] tmpProps = new PropertyValue[1];
    453                tmpProps[0] = new PropertyValue();
    454                tmpProps[0].Name = "Name";
    455                // 5.1.2.0 (2010/01/01) CentOS等は､OS_INFOがLinux UNKNOWNとなるため､判定条件を変更
    456                // OSがLinuxの場合は､ﾌﾟﾘﾝﾀ名称の前後に"<",">"を付加
    457                tmpProps[0].Value = "LINUX".indexOf( HybsSystem.sys( "OS_INFO" ).toUpperCase( Locale.JAPAN ) ) >= 0 ? "<" + printer + ">" : printer;
    458
    459                // 4.3.4.4 (2009/01/01)
    460                try {
    461                        xprintable.setPrinter( tmpProps );
    462                }
    463                catch( final IllegalArgumentException ex ) {
    464                        throw new HybsSystemException( "印刷時にｴﾗｰが発生しました｡", ex );
    465                }
    466
    467                // 4.3.7.3 (2009/06/22) 存在しないﾌﾟﾘﾝﾀを指定した場合は､PropertyValueに
    468                // ﾃﾞﾌｫﾙﾄﾌﾟﾘﾝﾀｰが入るため､引数の値と合致しているかで正しく設定されたかを確認
    469                String curPrinter = null;
    470                final PropertyValue[] chkProps = xprintable.getPrinter();
    471                for( int i=0; i<chkProps.length; i++ ) {
    472                        if( "Name".equals( chkProps[i].Name) ) {
    473                                curPrinter = (String)chkProps[i].Value;
    474                                break;
    475                        }
    476                }
    477                if( !(printer.equalsIgnoreCase( curPrinter ) ) ) {
    478                        final String errMsg = "ﾌﾟﾘﾝﾀｰ[" + printer + "]を発行先に指定できませんでした｡" + CR
    479                                                        + "存在しないﾌﾟﾘﾝﾀ名が指定されている可能性があります｡";
    480                        throw new HybsSystemException( errMsg );
    481                }
    482
    483                // 4.3.0.0 (2008/07/16)
    484                final PropertyValue[] printProps = new PropertyValue[1];
    485                printProps[0] = new PropertyValue();
    486                printProps[0].Name = "Wait";
    487                printProps[0].Value = true;
    488
    489                // 4.3.4.4 (2009/01/01)
    490                try {
    491                        xprintable.print( printProps );
    492                }
    493                catch( final IllegalArgumentException ex ) {
    494                        throw new HybsSystemException( "印刷時にｴﾗｰが発生しました｡", ex );
    495                }
    496
    497                // 4.3.0.0 (2008/07/16)
    498                // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
    499                if( listener.getStatus() == null
    500                                || listener.getStatus() != PrintableState.JOB_COMPLETED && listener.getStatus() != PrintableState.JOB_SPOOLED ) {
    501                        throw new HybsSystemException ( "Error Occured while spooling print job. Check Spooler-Service!!!");
    502                }
    503        }
    504
    505        /**
    506         * ﾌﾟﾘﾝﾀｼﾞｮﾌﾞの状況を監視するﾘｽﾅｰです｡
    507         *
    508         * @author Hiroki.Nakamura
    509         */
    510        private static final class MyPrintJobListener implements XPrintJobListener {
    511                private PrintableState status   ;
    512
    513                /**
    514                 * PrintJobEventのｽﾃｰﾀｽを内部変数にｾｯﾄします｡
    515                 *
    516                 * @param       event   PrintJobEventｵﾌﾞｼﾞｪｸﾄ
    517                 */
    518                @Override
    519                public void printJobEvent( final PrintJobEvent event ) {
    520                        status = event.State;
    521                }
    522
    523                /**
    524                 * EventObjectの処理を実施します｡(ここでは何も行いません｡)
    525                 *
    526                 * @param       event   EventObjectｵﾌﾞｼﾞｪｸﾄ
    527                 */
    528                @Override
    529                public void disposing( final EventObject event ) {
    530                        // 何もありません｡(PMD ｴﾗｰ回避)
    531                }
    532
    533                /**
    534                 * PrintableStateｵﾌﾞｼﾞｪｸﾄを返します｡
    535                 *
    536                 * @return      PrintableStateｵﾌﾞｼﾞｪｸﾄ
    537                 */
    538                public PrintableState getStatus() {
    539                        return status;
    540                }
    541        }
    542
    543        /**
    544         * PDF出力を行います｡
    545         *
    546         * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    547         *
    548         * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    549         * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    550         *
    551         * @param       outputName      出力ﾌｧｲﾙ名
    552         * @param       pdfPasswd       PDFﾊﾟｽﾜｰﾄﾞ
    553         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    554         */
    555        public void pdf( final String outputName, final String pdfPasswd ) throws Throwable {
    556        //      savePdf( outputName, getFilterName( getSuffix( inputName ), "pdf" ), pdfPasswd );
    557                savePdf( outputName, getFilterName( inputName, "pdf" ), pdfPasswd );
    558        }
    559
    560        /**
    561         * Calc(ods)出力を行います｡
    562         *
    563         * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    564         *
    565         * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    566         * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    567         *
    568         * @param       outputName      出力ﾌｧｲﾙ名
    569         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    570         */
    571//      public void ods( final String outputName ) throws Throwable {
    572//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "ods" ) );
    573//              saveDoc( outputName, getFilterName( inputName, "ods" ) );
    574//      }
    575
    576//      /**
    577//       * Excel(xls)出力を行います｡
    578//       *
    579//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    580//       *
    581//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    582//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    583//       *
    584//       * @param       outputName      出力ﾌｧｲﾙ名
    585//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    586//       */
    587//      public void xls( final String outputName ) throws Throwable {
    588//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "xls" ) );
    589//              saveDoc( outputName, getFilterName( inputName, "xls" ) );
    590//      }
    591
    592//      /**
    593//       * Excel2007(xlsx)出力を行います｡
    594//       *
    595//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    596//       *
    597//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    598//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    599//       *
    600//       * @og.rev 8.0.1.0 (2021/10/29) OUT_ODS_XSLX (Excel2007形式) 評価用
    601//       *
    602//       * @param       outputName      出力ﾌｧｲﾙ名
    603//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    604//       */
    605//      public void xlsx( final String outputName ) throws Throwable {
    606//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "xlsx" ) );
    607//              saveDoc( outputName, getFilterName( inputName, "xlsx" ) );
    608//      }
    609
    610//      /**
    611//       * Writer(ods)出力を行います｡
    612//       *
    613//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    614//       *
    615//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    616//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    617//       *
    618//       * @param       outputName      出力ﾌｧｲﾙ名
    619//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    620//       */
    621//      public void odt( final String outputName ) throws Throwable {
    622//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "odt" ) );
    623//              saveDoc( outputName, getFilterName( inputName, "odt" ) );
    624//      }
    625
    626//      /**
    627//       * Word(doc)出力を行います｡
    628//       *
    629//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    630//       *
    631//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    632//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    633//       *
    634//       * @param       outputName      出力ﾌｧｲﾙ名
    635//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    636//       */
    637//      public void doc( final String outputName ) throws Throwable {
    638//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "doc" ) );
    639//              saveDoc( outputName, getFilterName( inputName, "doc" ) );
    640//      }
    641
    642//      /**
    643//       * Impress(odp)出力を行います｡
    644//       *
    645//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    646//       *
    647//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    648//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    649//       *
    650//       * @param       outputName      出力ﾌｧｲﾙ名
    651//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    652//       */
    653//      public void odp( final String outputName ) throws Throwable {
    654//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "odp" ) );
    655//              saveDoc( outputName, getFilterName( inputName, "odp" ) );
    656//      }
    657
    658//      /**
    659//       * PowerPoint(ppt)出力を行います｡
    660//       *
    661//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    662//       *
    663//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    664//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    665//       *
    666//       * @param       outputName      出力ﾌｧｲﾙ名
    667//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    668//       */
    669//      public void ppt( final String outputName ) throws Throwable {
    670//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "ppt" ) );
    671//              saveDoc( outputName, getFilterName( inputName, "ppt" ) );
    672//      }
    673
    674        /**
    675         * 出力ﾌｧｲﾙから出力形式を自動判別し､変換を行います｡
    676         *
    677         * 入出力形式で未対応の場合(形式は入出力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    678         *
    679         * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    680         * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    681         *
    682         * @param       outputName      出力ﾌｧｲﾙ名
    683         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    684         */
    685        public void auto( final String outputName ) throws Throwable {
    686                final String outSuffix = getSuffix( outputName );
    687                if( "pdf".equalsIgnoreCase( outSuffix ) ) {
    688//                      savePdf( outputName, getFilterName( getSuffix( inputName ), outSuffix ), null );
    689                        savePdf( outputName, getFilterName( inputName, outSuffix ), null );
    690                }
    691                else {
    692//                      saveDoc( outputName, getFilterName( getSuffix( inputName ), outSuffix ) );
    693                        saveDoc( outputName, getFilterName( inputName, outSuffix ) );
    694                }
    695        }
    696
    697        /**
    698         * ﾌｨﾙﾀｰ名を指定して､各種ﾌｧｲﾙ形式に出力を行います｡
    699         *
    700         * @param       outputName      出力ﾌｧｲﾙ名
    701         * @param       filter          ﾌｨﾙﾀｰ名
    702         */
    703        private void saveDoc( final String outputName, final String filter ) {
    704                if( !checkOutput( outputName ) ){ return; }
    705
    706                final PropertyValue[] storeProps = new PropertyValue[1];
    707                storeProps[0] = new PropertyValue();
    708                storeProps[0].Name = "FilterName";
    709                storeProps[0].Value = filter;
    710
    711                final String url = "file:///" + outputName.replace( '\\', '/' );
    712        //      if( xComp == null ) { throw new HybsSystemException( "初めに､#open()を実行して下さい(2)" ); }
    713                @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    714                final XStorable xstorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xComp );
    715                try {
    716                        xstorable.storeAsURL( url, storeProps );
    717                }
    718                catch( final Throwable th ) {
    719                        throw new HybsSystemException( "ﾌｧｲﾙへの変換時にｴﾗｰが発生しました｡[filter=" + filter + "]", th );
    720                }
    721        }
    722
    723        /**
    724         * ﾌｨﾙﾀｰを指定してPDF出力を行います｡
    725         *
    726         * @param       outputName      出力ﾌｧｲﾙ名
    727         * @param       filter          ﾌｨﾙﾀｰ名
    728         * @param       pdfPasswd       PDFﾊﾟｽﾜｰﾄﾞ
    729         */
    730        private void savePdf( final String outputName, final String filter, final String pdfPasswd ) {
    731                if( !checkOutput( outputName ) ){ return; }
    732
    733                final PropertyValue[] storeProps;
    734                if( pdfPasswd == null || pdfPasswd.isEmpty() ) {
    735                        storeProps = new PropertyValue[1];
    736                        storeProps[0] = new PropertyValue();
    737                        storeProps[0].Name = "FilterName";
    738                        storeProps[0].Value = filter;
    739                }
    740                // 帳票要求ﾃｰﾌﾞﾙでPDFﾊﾟｽﾜｰﾄﾞが設定されている場合
    741                else {
    742                        final PropertyValue[] filterProps = new PropertyValue[2];
    743                        filterProps[0] = new PropertyValue();
    744                        filterProps[0].Name = "EncryptFile";
    745                        filterProps[0].Value = true;
    746                        filterProps[1] = new PropertyValue();
    747                        filterProps[1].Name = "DocumentOpenPassword";
    748                        filterProps[1].Value = pdfPasswd;
    749
    750                        storeProps = new PropertyValue[2];
    751                        storeProps[0] = new PropertyValue();
    752                        storeProps[0].Name = "FilterName";
    753                        storeProps[0].Value = "calc_pdf_Export";
    754                        storeProps[1] = new PropertyValue();
    755                        storeProps[1].Name = "FilterData";
    756                        storeProps[1].Value = filterProps;
    757                }
    758
    759                final String url = "file:///" + outputName.replace( '\\', '/' );
    760        //      if( xComp == null ) { throw new HybsSystemException( "初めに､#open()を実行して下さい(3)" ); }
    761                @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    762                final XStorable xstorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xComp );
    763                try {
    764                        xstorable.storeToURL( url, storeProps );
    765                }
    766                catch( final Throwable th ) {
    767                        final String err = "PDFﾌｧｲﾙへの変換時にｴﾗｰが発生しました｡[filter=" + filter + "]"
    768                                                        + " URL=" + url + " , storeProps=" + storeProps + " , xComp=" + xComp ;
    769
    770//                      throw new HybsSystemException( "PDFﾌｧｲﾙへの変換時にｴﾗｰが発生しました｡[filter=" + filter + "]", th );
    771                        throw new HybsSystemException( err, th );
    772                }
    773        }
    774
    775        /**
    776         * 出力ﾌｧｲﾙのﾁｪｯｸを行います｡
    777         *
    778         * @param       outputName      出力ﾌｧｲﾙ名
    779         *
    780         * @return      処理対象かどうか(入力ﾌｧｲﾙと出力ﾌｧｲﾙが同じ場合は､falseが返ります)
    781         */
    782        private boolean checkOutput( final String outputName ) {
    783                if( outputName == null || outputName.isEmpty() ) {
    784                        throw new HybsSystemException( "出力ﾌｧｲﾙが指定されていません｡" );
    785                }
    786
    787                final File inFile  = new File( inputName );
    788                final File outFile = new File( outputName );
    789
    790                if( outFile.exists() ) {
    791                        if( inFile.getAbsoluteFile().equals( outFile.getAbsoluteFile() ) ) {
    792                                // 入力と出力が同じﾌｧｲﾙの場合な何もしない
    793                                return false;
    794                        }
    795                        else if( !outFile.delete() ) {
    796                                throw new HybsSystemException( "出力先の既存ﾌｧｲﾙが削除できません｡[file=" + outputName + "]" );
    797                        }
    798                }
    799                return true;
    800        }
    801
    802        /**
    803         * 入出力の形式(拡張子)からﾌｨﾙﾀｰ名を取得します｡
    804         *
    805         * 入力ﾌｧｲﾙ名からｻﾌｨｯｸｽを取り出して､FILTER_MAP からﾌｨﾙﾀｰ名を取り出します｡
    806         *
    807         * @og.rev 8.0.1.0 (2021/10/29) ﾒｯｾｰｼﾞ修正
    808         *
    809//       * @param       inSuffix        入力拡張子
    810         * @param       inputName       入力ﾌｧｲﾙ名
    811         * @param       outSuffix       出力拡張子
    812         *
    813         * @return      ﾌｨﾙﾀｰ名
    814         */
    815//      private static String getFilterName( final String inSuffix, final String outSuffix ) {
    816        private static String getFilterName( final String inputName, final String outSuffix ) {
    817                final String inSuffix = getSuffix( inputName );
    818
    819                final String filterName = FILTER_MAP.get( inSuffix + "_" + outSuffix );
    820                if( filterName == null ) {
    821                        final String errMsg = "入力ﾌｧｲﾙ=[" + inputName + "] , 出力形式=[" + outSuffix + "]" + CR
    822                                                        + "入力形式､出力形式は､以下の対応表に基づき､設定して下さい｡" + CR
    823                                                        + "入力[Calc(ods)   ,Excel(xls)     ] ⇒ 出力[Calc(ods)   ,Excel(xls,xslx)     ,PDF]" + CR
    824                                                        + "入力[Writer(odt) ,Word(doc)      ] ⇒ 出力[Writer(odt) ,Word(doc,docx)      ,PDF]" + CR
    825                                                        + "入力[Impress(odp),PowerPoint(ppt)] ⇒ 出力[Impress(odp),PowerPoint(ppt,pptx),PDF]" + CR
    826                                                        + "xlsx,docx,pptx は､MS 2007形式の為､LibreOffice のみ利用できます｡" + CR ;
    827                        throw new HybsSystemException( errMsg );
    828                }
    829                return filterName;
    830        }
    831
    832        /**
    833         * ﾌｧｲﾙ名から拡張子(小文字)を求めます｡
    834         *
    835         * @param       fileName        ﾌｧｲﾙ名
    836         *
    837         * @return      拡張子(小文字)
    838         */
    839        private static String getSuffix( final String fileName ) {
    840                String suffix = null;
    841                if( fileName != null ) {
    842                        final int sufIdx = fileName.lastIndexOf( '.' );
    843                        if( sufIdx >= 0 ) {
    844                                suffix = fileName.substring( sufIdx + 1 ).toLowerCase( Locale.JAPAN );
    845                        }
    846                }
    847                return suffix;
    848        }
    849
    850        /**
    851         * ﾄﾞｷｭﾒﾝﾄの変換を行うための簡易ﾒｿｯﾄﾞです｡
    852         *
    853         * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
    854         *
    855         * @param       inputFile       入力ﾌｧｲﾙ名
    856         * @param       outputFile      出力ﾌｧｲﾙ名
    857         * @see #convert(String[], String, boolean)
    858         */
    859        public static final void convert( final String inputFile, final String outputFile ) {
    860                convert( StringUtil.csv2Array( inputFile ), outputFile );
    861        }
    862
    863        /**
    864         * ﾄﾞｷｭﾒﾝﾄの変換を行うための簡易ﾒｿｯﾄﾞです｡
    865         *
    866         * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
    867         *
    868         * @param       inputFile       入力ﾌｧｲﾙ名配列
    869         * @param       outputFile      出力ﾌｧｲﾙ名
    870         * @see #convert(String[], String, boolean)
    871         */
    872        public static final void convert( final String[] inputFile, final String outputFile ) {
    873                convert( inputFile, outputFile, true );
    874        }
    875
    876        /**
    877         * ﾄﾞｷｭﾒﾝﾄの変換を行うための簡易ﾒｿｯﾄﾞです｡
    878         *
    879         * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
    880         *
    881         * isOnlineがtrueに指定された場合､soffice.binのﾌﾟﾛｾｽをﾌｧｸﾄﾘｰｸﾗｽ経由で生成し､
    882         * ｷｬｯｼｭします｡
    883         * 但し､ｼｽﾃﾑﾘｿｰｽが読み込まれないような､ﾊﾞｯﾁﾌｧｲﾙから起動した場合は､この方法は
    884         * 利用できないため､isOnlineをfalseに指定する必要があります｡
    885         *
    886         * @param       inputFile       入力ﾌｧｲﾙ名配列
    887         * @param       outputFile      出力ﾌｧｲﾙ名
    888         * @param       isOnline        ｵﾝﾗｲﾝ(Web環境での使用)かどうか
    889         */
    890        public static final void convert( final String inputFile[], final String outputFile, final boolean isOnline ) {
    891                final DocConverter_OOO dc = new DocConverter_OOO( inputFile, isOnline );
    892                try {
    893                        dc.open();
    894                        dc.auto( outputFile );
    895                        dc.close();
    896                }
    897                catch( final Throwable th ) {
    898                        dc.close( true );
    899                        throw new HybsSystemException( th );
    900                }
    901        }
    902
    903        /**
    904         * ﾄﾞｷｭﾒﾝﾄの変換を行います｡
    905         *
    906         * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
    907         *
    908         * @og.rev 4.3.1.1 (2008/08/23) mkdirs の戻り値判定
    909         * @og.rev 6.3.9.1 (2015/11/27) A method/constructor shouldnt explicitly throw java.lang.Exception(PMD)｡
    910         *
    911         * @param       args    ｺﾏﾝﾄﾞ引数配列
    912         */
    913        public static void main( final String[] args ) {
    914                if( args.length < 2 ) {
    915                        System.out.println( "usage : OdsConverter [inputFile or inputDir] [outputDir]" );
    916                        return;
    917                }
    918
    919                final File input = new File( args[0] );
    920                final File output = new File( args[1] );
    921
    922                // 4.3.1.1 (2008/08/23) mkdirs の戻り値判定
    923                if( output.mkdirs() ) {
    924                        System.err.println( args[1] + " の ﾃﾞｨﾚｸﾄﾘ作成に失敗しました｡" );
    925                }
    926
    927                if( input.isDirectory() ) {
    928                        final File[] inputFiles = input.listFiles();
    929                        // 6.3.9.0 (2015/11/06) null になっている可能性があるﾒｿｯﾄﾞの戻り値を利用している(findbugs)
    930                        if( inputFiles != null ) {
    931                                for( final File file : inputFiles ) {
    932                                        final String inputFile = file.getAbsolutePath();
    933                                        final String outputFile = output.getAbsolutePath() + File.separator + file.getName().replace( ".xls", ".ods" );
    934                                        convert( StringUtil.csv2Array( inputFile ), outputFile, false );
    935                                }
    936                        }
    937                }
    938                else {
    939                        final String inputFile = input.getAbsolutePath();
    940                        final String outputFile = output.getAbsolutePath() + File.separator + input.getName().replace( ".xls", ".ods" );
    941                        convert( StringUtil.csv2Array( inputFile ), outputFile, false );
    942                }
    943        }
    944}