2016-09-29 22 views
0

私はJava-AppからMS-Wordテンプレートから新しい文書を開きたいが、テンプレート自体を編集することしかできない。テンプレートから新しい文書を作成

ここに私の状況はあります: 私のJarファイルの中には単語テンプレートがあり、そのユーザーが指定した場所にコピーされて編集できます。その後、アプリケーションはこの編集されたテンプレートを開いてデータを挿入し、単語で開くことができます。これはすべて正常に動作します(Apache-POIを使用します)が、最後のステップは完全に私が望むものではありません。

通常、単語テンプレートをダブルクリックすると、Wordはまだどこにも保存されていない新しい文書(Document1というタイトル)を開きます。私の場合、Wordは編集用の単語テンプレート(blablaMyTemplateというタイトル)を開きます。これは、文書を作成するために保存済みのテンプレートを意味します。 Javaを使用して、テンプレートから新しく作成したドキュメントを開く方法を教えてください。

は、これは(省略のtry/catchとストリーム閉鎖)私のコードです:

File bbb = new File(new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getParentFile().getAbsolutePath() + "/blablaMyTemplate.dotx"); 
    if (!bbb.exists()) { //copy file to outside of jar for user editing 
     Files.copy(Buchungsbegleitblatt.class.getResourceAsStream("bbb.dotx"), bbb.toPath(), StandardCopyOption.REPLACE_EXISTING); 
    } 
    File tmp = File.createTempFile("bbb", ".dotx"); //create tmp file to insert data 
    InputStream in = new FileInputStream(bbb); 
    OutputStream out = new FileOutputStream(tmp); 
    XWPFDocument document = new XWPFDocument(in); 
    //here, some data is filled into the document using Apache-POI (omitted, because it works fine) 
    document.write(out); 
    if (Desktop.isDesktopSupported()) { 
     Desktop.getDesktop().open(tmp); //this opens the template for editing, it does not create a new doc from template 
    } 

問題は最後の行の範囲内にあるが、私はここに呼び出すことができます他に何見当がつかない。これを行うには

context menu on template

答えて

2

あなたはすでに問題を正確に記述しました。 Desktop.openはそれが言うことを正確に行います。ファイルタイプに割り当てられた呼び出されたアプリケーションに対してopenイベントを実行します。

newイベントを実行する必要があります。これはstartup command-line switches to start Wordを使用してWordで達成できます。あなたが見つけることができるリンクナレッジベースエントリで

...

/ttemplate_name Starts Word with a new document based on a template other than the Normal template.

...

JavaいずれかRuntime.getRuntime().execまたはProcessBuilderでそうするにはに使える。両方とも私は最初にコマンドインタープリタCMDをシェルとして起動し、これからstartコマンドを使用してアプリケーションを起動することをお勧めします。したがって、アプリケーションへの正確なパスを知る必要はありません。

例:

import java.io.*; 

class RuntimeExec { 
    public static void main(String[] args) { 
     try { 
     // Execute a command as a single line 
     File f = new File("C:/Users/axel/Documents/The Template.dotx"); 
     System.out.println(f.getAbsolutePath()); 
     String cmd = "cmd /C start winword.exe /t\"" + f.getAbsolutePath() + "\""; 
     Process child = Runtime.getRuntime().exec(cmd); 

     } catch (IOException e) { 
     e.printStackTrace(); 
     } 

    } 
} 

class UseProcessBuilder { 
    public static void main(String[] args) { 
     try { 
     //use ProcessBuilder to have more control 
     File f = new File("C:/Users/axel/Documents/The Template.dotx"); 
     System.out.println(f.getAbsolutePath()); 
     String application = "winword.exe"; 
     String switchNewFromTemplate = "/t"; 
     String file = f.getAbsolutePath(); 
     ProcessBuilder pb = new ProcessBuilder("cmd", "/C", "start", application, switchNewFromTemplate+file); 
     Process process = pb.start(); 

     } catch (IOException e) { 
     e.printStackTrace(); 
     } 
    } 
} 

明示的winwordアプリケーションを起動しないように一つの可能​​性があります。startコマンドは、我々は、アプリケーション名として空の文字列""を与えれば、与えられたファイルで、ファイルの拡張子に応じて、デフォルトのアクションを実行する機能があります:

start "" "The name of the file.ext"

例:

start "" "The name of the file.dotx"

これは、レジストリデータベース内のdotx拡張に関連する、のwinwordアプリケーションでデフォルトアクションを実行します。だから、

:最後の行が...それは、指定されたファイルを開くには、ネイティブのOS(この場合はWindows)をコールしない、まさにザッツ

class RuntimeExec { 
    public static void main(String[] args) { 
     try { 
     // Execute a command as a single line 
     File f = new File("C:/Users/Axel Richter/Documents/The Template.dotx"); 
     System.out.println(f.getAbsolutePath()); 
     String cmd = "cmd /C start \"\" \"" + f.getAbsolutePath() + "\""; 
     Process child = Runtime.getRuntime().exec(cmd); 

     InputStream in = child.getErrorStream(); 
     int c; 
     while ((c = in.read()) != -1) { 
      System.out.print((char)c); 
     } 
     in.close(); 

     } catch (IOException e) { 
     e.printStackTrace(); 
     } 

    } 
} 

class UseProcessBuilder { 
    public static void main(String[] args) { 
     try { 
     //use ProcessBuilder to have more control 
     File f = new File("C:/Users/Axel Richter/Documents/The Template.dotx"); 
     System.out.println(f.getAbsolutePath()); 
     String file = f.getAbsolutePath(); 
     ProcessBuilder pb = new ProcessBuilder("cmd", "/C", "start", "\"\"", file); 
     Process process = pb.start(); 

     InputStream in = process.getErrorStream(); 
     int c; 
     while ((c = in.read()) != -1) { 
      System.out.print((char)c); 
     } 
     in.close(); 

     } catch (IOException e) { 
     e.printStackTrace(); 
     } 
    } 
} 
+0

これはうまくいきました、ありがとう!私はわずかなフォローアップの質問があります:winword.exeが実際に存在するかどうかを検出する方法はありますか?そうでなければ、明らかにエラーがスローされます(「windord.exeが見つかりません」など)が、エラーが発生した場合はプロセスは「1」を返します(例:アクセス拒否)。私はそれだけで行くことはできません... – user2336377

+0

目的は何ですか? Windowsのエラーメッセージを回避するには?これは不可能です。このためには、アプリケーションがインストールされているかどうかにかかわらず** Windowsシステム全体を調べてから**起動するようにしなければなりません。さもなければ、 'ProcessBuilder'はエラーストリームを出力ストリームと一緒にファイルにリダイレクトできます。あるいは、 'Process.getErrorStream();'を使って 'Process'からErrorストリームを取得し、これから読み取ることができます。 –

+0

目的は次の通りです:MSWordが正しくインストールされているかどうかをチェックし、もしそうなら 'ProcessBuilder'を使ってテンプレートから新しい文書を起動します。さもなければ、定期的に 'Desktop.open(...)'を使用しています(例えば、LibreOfficeを使用するか、ユーザがインストールしたものであれ)。 私はちょっと遊んで、 'process.getErrorStream();'で管理できるものを見ていきます。あなたの助けをもう一度ありがとう。 – user2336377

0

一つの方法を開始することです:

は、ここで私は、テンプレートファイルを取得するコンテキストメニューの画像であり、何が起こることになっている、それは少しより明確にするために、テンプレートを処理して、Windowsがそのオープニングを処理し、デフォルトのインテントを使用するようにします。 Javaに触れてからしばらくしてきましたが、C#の場合はnew Process(tmp).Start()のようになります。

これがあなたが探しているものであれば、私は本当にわかりません。

+0

。ここを参照してください:https://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#open-java.io.File- – user2336377

+0

それはそのようなサウンドをします。それは意図の部分をスキップするかもしれないような音のようなものでもあります。 'Process'を試す価値がある。 – Chris

+0

私はC#で多大なことをしたことはありませんが、Javaの「プロセス」はC#と同じではないと思います。少なくとも私はファイルを渡して、あなたが述べたようにそれを始めることについて、どのようにすればいいのか分かりません。^^ – user2336377

関連する問題