SlideRangeオブジェクトはFor Each~Next文で処理できる記事に関して、PowerPoint VBAで文字列操作するならば知っておきたい、重要な点を示唆するツイートをいただきました。
SlideRangeはコレクションでFor Each~Nextでも処理できる:パワーポイントマクロ・PowerPoint VBAの使い方-Slide・スライド https://t.co/isxEZQQrze #Zenback @kiyotoiさんから
— いみひと (@nukie_53) 2018年9月29日
○○Range系は大体列挙可能ですし、これを知らないとPowerPoint.TextRangeの操作が結構面倒に...
いい機会ですから、PowerPointのTextRangeオブジェクトのループ処理について書かせていただきます。
TextRangeをFor Each~Next文で処理するサンプルマクロ
まずはアクティブなスライド上で、文字列を選択しておいてから、以下のSubプロシージャを実行してみてください。
With ActiveWindow.Selection
If .Type <> ppSelectionText Then
MsgBox "スライド上で文字列を選択してから実行してください。"
Exit Sub
End If Dim itm As TextRange
For Each itm In .TextRange
MsgBox itm.Text
Next itm
End With
End Sub
選択していた文字列が1文字ずつ、メッセージボックスに表示されるはずです。
PowerPoint VBAで、文字列を1文字ずつ処理したいときに、とても便利な書き方です。
TextRangeオブジェクトを確認する
上記の挙動をする理由は、以下のSubプロシージャを実行すると垣間見ることができます。
With ActiveWindow.Selection
If .Type <> ppSelectionText Then
MsgBox "スライド上で文字列を選択してから実行してください。"
Exit Sub
End If Dim coll As TextRange
Set coll = .TextRange
Stop
End With
End Sub
Stopステートメントで、ステップ実行モードになったら、ローカルウィンドウを確認しましょう。
例えば、スライド上で「イロハ」という文字列を選択しておいて、上記Subプロシージャを実行すると、ローカルウィンドウは下図のような状態になります。
一般的なコレクションを、オブジェクト変数に代入したときと同様、「Item〇」という項目が見えます。
そして各Itemは、下図のように1文字ずつの文字列が含まれるTextRangeオブジェクトであることも確認できます。
VBAのFor Each~Next文は、これらの各Itemを、おのおの(Each)処理するという構文なのです。
TextRangeオブジェクトの不思議なところ
このTextRangeオブジェクトには不思議な点があります。
For Each~Next文で書けるのに、For~Next文では書けないという点です。
ShapeRangeに対するFor Each~NextをFor~Nextで
VBAではほとんどの場合、For Each~Next文を、Countプロパティを利用したFor~Next文でも書けます。
例えば、先述のTextRangeをFor Each~Next文で処理するSubプロシージャによく似た、ShapeRangeを処理する以下のようなSubプロシージャの、
With ActiveWindow.Selection
If .Type <> ppSelectionShapes Then
MsgBox "スライド上で図形を選択してから実行してください。"
Exit Sub
End If Dim itm As Shape
For Each itm In .ShapeRange
MsgBox itm.Name
Next itm
End With
End Sub
For i = 1 To .ShapeRange.Count
MsgBox .ShapeRange.Item(i).Name '「.Item」は省略可能
Next i
For Each~Next文は、上述のようにCountプロパティを利用したFor~Next文で書き直せるという経験則が、VBAのコレクションでは基本的に当てはまります(ぜひ他のコレクションでも確認してみてください)。
PowerPoint.TextRangeに対するFor Each~NextはFor~Nextで書き直せない
ところがTextRangeの場合は、以下のようには書くことができません。
Dim i As Long
For i = 1 To .TextRange.Count
MsgBox .TextRange.Item(i).Name
Next i
オブジェクトブラウザーで非表示メンバーを表示してみても、TextRangeオブジェクトには、Itemという名前のプロパティもメソッドも見当たりませんから当然です。
また「.Item」を省略した、
Dim i As Long
For i = 1 To .TextRange.Count
MsgBox .TextRange(i).Name
Next i
では、TextRangeオブジェクトの既定メンバーであるTextプロパティを指定したと見なされますから、
やっぱりダメです。
TextRangeは、他のほとんどのコレクションに用意されている(単独のオブジェクトを取得するための)ItemメソッドまたはItemプロパティは、なぜか用意されていないといちょっと謎なオブジェクトです。
Microsoftの提示しているコレクションのItemについてのガイドライン
ちなみにコレクションのItemメソッドについて、『オートメーションプログラマーズリファレンス―ActiveXテクノロジを使用したアプリケーション開発技法 (MicrosoftPRESS) 』のp.107でMicrosoftは、以下のようなガイドラインを提示しています。コレクション内の該当項目を返す。必須。である。1つまたは複数の引数によって、返すコレクション要素を指定できる。コレクションブジェクトのデフォルトメンバ(DISPID_VALUE)。
※誤植と思われる「必須。である。」「コレクションブジェクト」は、原著に存在するものです。
Office.TextRange2オブジェクトはItemメソッドも存在するコレクション
この気持ち悪さは、PowerPoint 2007で登場した(TextRangeオブジェクトの進化系オブジェクトである)Office.TextRange2オブジェクトでは解消されています。
オブジェクトブラウザーを確認すると、
Itemメソッドが存在し、_NewEnumプロパティも見えます。
TextRange2オブジェクトなら、For Each~Next文でも、
Dim itm As TextRange2
For Each itm In .TextRange2
MsgBox itm.Text
Next itm
For~Next文でも、
Dim i As Long
For i = 1 To .TextRange2.Count
MsgBox .TextRange2.Item(i).Text ' 「.Item」は省略不可
Next i
書けます。
Office.TextRange2の既定メンバーはTextプロパティ
ただしFor~Nextループ内の、
MsgBox .TextRange2.Item(i).Text
の部分は、他の多くのコレクションのように「.Item」を省略して、
MsgBox .TextRange2(i).Text
とは書けません。
OfficeライブラリーのTextRange2オブジェクトの既定メンバーは、
PowerPointライブラリーのTextRangeオブジェクトと同じく、Textプロパティだからです。
最終更新日時:2018-10-10 15:29
- Newer:Workbooksの引数にフルパスを指定したい?
- Older:_NewEnumプロパティがない?
Home » パワーポイントマクロ・PowerPoint VBAの使い方 » TextFrame・TextRange » TextRangeはFor Each~Next処理できるけれど...