選択しているオブジェクトを一時保管する方法|CATIAマクロの作成方法
CATIAマクロでは「Selectionオブジェクト」と「For~Next文」を組み合わせた以下のような構文がよく見られます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Sub CATMain() Dim SEL As Selection Set SEL = CATIA.ActiveDocument.Selection 'SEL.Search ("XXXXXXXX") 場合によって「Searchメソッド」でオブジェクトの種類を指定する Dim i As Integer Dim SELItem As AnyObject For i = 1 To SEL.Count Set SELItem = SEL.Item(i).Value '選択状態のオブジェクトの中で上からi番目にあるオブジェクトをSELItemに代入 'SELItemを使った処理 Next i End Sub |
このように「For文(カウント変数: i )」と「SEL.Item(i).Value」を使うことで、選択されているすべてのオブジェクトに対して何らかの処理を行うことができるようになります。
かなり便利かつ基本的な構文ですが、実はこのままでは少し問題があります。
それは選択が解除されてしまうとループが回らなくなってしまうという点です。
というお話になるかもしれませんが、コピペしたり、オブジェクトの色を変えたりといった「Selectionオブジェクト」や「VisPropertySetオブジェクト」を使った操作をしようとするとどうしても選択を解除しないといけなくなる場面に出くわします。
というわけで今回は、これらの操作をループ文を使って処理したいという場合に知っておくべき「選択しているオブジェクトを一時保管する方法」を解説していきます。
Collectionを使って選択オブジェクトを一時保管
結論からいうと選択状態のオブジェクトをコレクションの中に入れれば問題は解決します。
たとえば以下のコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
Sub CATMain() Dim SEL As Selection Set SEL = CATIA.ActiveDocument.Selection Dim i As Integer Dim SELCollection As Collection Set SELCollection = New Collection 'コレクションを作成 For i = 1 To SEL.Count SELCollection.Add SEL.Item(i).Value 'コレクション内に選択オブジェクトを代入 Next i SEL.Clear '<-ここで選択を解除しても問題なし Dim j As Integer Dim SELItem As AnyObject For j = 1 To SELCollection.Count Set SELItem = SELCollection.Item(j) Msgbox SELItem.Name Next j End Sub |
複数のオブジェクトを選択した状態で上記のコードを実行すると、選択したオブジェクト順に名前が表示されていきます。
冒頭で説明したコードとの違いは『コレクション』を使っている点です。
VBAでは「Documentsコレクション」や「Bodiesコレクション」といった用意されているコレクション以外に、自分専用のコレクションを作ることができます。
ちなみに、このようなコレクションのことを「Collectionオブジェクト」といいます。
そしてこのCollectionオブジェクトには任意のオブジェクトを何個でも代入することができます。
またオブジェクトの種類の制限もないのでポイポイ入れていくことができます。
コレクション内にオブジェクトを代入
このコードでは「SELCollection」というCollectionオブジェクトを作成しています。
(Collectionオブジェクトの作成方法は下記コードを参照)
Dim SELCollection As Collection
Set SELCollection = New Collection ‘コレクションを作成
For i = 1 To SEL.Count
SELCollection.Add SEL.Item(i).Value ‘コレクション内に選択オブジェクトを代入
Next i
オブジェクトは上記のように「Addメソッド」を使うことでコレクション内に入れることができます。
つまり上記コードではループを使って、「SELCollection」に選択オブジェクトをすべて入れるという処理を行っています。
コレクション内のオブジェクトは「Itemメソッド」で表すことができます。
Selectionオブジェクトと同様にコレクションに入れた順に「Item(1)」「Item(2)」…となります。
よって「SELCollection.Item(1)」と「SEL.Item(1).Value」は同じオブジェクトを表します。
このコードによりすべての選択オブジェクトをSELCollection内に保管することができました。
あとはこのコレクションとループ文を使えば選択の状態は関係なく、すべての選択オブジェクトに処理を行うことができます。
コレクションを使ったループ
先ほど保管した全てのオブジェクトに対して処理を行うにはループ文を使って以下のように書きます。
Dim j As Integer
Dim SELItem As AnyObject
For j = 1 To SELCollection.Count
Set SELItem = SELCollection.Item(j)
Msgbox SELItem.Name
Next j
ループの条件は冒頭で紹介した構文の「For i = 1 To SEL.Count」と同じ考えです。
CollectionオブジェクトもSelectionオブジェクトと同様に「Countプロパティ」を持っているので、ループ条件は「For j = 1 To SELCollection.Count」と表します。
あとは先ほども説明した通り「Itemメソッド」を使って「SELCollection.Item(j)」を使って、冒頭の「SEL.Item(i).Value」と同じように扱えばいいだけです。
上記では「SELItem」に「SELCollection.Item(j)」を入れて以降の処理で毎回「SELCollection.Item(j)」と書くのを防いでいますが、必ず代入する必要はありません。
配列を使って選択オブジェクトを一時保管
Collectionオブジェクトの方が使い勝手はいいですが、「配列」を使った一時保管の方法もあります。
Collectionオブジェクトの説明で使ったコードを配列に書き直すと以下のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Sub CATMain() Dim SEL As Selection Set SEL = CATIA.ActiveDocument.Selection SEL.Search ("ジェネレーティブ・シェイプ・デザイン.点,all") 'CATPart内の点をすべて選択 Dim i As Integer Dim SELItemArray ReDim SELItemArray(SEL.Count - 1) For i = 1 To SEL.Count Set SELItemArray(i - 1) = SEL.Item(i).Value '配列内に選択オブジェクトを代入 Next i SEL.Clear '<-選択を解除しても問題なし Dim j As Integer Dim SELItem As AnyObject For j = 1 To UBound(SELItemArray) + 1 Set SELItem = SELItemArray(j - 1) MsgBox SELItem.Name Next j End Sub |
やっていることはCollectionオブジェクトのときと全く同じです。
ただ配列は「0」スタートなので「SELItemArray(SEL.Count – 1)」や「For j = 1 To UBound(SELItemArray) + 1」というように数を調整してあげる必要があります。
配列での一時保管でも問題なく実行できますが、コードの見やすさや使いやすさを考えるとCollectionオブジェクトでの一時保管の方がオススメです。
まとめ
今回は選択しているオブジェクトを一時保管しておく方法についての内容でした。
ヘルプに書かれているいくつかの例文にも使われている内容なので使用頻度は高めだと思います。
今回の内容が理解できた方は今後のマクロ作成で、一時保管の必要がない場合でも毎回一時保管のコードを書いておくことをオススメします。
数行書くだけで選択解除に対するエラーの心配もなくなりますし、マクロ内で何度かループを回す場合にも対応することができます。