Vba excel массив или нет

AndreA SN

1014 / 118 / 2

Регистрация: 26.08.2011

Сообщений: 1,113

Записей в блоге: 2

1

Как проверить пуст ли массив?

22.07.2015, 09:47. Показов 29881. Ответов 42

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

это продолжение темы. интересует грамотность записи

Visual Basic
1
If Массив(0) = "" Then ' вот эта проверка мне кажется неграмотная

Добавлено через 1 минуту
Еще интересно: как его грамотно начать заполнять. Так чтобы не было нулевой позиции в начале и постоянной проверки на ее заполненность в последующем



0



3827 / 2254 / 751

Регистрация: 02.11.2012

Сообщений: 5,930

22.07.2015, 10:13

2

Цитата
Сообщение от AndreA SN
Посмотреть сообщение

чтобы не было нулевой позиции

перед внесением проверять.
если ячейка не пустая то вносим значение в массив.



0



1014 / 118 / 2

Регистрация: 26.08.2011

Сообщений: 1,113

Записей в блоге: 2

22.07.2015, 11:12

 [ТС]

3

Vlad999, согласен. Я постоянно так и делаю. Но проверять постоянно есть-ли запись в первой строке — это увеличение операций по заполнению массива в 2 раза. Вот я и спрашиваю: какие технологии заполнения массивов спецами используются. Чтобы не было лишних проверок состояния массива на «полный, пустой»



0



1337 / 308 / 74

Регистрация: 13.11.2008

Сообщений: 635

22.07.2015, 11:53

4

Трудно что-то советовать, когда не видно как Вы этот массив заполнять собрались.
Есть определенные костыли, чтобы проверить является ли переменная массивом и есть ли в нем хоть какое-то значение. Но здесь большую роль играет и то как переменная массива была объявлена — как массив
Dim Arr()
или как переменная типа Variant
Dim Arr



0



AndreA SN

1014 / 118 / 2

Регистрация: 26.08.2011

Сообщений: 1,113

Записей в блоге: 2

22.07.2015, 12:37

 [ТС]

5

The_Prist, привожу пример

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
For i = 0 to дофига ' это цикл внешних проверок
Dim garbV As Long, is_ As Long
      varGarbagCombo = mc1.VarGARBAG_POST ' получаю данные из другого массива
      garbV = UBound(varGarbagCombo)
      For is_ = 0 To garbV
           If Iskl2(0) = "" Then ' вот эта проверка мне кажется неграмотная
                Iskl2(0) = varGarbagCombo(is_)
           Else 
                ReDim Preserve Iskl2(UBound(Iskl2) + 1) 
                Iskl2(UBound(Iskl2)) = varGarbagCombo(is_) 
           End If 
      Next is_
Next i

В первой части If заполняю первую позицию массива, а в части Else — постоянно проверяю на заполненность первую строку. Вот эта необходимость постоянной проверки вызывает вопрос.
Рабочий массив постоянно обновляется и дополняется частью глобального массива. Проводятся какие-то операции, потом рабочий массив очищается и снова всё повторяется. Вот такие циклы заполнения исчисляются десятками и сотнями тысяч. Соответственно число операций по проверке удваивает эту величину. И наворачивает код



0



The_Prist

1337 / 308 / 74

Регистрация: 13.11.2008

Сообщений: 635

22.07.2015, 12:50

6

Лучший ответ Сообщение было отмечено AndreA SN как решение

Решение

И все же не видно как объявлен этот массив. Где строка объявления Iskl2?
Он как объявлен?
dim Iskl2()? Или иначе?
В общем случае куда грамотнее завести отдельную переменную-счетчик
dim Iskl2_Cnt as Long
и потом просто её увеличивать:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
Dim Iskl2_Cnt as Long
Dim garbV As Long, is_ As Long
For i = 0 to дофига ' это цикл внешних проверок
      varGarbagCombo = mc1.VarGARBAG_POST ' получаю данные из другого массива
      garbV = UBound(varGarbagCombo)
      For is_ = 0 To garbV
            ReDim Preserve Iskl2(Iskl2_Cnt) 
            Iskl2(Iskl2_Cnt) = varGarbagCombo(is_)
            Iskl2_Cnt = Iskl2_Cnt + 1
      Next is_
Next i



1



AndreA SN

1014 / 118 / 2

Регистрация: 26.08.2011

Сообщений: 1,113

Записей в блоге: 2

22.07.2015, 13:00

 [ТС]

7

The_Prist, извиняюсь… проглядел ответный вопрос об объявлении массива
уточняю объявление

Visual Basic
1
Dim Iskl2() As String

в связке с этим вопросом интересует просто вопрос грамотной проверки массива на непустотность

Добавлено через 2 минуты
кстати. Спасибо за ответ для общего случая. Это, наверное, самый понятный мне подход…



0



Dragokas

Эксперт WindowsАвтор FAQ

17992 / 7618 / 890

Регистрация: 25.12.2011

Сообщений: 11,351

Записей в блоге: 17

22.07.2015, 13:44

8

Смотря что считать пустым массивом…

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
Dim arr() As String
'сейчас массив пустой
redim arr(0)
'теперь уже не пустой
erase arr
'снова пустой
If Not Not arr Then
  Debug.Print "Not Empty"
Else
  Debug.Print "Empty"
End If



2



4038 / 1423 / 394

Регистрация: 07.08.2013

Сообщений: 3,541

22.07.2015, 13:51

9

а массивы большие



0



1014 / 118 / 2

Регистрация: 26.08.2011

Сообщений: 1,113

Записей в блоге: 2

22.07.2015, 13:52

 [ТС]

10

Dragokas, спасибо)))
Самая крутая сводка пустых-непустых массивов)))



0



Dragokas

Эксперт WindowsАвтор FAQ

17992 / 7618 / 890

Регистрация: 25.12.2011

Сообщений: 11,351

Записей в блоге: 17

22.07.2015, 14:31

11

AndreA SN, только не забывайте, что результат операции — это не BOOL, а указатель на SAFEARRAY.
Так, что если нужно проверить на «Empty», пишем:

Visual Basic
1
If Not Cbool(Not Not arr) Then Debug.Print "Empty"



2



AndreA SN

1014 / 118 / 2

Регистрация: 26.08.2011

Сообщений: 1,113

Записей в блоге: 2

22.07.2015, 14:45

 [ТС]

12

snipe, опять же смотря из какого объема действий исходить.
вот две обработки одного и того же суммирования

Visual Basic
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
Public Sub Вложенность_циклов()
    Dim ndd, t, ewq, s
ndd = 1000
 
    DoEvents: t = Timer
    For idd = 1 To ndd
        For h = 1 To 6000
            s = s + 1
        Next h
    Next idd
    ewq = Timer - t
Debug.Print ewq, s
s = 0
    DoEvents: t = Timer
    For idd = 1 To ndd
        For h = 1 To 20
        For hh = 1 To 20
        For hhh = 1 To 15
            s = s + 1
        Next hhh
        Next hh
        Next h
    Next idd
    ewq = Timer - t
Debug.Print ewq, s
 
End Sub

в итоге получаем за счет суммирования 6000000
Но!
У меня по времени получилась разница в 1,5 раза
0,15625 6000000
0,2617188 6000000

а по максимальному размеру цикла — читай по Ubound(массив) разница составила 300 раз…
Хотя я понимаю, что мне сейчас выставят произведение размеров как конечное количество действий
но речь в данном случае всё таки о размерах обрабатываемой информации в зависимости от сложности шага обработки…

Добавлено через 13 минут
Dragokas,

Цитата
Сообщение от Dragokas
Посмотреть сообщение

If Not Cbool(Not Not arr) Then

очень прошу (хотя понимаю, что мой вопрос кошмарит грамотных людей), объяснить все эти Not понятным языком — что за что отвечает.



0



Dragokas

Эксперт WindowsАвтор FAQ

17992 / 7618 / 890

Регистрация: 25.12.2011

Сообщений: 11,351

Записей в блоге: 17

22.07.2015, 22:31

13

Лучший ответ Сообщение было отмечено AndreA SN как решение

Решение

AndreA SN, да. Вы правы. Перемудрил. Можно проще.

Visual Basic
1
2
if -1 = not arr then debug.? "Empty"
if -1 <> not arr then debug.? "not Empty"

Если кратко, то оператор Not кроме основной функции (побитовое отрицание) умеет разыменовывать указатель,
что он и делает. Если указатель нулевой (т.е. массив неинициализирован), тогда Not 0 = -1.



1



snipe

4038 / 1423 / 394

Регистрация: 07.08.2013

Сообщений: 3,541

23.07.2015, 04:02

14

AndreA SN, есть 2 функции Join и Split
первая собирает массив в текстовую переменную а вторая наоборот разбирает текстовую переменную в массив
если текстовая переменная выдержит то работать по идее это должно быстрее
вы ведь пытаетесь из много массивов сделать один
код будет выглядеть примерно так

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
dim asd as string
for i=1 to m' где m количество массивов
' тут строка с проверкой массива на пустоту и если не пустой то
if asd="" Then
asd=Join(dfg(),"*")' где dfg имя массива
else
asd=asd & "*" & Join(dfg(),"*")
end if
next i
dim a() as string
a=Split(asd,"*")



1



4038 / 1423 / 394

Регистрация: 07.08.2013

Сообщений: 3,541

23.07.2015, 04:09

15

Dragokas,
в коде VBA номера строк сползают вверх относительно текста строк

Миниатюры

Как проверить пуст ли массив?
 



0



Эксперт NIX

2670 / 786 / 176

Регистрация: 14.01.2013

Сообщений: 3,674

23.07.2015, 06:54

16

В Опере всё норм выглядит.

Миниатюры

Как проверить пуст ли массив?
 



1



snipe

23.07.2015, 09:01

Не по теме:

так я тоже в опере делал



0



1014 / 118 / 2

Регистрация: 26.08.2011

Сообщений: 1,113

Записей в блоге: 2

23.07.2015, 10:54

 [ТС]

18

snipe,

Цитата
Сообщение от snipe
Посмотреть сообщение

из много массивов сделать один

нет… у меня задача другая… я делаю маленький реплик-массив из большого массива. причем оба они двумерны. реплик-массив как правило варьирует от 2 до нескольких десятков записей (встречаются редко случаи и до 2500), а большой массив может включать десятки тысяч записей. Постоянная перезапись реплик-массива с изменяющимися исходными условиями вынуждают при последующей работе проверять : а записалось ли чего-то в реплик-массив, или он при изменившихся условиях отбора записей остался пустым? Вот последнее хочется грамотно проверять, что Dragokas и подсказал как делать.

Добавлено через 11 минут
snipe, по поводу строчек… у меня в Chrom всё вроде норм выглядит



0



4038 / 1423 / 394

Регистрация: 07.08.2013

Сообщений: 3,541

23.07.2015, 11:01

19

AndreA SN, вы тему разместили в разделе VBA, а в какой программе вы все это делаете?



0



1014 / 118 / 2

Регистрация: 26.08.2011

Сообщений: 1,113

Записей в блоге: 2

23.07.2015, 11:25

 [ТС]

20

snipe, толковый вопрос))) мне уже столько людей у виска пальцем крутит по поводу моего проекта в VBA))) И Вы почуяли, что моя задача монстрифицирована.
Пишу всё в Excel. Начиналось как побочная группа минимакросов по предварительной обработке данных. Разрослось до масштабного проекта по верификации сведений с функцией минимизации влияния «шаловливых ручек». В итоге на стадии завершения программа-прототип.
Конечный продукт будет рисоваться в Шарпее.

Добавлено через 9 минут
Просто почему VBA:
1. Если на VBA будет быстрей — то на шарпее будет летать аки бчёл!
2. excel — замечательный полигон для отладки работы с двумерными базами данных при сложном аналитическом инструментарии. Я вижу что происходит с данными и соответственно отлаживаю инструменты поиска
3. размечаю в цвете измененные позиции — получается учет изменений для оценки объемов корректировок
4. не нужно специального программного обеспечения — работаю на 5 машинах в разное время — нигде не ставлю шарпик
это быстрый список причин — почему VBA.



0



I want to check for empty arrays. Google gave me varied solutions but nothing worked. Maybe I am not applying them correctly.

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

Here if FileNamesList array is empty, GetBoiler(SigString) should not get called at all. When FileNamesList array is empty, SigString is also empty and this calls GetBoiler() function with empty string. I get an error at line

Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)

since sFile is empty. Any way to avoid that?

Guy's user avatar

Guy

10.7k5 gold badges34 silver badges47 bronze badges

asked Oct 15, 2008 at 20:31

Vicky's user avatar

2

Go with a triple negative:

If (Not Not FileNamesList) <> 0 Then
    ' Array has been initialized, so you're good to go.
Else
    ' Array has NOT been initialized
End If

Or just:

If (Not FileNamesList) = -1 Then
    ' Array has NOT been initialized
Else
    ' Array has been initialized, so you're good to go.
End If

In VB, for whatever reason, Not myArray returns the SafeArray pointer. For uninitialized arrays, this returns -1. You can Not this to XOR it with -1, thus returning zero, if you prefer.

               (Not myArray)   (Not Not myArray)
Uninitialized       -1                 0
Initialized    -someBigNumber   someOtherBigNumber

Source

Community's user avatar

answered Jan 17, 2013 at 15:49

ahuth's user avatar

ahuthahuth

1,34911 silver badges15 bronze badges

3

As you are dealing with a string array, have you considered Join?

If Len(Join(FileNamesList)) > 0 Then

answered Oct 15, 2008 at 21:14

Fionnuala's user avatar

FionnualaFionnuala

90.1k7 gold badges110 silver badges148 bronze badges

8

If you test on an array function it’ll work for all bounds:

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

answered Mar 6, 2009 at 19:10

Lance Roberts's user avatar

Lance RobertsLance Roberts

22.2k32 gold badges112 silver badges129 bronze badges

3

I see similar answers on here… but not mine…

This is how I am unfortunatley going to deal with it… I like the len(join(arr)) > 0 approach, but it wouldn’t work if the array was an array of 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

answered Jun 26, 2015 at 21:26

Perposterer's user avatar

PerpostererPerposterer

3293 silver badges8 bronze badges

When writing VBA there is this sentence in my head: «Could be so easy, but…»

Here is what I adopted it to:

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

Lance Roberts's user avatar

Lance Roberts

22.2k32 gold badges112 silver badges129 bronze badges

answered Apr 1, 2011 at 9:55

BBQ Chef's user avatar

BBQ ChefBBQ Chef

6964 gold badges11 silver badges21 bronze badges

2

This code doesn’t do what you expect:

If Dir(SigString) <> "" Then
    Signature = GetBoiler(SigString) 
Else
    Signature = "" 
End If

If you pass an empty string ("") or vbNullString to Dir, it will return the name of the first file in the current directory path (the path returned by CurDir$). So, if SigString is empty, your If condition will evaluate to True because Dir will return a non-empty string (the name of the first file in the current directory), and GetBoiler will be called. And if SigString is empty, the call to fso.GetFile will fail.

You should either change your condition to check that SigString isn’t empty, or use the FileSystemObject.FileExists method instead of Dir for checking if the file exists. Dir is tricky to use precisely because it does things you might not expect it to do. Personally, I would use Scripting.FileSystemObject over Dir because there’s no funny business (FileExists returns True if the file exists, and, well, False if it doesn’t). What’s more, FileExists expresses the intent of your code much clearly than Dir.

Method 1: Check that SigString is non-empty first

If SigString <> "" And Dir(SigString) <> "" Then
    Signature = GetBoiler(SigString) 
Else
    Signature = "" 
End If

Method 2: Use the FileSystemObject.FileExists method

Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")

If fso.FileExists(SigString) Then
    Signature = GetBoiler(SigString) 
Else
    Signature = "" 
End If

answered Oct 15, 2008 at 21:14

Mike Spross's user avatar

Mike SprossMike Spross

7,9596 gold badges49 silver badges75 bronze badges

I am simply pasting below the code by the great Chip Pearson. It works a charm.
Here’s his page on array functions.

I hope this helps.

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

Community's user avatar

answered Sep 30, 2013 at 13:52

sancho.s ReinstateMonicaCellio's user avatar

1

Simplified check for Empty Array:

Dim exampleArray() As Variant 'Any Type

If ((Not Not exampleArray) = 0) Then
      'Array is Empty
Else
      'Array is Not Empty
End If

arghtype's user avatar

arghtype

4,34611 gold badges47 silver badges59 bronze badges

answered Oct 21, 2014 at 15:25

Robert S.'s user avatar

1

Here is another way to do it. I have used it in some cases and it’s working.

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

Fabio says Reinstate Monica's user avatar

answered May 12, 2016 at 15:38

Surya's user avatar

SuryaSurya

211 bronze badge

Based on ahuth’s answer;

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

Check for an empty array; is_empty = AryLen(some_array)=0

answered Jul 15, 2017 at 22:28

user425678's user avatar

user425678user425678

7107 silver badges16 bronze badges

Public Function IsEmptyArray(InputArray As Variant) As Boolean

   On Error GoTo ErrHandler:
   IsEmptyArray = Not (UBound(InputArray) >= 0)
   Exit Function

   ErrHandler:
   IsEmptyArray = True

End Function

answered Jan 15, 2014 at 23:14

Zhenya's user avatar

ZhenyaZhenya

1741 silver badge8 bronze badges

1

You can use the below function to check if variant or string array is empty in 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

Sample usage

Public Function test()
Dim Arr(1) As String
Arr(0) = "d"
Dim x As Boolean
x = IsArrayAllocated(Arr)
End Function

answered May 4, 2015 at 8:43

Vignesh Subramanian's user avatar

0

Another method would be to do it sooner. You can create a Boolean variable and set it to true once you load data to the array. so all you really need is a simple if statement of when you load data into the array.

answered Feb 11, 2016 at 14:22

Tim Boutchia's user avatar

To check whether a Byte array is empty, the simplest way is to use the VBA function StrPtr().

If the Byte array is empty, StrPtr() returns 0; otherwise, it returns a non-zero value (however, it’s not the address to the first element).

Dim ar() As Byte
Debug.Assert StrPtr(ar) = 0

ReDim ar(0 to 3) As Byte
Debug.Assert StrPtr(ar) <> 0

However, it only works with Byte array.

answered Oct 30, 2016 at 6:49

Fuzzier's user avatar

Function IsVarArrayEmpty(anArray As Variant) as boolean
    On Error Resume Next
    IsVarArrayEmpty = true
    IsVarArrayEmpty = UBound(anArray) < LBound(anArray)
End Function

Maybe ubound crashes and it remains at true, and if ubound < lbound, it’s empty

cssyphus's user avatar

cssyphus

37.1k18 gold badges93 silver badges109 bronze badges

answered Sep 30, 2016 at 15:49

Pierre's user avatar

PierrePierre

1,0267 silver badges20 bronze badges

I’ll generalize the problem and the Question as intended.
Test assingment on the array, and catch the eventual error

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

Sure it misses arrays with all negative indexes or all > 1… is that likely? in weirdland, yes.

Lance Roberts's user avatar

Lance Roberts

22.2k32 gold badges112 silver badges129 bronze badges

answered Nov 12, 2008 at 19:00

jpinto3912's user avatar

jpinto3912jpinto3912

1,4652 gold badges12 silver badges19 bronze badges

1

Personally, I think one of the answers above can be modified to check if the array has contents:

if UBound(ar) > LBound(ar) Then

This handles negative number references and takes less time than some of the other options.

answered Mar 27, 2013 at 20:05

Jim Snyder's user avatar

Jim SnyderJim Snyder

391 silver badge3 bronze badges

1

You can check if the array is empty by retrieving total elements count using JScript’s VBArray() object (works with arrays of variant type, single or 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

For me it takes about 0.3 mksec for each element + 15 msec initialization, so the array of 10M elements takes about 3 sec. The same functionality could be implemented via ScriptControl ActiveX (it is not available in 64-bit MS Office versions, so you can use workaround like this).

Community's user avatar

answered Aug 5, 2016 at 10:45

omegastripes's user avatar

omegastripesomegastripes

12.3k4 gold badges44 silver badges95 bronze badges

1

if Ubound(yourArray)>-1 then
 debug.print "The array is not empty"
else
 debug.print "EMPTY"
end if

answered Dec 1, 2016 at 11:32

Dave Poole's user avatar

Dave PooleDave Poole

9987 silver badges13 bronze badges

0

You can check its count.

Here cid is an array.

if (jsonObject("result")("cid").Count) = 0 them
MsgBox "Empty Array"

I hope this helps.
Have a nice day!

answered Jun 19, 2018 at 16:43

Mantej Singh's user avatar

Another solution to test for empty array

if UBound(ar) < LBound(ar) then msgbox "Your array is empty!"

Or, if you already know that LBound is 0

if -1 = UBound(ar) then msgbox "Your array is empty!"

This may be faster than join(). (And I didn’t check with negative indexes)

Here is my sample to filter 2 string arrays so they do not share same strings.

' 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 
'

mmmmmm's user avatar

mmmmmm

32.1k27 gold badges89 silver badges116 bronze badges

answered Jul 15, 2012 at 10:43

irm's user avatar

1

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

answered Nov 3, 2012 at 17:38

Stefanos Kargas's user avatar

Stefanos KargasStefanos Kargas

10.3k22 gold badges75 silver badges101 bronze badges

1

Массивы в VBA Excel: одномерные, многомерные и динамические. Объявление и использование массивов. Операторы Public, Dim и ReDim. Функции Array, LBound, UBound.

Массивы – это множества однотипных элементов, имеющих одно имя и отличающиеся друг от друга индексами. Они могут быть одномерными (линейными), многомерными и динамическими. Массивы в VBA Excel, как и другие переменные, объявляются с помощью операторов Dim и Public. Для изменения размерности динамических массивов используется оператор ReDim. Массивы с заранее объявленной размерностью называют статическими.

Одномерные массивы

Объявление одномерных (линейных) статических массивов в VBA Excel:

Public Massiv1(9) As Integer

Dim Massiv2(1 To 9) As String

В первом случае публичный массив содержит 10 элементов от 0 до 9 (нижний индекс по умолчанию — 0, верхний индекс — 9), а во втором случае локальный массив содержит 9 элементов от 1 до 9.

По умолчанию VBA Excel считает в массивах нижним индексом нуль, но, при желании, можно сделать нижним индексом по умолчанию единицу, добавив в самом начале модуля объявление «Option Base 1».

Многомерные массивы

Объявление многомерных статических массивов в VBA Excel аналогично объявлению одномерных массивов, но с добавлением размерностей дополнительных измерений через запятую:

‘Массив двухмерный

Public Massiv1(3, 6) As Integer

‘Массив трехмерный

Dim Massiv2(1 To 6, 1 To 8, 1 To 5) As String

‘Массив четырехмерный

Dim Massiv3(9, 9, 9, 9) As Date

Третий массив состоит из 10000 элементов — 10×10×10×10.

Динамические массивы

Динамические массивы в VBA Excel, в отличие от статических, объявляются без указания размерности:

Public Massiv1() As Integer

Dim Massiv2() As String

Такие массивы используются, когда заранее неизвестна размерность, которая определяется в процессе выполнения программы. Когда нужная размерность массива становится известна, она в VBA Excel переопределяется с помощью оператора ReDim:

Public Massiv1() As Integer

Dim Massiv2() As String

ReDim Massiv1(1 To 20)

ReDim Massiv2(3, 5, 4)

При переопределении размерности массива вместо верхнего индекса можно использовать переменную:

Dim Massiv1() as Variant, x As Integer

x = 20

ReDim Massiv1(1 To x)

Переопределять размерность динамических массивов в процессе работы программы можно неоднократно, как по количеству измерений, так и по количеству элементов в измерении.

С помощью оператора ReDim невозможно изменить обычный массив, объявленный с заранее заданной размерностью. Попытка переопределить размерность такого массива вызовет ошибку компиляции с сообщением: Array already dimensioned (Массив уже измерен).

При переопределении размерности динамических массивов в VBA Excel теряются значения их элементов. Чтобы сохранить значения, используйте оператор Preserve:

Dim Massiv1() As String

операторы

ReDim Massiv1(5, 2, 3)

операторы

ReDim Preserve Massiv1(5, 2, 7)

Обратите внимание!
Переопределить с оператором Preserve можно только последнюю размерность динамического массива. Это недоработка разработчиков, которая сохранилась и в VBA Excel 2016. Без оператора Preserve можно переопределить все размерности.

Максимальный размер

Размер массива – это произведение длин всех его измерений. Он представляет собой общее количество элементов, содержащихся в данный момент в массиве.

По информации с сайта разработчиков, максимальный размер массивов зависит от операционной системы и доступного объема памяти. Использование массивов, размер которых превышает объем доступной оперативной памяти компьютера, приводит к снижению скорости, поскольку системе необходимо выполнять запись данных и чтение с диска.

Использование массивов

Приведу два примера, где не обойтись без массивов.

1. Как известно, функция Split возвращает одномерный массив подстрок, извлеченных из первоначальной строки с разделителями. Эти данные присваиваются заранее объявленному строковому (As String) одномерному динамическому массиву. Размерность устанавливается автоматически в зависимости от количества подстрок.

2. Данные в массивах обрабатываются значительно быстрее, чем в ячейках рабочего листа. Построчную обработку информации в таблице Excel можно наблюдать визуально по мерцаниям экрана, если его обновление (Application.ScreenUpdating) не отключено. Чтобы ускорить работу кода, можно значения из диапазона ячеек предварительно загрузить в динамический массив с помощью оператора присваивания (=). Размерность массива установится автоматически. После обработки данных в массиве кодом VBA полученные результаты выгружаются обратно на рабочий лист Excel. Обратите внимание, что загрузить значения в диапазон ячеек рабочего листа через оператор присваивания (=) можно только из двумерного массива.

Функции Array, LBound, UBound

Функция Array

Функция Array возвращает массив элементов типа Variant из первоначального списка элементов, перечисленных через запятую. Нумерация элементов в массиве начинается с нуля. Обратиться к элементу массива можно, указав в скобках его номер (индекс).

Sub Test1()

Dim a() As Variant

a = Array(«text», 25, «solo», 35.62, «stop»)

MsgBox a(0) & vbNewLine & a(1) & vbNewLine _

& a(2) & vbNewLine & a(3) & vbNewLine & a(4)

End Sub

Скопируйте код в модуль VBA Excel и запустите его на выполнение. Информационное сообщение MsgBox покажет значения массива, извлеченные по индексу.

Функция LBound

Функция LBound возвращает значение типа Long, равное наименьшему (нижнему) доступному индексу в указанном измерении массива.
Синтаксис:
LBound (arrayname[, dimension])

  • arrayname — это имя переменной массива, является обязательным аргументом;
  • dimension — это номер измерения массива, необязательный аргумент, по умолчанию принимает значение 1.

Наименьший индекс по-умолчанию может быть равен 0 или 1 в зависимости от настроек оператора Option Base. Нижняя граница архива, полученного с помощью функции Array, всегда равна 0.

При объявлении переменных массивов или переопределении их размерности наименьшие индексы могут быть любыми целыми числами, в том числе отрицательными.

Функция UBound

Функция UBound возвращает значение типа Long, равное наибольшему (верхнему) доступному индексу в указанном измерении массива.
Синтаксис:
UBound( arrayname[, dimension])

  • arrayname — это имя переменной массива, является обязательным аргументом;
  • dimension — это номер измерения массива, необязательный аргумент, по умолчанию принимает значение 1.

Функция UBound используется вместе с функцией LBound для определения размера массива.

Sub Test2()

Dim a(2 To 53) As String

MsgBox «Наименьший индекс = « & LBound(a) & _

vbNewLine & «Наибольший индекс = « & UBound(a)

End Sub

Скопируйте код в модуль VBA Excel и запустите его на выполнение. Информационное сообщение MsgBox покажет значения наименьшего и наибольшего индекса переменной массива a.

Обход массива циклом

Обход одномерного массива циклом For… Next, в котором для определения границ массива используются функции UBound и LBound:

Sub Test3()

Dim a() As Variant, i As Long

a = Array(«text», 25, «solo», 35.62, «stop»)

    For i = LBound(a) To UBound(a)

        Debug.Print «a(« & i & «) = « & a(i)

    Next

End Sub

Результат работы цикла вы увидите в окне Immediate.

Очистка (обнуление) массивов

Первый способ

Очистить любой массив, статический или динамический, без использования цикла можно с помощью оператора Erase. Термин «обнуление» можно применить только к массиву числового типа.

Dim Massiv1(4, 3) As String,  Massiv2() As Variant

операторы

‘переопределяем динамический массив

ReDim Massiv2(2, 5, 3)

операторы

‘очищаем массивы

Erase Massiv1

Erase Massiv2

Обратите внимание, что оба массива при таком способе очистки будут возвращены в исходное состояние, которое они имели сразу после объявления:

  • статический Massiv1 сохранит размерность (4, 3);
  • динамический Massiv2 не сохранит размерность ().

Второй способ

Динамический массив можно очистить (обнулить) без использования цикла с помощью оператора ReDim. Просто переопределите его с той же размерностью.

Dim Massiv() As Double

операторы

‘переопределяем массив

ReDim Massiv(5, 6, 8)

операторы

‘очищаем массив

ReDim Massiv(5, 6, 8)


 

Добрый день.  
Как правильно записать строчку кода, чтобы проверить, является ли массив MyArray непустым? Т.е. если в массиве есть хоть один элемент, то погнали дальше, если нет ни одного, то перескочили.  
Спасибо.

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

Sub Arr_Initialize()  
Dim avArr()  
   If (Not Not avArr) = 0 Then  
       MsgBox «массив пуст и записей в нем не было»  
   Else  
       MsgBox «массив заполнен чем-то»  
   End If  
ReDim avArr(1): avArr(1) = 1  
   If (Not Not avArr) = 0 Then  
       MsgBox «массив пуст и записей в нем не было»  
   Else  
       MsgBox «массив заполнен чем-то»  
   End If  
End Sub

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

Спасибо большое. Все очень понятно объяснили.  
Правда, не понял смысл двойного отрицания (Not Not).  
Если не затруднит, просветите.

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

Впишите в ячейку А1 формулу:  
=НЕ(НЕ(A1=0))  

  Вычислите её пошагово и все поймете.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

{quote}{login=The_Prist}{date=06.06.2010 11:30}{thema=}{post}Впишите в ячейку А1 формулу:  
=НЕ(НЕ(A1=0))  

  Вычислите её пошагово и все поймете.{/post}{/quote}  

  Вписал в ячейку B1 формулу =НЕ(НЕ(A1=0)),  
в ячейку B2 формулу =A2=0.  
Поигрался с нулями,цифрами и пустотами — разницы в работе обеих формул не увидел.

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

Эх…Простой конструкцией типа avArr = 0 не получиться узнать наполнение массива — такая конструкция недопустима, сначала необходимо переопределить размерность, т.к. VBA считает, что Вы хотите присвоить массиву значение.  

  В этом выражении:  
Not Not avArr  

  VBA сначала сравнивает массив, преобразуя его в тип Integer, независимо от данных в нем(на сами данные не влияет), не вызывая ошибку.    
В общем-то можно и так записать для достижения цели:  
(Not avArr) = 0    

  Но все равно придется добавлять Not, чтобы было вроде как понятней(или поменять условия местами).  
Не знаю, понятно объяснил или нет — по-другому не умею.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

Еще раз спасибо огромное.

 

KuklP

Пользователь

Сообщений: 14868
Регистрация: 21.12.2012

E-mail и реквизиты в профиле.

{quote}{login=The_Prist}{date=06.06.2010 12:22}{thema=}{post}  
В общем-то можно и так записать для достижения цели:  
(Not avArr) = 0    
{/post}{/quote}    
Дим, ты наверное хотел сказать  
(Not avArr) = -1 Then массив пустой

Я сам — дурнее всякого примера! …

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

{quote}{login=KuklP}{date=06.06.2010 01:27}{thema=Re: }{post}{quote}{login=The_Prist}{date=06.06.2010 12:22}{thema=}{post}  
В общем-то можно и так записать для достижения цели:  
(Not avArr) = 0    
{/post}{/quote}    
Дим, ты наверное хотел сказать  
(Not avArr) = -1 Then массив пустой{/post}{/quote}Нет, Сергей, я написал ровно то, что хотел.  

  «В общем-то можно и так записать для достижения цели:  
(Not avArr) = 0    
Но все равно придется добавлять Not, чтобы было вроде как понятней(или поменять условия местами).»  

  Это же конструкция сравнения. С нулем как-то смотрится более информативно.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

KuklP

Пользователь

Сообщений: 14868
Регистрация: 21.12.2012

E-mail и реквизиты в профиле.

Дим, при (Not avArr) = 0 выдаст, что массив не пустой в обоих случаях.  
при пустом массиве (Not avArr) = -1.  
Проверь.

Я сам — дурнее всякого примера! …

 

KuklP

Пользователь

Сообщений: 14868
Регистрация: 21.12.2012

E-mail и реквизиты в профиле.

Да, а Not(-1) как раз и дает 0.

Я сам — дурнее всякого примера! …

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

{quote}{login=KuklP}{date=06.06.2010 02:07}{thema=}{post}Дим, при (Not avArr) = 0 выдаст, что массив не пустой в обоих случаях.  
при пустом массиве (Not avArr) = -1.  
Проверь.{/post}{/quote}Почему?  

  Sub Arr_Initialize()  
   Dim avArr()  
   If (Not avArr) = 0 Then  
       MsgBox «массив пуст и записей в нем не было»  
   Else  
       MsgBox «массив заполнен чем-то»  
   End If  
   ReDim avArr(1): avArr(1) = 1  
   If (Not avArr) = 0 Then  
       MsgBox «массив пуст и записей в нем не было»  
   Else  
       MsgBox «массив заполнен чем-то»  
   End If  
End Sub  

  Вот в этой процедуре получиться, что условия перепутаны. Именно про это я и писал: «Но все равно придется добавлять Not, чтобы было вроде как понятней(или поменять условия местами)»  
Ключевая фраза: поменять условия местами

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

KuklP

Пользователь

Сообщений: 14868
Регистрация: 21.12.2012

E-mail и реквизиты в профиле.

Да нет же, Дим(вот я не умею так понятно объяснять как ты)  
Это константы:  
true в Exsel = -1  
False=0  
В твоей конструкции  (Not avArr) = 0 никогда не наступит, ибо для пустого массива  
(Not avArr) = -1  
Для непустого напрмер -2390769 (у меня эта цифра меняется).  
Поэтому твоя программа всегда будет выводить МСГ — «массив заполнен чем-то».

Я сам — дурнее всякого примера! …

 

Юрий М

Модератор

Сообщений: 60575
Регистрация: 14.09.2012

Контакты см. в профиле

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

А, ну да. Чет я сразу не догнал.  
Но первый вариант — (Not Not avArr) = 0 — работает на ура! :-)

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

KuklP

Пользователь

Сообщений: 14868
Регистрация: 21.12.2012

E-mail и реквизиты в профиле.

Все, сдаюсь.

Я сам — дурнее всякого примера! …

 

Извиняюсь, что вклиниваюсь в беседу, но у меня  
первый вариант The_Pristа If (Not Not avArr) = 0 Then  
прошел изумительно.

 

KuklP

Пользователь

Сообщений: 14868
Регистрация: 21.12.2012

E-mail и реквизиты в профиле.

{quote}{login=Егор}{date=06.06.2010 02:36}{thema=}{post}Извиняюсь, что вклиниваюсь в беседу, но у меня  
первый вариант The_Pristа If (Not Not avArr) = 0 Then  
прошел изумительно.{/post}{/quote}  
Егор, это же Вам не понравилось двойное отрицание. Из-за этого и весь этот диспут.  
Прграмма The_Prist работает на ура и без двойного отрицания при  (Not avArr) = -1.

Я сам — дурнее всякого примера! …

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

Вообще главная фишка такой проверки в том, что можно проверить даже неинициализированный массив. Т.к. неинициализированный массив при помощи UBound() не проверить — выдаст ошибку.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

{quote}{login=KuklP}{date=06.06.2010 02:43}{thema=Re: }{post}{quote}{login=Егор}{date=06.06.2010 02:36}{thema=}{post}Извиняюсь, что вклиниваюсь в беседу, но у меня  
первый вариант The_Pristа If (Not Not avArr) = 0 Then  
прошел изумительно.{/post}{/quote}  
Егор, это же Вам не понравилось двойное отрицание. Из-за этого и весь этот диспут.  
Прграмма The_Prist работает на ура и без двойного отрицания при  (Not avArr) = -1.{/post}{/quote}  

  мне двойное отрицание не не понравилось, а просто я не знал, что ему может быть  
логичное применение.  
А из вашей беседы я вынес много для себя поучительного, за что вам всем  
очень признателен.

 

ZVI

Пользователь

Сообщений: 4328
Регистрация: 23.12.2012

Массивы бывают разные.  
В частности, переменная типа Variant тоже может стать массивом,  
и в таком случае (Not Not Arr) = 0 глюканет.  
Пример:  

  Sub Test1()  
 Dim a(), b  
 Debug.Print «a», (Not Not a) = 0  
 Debug.Print «b», (Not Not b) = 0  
 ReDim a(1 To 1)  
 ReDim b(1 To 1)  
 Debug.Print «a1», (Not Not a) = 0  
 Debug.Print «b1», (Not Not b) = 0 ‘ <— выдает ошибку  
End Sub  

  Это потому, что в переменной типа Variant хранится не указатель на массив, а указатель на указатель на массив :-)  

  Поэтому надежнее так:  

  Function IsArrayEmpty(x) As Boolean  
 Dim i&  
 On Error Resume Next  
 i = LBound(x)  
 IsArrayEmpty = Err <> 0  
End Function  

  Sub Test2()  
 Dim a(), b  
 Debug.Print «a», IsArrayEmpty(a)  
 Debug.Print «b», IsArrayEmpty(b)  
 ReDim a(1 To 1)  
 ReDim b(1 To 1)  
 Debug.Print «a1», IsArrayEmpty(a)  
 Debug.Print «b1», IsArrayEmpty(b)  
End Sub

 

В моем массиве каждый элемент это название,состоящее из 2-10 букв.  
(Not Not Arr) = 0 Когда-нибудь глюканет или не глюканет?

 

KuklP

Пользователь

Сообщений: 14868
Регистрация: 21.12.2012

E-mail и реквизиты в профиле.

{quote}{login=ZVI}{date=06.06.2010 03:34}{thema=}{post}Массивы бывают разные.  
Поэтому надежнее так:  
{/post}{/quote}  
Тоже вкусно. Имхо такие фишки как:  
(Not Not avArr) = 0 (The_Prist)  
IsArrayEmpty = Err <> 0 (Ваша ZVI)  
If wsSh.Cells(1, 1).End(xlDown) <> «» (проверка на пустую строку от Слэн)  
и им подобные должны быть в приемах.  
Или, на худой конец, как писал вчера kim:  
«Пора копать землянку макросописателей/(писцев)…». Но это будет не так доступно(разве что беседку, избушку и землянку прилепить в начало форума. Мож как-то к тем 300 советам добавить(это я к модераторам)?

Я сам — дурнее всякого примера! …

 

ZVI

Пользователь

Сообщений: 4328
Регистрация: 23.12.2012

{quote}{login=Егор}{date=06.06.2010 04:20}{thema=}{post}В моем массиве каждый элемент это название,состоящее из 2-10 букв.  
(Not Not Arr) = 0 Когда-нибудь глюканет или не глюканет?{/post}{/quote}  
Не глюканет, если переменная Arr объявлена так: Dim Arr()  
Глюканет, если переменная Arr не будет никак объявлена, или если будет объявлена так: Dim Arr

 

{quote}{login=ZVI}{date=06.06.2010 04:26}{thema=}{post}{quote}{login=Егор}{date=06.06.2010 04:20}{thema=}{post}В моем массиве каждый элемент это название,состоящее из 2-10 букв.  
(Not Not Arr) = 0 Когда-нибудь глюканет или не глюканет?{/post}{/quote}  
Не глюканет, если переменная Arr объявлена так: Dim Arr()  
Глюканет, если переменная Arr не будет никак объявлена, или если будет объявлена так: Dim Arr{/post}{/quote}  

  Я объявил массив Dim Arr() As Variant в процедуре обработки события в юзерформе, а затем передал его в качестве аргумента в другую процедуру, которая находится в модуле. В модуле делаю проверку на пустойнепустой.  
Так считается , что я его объявил?

 

ZVI

Пользователь

Сообщений: 4328
Регистрация: 23.12.2012

{quote}{login=}{date=06.06.2010 05:00}{thema=Re: }{post}Я объявил массив Dim Arr() As Variant в процедуре обработки события в юзерформе, а затем передал его в качестве аргумента в другую процедуру, которая находится в модуле. В модуле делаю проверку на пустойнепустой.  
Так считается , что я его объявил?{/post}{/quote}  
Dim Arr() As Variant — это то же самое, что Dim Arr()  
Если в объявлении переменной присутствуют круглые скобки, то это явное объявление переменной массива. При этом проблемы с (Not Not Arr) = 0 не будет.  
Если же круглых скобок нет: Dim Arr  
то возникнет указанная проблема с (Not Not Arr) = 0  
Ещё раз — важны именно круглые скобки при объявлении, а As ЛюбойТип — не имеет значения для метода (Not Not Arr) = 0

 

Егор

Гость

#27

06.06.2010 17:55:42

Ясно. Спасибо.

While this is essentially just @Brad’s answer again, I thought it might be worth including a slightly modified function which will return the index of the item you’re searching for if it exists in the array. If the item is not in the array, it returns -1 instead.

The output of this can be checked just like the «in string» function, If InStr(...) > 0 Then, so I made a little test function below it as an example.

Option Explicit

Public Function IsInArrayIndex(stringToFind As String, arr As Variant) As Long

    IsInArrayIndex = -1

    Dim i As Long
    For i = LBound(arr, 1) To UBound(arr, 1)
        If arr(i) = stringToFind Then
            IsInArrayIndex = i
            Exit Function
        End If
    Next i

End Function

Sub test()

    Dim fruitArray As Variant
    fruitArray = Array("orange", "apple", "banana", "berry")

    Dim result As Long
    result = IsInArrayIndex("apple", fruitArray)

    If result >= 0 Then
        Debug.Print chr(34) & fruitArray(result) & chr(34) & " exists in array at index " & result
    Else
        Debug.Print "does not exist in array"
    End If

End Sub

Then I went a little overboard and fleshed out one for two dimensional arrays because when you generate an array based on a range it’s generally in this form.

It returns a single dimension variant array with just two values, the two indices of the array used as an input (assuming the value is found). If the value is not found, it returns an array of (-1, -1).

Option Explicit

Public Function IsInArray2DIndex(stringToFind As String, arr As Variant) As Variant

    IsInArray2DIndex= Array(-1, -1)

    Dim i As Long
    Dim j As Long

    For i = LBound(arr, 1) To UBound(arr, 1)
        For j = LBound(arr, 2) To UBound(arr, 2)
            If arr(i, j) = stringToFind Then
                IsInArray2DIndex= Array(i, j)
                Exit Function
            End If
        Next j
    Next i

End Function

Here’s a picture of the data that I set up for the test, followed by the test:

test 2

Sub test2()

    Dim fruitArray2D As Variant
    fruitArray2D = sheets("Sheet1").Range("A1:B2").value

    Dim result As Variant
    result = IsInArray2DIndex("apple", fruitArray2D)

    If result(0) >= 0 And result(1) >= 0 Then
        Debug.Print chr(34) & fruitArray2D(result(0), result(1)) & chr(34) & " exists in array at row: " & result(0) & ", col: " & result(1)
    Else
        Debug.Print "does not exist in array"
    End If

End Sub

Понравилась статья? Поделить с друзьями:
  • Vba excel копировать диапазон ячеек
  • Vba excel копирование ячейки на другой лист
  • Vba excel копирование формул
  • Vba excel копирование форматов ячеек excel
  • Vba excel копирование формата ячейки