una - matrices en vba excel
Cómo comprobar si hay una matriz vacía en la macro vba (23)
Quiero verificar las matrices vacías. Google me dio soluciones variadas pero nada funcionó. Tal vez no los estoy aplicando correctamente.
Function GetBoiler(ByVal sFile As String) As String
''Email Signature
Dim fso As Object
Dim ts As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)
GetBoiler = ts.ReadAll
ts.Close
End Function
Dim FileNamesList As Variant, i As Integer
'' activate the desired startfolder for the filesearch
FileNamesList = CreateFileList("*.*", False) '' Returns File names
'' performs the filesearch, includes any subfolders
'' present the result
'' If there are Signatures then populate SigString
Range("A:A").ClearContents
For i = 1 To UBound(FileNamesList)
Cells(i + 1, 1).Formula = FileNamesList(i)
Next i
SigString = FileNamesList(3)
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
Aquí si la matriz FileNamesList
está vacía, GetBoiler(SigString)
no debería llamarse en absoluto. Cuando la matriz FileNamesList
está vacía, SigString
también está vacía y esto llama a la función GetBoiler()
con una cadena vacía. Me sale un error en la línea
Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)
ya que sFile
está vacío. ¿Alguna forma de evitar eso?
Aquí hay otra manera de hacerlo. Lo he usado en algunos casos y está funcionando.
Function IsArrayEmpty(arr As Variant) As Boolean
Dim index As Integer
index = -1
On Error Resume Next
index = UBound(arr)
On Error GoTo 0
If (index = -1) Then IsArrayEmpty = True Else IsArrayEmpty = False
End Function
Auth estuvo más cerca pero su respuesta arroja un error de desajuste de tipo.
En cuanto a las otras respuestas, debe evitar el uso de un error para probar una condición, si puede, porque al menos complica la depuración (y si algo más está causando ese error).
Aquí hay una solución simple y completa:
option explicit
Function foo() As Variant
Dim bar() As String
If (Not Not bar) Then
ReDim Preserve bar(0 To UBound(bar) + 1)
Else
ReDim Preserve bar(0 To 0)
End If
bar(UBound(bar)) = "it works!"
foo = bar
End Function
Basado en la answer de ahuth;
Function AryLen(ary() As Variant, Optional idx_dim As Long = 1) As Long
If (Not ary) = -1 Then
AryLen = 0
Else
AryLen = UBound(ary, idx_dim) - LBound(ary, idx_dim) + 1
End If
End Function
Compruebe si hay una matriz vacía; is_empty = AryLen(some_array)=0
Como está tratando con una matriz de cadenas, ¿ha considerado unirse?
If Len(Join(FileNamesList)) > 0 Then
Cuando escribo VBA, hay una frase en mi cabeza: "Podría ser tan fácil, pero ..."
Aquí es a lo que lo adopté:
Private Function IsArrayEmpty(arr As Variant)
'' This function returns true if array is empty
Dim l As Long
On Error Resume Next
l = Len(Join(arr))
If l = 0 Then
IsArrayEmpty = True
Else
IsArrayEmpty = False
End If
If Err.Number > 0 Then
IsArrayEmpty = True
End If
On Error GoTo 0
End Function
Private Sub IsArrayEmptyTest()
Dim a As Variant
a = Array()
Debug.Print "Array is Empty is " & IsArrayEmpty(a)
If IsArrayEmpty(a) = False Then
Debug.Print " " & Join(a)
End If
End Sub
Este código no hace lo que esperas:
If Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
Si pasa una cadena vacía ( ""
) o vbNullString
a Dir
, devolverá el nombre del primer archivo en la ruta del directorio actual (la ruta devuelta por CurDir$
). Entonces, si SigString
está vacío, su condición If
se evaluará a True
porque Dir
devolverá una cadena no vacía (el nombre del primer archivo en el directorio actual), y se GetBoiler
a GetBoiler
. Y si SigString
está vacío, la llamada a fso.GetFile
fallará.
Debería cambiar su condición para verificar que SigString
no esté vacío, o usar el método FileSystemObject.FileExists
lugar de Dir
para verificar si el archivo existe. Dir
es complicado de usar precisamente porque hace cosas que no esperas que haga. Personalmente, utilizaría Scripting.FileSystemObject
sobre Dir
porque no hay negocios graciosos ( FileExists
devuelve True
si el archivo existe, y, bueno, False
si no es así). Lo que es más, FileExists
expresa la intención de su código mucho más claramente que Dir
.
Método 1: compruebe que SigString
no esté primero en SigString
If SigString <> "" And Dir(SigString) <> "" Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
Método 2: utilice el método FileSystemObject.FileExists
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(SigString) Then
Signature = GetBoiler(SigString)
Else
Signature = ""
End If
Generalizaré el problema y la Cuestión según lo previsto. Prueba de assingment en la matriz, y atrapa el error eventual
Function IsVarArrayEmpty(anArray as Variant)
Dim aVar as Variant
IsVarArrayEmpty=False
On error resume next
aVar=anArray(1)
If Err.number then ''...still, it might not start at this index
aVar=anArray(0)
If Err.number then IsVarArrayEmpty=True '' neither 0 or 1 yields good assignment
EndIF
End Function
Claro que pierde arreglos con todos los índices negativos o todo> 1 ... ¿es probable? en Weirdland, sí.
Ir con un triple negativo:
If (Not Not FileNamesList) <> 0 Then
'' Array has been initialized, so you''re good to go.
Else
'' Array has NOT been initialized
End If
O solo:
If (Not FileNamesList) = -1 Then
'' Array has NOT been initialized
Else
'' Array has been initialized, so you''re good to go.
End If
En VB, por cualquier razón, Not myArray
devuelve el puntero SafeArray. Para matrices no inicializadas, devuelve -1. No puedes hacer esto para XOR con -1, y así devolver cero, si lo prefieres.
(Not myArray) (Not Not myArray)
Uninitialized -1 0
Initialized -someBigNumber someOtherBigNumber
Otra solución para probar la matriz vacía
if UBound(ar) < LBound(ar) then msgbox "Your array is empty!"
O bien, si ya sabes que LBound es 0
if -1 = UBound(ar) then msgbox "Your array is empty!"
Esto puede ser más rápido que join (). (Y no verifiqué con índices negativos)
Aquí está mi ejemplo para filtrar dos matrices de cadenas para que no compartan las mismas cadenas.
'' Filtering ar2 out of strings that exists in ar1
For i = 0 To UBound(ar1)
'' filter out any ar2.string that exists in ar1
ar2 = Filter(ar2 , ar1(i), False)
If UBound(ar2) < LBound(ar2) Then
MsgBox "All strings are the same.", vbExclamation, "Operation ignored":
Exit Sub
End If
Next
'' At this point, we know that ar2 is not empty and it is filtered
''
Otro método sería hacerlo antes. Puede crear una variable booleana y establecerla en verdadero una vez que cargue los datos en la matriz. entonces todo lo que realmente necesitas es una declaración simple de cuándo cargas datos en la matriz.
Para comprobar si una matriz de bytes está vacía, la forma más sencilla es utilizar la función VBA StrPtr()
.
Si la matriz de bytes está vacía, StrPtr()
devuelve 0
; de lo contrario, devuelve un valor distinto de cero (sin embargo, no es la dirección del primer elemento).
Dim ar() As Byte
Debug.Assert StrPtr(ar) = 0
ReDim ar(0 to 3) As Byte
Debug.Assert StrPtr(ar) <> 0
Sin embargo, solo funciona con la matriz Byte.
Personalmente, creo que una de las respuestas anteriores se puede modificar para verificar si la matriz tiene contenido:
if UBound(ar) > LBound(ar) Then
Esto maneja referencias numéricas negativas y toma menos tiempo que algunas de las otras opciones.
Puede usar la función siguiente para verificar si la variante o conjunto de cadenas está vacío en vba
Function IsArrayAllocated(Arr As Variant) As Boolean
On Error Resume Next
IsArrayAllocated = IsArray(Arr) And _
Not IsError(LBound(Arr, 1)) And _
LBound(Arr, 1) <= UBound(Arr, 1)
End Function
Uso de muestra
Public Function test()
Dim Arr(1) As String
Arr(0) = "d"
Dim x As Boolean
x = IsArrayAllocated(Arr)
End Function
Puede verificar si la matriz está vacía al recuperar el recuento total de elementos utilizando el objeto VBArray()
JScript (funciona con matrices de tipo variante, individual o multidimensional):
Sub Test()
Dim a() As Variant
Dim b As Variant
Dim c As Long
'' Uninitialized array of variant
'' MsgBox UBound(a) '' gives ''Subscript out of range'' error
MsgBox GetElementsCount(a) '' 0
'' Variant containing an empty array
b = Array()
MsgBox GetElementsCount(b) '' 0
'' Any other types, eg Long or not Variant type arrays
MsgBox GetElementsCount(c) '' -1
End Sub
Function GetElementsCount(aSample) As Long
Static oHtmlfile As Object '' instantiate once
If oHtmlfile Is Nothing Then
Set oHtmlfile = CreateObject("htmlfile")
oHtmlfile.parentWindow.execScript ("function arrlength(arr) {try {return (new VBArray(arr)).toArray().length} catch(e) {return -1}}"), "jscript"
End If
GetElementsCount = oHtmlfile.parentWindow.arrlength(aSample)
End Function
Para mí, se necesitan aproximadamente 0,3 mksec por cada elemento + 15 mseg de inicialización, por lo que la matriz de elementos de 10M tarda unos 3 segundos. La misma funcionalidad podría implementarse a través de ScriptControl
ActiveX (no está disponible en las versiones de 64 bits de MS Office, por lo que puede usar una solución como this ).
Si prueba en una función de matriz funcionará para todos los límites:
Function IsVarArrayEmpty(anArray As Variant)
Dim i As Integer
On Error Resume Next
i = UBound(anArray,1)
If Err.number = 0 Then
IsVarArrayEmpty = False
Else
IsVarArrayEmpty = True
End If
End Function
Simplemente estoy pegando debajo del código el gran Chip Pearson. Funciona un encanto.
Aquí está su modArraySupport .
Espero que esto ayude.
Public Function IsArrayEmpty(Arr As Variant) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' IsArrayEmpty
'' This function tests whether the array is empty (unallocated). Returns TRUE or FALSE.
''
'' The VBA IsArray function indicates whether a variable is an array, but it does not
'' distinguish between allocated and unallocated arrays. It will return TRUE for both
'' allocated and unallocated arrays. This function tests whether the array has actually
'' been allocated.
''
'' This function is really the reverse of IsArrayAllocated.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim LB As Long
Dim UB As Long
err.Clear
On Error Resume Next
If IsArray(Arr) = False Then
'' we weren''t passed an array, return True
IsArrayEmpty = True
End If
'' Attempt to get the UBound of the array. If the array is
'' unallocated, an error will occur.
UB = UBound(Arr, 1)
If (err.Number <> 0) Then
IsArrayEmpty = True
Else
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' On rare occasion, under circumstances I
'' cannot reliably replicate, Err.Number
'' will be 0 for an unallocated, empty array.
'' On these occasions, LBound is 0 and
'' UBound is -1.
'' To accommodate the weird behavior, test to
'' see if LB > UB. If so, the array is not
'' allocated.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
err.Clear
LB = LBound(Arr)
If LB > UB Then
IsArrayEmpty = True
Else
IsArrayEmpty = False
End If
End If
End Function
Usted puede verificar su conteo.
Aquí cid es una matriz.
if (jsonObject("result")("cid").Count) = 0 them
MsgBox "Empty Array"
Espero que esto ayude. ¡Que tengas un buen día!
Veo respuestas similares aquí ... pero no las mías ...
Así es como desafortunadamente voy a manejarlo ... Me gusta el enfoque len (join (arr))> 0, pero no funcionaría si la matriz fuera una matriz de emptystrings ...
Public Function arrayLength(arr As Variant) As Long
On Error GoTo handler
Dim lngLower As Long
Dim lngUpper As Long
lngLower = LBound(arr)
lngUpper = UBound(arr)
arrayLength = (lngUpper - lngLower) + 1
Exit Function
handler:
arrayLength = 0 ''error occured. must be zero length
End Function
Verificación simplificada para Empty Array:
Dim exampleArray() As Variant ''Any Type
If ((Not Not exampleArray) = 0) Then
''Array is Empty
Else
''Array is Not Empty
End If
Function IsVarArrayEmpty(anArray As Variant) as boolean
On Error Resume Next
IsVarArrayEmpty = true
IsVarArrayEmpty = UBound(anArray) < LBound(anArray)
End Function
Tal ubound
bloqueos ubound
y sigue siendo verdadero, y si ubound < lbound
, está vacío
Public Function IsEmptyArray(InputArray As Variant) As Boolean
On Error GoTo ErrHandler:
IsEmptyArray = Not (UBound(InputArray) >= 0)
Exit Function
ErrHandler:
IsEmptyArray = True
End Function
Public Function arrayIsEmpty(arrayToCheck() As Variant) As Boolean
On Error GoTo Err:
Dim forCheck
forCheck = arrayToCheck(0)
arrayIsEmpty = False
Exit Function
Err:
arrayIsEmpty = True
End Function
if Ubound(yourArray)>-1 then
debug.print "The array is not empty"
else
debug.print "EMPTY"
end if