ちょいと小ネタです。
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
夏休み、停電にならないといいなー。