Home » パワーポイントマクロ・PowerPoint VBAの使い方 » TextFrame・TextRange » TextRangeはFor Each~Next処理できるけれど...

TextRangeはFor Each~Next処理できるけれど...

動作検証バージョン:Windows版PowerPoint2016(バージョン1808 ビルド10730.20102)

SlideRangeオブジェクトはFor Each~Next文で処理できる記事に関して、PowerPoint VBAで文字列操作するならば知っておきたい、重要な点を示唆するツイートをいただきました。

いい機会ですから、PowerPointのTextRangeオブジェクトのループ処理について書かせていただきます。

[スポンサードリンク]

TextRangeをFor Each~Next文で処理するサンプルマクロ

まずはアクティブなスライド上で、文字列を選択しておいてから、以下のSubプロシージャを実行してみてください。

Sub TextRangeをForEachで処理する()
 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プロシージャを実行すると垣間見ることができます。

Sub TextRangeの確認()
 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プロシージャの、

Sub ShapeRangeをForEachで処理する()
 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 Each~Next文は、以下のようなFor~Next文でも書けます。
  Dim i As Long
  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

[スポンサードリンク]

Home » パワーポイントマクロ・PowerPoint VBAの使い方 » TextFrame・TextRange » TextRangeはFor Each~Next処理できるけれど...

「TextFrame・TextRange」の記事一覧

検索


Copyright © インストラクターのネタ帳 All Rights Reserved.

.