PythonでWordのハイパーリンクを追加、削除する

Word文書において、ハイパーリンクとは、テキストや画像を他の文書やウェブページ、または同じ文書の異なる部分に接続する機能です。ハイパーリンクを追加することで、ユーザーは関連する情報に簡単に移動できるようになり、文書の双方向性と読みやすさが向上します。この記事では、**Pythonを使ってWordにハイパーリンクを追加したり、Word文書からハイパーリンクを削除する**方法を紹介します。

* [PythonでWordにハイパーリンクを追加する](#pythonでwordにハイパーリンクを追加する) 
* [PythonでWordのハイパーリンクを削除する]()

## Python Word ライブラリ
PythonによるWord文書操作を実装するには、[**Spire.Doc for Python**](https://www.e-iceblue.com/Introduce/doc-for-python.html)ライブラリをインストールする必要があります。このライブラリのpip installコマンドは以下の通りです：
> pip install Spire.Doc

## PythonでWordにハイパーリンクを追加する
Spire.Doc for Python ライブラリには、ハイパーリンクを追加するための **`AppendHyperlink()`** メソッドがあります：
* **`link`** - ハイパーリンクのアドレス
* **`text`** - 表示するテキスト（画像にハイパーリンクを追加するために画像を渡すこともできます）。
* **`type`** - ハイパーリンクのタイプを表します (WebLink、EMailLink、Bookmark、FileLink など)。

Python コード：
```python
from spire.doc import *
from spire.doc.common import *

# Word文書を作成する
doc = Document()

# セクションの追加
section = doc.AddSection()

# 段落を追加する
paragraph = section.AddParagraph()

# シンプルなウェブリンクを追加する
paragraph.AppendHyperlink("https://ABCD.com/", "ホームページ", HyperlinkType.WebLink)

# 改行を加える
paragraph.AppendBreak(BreakType.LineBreak)
paragraph.AppendBreak(BreakType.LineBreak)

# Eメールリンクを追加する
paragraph.AppendHyperlink("mailto:support@e-iceblue.com", "メールアドレス", HyperlinkType.EMailLink)

# 改行を加える
paragraph.AppendBreak(BreakType.LineBreak)
paragraph.AppendBreak(BreakType.LineBreak)

# ドキュメントリンクの追加
filePath = "C:\\Users\\Administrator\\Desktop\\report.xlsx"
paragraph.AppendHyperlink(filePath, "クリックしてファイルを表示", HyperlinkType.FileLink)

# 改行を加える
paragraph.AppendBreak(BreakType.LineBreak)
paragraph.AppendBreak(BreakType.LineBreak)

# 新しいセクションを追加し、ブックマークを作成する
section2 = doc.AddSection()
bookmarkParagrapg = section2.AddParagraph()
bookmarkParagrapg.AppendText("新しい段落を追加する")
start = bookmarkParagrapg.AppendBookmarkStart("Bookmark")
bookmarkParagrapg.Items.Insert(0, start)
bookmarkParagrapg.AppendBookmarkEnd("Bookmark")

# ブックマークへのリンク
paragraph.AppendHyperlink("Bookmark", "クリックすると、文書内の指定された場所にジャンプします", HyperlinkType.Bookmark)

# 改行を加える
paragraph.AppendBreak(BreakType.LineBreak)
paragraph.AppendBreak(BreakType.LineBreak)

# 画像のハイパーリンクを追加する
image = "C:\\Users\\Administrator\\Desktop\\work1.jpg"
picture = paragraph.AppendPicture(image)
paragraph.AppendHyperlink("https://ABCD.com/", picture, HyperlinkType.WebLink)

# ファイルの保存
doc.SaveToFile("WordHyperlink.docx", FileFormat.Docx2019);
doc.Dispose()
```
![WordHyperLink.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/ac40a7f5-0349-404d-a30f-e81ec550f455.png)


## PythonでWordのハイパーリンクを削除する
Word文書からすべてのハイパーリンクを削除するには、まずカスタムメソッド **`FindAllHyperlinks()`** を使用して文書内のすべてのハイパーリンクを検索し、カスタムメソッド **`FlattenHyperlinks()`** でハイパーリンクを平坦化する必要があります。

Python コード：
```python
from spire.doc import *
from spire.doc.common import *

# 文書内のすべてのハイパーリンクを検索する
def FindAllHyperlinks(document):
    hyperlinks = []
    for i in range(document.Sections.Count):
        section = document.Sections.get_Item(i)
        for j in range(section.Body.ChildObjects.Count):
            sec = section.Body.ChildObjects.get_Item(j)
            if sec.DocumentObjectType == DocumentObjectType.Paragraph:
                for k in range((sec if isinstance(sec, Paragraph) else None).ChildObjects.Count):
                    para = (sec if isinstance(sec, Paragraph)
                            else None).ChildObjects.get_Item(k)
                    if para.DocumentObjectType == DocumentObjectType.Field:
                        field = para if isinstance(para, Field) else None
                        if field.Type == FieldType.FieldHyperlink:
                            hyperlinks.append(field)
    return hyperlinks

# ハイパーリンク・フィールドをフラットにする
def FlattenHyperlinks(field):
    ownerParaIndex = field.OwnerParagraph.OwnerTextBody.ChildObjects.IndexOf(
        field.OwnerParagraph)
    fieldIndex = field.OwnerParagraph.ChildObjects.IndexOf(field)
    sepOwnerPara = field.Separator.OwnerParagraph
    sepOwnerParaIndex = field.Separator.OwnerParagraph.OwnerTextBody.ChildObjects.IndexOf(
        field.Separator.OwnerParagraph)
    sepIndex = field.Separator.OwnerParagraph.ChildObjects.IndexOf(
        field.Separator)
    endIndex = field.End.OwnerParagraph.ChildObjects.IndexOf(field.End)
    endOwnerParaIndex = field.End.OwnerParagraph.OwnerTextBody.ChildObjects.IndexOf(
        field.End.OwnerParagraph)

    FormatFieldResultText(field.Separator.OwnerParagraph.OwnerTextBody,
                           sepOwnerParaIndex, endOwnerParaIndex, sepIndex, endIndex)

    field.End.OwnerParagraph.ChildObjects.RemoveAt(endIndex)
    
    for i in range(sepOwnerParaIndex, ownerParaIndex - 1, -1):
        if i == sepOwnerParaIndex and i == ownerParaIndex:
            for j in range(sepIndex, fieldIndex - 1, -1):
                field.OwnerParagraph.ChildObjects.RemoveAt(j)

        elif i == ownerParaIndex:
            for j in range(field.OwnerParagraph.ChildObjects.Count - 1, fieldIndex - 1, -1):
                field.OwnerParagraph.ChildObjects.RemoveAt(j)

        elif i == sepOwnerParaIndex:
            for j in range(sepIndex, -1, -1):
                sepOwnerPara.ChildObjects.RemoveAt(j)
        else:
            field.OwnerParagraph.OwnerTextBody.ChildObjects.RemoveAt(i)

# フィールドをテキスト範囲に変換し、テキスト書式をクリアする
def FormatFieldResultText(ownerBody, sepOwnerParaIndex, endOwnerParaIndex, sepIndex, endIndex):
    for i in range(sepOwnerParaIndex, endOwnerParaIndex + 1):
        para = ownerBody.ChildObjects[i] if isinstance(
            ownerBody.ChildObjects[i], Paragraph) else None
        if i == sepOwnerParaIndex and i == endOwnerParaIndex:
            for j in range(sepIndex + 1, endIndex):
               if isinstance(para.ChildObjects[j], TextRange):
                 FormatText(para.ChildObjects[j])

        elif i == sepOwnerParaIndex:
            for j in range(sepIndex + 1, para.ChildObjects.Count):
                if isinstance(para.ChildObjects[j], TextRange):
                  FormatText(para.ChildObjects[j])
        elif i == endOwnerParaIndex:
            for j in range(0, endIndex):
               if isinstance(para.ChildObjects[j], TextRange):
                 FormatText(para.ChildObjects[j])
        else:
            for j, unusedItem in enumerate(para.ChildObjects):
                if isinstance(para.ChildObjects[j], TextRange):
                  FormatText(para.ChildObjects[j])

# テキストスタイルの設定
def FormatText(tr):
    tr.CharacterFormat.TextColor = Color.get_Black()
    tr.CharacterFormat.UnderlineStyle = UnderlineStyle.none

# Word文書を読み込む
doc = Document()
doc.LoadFromFile("WordHyperlink.docx")

# すべてのハイパーリンクを取得する
hyperlinks = FindAllHyperlinks(doc)

# フラット・ハイパーリンク
for i in range(len(hyperlinks) - 1, -1, -1):
    FlattenHyperlinks(hyperlinks[i])

# ファイルの保存
doc.SaveToFile("DeleteHyperlink.docx", FileFormat.Docx)
doc.Close()
```
![RemoveWordLinkR.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/9c9caf12-c7bd-467c-bf74-eb6ba42fc67a.png)


ウォーターマークを削除するには？クリックして1ヶ月のトライアルライセンスをリクエストする：

https://www.e-iceblue.com/TemLicense.html