ちょいと小ネタです。
Excelには、
Workbooksコレクションオブジェクト
Worksheetsコレクションオブジェクト
Windowsコレクションオブジェクト
CharObjectsコレクションオブジェクト
……などなど、たくさんの「~コレクションオブジェクト」がありますね。
汎用的なマクロを組んでいると、「ブック内に特定のワークシートがあるか?」と
確認したいシーンがあったりします。
存在確認用のメソッドがあっても良さそうなものなのに、無かったりしますね。
各々のコレクションから、特定のアイテムがあるか確認する(確認するだけ)
汎用的な関数、「ExistsItem」関数を作って見ました。 (邪道なコードかも知れませんが……)
ExistsItem コード
ChartObjectsコレクションだろーが、
「Itemプロパティを持つ」コレクションオブジェクトに対してなら、フツーに使えます。
あと、ごくごく「普通の配列」に対しても使えます(これがミソ)。
アイテムを指定する前に、いちいち存在確認のコードを書くのが面倒な時にご使用ください。
あと、これ、名前だけでなく、インデックス(添え字)でも存在確認できます。
具体的なサンプル。ワークブックコレクションオブジェクト(開いた複数のブック)の中に、
「Book1」(保存前のファイル)があるか確認しています。
元々が、「VBA.Collection オブジェクトでのキー存在」チェックコードが元なので、
エラー発生が前提になってしまったのです(笑)。
で、作っているうちに、「あれ? これ、もっと汎用性高くね?」
「どーせなら、それぞれのコレクションオブジェクトにも、さらに配列にも使えちゃったら楽だよねー」と
色々と欲張って見てみました。(^^ゞ
配列には添え字のみで、Itemプロパティはありませんけれども、
ほら、(Itemプロパティの表示)省略した時の見た目は同じだし……(笑)。
さらに、「これは邪道じゃー」という心のささやきのため(?)に
エラートラップなしの王道(?)の名前存在確認のコードも作って見ました。
ただし、Nameプロパティを使用しているので、元々Nameプロパティの無いオブジェクト(例:Windows)に対しては使用できません。
オブジェクトを引き渡すと、エラーが発生して止まります。
ExistsName 関数
夏休み、停電にならないといいなー。
Excelには、
Workbooksコレクションオブジェクト
Worksheetsコレクションオブジェクト
Windowsコレクションオブジェクト
CharObjectsコレクションオブジェクト
……などなど、たくさんの「~コレクションオブジェクト」がありますね。
汎用的なマクロを組んでいると、「ブック内に特定のワークシートがあるか?」と
確認したいシーンがあったりします。
存在確認用のメソッドがあっても良さそうなものなのに、無かったりしますね。
各々のコレクションから、特定のアイテムがあるか確認する(確認するだけ)
汎用的な関数、「ExistsItem」関数を作って見ました。 (邪道なコードかも知れませんが……)
ExistsItem コード
Function ExistsItem(ByRef obj As Variant, ByVal index As Variant) As Boolean Dim dammy As Variant, rtn As Boolean On Error Resume Next Err.Clear If IsObject(obj) Then dammy = IsObject(obj.item(index)) Else dammy = obj(index) End If If Err.Number = 0 Then rtn = True Else rtn = False If Err.Number = 438 Then MsgBox ("このコレクションにItemプロパティが存在しないため、判別できません") End If ExistsItem = rtn End Functionぶっちゃけ、Workbooksコレクションだろーが、Windowsコレクションだろーが、Worksheetsコレクションだろーが、
ChartObjectsコレクションだろーが、
「Itemプロパティを持つ」コレクションオブジェクトに対してなら、フツーに使えます。
あと、ごくごく「普通の配列」に対しても使えます(これがミソ)。
アイテムを指定する前に、いちいち存在確認のコードを書くのが面倒な時にご使用ください。
あと、これ、名前だけでなく、インデックス(添え字)でも存在確認できます。
具体的なサンプル。ワークブックコレクションオブジェクト(開いた複数のブック)の中に、
「Book1」(保存前のファイル)があるか確認しています。
Sub test() Dim v Set v = Application.Workbooks MsgBox (ExistsItem(v, "Book1")) End Sub Function ExistsItem(ByRef obj As Variant, ByVal index As Variant) As Boolean Dim dammy As Variant, rtn As Boolean On Error Resume Next Err.Clear If IsObject(obj) Then dammy = IsObject(obj.item(index)) Else dammy = obj(index) End If If Err.Number = 0 Then rtn = True Else rtn = False If Err.Number = 438 Then MsgBox ("このコレクションにItemプロパティが存在しないため、判別できません") End If ExistsItem = rtn End Function関数の中が、「エラーの発生前提」になっているところがツッコミどこです。(^^ゞ
元々が、「VBA.Collection オブジェクトでのキー存在」チェックコードが元なので、
エラー発生が前提になってしまったのです(笑)。
で、作っているうちに、「あれ? これ、もっと汎用性高くね?」
「どーせなら、それぞれのコレクションオブジェクトにも、さらに配列にも使えちゃったら楽だよねー」と
色々と欲張って見てみました。(^^ゞ
配列には添え字のみで、Itemプロパティはありませんけれども、
ほら、(Itemプロパティの表示)省略した時の見た目は同じだし……(笑)。
さらに、「これは邪道じゃー」という心のささやきのため(?)に
エラートラップなしの王道(?)の名前存在確認のコードも作って見ました。
ただし、Nameプロパティを使用しているので、元々Nameプロパティの無いオブジェクト(例:Windows)に対しては使用できません。
オブジェクトを引き渡すと、エラーが発生して止まります。
ExistsName 関数
Function ExistsName(ByRef obj As Variant, ByVal name As String) As Boolean Dim x As Object, rtn As Boolean rtn = False For Each x In obj If x.name = name Then rtn = True Exit For End If Next x ExistsName = rtn End Function
夏休み、停電にならないといいなー。