Twitterで@terrysaitoさんが下記のようなツイートをされていました。
VBAでSmartArtの文字列を抜く方法を、誰か伝授して下さらぬか?
— Terry Saito / 齊藤貴昭 (@terrysaito) 2015, 7月 7
そういえばマクロでSmartArtを意識して取り扱ったことなかったなー、と思い、良い機会なのでコードを書いてみることにしました。
Public Sub Sample1() Dim shp As PowerPoint.Shape Dim s As PowerPoint.Shape 'スライド1の図形を順次処理 For Each shp In Application.ActivePresentation.Slides(1).Shapes 'SmartArtのみ処理 If shp.Type = msoSmartArt Then If shp.GroupItems.Count > 0 Then For Each s In shp.GroupItems If s.HasTextFrame = True Then If s.TextFrame2.HasText = True Then Debug.Print s.TextFrame2.TextRange.Text End If End If Next End If End If Next End Sub
まずはShapeオブジェクトのTypeプロパティでSmartArtかどうかを判別し、グループ内の図形を取得するGroupItemsプロパティを使って順番にテキストを取得するコードです。
下図のスライドに対しコードを実行すると、
下図のような結果になります。
図中にある矢印内のテキストも取得しています。
今度はHasSmartArtプロパティでSmartArtかどうかを判別し、SmartArtNodeオブジェクトから順番にテキストを取得するコードです。
Public Sub Sample2() Dim shp As PowerPoint.Shape Dim n As Office.SmartArtNode 'スライド1の図形を順次処理 For Each shp In Application.ActivePresentation.Slides(1).Shapes 'SmartArtのみ処理 If shp.HasSmartArt = True Then For Each n In shp.SmartArt.AllNodes If n.TextFrame2.HasText = True Then Debug.Print n.TextFrame2.TextRange.Text End If Next End If Next End Sub
結果は下図の通りで、こちらは図中の矢印のテキストを取得できていません。
矢印はノードに含まれていないようです。
この結果からすると、テキストを取得する際はGroupItemsプロパティ(GroupShapesオブジェクト)を使った方が漏れが無さそうです。
ただし、ノードを追加したりレイアウトを変更したりするときは、専用のプロパティやメソッドが用意されたSmartArtオブジェクトを使った方が良いでしょう。
(SmartArtかどうかは、ShapeオブジェクトのTypeプロパティとHasSmartArtプロパティのどちらでも判別できるようです。)
以上、SmartArtからテキストを取得するマクロの紹介でした。
2015/7/8 追記:
@terrysaitoさんから下記返信がありました。
@kinuasa 一つ目試しました。13行目で「このメンバにアクセスできるのは、単一の図形の場合だけです」というエラーになりました<(_ _)> @SHINHAM3
— Terry Saito / 齊藤貴昭 (@terrysaito) 2015, 7月 8
このツイートからすると引っ掛かっているのはグループ化されている図形でしょうか?
この際SmartArtかどうか無視して再帰的に処理するマクロも考えてみました。
Option Explicit Public Sub Sample() Dim shp As PowerPoint.Shape For Each shp In Application.ActivePresentation.Slides(1).Shapes ListShape shp Next End Sub Private Sub ListShape(ByVal TargetShape As PowerPoint.Shape) Dim gshps As PowerPoint.GroupShapes Dim shp As PowerPoint.Shape On Error Resume Next Set gshps = TargetShape.GroupItems On Error GoTo 0 If Not gshps Is Nothing Then If gshps.Count > 0 Then For Each shp In gshps ListShape shp DoEvents Next End If End If If TargetShape.HasTextFrame = True Then If TargetShape.TextFrame2.HasText = True Then GetShapeText TargetShape End If End If End Sub Private Sub GetShapeText(ByVal TargetShape As PowerPoint.Shape) Debug.Print TargetShape.TextFrame2.TextRange.Text End Sub
あとは、数年前に「各スライドに配置されたオートシェイプからテキストを取得するPowerPointマクロ」も書いたことがあるので、そちらが参考になるのかもしれません。
2015/7/8 追記2:
@terrysaitoさんのツイートによると、やっぱり上手くいかないとのこと。
@kinuasa 早速ありがとうございます。結論から言うと35行で同じエラーでした(^_^;)
古い記事は既に拝読してまして SmartArtNodeで引っ掛かるので、他の方法を探していたのでした(^^) @SHINHAM3
— Terry Saito / 齊藤貴昭 (@terrysaito) 2015, 7月 8
私にも理由が分からなかったのですが、検索したらヒントがありました。
・How to access textrange members inside SmartArt
https://groups.google.com/d/topic/microsoft.public.powerpoint/zkg4d5Ioh5A/discussion
for (int i=1;i<=textRange.Count;i++) { TextRange ranger=textRange._item(1); ....... }
“TextRange(TextRange2)オブジェクトってコレクションだったのか!?”と。
であれば、For Eachでループさせれば上手くいくかもしれません。
(私の方では問題環境が再現できなかったので未確認です。)
Option Explicit Public Sub Sample() Dim shp As PowerPoint.Shape For Each shp In Application.ActivePresentation.Slides(1).Shapes ListShape shp Next End Sub Private Sub ListShape(ByVal TargetShape As PowerPoint.Shape) Dim gshps As PowerPoint.GroupShapes Dim shp As PowerPoint.Shape Dim trng As Office.TextRange2 On Error Resume Next Set gshps = TargetShape.GroupItems On Error GoTo 0 If Not gshps Is Nothing Then If gshps.Count > 0 Then For Each shp In gshps ListShape shp DoEvents Next End If End If If TargetShape.HasTextFrame = True Then If TargetShape.TextFrame2.HasText = True Then For Each trng In TargetShape.TextFrame2.TextRange GetTextRangeText trng Next End If End If End Sub Private Sub GetTextRangeText(ByVal TargetTextRange As Office.TextRange2) Debug.Print TargetTextRange.Text End Sub
この記事へのコメントはありません。