Excel VBAで図形内文字を置換する方法|グループ図形も対応&アドイン不要

  • URLをコピーしました!

Excelで業務資料を作っていると、テキストボックスや吹き出し、さらにはグループ図形の中にある文字を一括で置換したい場面ってありますよね。

でも、検索(Ctrl+H)では反応せず、「なぜ置き換わらないの!?」と戸惑った経験がある方も多いはず。

この記事では、図形内テキストを対象にしたVBAによる置換方法を、コピペで使えるコード付きで丁寧に解説します。アドイン不要で、グループ図形にも対応しているので、実務でも即活用できます!

この記事を読むとわかること

  • Excel図形内テキストが置換されない理由とその仕組み
  • グループ図形を含めた一括置換用VBAの実装方法
  • 実行時にハマりやすいポイントとその回避策
目次

なぜ図形内の文字は置換されないのか?

Excelの図形に含まれる文字列は、一見セルのデータと同じように見えますが、実は内部構造がまったく異なります。

検索・置換(Ctrl + H)で反応しないのは、図形の中のテキストがセルとは別のプロパティに格納されているためです。地味に気づきづらいところですが、ここが自動化の第一の壁になります。

また、よくある「テキストボックス」や「吹き出し」なども、Shapeオブジェクトの種類としては違う扱いになっており、処理の仕方に工夫が必要です。

特に業務資料などでグループ化されている図形は、外から見るとひとまとまりですが、内部的には再帰処理しないとたどり着けない構造になっていたりします。

図形のテキストはセルとまったく別物

Excelのセル内のデータはWorksheet.Cellsで扱えますが、図形に含まれる文字は Shape.TextFrame.TextRange.Text に格納されています。これは検索・置換のUIが見ている領域とは別なんですね。

したがって、通常の置換操作では図形内の文字列は無視されます。地味に見落とされがちですが、これを理解しておかないと「VBAで一括置換したいのに反応しない…」という状態に陥ります。

テキストボックスと吹き出しは同じじゃない

見た目が似ている「テキストボックス」と「吹き出し」も、VBAの視点では異なる AutoShapeType を持ちます。たとえば、テキストボックスは msoTextBox、吹き出しは msoShapeOvalCallout など。

ただ、すべてを網羅しようとすると逆にややこしくなるので、HasTextFrameHasText を使って「文字を持っている図形かどうか」で判定するのが現実的です。

グループ図形の中にはさらに図形がある

複数の図形を選択して「グループ化」すると、VBA上では GroupItems というコレクションとして扱われます。つまり、グループ図形1個を処理するだけでは中のテキストには届かないのです。

ここを知らずにマクロを書いても、「なんで一部だけ置換されないの?」となってしまいます。再帰的に中に潜って処理するという考え方が大事になってきます。


実務で使える図形テキスト置換マクロ

という点も踏まえて、実務で使えるVBAマクロをご紹介します。これ一つで、単独図形もグループ図形も、さらに複数の語句の置換も対応できます。

コピペで使えるVBAソースコード

以下のコードは、アクティブシートのすべての図形を対象に、指定した語句をまとめて置換します。

' ===============================
' メイン処理:置換キーワードのセットと全体実行
' ===============================
Sub ReplaceTextInShapesMain()
    Dim findWords As Variant     ' 置換対象語句の配列
    Dim repWords As Variant      ' 置換後語句の配列
    Dim i As Long

    ' ***** 適宜変更してください START *****
    ' 置換対象と置換後の語句を1対1対応で定義(順序に注意)
    findWords = Array("旧語句①", "旧語句②")
    repWords = Array("新語句①", "新語句②")
    ' ***** 適宜変更してください END *****

    Application.ScreenUpdating = False

    ' それぞれの語句ペアについて、図形内テキストを一括置換
    For i = 0 To UBound(findWords)
        ReplaceTextRecursive ActiveSheet.Shapes, CStr(findWords(i)), CStr(repWords(i))
    Next i

    Application.ScreenUpdating = True

End Sub

' ===============================
' 再帰処理:図形/グループ図形の中をたどって置換処理を実行
' ===============================
Sub ReplaceTextRecursive(ByVal shapes As Object, findText As String, replText As String)
    Dim shp As Shape

    ' 各図形について順に処理
    For Each shp In shapes
        If shp.Type = msoGroup Then
            ' 図形がグループだった場合は、GroupItems を再帰的に処理
            ReplaceTextRecursive shp.GroupItems, findText, replText
        Else
            ' 単体図形の場合は、テキストを置換
            ReplaceTextInShape shp, findText, replText
        End If
    Next shp
End Sub

' ===============================
' テキスト置換処理
' ===============================
Private Sub ReplaceTextInShape(shp As Shape, findText As String, replText As String)
    On Error Resume Next

    ' TextFrame2 が存在し、かつテキストを持っている場合のみ処理
    If Not shp.TextFrame2 Is Nothing Then
        If shp.TextFrame2.HasText Then
            ' テキストの中で、findText を replText に置換
            shp.TextFrame2.TextRange.Text = Replace(shp.TextFrame2.TextRange.Text, findText, replText)
        End If
    End If

    On Error GoTo 0
End Sub

このコードを実行することで、図形がグループ化されていても、テキストが複数あっても、自動的に置換してくれます。

なお、置換対象と置換後の語句ですが、以下変数のArray()内の値を適宜変更してください(findWords = 置換対象、repWords = 置換後 を1対1で定義してください)。

' ***** 適宜変更してください START *****
' 置換対象と置換後の語句を1対1対応で定義(順序に注意)
findWords = Array("旧語句①", "旧語句②")
repWords = Array("新語句①", "新語句②")
' ***** 適宜変更してください END *****

マクロの実行方法

  1. 「開発」タブをクリック(※表示されていない場合は、オプション→リボンのユーザー設定で表示させてください)
  2. 「挿入」→「フォームコントロール」の中から、「ボタン(フォームコントロール)」を選択
  3. ワークシート上にボタンを配置すると、マクロ選択画面が自動で開くので、ReplaceTextInShapesMain を選んで「OK」
  4. ボタンのラベルを変更(例:「図形置換実行」など)

注意:このマクロは .xlsx では使えません。必ず .xlsm(マクロ有効ブック)形式で保存してください。


ハマりやすいポイントとその回避策

ここではよくあるトラブルと、その対策を整理しておきます。

重くなったときの対策

図形が多いファイルや階層が深いグループ構造では、どうしても処理に時間がかかります。そんなときは Application.ScreenUpdating = False を使うことで、描画処理を止めて高速化できます(今回のVBAマクロには既に実装済み)。

それでも重い場合は、対象の図形を絞る/対象の語句数を減らすなど、負荷を分散する工夫も有効です。

なぜか置換されない…その原因とは?

いくつか原因が考えられますが、よくあるのは次のようなケースです:

  • TextFrame2.HasText = False → 中身が空または非表示
  • Shape.Visible = False → 表示されていない図形

このあたりは条件付きでログを出すようにすれば、調査がしやすくなります。

試しに Debug.Print shp.Name で置換対象外になっている図形の名前を確認してみると、原因がわかるかもしれません。置換されない図形がある場合、以下でReplaceTextInShapeプロシージャを置き換えて試してみてください。

' ===============================
' テキスト置換処理+デバッグログ
' ===============================
Private Sub ReplaceTextInShape(shp As Shape, findText As String, replText As String)
    On Error Resume Next

    Debug.Print "図形名: " & shp.Name

    If shp.Visible = msoFalse Then
        Debug.Print " 非表示の図形です" ' ※VBAで意図的に非表示にした図形が対象
    End If

    If shp.TextFrame2 Is Nothing Then
        Debug.Print " TextFrame2 が存在しません"
    ElseIf shp.TextFrame2.HasText = msoFalse Then
        Debug.Print " テキストが存在しません"
    Else
        Dim originalText As String
        originalText = shp.TextFrame2.TextRange.Text

        If InStr(originalText, findText) > 0 Then
            shp.TextFrame2.TextRange.Text = Replace(originalText, findText, replText)
            Debug.Print " 置換成功"
        Else
            Debug.Print " 該当語句なし"
        End If
    End If

    On Error GoTo 0
End Sub

まとめ

Excelで図形内の文字を置換するには、セルと異なる構造を理解し、再帰的に処理するVBAが必要です。

本記事では、グループ図形にも対応した実用的なマクロを紹介しました。実際に試してみて「一括置換がうまくいった」と感じたときのスッキリ感は格別です。

とはいえ、図形の構成や使い方はケースバイケースなので、自分の環境に合うように少しずつ調整していくのがよさそうです。

この記事を書いた人

業務システムとWebアプリの開発に20年以上携わるフリーランスエンジニア。
製造業や物流業界のシステム保守・改修を中心に、要件定義から運用改善まで幅広く対応してきました。Laravelや業務改善、AI活用など、現場で実際に試し・使い続けている技術や設計の工夫を、トラブル対応の視点も交えてブログに記録しています。

日々の業務で直面した「困ったこと」をベースに、再現性のあるノウハウをシンプルな言葉で伝えることを意識しています。

目次