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