2016-09-29 7 views
0

Ich möchte ein neues Dokument aus einer MS-Word-Vorlage aus meiner Java-App öffnen, aber nur verwalten, um die Vorlage selbst zu bearbeiten.neues Dokument von Vorlage erstellen

Hier ist meine Situation: Innerhalb meiner Jar-Datei ist eine Word-Vorlage, die an einen benutzerdefinierten Speicherort kopiert wird, so dass er/sie es bearbeiten kann. Anschließend kann die Anwendung diese bearbeitete Vorlage öffnen, Daten einfügen und in Word öffnen. Das alles funktioniert gut (mit Apache-POI), aber der letzte Schritt ist nicht ganz das, was ich will.

Normalerweise würde Word beim Doppelklicken auf eine Word-Vorlage ein NEUES Dokument (mit dem Titel "Document1") öffnen, das noch nirgendwo gespeichert ist. In meinem Fall öffnet Word die Word-Vorlage zur Bearbeitung (betitelt blablaMyTemplate), also die bereits gespeicherte Vorlage, aus der Dokumente erstellt werden sollen. Wie kann ich ein neu erstelltes Dokument mit Java aus der Vorlage öffnen?

Dies ist mein Code (try/catch und Strom Schließung weggelassen):

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 
    } 

Das Problem liegt in der letzten Zeile, aber ich habe keine Ahnung, was sonst ich hier nennen könnte.

es ein wenig klarer zu machen, hier ist ein Bild des Kontextmenüs ich auf der Template-Datei und was geschehen soll:

context menu on template

Antwort

2

Sie haben das Problem bereits genau beschrieben. Desktop.open wird genau das tun, was es sagt. Es wird das Ereignis open für die aufgerufene Anwendung ausgeführt, die dem Dateityp zugeordnet ist.

Sie müssen das Ereignis new ausführen. Dies kann in Word unter Verwendung von startup command-line switches to start Word erreicht werden.

In dem verknüpften Wissensbasis-Eintrag können Sie finden:

...

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

...

Um dies zu tun mit Java entweder Runtime.getRuntime().exec oder ProcessBuilder kann verwendet werden. Bei beiden würde ich empfehlen, zunächst den Kommandointerpreter CMD als Shell zu starten und den Befehl start von diesem zu verwenden, um die Anwendung zu starten. So vermeiden wir es, den genauen Pfad zur Anwendung zu kennen.

Beispiele:

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(); 
     } 
    } 
} 

Es gibt eine Möglichkeit nicht explizit die winword Anwendung zu starten.Der start Befehl hat die Funktion die Standardaktion nach der Dateierweiterung mit der angegebenen Datei auszuführen, wenn wir einer leeren Zeichenfolge "" als Anwendungsname geben:

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

Beispiel:

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

Dies führt die Standardaktion new in winword Anwendung, die mit der dotx Erweiterung in der Registrierungsdatenbank verwandt ist. So

:

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

Das funktioniert, vielen Dank! Ich habe nur eine kleine Follow-up-Frage: Gibt es eine Möglichkeit zu erkennen, ob winword.exe tatsächlich existiert? Wenn dies nicht der Fall ist, wird offensichtlich ein Fehler ausgelöst ("windord.exe konnte nicht gefunden werden" oder etwas), aber der Prozess gibt '1' für jeden Fehler zurück, den ich erzeugen konnte (zum Beispiel: Zugriff verweigert), also Ich kann nicht nur darauf gehen ... – user2336377

+0

Was ist das Ziel? Windows-Fehlermeldung vermeiden? Dies wird nicht möglich sein. Dazu müssten wir das gesamte Windows-System untersuchen, ob die Anwendung installiert ist oder nicht ** bevor ** wir versuchen, es zu starten. Andernfalls kann der 'ProcessBuilder' den Error-Stream zusammen mit dem Ausgabestream in eine Datei umleiten. Oder Sie könnten den Error-Stream vom 'Process' mit' process.getErrorStream(); 'abrufen und daraus lesen. –

+0

Ihr Ziel wäre es, dies wie folgt zu tun: Überprüfen Sie, ob MSWord korrekt installiert ist, und falls ja, starten Sie ein neues Dokument mit dem 'ProcessBuilder' aus der Vorlage, ansonsten erstellen Sie ein gespeichertes Dokument aus der Vorlage in einem temporären Ordner und öffnen es Es verwendet regelmäßig 'Desktop.open (...)' (zum Beispiel mit LibreOffice, oder was auch immer der Benutzer installiert hat). Ich werde ein wenig herumspielen und sehen, was ich mit 'process.getErrorStream();' verwalten kann. Danke nochmal für deine Hilfe. – user2336377

0

Eine Möglichkeit, dies zu tun, ist ein starten Prozess auf der Vorlage, so dass Windows die Öffnung behandelt und die Standardabsicht verwendet. Es ist eine Weile her, seit ich Java berührt habe, aber wenn es wie C# ist, wird es so etwas wie new Process(tmp).Start() sein.

Obwohl, ich bin nicht wirklich sicher, ob das genau das ist, wonach Sie suchen.

+0

Das ist genau das, was die letzte Zeile tut ... Es ruft die native OS (in diesem Fall Windows) die angegebene Datei zu öffnen. Siehe hier: https://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#open-java.io.File- – user2336377

+0

Es klingt irgendwie so. Es klingt auch so, als würde es den Vorsatz überspringen. Es lohnt sich, 'Process' imo zu versuchen. – Chris

+0

Ich habe noch nie viel mit C# gemacht, aber ich glaube nicht, dass der Java 'Prozess' der gleiche wie der C# ist. Wenigstens habe ich keine Ahnung, wie ich die Datei einfach weiterleiten und starten würde, wie du es gesagt hast. ^^ – user2336377

Verwandte Themen