2017-12-01 272 views
6

Birçok dilde bir nesnenin yinelenebilir olup olmadığını kontrol etmek mümkündür, bunu VBA için nasıl yapabilirim?Değerin yinelenebilir olup olmadığını kontrol edin vba

Function isIterable(obj As Variant) As Boolean 
    On Error Resume Next 
    Dim iterator As Variant 
    For Each iterator In obj 
     Exit For 
    Next 
    isIterable = Err.Number = 0 
End Function 

Ama bir yerleşik veya daha iyi bir yaklaşım olmadığını merak:

Deneyebilirim?

+0

Not değil, bir' Her 'için (önemli performans nedenleriyle). Çağıran kod, bu varyantı yerine "IsArray" ile test etmelidir. –

+0

Ancak, yinelenebilirliği test etmek için listedeki ilk öğeyi yinelediğinden (şimdi bir kelime!), O kadar da önemli değil, Mat'sMug. – FreeMan

+1

@FreeMan değil * bu * işlevi - ama eğer bir kod bir "For Her" döngüsü ile yinelenip yinelenemeyeceğini bulmak için bu işlevi çağırıyorsa ve işlev bir dizi alır ve "evet sorun yok" diyorsa, o zaman Çağıran kodun, her ne olursa olsun "objesi" için bir "Her" döngüsüne dalılacağını varsaymak makul görünmektedir. Ve eğer bu bir dizi ise, o zaman kanlı verimsiz. –

cevap

4

yerleşik bir işleve var mı: sayılı

daha iyi bir yaklaşım var mı?:

ben böyle yapardı

:

Function isIterable(obj As Variant) As Boolean 

    On Error GoTo isIterable_Error 

    Dim iterator As Variant 

    For Each iterator In obj 
     isIterable = True 
     Exit Function 
    Next 

isIterable_Error: 

End Function 

aynı satırda iki kez = koyarak biraz fazla olduğu için.

+2

Neden "Hata Goto 0", bir işlevden çıkarken otomatik değil mi? Ayrıca, bir satırı yükseltmemek yine de bu satırı atlatamaz mı? Ben de senin yaklaşımı olduğunu da daha iyi olduğunu '' Err.Number' – Greedo

+0

@Greedo - 'Hata On GoTo 0' bir çağrı (ve hata için kullandığım MZTools, işlevinde yerleşik bir işlevi içermez taşıma). Gerçekten de, onsuz da çalışır. Ve bir hatayı yükseltmek onu atlardı, evet. Aslına bakarsanız, bu hatta her durumda ulaşılamaz :) – Vityata

+0

'=' iki kez çok fazla yazmaktan çekinmeyin. Bir hata döndüren _is hatası olarak düşünmeyi daha kolay buluyorum? Bu cevabı bir değişkene yerleştirin. DOĞRUYU YANLIŞ ve Görünmez olarak görünür hale getirmek için _Boolean = Not Boolean_ ile aynı düşünce. –

2

Ben Vityata en işlevi daha iyi olduğunu düşünüyorum, ama yok sadece alternatif olarak: sizin fonksiyon dizileri desteklemekle birlikte, diziler bir `For` döngü ile iterated gerektiğini

Function isIterable(obj As Object) As Boolean 

    On Error Resume Next 

    isIterable = TypeName(CallByName(obj, "_NewEnum", VbGet)) = "Unknown" 
    If Not isIterable Then isIterable = TypeName(CallByName(obj, "_NewEnum", VbMethod)) = "Unknown" 

End Function 
+0

bir şey bu (bu OP'in kodu yapar) işlemek değil bir şey dizilerdir - bir 'Variant' parametre ve sopa almak 'IsArray (obj) Sonra isIterable = True: En üstte Fonksiyondan Çık 've gitmekte fayda var. Ayrıca özel koleksiyon sınıfları '_NewEnum' üyesine sahip olamazdı (bir alt çizgi öneki bir VBA tanımlayıcısında yasa dışıdır). Bir 'NewEnum 'özellik getterini (' VB_UserMemId = -4 'üye özniteliği kadar önemli olduğundan emin değilim), bu yüzden bir üye adı için' 'NewEnum'' kullanıp kullanamayacağımı kontrol ediyorum… ama% 100 değil güvenilir. Bunu gerçekten yapmanın tek yolu, bazı yansıma API'larıyla olur. –

+0

'_' e.g. 'MsgBox TypeName (aCollection. [_ NewEnum]) –

+0

@AlexK. Evet, özel koleksiyonlar kendi koleksiyonlarının numaralandırıcısını böyle çağırıyor ... diyorum ki özel bir koleksiyon çok iyi bir 'Kamu Mülkiyeti Get NextItem() IUnknown' üye özniteliğiyle 'NextItem.VB_UserMemId = -4 Ve orada, işlev yanlış bir negatif olacaktır. IOW, belirli bir öznitelik değeri için bir üyenin sorgulanmasını sağlayan bir yansıma API'sı kullanmanın kısa yolu, OP'in sahip olduğu en iyi çözümdür. –