Excelで業務資料を作っていると、テキストボックスや吹き出し、さらにはグループ図形の中にある文字を一括で置換したい場面ってありますよね。
でも、検索(Ctrl+H)では反応せず、「なぜ置き換わらないの!?」と戸惑った経験がある方も多いはず。
この記事では、図形内テキストを対象にしたVBAによる置換方法を、コピペで使えるコード付きで丁寧に解説します。アドイン不要で、グループ図形にも対応しているので、実務でも即活用できます!
この記事を読むとわかること
- Excel図形内テキストが置換されない理由とその仕組み
- グループ図形を含めた一括置換用VBAの実装方法
- 実行時にハマりやすいポイントとその回避策
なぜ図形内の文字は置換されないのか?
Excelの図形に含まれる文字列は、一見セルのデータと同じように見えますが、実は内部構造がまったく異なります。
検索・置換(Ctrl + H)で反応しないのは、図形の中のテキストがセルとは別のプロパティに格納されているためです。地味に気づきづらいところですが、ここが自動化の第一の壁になります。
また、よくある「テキストボックス」や「吹き出し」なども、Shapeオブジェクトの種類としては違う扱いになっており、処理の仕方に工夫が必要です。
特に業務資料などでグループ化されている図形は、外から見るとひとまとまりですが、内部的には再帰処理しないとたどり着けない構造になっていたりします。
図形のテキストはセルとまったく別物
Excelのセル内のデータはWorksheet.Cellsで扱えますが、図形に含まれる文字は Shape.TextFrame.TextRange.Text
に格納されています。これは検索・置換のUIが見ている領域とは別なんですね。
したがって、通常の置換操作では図形内の文字列は無視されます。地味に見落とされがちですが、これを理解しておかないと「VBAで一括置換したいのに反応しない…」という状態に陥ります。
テキストボックスと吹き出しは同じじゃない
見た目が似ている「テキストボックス」と「吹き出し」も、VBAの視点では異なる AutoShapeType
を持ちます。たとえば、テキストボックスは msoTextBox
、吹き出しは msoShapeOvalCallout
など。
ただ、すべてを網羅しようとすると逆にややこしくなるので、HasTextFrame
と HasText
を使って「文字を持っている図形かどうか」で判定するのが現実的です。
グループ図形の中にはさらに図形がある
複数の図形を選択して「グループ化」すると、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 *****
マクロの実行方法
- 「開発」タブをクリック(※表示されていない場合は、オプション→リボンのユーザー設定で表示させてください)
- 「挿入」→「フォームコントロール」の中から、「ボタン(フォームコントロール)」を選択
- ワークシート上にボタンを配置すると、マクロ選択画面が自動で開くので、
ReplaceTextInShapesMain
を選んで「OK」 - ボタンのラベルを変更(例:「図形置換実行」など)
注意:このマクロは .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が必要です。
本記事では、グループ図形にも対応した実用的なマクロを紹介しました。実際に試してみて「一括置換がうまくいった」と感じたときのスッキリ感は格別です。
とはいえ、図形の構成や使い方はケースバイケースなので、自分の環境に合うように少しずつ調整していくのがよさそうです。