【Java】Word文書に数式を追加または読み取る

数式とは、特定の概念や原理、計算を表す数式や表現です。科学論文や数学の文書には欠かせない要素です。文書に方程式を組み込むことで、複雑な数学的概念や計算を読者にわかりやすく、専門的に効果的に伝えることができます。今回は、無料の[Free Spire.Doc for Java](https://jp.e-iceblue.com/introduce/free-spire-doc-for-java.html)ライブラリを使用して、**Word文書に数式を追加したり読み取ったりする方法**について説明します。
- **[Word文書に数式を追加する](#word文書に数式を追加する)**
- **[Word文書で数式を読み取る](#word文書で数式を読み取る)**

### 【依存関係の追加】
この方法は、無料のFree Spire.Doc for Javaが必要ですので、先にjarファイルをインポートしてください。
#### 1. Maven
Maven を使用している場合、プロジェクトの pom.xml ファイルに以下のコードを追加することで、簡単にアプリケーションに JAR ファイルをインポートすることができます。
```xml
<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.doc.free</artifactId>
        <version>5.2.0</version>
    </dependency>
</dependencies>
```

#### 2. 公式サイトよりJarファイルをダウンロード
まず、[Free Spire.Doc for Javaの公式サイト](https://jp.e-iceblue.com/download/free-spire-doc-for-java.html)よりzipファイルをダウンロードします。zipファイルを解凍し、libフォルダの下にあるSpire.Doc.jarファイルを依存関係としてプロジェクトにインポートしてください。

## Word文書に数式を追加する
Free Spire.Doc for Javaでは、**OfficeMath.fromLatexMathCode(String latexMathCode)** または **OfficeMath.fromMathMLCode(String mathMLCode)** メソッドを使用して、LateXコードまたはMathMLコードを指定することで数式を簡単に作成することができます。その後、**Paragraph.getItems().add(IDocumentObject entity)** メソッドを使用して、Word文書の特定の段落に方程式を追加できます。
以下の手順で、Word文書に数式を作成し追加する方法を説明します。
- LateXのコードを **String** の配列に入れます。
- MathMLのコードを **String** の配列に入れます。
- **Document** のインスタンスを作成します。
- **Document.addSection()** メソッドを使用してセクションを追加します。
- **String** 配列内のすべてのLateXコードを循環させます。
- **Section.addParagraph()** メソッドを使用して、セクションに段落を追加します。
- OfficeMathのインスタンスを作成し、**OfficeMath.fromLatexMathCode(String latexMathCode)** メソッドを使用して、現在のLateXコードを数式に変換します。
- **Paragraph.getItems().add(IDocumentObject entity)** メソッドを使用して、数式を段落に追加します。
- **String** 配列のすべての MathML コードを循環さ せます。
- **Section.addParagraph()** メソッドを使用して、セクションに段落を追加します。
- OfficeMathのインスタンスを作成し、**OfficeMath.fromMathMLCode(String mathMLCode)** メソッドを使用して、現在のMathMLコードを数式に変換します。
- **Paragraph.getItems().add(IDocumentObject entity)** メソッドを使用して、数式を段落に追加します。
- **Document.saveToFile(String filename, FileFormat fileFormat)** メソッドを使用して、文書を保存します。

**Java**
```java
import com.spire.doc.*;
import com.spire.doc.documents.HorizontalAlignment;
import com.spire.doc.documents.Paragraph;
import com.spire.doc.documents.Style;
import com.spire.doc.fields.TextRange;
import com.spire.doc.fields.omath.OfficeMath;

public class AddMathEquations {
    public static void main(String[] args) {

        //LateXのコードをString配列に入れる
        String[] latexMathCode = {
                "\\left(a+\\frac{b}{c}\\right)",
                "\\rect{\\frac{a}{b}}",
                "\\frac{a}{b+c}",
                "\\sqrt[5]{a^2}",
        };

        //MathMLのコードをStringの配列に入れる
        String[] mathMLCode = {
                "<mml:math xmlns:mml=\"http://www.w3.org/1998/Math/MathML\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"><mml:msup><mml:mrow><mml:mi>x</mml:mi></mml:mrow><mml:mrow><mml:mn>2</mml:mn></mml:mrow></mml:msup><mml:mo>+</mml:mo><mml:msqrt><mml:msup><mml:mrow><mml:mi>x</mml:mi></mml:mrow><mml:mrow><mml:mn>2</mml:mn></mml:mrow></mml:msup><mml:mo>+</mml:mo><mml:mn>1</mml:mn></mml:msqrt><mml:mo>+</mml:mo><mml:mn>1</mml:mn></mml:math>",
                "<mml:math xmlns:mml=\"http://www.w3.org/1998/Math/MathML\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"><mml:mn>2</mml:mn><mml:mi>α</mml:mi><mml:mo>-</mml:mo><mml:mi>s</mml:mi><mml:mi>i</mml:mi><mml:mi>n</mml:mi><mml:mi>y</mml:mi><mml:mo>+</mml:mo><mml:mi>x</mml:mi></mml:math>",
                "<mml:math xmlns:mml=\"http://www.w3.org/1998/Math/MathML\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"><mml:mfrac><mml:mrow><mml:mn>1</mml:mn></mml:mrow><mml:mrow><mml:mn>2</mml:mn><mml:mo>+</mml:mo><mml:mi>x</mml:mi></mml:mrow></mml:mfrac></mml:math>",
                "<mml:math xmlns:mml=\"http://www.w3.org/1998/Math/MathML\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"><mml:mfenced><mml:mrow><mml:mn>1</mml:mn><mml:mo>+</mml:mo><mml:mo>|</mml:mo><mml:mi>x</mml:mi><mml:mo>-</mml:mo><mml:mfenced open=\"[\" close=\"]\"><mml:mrow><mml:mi>a</mml:mi><mml:mo>-</mml:mo><mml:mi>b</mml:mi></mml:mrow></mml:mfenced><mml:mo>|</mml:mo></mml:mrow></mml:mfenced></mml:math>",
        };

        //Documentのインスタンスを作成する
        Document doc = new Document();

        //セクションを追加する
        Section section = doc.addSection();

        //セクションに段落を追加する
        Paragraph paragraph = section.addParagraph();
        TextRange textRange = paragraph.appendText("数式の例\n");
        textRange.getCharacterFormat().setFontName("BIZ UDGothic");
        textRange.getCharacterFormat().setFontSize(16);
        textRange.getCharacterFormat().setBold(true);
        paragraph.getStyle().getParagraphFormat().setHorizontalAlignment(HorizontalAlignment.Center);

        Paragraph paragraph1 = null;
        OfficeMath officeMath;

        //LaTeXコードを指定して数式をセクションに追加する
        for (int i = 0; i < latexMathCode.length; i++) {
            paragraph1 = section.addParagraph();
            officeMath = new OfficeMath(doc);
            officeMath.fromLatexMathCode(latexMathCode[i]);
            paragraph1.getItems().add(officeMath);
        }

        //MathMLコードを指定して、数式をセクションに追加する
        for (int i = 0; i < mathMLCode.length; i++) {
            paragraph1 = section.addParagraph();
            officeMath = new OfficeMath(doc);
            officeMath.fromMathMLCode(mathMLCode[i]);
            paragraph1.getItems().add(officeMath);
        }

        //ドキュメントを保存する
        String result = "数式の追加.docx";
        doc.saveToFile(result, FileFormat.Docx_2013);
    }
}
```
![Word文書に数式を追加する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/f7538504-294b-27ae-ed10-67d809d9783e.png)

## Word文書で数式を読み取る
Word文書内の数式をMathMLコードに戻すには、文書内の要素を循環させ、OfficeMath型の要素を見つけ、**OfficeMath.toMathMLCode()** メソッドを使用してMathMLコードに変換します。
以下の手順で、Word文書内の数式をMathMLコードに読み戻す方法を説明します。
- **Document** のインスタンスを作成し、**Document.loadFromFile(String fileName)** メソッドを使用してWord文書を読み込みます。
- **StringBuilder** のインスタンスを作成します。
- 文書内のすべてのセクションを循環させます。
- 各セクションのすべての段落を循環させます。
- 各段落にあるすべての子オブジェクトを循環させます。
- オブジェクトがOfficeMath型であるかどうかを判断します。
- 結果が真であれば、オブジェクトをOfficeMath型にタイプキャストし、**OfficeMath.toMathMLCode()** メソッドを用いてMathMLコードに変換し、結果を **StringBuilder** インスタンスに追加します。
- **StringBuilder** インスタンスの内容をTXTファイルに書き込みます。

**Java**
```java
import com.spire.doc.*;
import com.spire.doc.fields.omath.OfficeMath;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class ReadMathEquations {
    public static void main(String[] args) {

        //Documentのインスタンスを作成する
        Document doc = new Document();
        //Word文書を読み込む
        doc.loadFromFile("数式の追加.docx");

        //StringBuilderのインスタンスを作成する
        StringBuilder stringBuilder = new StringBuilder();

        //ドキュメント内のすべてのセクションをループする
        for(int i = 0; i < doc.getSections().getCount(); i++){
            //各セクションのすべての段落をループする
            for(int j = 0; j < doc.getSections().get(i).getParagraphs().getCount(); j++){
                //各段落のすべての子オブジェクトをループする
                for(int k = 0;k < doc.getSections().get(i).getParagraphs().get(j).getChildObjects().getCount(); k++){
                    DocumentObject obj =doc.getSections().get(i).getParagraphs().get(j).getChildObjects().get(k);
                    //オブジェクトがOfficeMath型であるかどうかをチェックする
                    if (obj instanceof OfficeMath) {
                        OfficeMath math=(OfficeMath)doc.getSections().get(i).getParagraphs().get(j).getChildObjects().get(k);
                        //数式をMathMLのコードに読み替えて、その結果をStringBuilderに追加する
                        stringBuilder.append(math.toMathMLCode()+"\n");
                    }
                }
            }
        }

        //StringBuilderの内容をTXTファイルに書き込む
        File file = new File("数式の読み取り.txt");
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
            writer.append(stringBuilder);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
```
![Word文書で数式を読み取る](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/fbb0c0f4-a67a-1f8f-4358-fe7fdcee7431.png)

> **Spire.Doc for Javaは、その他にもWord文書に含まれる様々な要素の追加や読み込みが可能です。もっと詳しく知りたい方は、[Spire.Doc for Javaチュートリアル](https://jp.e-iceblue.com/tutorials/java/spire-doc-java/doc-java-program-guide-content.html)へどうぞ。**