JavaでWord文書/テンプレートを開いて操作する方法は?

kensvebary:

.doc/.dot/.docx/.dotx(私はうるさいので、私はそれを機能させたい)ドキュメントを開き、プレースホルダー(または同様の何か)を解析し、独自のデータを入力して、生成された.doc/.docx/.dotx/.pdfドキュメントを返す必要があります。

そして何よりも、それを無料で実現するためのツールが必要です。

私は自分のニーズに合うものを探して回りましたが、何も見つかりません。Docmosis、Javadocx、Asposeなどのツールは商用です。私が読んだことによると、Apache POIはこれをうまく実装できていません(現在、フレームワークのWord部分に取り組んでいる公式の開発者はいません)。

トリックを行うことができるように見える唯一のものは、OpenOffice UNO APIです。しかし、それはこのAPIを使用したことがない人(私のように)にとってはかなり大きなバイトです。

だから、これに飛び込むつもりなら、私が正しい道にいることを確認する必要があります。

誰かがこれについてアドバイスをくれますか?

kensvebary:

私はこの質問を投稿してから長い時間が経過していることを知っており、終了したら解決策を投稿すると述べました。だからここにあります。

いつか誰かのお役に立てば幸いです。これは完全なワーキングクラスであり、アプリケーションに配置し、.docxテンプレートを含むTEMPLATE_DIRECTORY_ROOTディレクトリをルートディレクトリに配置するだけです。

使い方はとても簡単です。.docxファイルにプレースホルダー(キー)を配置し、ファイル名と、そのファイルに対応するキーと値のペアを含むマップを渡します。

楽しい!

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URI;
import java.util.Deque;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;

public class DocxManipulator {

    private static final String MAIN_DOCUMENT_PATH = "word/document.xml";
    private static final String TEMPLATE_DIRECTORY_ROOT = "TEMPLATES_DIRECTORY/";


    /*    PUBLIC METHODS    */

    /**
     * Generates .docx document from given template and the substitution data
     * 
     * @param templateName
     *            Template data
     * @param substitutionData
     *            Hash map with the set of key-value pairs that represent
     *            substitution data
     * @return
     */
    public static Boolean generateAndSendDocx(String templateName, Map<String,String> substitutionData) {

        String templateLocation = TEMPLATE_DIRECTORY_ROOT + templateName;

        String userTempDir = UUID.randomUUID().toString();
        userTempDir = TEMPLATE_DIRECTORY_ROOT + userTempDir + "/";

        try {

            // Unzip .docx file
            unzip(new File(templateLocation), new File(userTempDir));       

            // Change data
            changeData(new File(userTempDir + MAIN_DOCUMENT_PATH), substitutionData);

            // Rezip .docx file
            zip(new File(userTempDir), new File(userTempDir + templateName));

            // Send HTTP response
            sendDOCXResponse(new File(userTempDir + templateName), templateName);

            // Clean temp data
            deleteTempData(new File(userTempDir));
        } 
        catch (IOException ioe) {
            System.out.println(ioe.getMessage());
            return false;
        }

        return true;
    }


    /*    PRIVATE METHODS    */

    /**
     * Unzipps specified ZIP file to specified directory
     * 
     * @param zipfile
     *            Source ZIP file
     * @param directory
     *            Destination directory
     * @throws IOException
     */
    private static void unzip(File zipfile, File directory) throws IOException {

        ZipFile zfile = new ZipFile(zipfile);
        Enumeration<? extends ZipEntry> entries = zfile.entries();

        while (entries.hasMoreElements()) {
          ZipEntry entry = entries.nextElement();
          File file = new File(directory, entry.getName());
          if (entry.isDirectory()) {
            file.mkdirs();
          } 
          else {
            file.getParentFile().mkdirs();
            InputStream in = zfile.getInputStream(entry);
            try {
              copy(in, file);
            } 
            finally {
              in.close();
            }
          }
        }
      }


    /**
     * Substitutes keys found in target file with corresponding data
     * 
     * @param targetFile
     *            Target file
     * @param substitutionData
     *            Map of key-value pairs of data
     * @throws IOException
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static void changeData(File targetFile, Map<String,String> substitutionData) throws IOException{

        BufferedReader br = null;
        String docxTemplate = "";
        try {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(targetFile), "UTF-8"));
            String temp;
            while( (temp = br.readLine()) != null)
                docxTemplate = docxTemplate + temp; 
            br.close();
            targetFile.delete();
        } 
        catch (IOException e) {
            br.close();
            throw e;
        }

        Iterator substitutionDataIterator = substitutionData.entrySet().iterator();
        while(substitutionDataIterator.hasNext()){
            Map.Entry<String,String> pair = (Map.Entry<String,String>)substitutionDataIterator.next();
            if(docxTemplate.contains(pair.getKey())){
                if(pair.getValue() != null)
                    docxTemplate = docxTemplate.replace(pair.getKey(), pair.getValue());
                else
                    docxTemplate = docxTemplate.replace(pair.getKey(), "NEDOSTAJE");
            }
        }

        FileOutputStream fos = null;
        try{
            fos = new FileOutputStream(targetFile);
            fos.write(docxTemplate.getBytes("UTF-8"));
            fos.close();
        }
        catch (IOException e) {
            fos.close();
            throw e;
        }
    }

    /**
     * Zipps specified directory and all its subdirectories
     * 
     * @param directory
     *            Specified directory
     * @param zipfile
     *            Output ZIP file name
     * @throws IOException
     */
    private static void zip(File directory, File zipfile) throws IOException {

        URI base = directory.toURI();
        Deque<File> queue = new LinkedList<File>();
        queue.push(directory);
        OutputStream out = new FileOutputStream(zipfile);
        Closeable res = out;

        try {
          ZipOutputStream zout = new ZipOutputStream(out);
          res = zout;
          while (!queue.isEmpty()) {
            directory = queue.pop();
            for (File kid : directory.listFiles()) {
              String name = base.relativize(kid.toURI()).getPath();
              if (kid.isDirectory()) {
                queue.push(kid);
                name = name.endsWith("/") ? name : name + "/";
                zout.putNextEntry(new ZipEntry(name));
              } 
              else {
                if(kid.getName().contains(".docx"))
                    continue;  
                zout.putNextEntry(new ZipEntry(name));
                copy(kid, zout);
                zout.closeEntry();
              }
            }
          }
        } 
        finally {
          res.close();
        }
      }

    /**
     * Sends HTTP Response containing .docx file to Client
     * 
     * @param generatedFile
     *            Path to generated .docx file
     * @param fileName
     *            File name of generated file that is being presented to user
     * @throws IOException
     */
    private static void sendDOCXResponse(File generatedFile, String fileName) throws IOException {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        HttpServletResponse response = (HttpServletResponse) externalContext
                .getResponse();

        BufferedInputStream input = null;
        BufferedOutputStream output = null;

        response.reset();
        response.setHeader("Content-Type", "application/msword");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        response.setHeader("Content-Length",String.valueOf(generatedFile.length()));

        input = new BufferedInputStream(new FileInputStream(generatedFile), 10240);
        output = new BufferedOutputStream(response.getOutputStream(), 10240);

        byte[] buffer = new byte[10240];
        for (int length; (length = input.read(buffer)) > 0;) {
            output.write(buffer, 0, length);
        }

        output.flush();
        input.close();
        output.close();

        // Inform JSF not to proceed with rest of life cycle
        facesContext.responseComplete();
    }


    /**
     * Deletes directory and all its subdirectories
     * 
     * @param file
     *            Specified directory
     * @throws IOException
     */
    public static void deleteTempData(File file) throws IOException {

        if (file.isDirectory()) {

            // directory is empty, then delete it
            if (file.list().length == 0)
                file.delete();
            else {
                // list all the directory contents
                String files[] = file.list();

                for (String temp : files) {
                    // construct the file structure
                    File fileDelete = new File(file, temp);
                    // recursive delete
                    deleteTempData(fileDelete);
                }

                // check the directory again, if empty then delete it
                if (file.list().length == 0)
                    file.delete();
            }
        } else {
            // if file, then delete it
            file.delete();
        }
    }

    private static void copy(InputStream in, OutputStream out) throws IOException {

        byte[] buffer = new byte[1024];
        while (true) {
          int readCount = in.read(buffer);
          if (readCount < 0) {
            break;
          }
          out.write(buffer, 0, readCount);
        }
      }

      private static void copy(File file, OutputStream out) throws IOException {
        InputStream in = new FileInputStream(file);
        try {
          copy(in, out);
        } finally {
          in.close();
        }
      }

      private static void copy(InputStream in, File file) throws IOException {
        OutputStream out = new FileOutputStream(file);
        try {
          copy(in, out);
        } finally {
          out.close();
        }
     }

}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Javaを使用してWord文書テンプレートを編集する方法

分類Dev

ブラウザからWord文書をテンプレートとして起動するにはどうすればよいですか?

分類Dev

Word文書テンプレートの変数をJavaで置き換える

分類Dev

ネットワーク上のWord2010ユーザーとWord2011ユーザーの間で同じテンプレート(.dotm)に基づいてWord文書を共有するにはどうすればよいですか?

分類Dev

閉じたWord文書からWordテンプレート(VBA)でテキストを取得する

分類Dev

Word文書を開いて、文書を表示せずにその中のテキストを見つけるにはどうすればよいですか?

分類Dev

PowershellでWordテンプレートを操作する

分類Dev

Microsoft Word文書を保存して、アウトラインビューで自動的に開くようにする方法はありますか?

分類Dev

入力フィールドのフォームからWord文書を生成する方法は?本当のテンプレート?

分類Dev

XMLファイルのデータを使用してWord文書(docx)を生成する/テンプレートに基づいてXMLをWord文書に変換する

分類Dev

djangoテンプレートのcondtionalステートメントで辞書の値を操作する方法

分類Dev

djangoテンプレートの辞書で辞書を反復する方法は?

分類Dev

オープンAPIを公開して文書化することは良い習慣ですか?

分類Dev

Mojoliciousテンプレートで新しい構文機能を使用する方法

分類Dev

JavaまたはJava Native Accessを使用してローカルで開いているMS Wordドキュメントのテキストを読み取る方法

分類Dev

rubyを使用してmailchimpテンプレートを操作するにはどうすればよいですか?

分類Dev

翡翠テンプレートでHTML構文を使用する方法

分類Dev

phpwordで他のいくつかのコンテンツをすべて含むWord文書を作成する方法

分類Dev

フォームを開いた後、Word文書の最後にサブドキュメントを追加するにはどうすればよいですか?

分類Dev

ページの向きを変えてJavaScriptからWord文書を生成するにはどうすればよいですか?(ポートレートからランドスケープ)

分類Dev

Javaを使用してWord文書に動的テーブルを作成する方法

分類Dev

VB(VS2019)のWord文書から印刷するときに、コードを使用してプリンターのトレイを選択する方法

分類Dev

Word文書テンプレートの問題で太字のスニペットをフォーマットするxmlコード

分類Dev

Word文書でAUTOITを使用して貼り付け(CTRL + V)をシミュレートする方法

分類Dev

JavaScriptを使用してブラウザーでWord文書(.doc、.docx)をレンダリングするにはどうすればよいですか?

分類Dev

開いているWord文書を閉じずに名前を変更することはできますか?

分類Dev

VB.netアプリケーションでWord文書のフッター内のテキストを見つけて置き換えるにはどうすればよいですか?

分類Dev

Matlab: テンプレートに基づいてデータ レポートを公開する方法

分類Dev

Djangoテンプレート:含まれている子テンプレートのブロックを拡張テンプレートで上書きする

Related 関連記事

  1. 1

    Javaを使用してWord文書テンプレートを編集する方法

  2. 2

    ブラウザからWord文書をテンプレートとして起動するにはどうすればよいですか?

  3. 3

    Word文書テンプレートの変数をJavaで置き換える

  4. 4

    ネットワーク上のWord2010ユーザーとWord2011ユーザーの間で同じテンプレート(.dotm)に基づいてWord文書を共有するにはどうすればよいですか?

  5. 5

    閉じたWord文書からWordテンプレート(VBA)でテキストを取得する

  6. 6

    Word文書を開いて、文書を表示せずにその中のテキストを見つけるにはどうすればよいですか?

  7. 7

    PowershellでWordテンプレートを操作する

  8. 8

    Microsoft Word文書を保存して、アウトラインビューで自動的に開くようにする方法はありますか?

  9. 9

    入力フィールドのフォームからWord文書を生成する方法は?本当のテンプレート?

  10. 10

    XMLファイルのデータを使用してWord文書(docx)を生成する/テンプレートに基づいてXMLをWord文書に変換する

  11. 11

    djangoテンプレートのcondtionalステートメントで辞書の値を操作する方法

  12. 12

    djangoテンプレートの辞書で辞書を反復する方法は?

  13. 13

    オープンAPIを公開して文書化することは良い習慣ですか?

  14. 14

    Mojoliciousテンプレートで新しい構文機能を使用する方法

  15. 15

    JavaまたはJava Native Accessを使用してローカルで開いているMS Wordドキュメントのテキストを読み取る方法

  16. 16

    rubyを使用してmailchimpテンプレートを操作するにはどうすればよいですか?

  17. 17

    翡翠テンプレートでHTML構文を使用する方法

  18. 18

    phpwordで他のいくつかのコンテンツをすべて含むWord文書を作成する方法

  19. 19

    フォームを開いた後、Word文書の最後にサブドキュメントを追加するにはどうすればよいですか?

  20. 20

    ページの向きを変えてJavaScriptからWord文書を生成するにはどうすればよいですか?(ポートレートからランドスケープ)

  21. 21

    Javaを使用してWord文書に動的テーブルを作成する方法

  22. 22

    VB(VS2019)のWord文書から印刷するときに、コードを使用してプリンターのトレイを選択する方法

  23. 23

    Word文書テンプレートの問題で太字のスニペットをフォーマットするxmlコード

  24. 24

    Word文書でAUTOITを使用して貼り付け(CTRL + V)をシミュレートする方法

  25. 25

    JavaScriptを使用してブラウザーでWord文書(.doc、.docx)をレンダリングするにはどうすればよいですか?

  26. 26

    開いているWord文書を閉じずに名前を変更することはできますか?

  27. 27

    VB.netアプリケーションでWord文書のフッター内のテキストを見つけて置き換えるにはどうすればよいですか?

  28. 28

    Matlab: テンプレートに基づいてデータ レポートを公開する方法

  29. 29

    Djangoテンプレート:含まれている子テンプレートのブロックを拡張テンプレートで上書きする

ホットタグ

アーカイブ