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