Excel vba как проверить что массив пустой

AndreA SN

1014 / 118 / 2

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

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

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

1

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

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

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


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

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

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

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



0



3827 / 2254 / 751

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

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

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

17991 / 7617 / 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

17991 / 7617 / 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

17991 / 7617 / 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,672

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



 

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

 

The_Prist

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

Сообщений: 14181
Регистрация: 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

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

Сообщений: 14181
Регистрация: 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

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

Сообщений: 14181
Регистрация: 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

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

Сообщений: 14181
Регистрация: 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

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

Сообщений: 14181
Регистрация: 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 (у меня эта цифра меняется).  
Поэтому твоя программа всегда будет выводить МСГ — «массив заполнен чем-то».

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

 

Юрий М

Модератор

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

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

 

The_Prist

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

Сообщений: 14181
Регистрация: 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

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

Сообщений: 14181
Регистрация: 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

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

When a list or collection of items that are the same data type are stored in continuous memory locations, we call it an array. Arrays are useful objects that are widely used in software development to organize data. Some real examples of where you might use them might include:

  1. Online games, like chess, make use of two dimensional arrays.
  2. An ECG waveform is a realtime example of array usage.

I’ll show you a couple array examples, then we’ll get into how to check if one is empty.

Sub array_demo()

'Declaration of array variable
Dim arr() As String

'Defining length of array
ReDim arr(8)

For i = 0 To 8
    'Allocate data for each array item through a loop
    arr(i) = Cells(i + 2, 1).Value
    
    'Print each item
    Debug.Print arr(i)
Next

End Sub

Output in Excel for array with wonders of the world

Here is another example that creates an array as a result of using the Split function.

Sub array_split_demo()

'list of days in a string separated by a single space
days_string = "sunday monday tuesday wednesday thursday friday saturday"

'splitting the string into an array using a delimiter
weekdays = Split(days_string, " ")

'printing them all
For i = LBound(weekdays) To UBound(weekdays)
Debug.Print weekdays(i)
Next

End Sub

The above code prints a list of days while iterating through the array in that was created when the string was split and stored.

Types of arrays

In VBA arrays can either be static or dynamic.

Static arrays

The size of the array is fixed and cannot be changed.

Dynamic arrays

The size of the array is not fixed and can be modified based on your requirements.

Check if an array is empty or contains data

In VBA, unless we first define the size of an array, we cannot use the Lbound() and UBound functions. It will throw an error. So, we need to use the Redim keyword and define a size as soon as we declare an array.

Also there isn’t a specific function that can validate the existence of data in an array. So, we have to make use pf other available functions, along with some logic, to determine if an array is empty or not.

Below are a few methods you can utilize.

Join function

Just like how we used the split function to split a string into an array, a Join function can be used to concatenate all elements of an array into a single string.

Syntax:

Join ( <source array> , [ < Delimiter > ] )

Where

Source array is the name of the array whose elements need to be joined.

Delimiter is the character that is going to be placed between the concatenation of every two elements while joining the array elements. This is an optional parameter and if it’s not provided, a space “ “ is used by default.

If a zero length string “” is provided as a delimiter, the joining happens without inserting any characters during concatenation.

For example:

Sub join_arraydemo()

' Join together the strings "Orange", "Apple" and "Mango".
Dim all_fruits As String
Dim fruits(0 To 2) As String

'assign values for all fruits
fruits(0) = "Orange"
fruits(1) = "Apple"
fruits(2) = "Mango"

'Join using the built-in function
all_fruits = Join(fruits)

' The variable all_fruits is now set to "Orange Apple Mango"
Debug.Print all_fruits
End Sub

So, first all the elements of the array are concatenated using the Join function, then the resulting string’s length can be checked to check if the array is empty or not.

The below piece of code can be added to the above code sample to notify you if the array is empty or not.

If Len(all_fruits) &amp;amp;amp;gt; 0 Then
Debug.Print "fruits array is not empty"
Else
Debug.Print "Fruits array is empty"
End If

In short, we can use the below line to achieve the same results.

If Len(Join(all_fruits)) &amp;amp;amp;gt; 0 Then

Iterate through all the items in the array

Using a For loop, we can iterate through each element in an array to validate whether the array has some data or it is completely empty. Here’s a ready to use function for you.

Function IsEmptyArray(arr)

'a normal flag variable
flag = 0

'loop to check if atleast one element of te array has data
For i = LBound(arr) To UBound(arr)
If IsEmpty(arr(i)) = False Then
    Debug.Print "The array has data"
    flag = 1
    Exit For
End If
Next

'Check if flag value has changed because data is present
If flag = 0 Then
    Debug.Print "The array is empty"
End If

End Function

UBound function + bypass an error

Because an error will be thrown if we use the Ubound or Lbound function on an empty array, we are going to use the “On Error Resume Next” statement and catch the error number to test if the array is empty. Here the array is considered empty if it doesn’t have a size defined. I created a function to help you better understand and use the code.

Sub array_check_demo()

'Declaration of array variable
Dim arr() As Variant

'The array should be empty now
Debug.Print Is_Var_Array_Empty(arr)

'Defining length of array
ReDim arr(8)

'The array has a size . So, as per this logic, it is not empty
Debug.Print Is_Var_Array_Empty(arr)
'We check if the array is empty before assigning values

'Assign values to array elements
For i = 0 To 8
    'Allocate data for each array item through a loop
    arr(i) = Cells(i + 2, 1).Value
Next

'validate if array is empty again
Debug.Print Is_Var_Array_Empty(arr)

End Sub
Function Is_Var_Array_Empty(arr_var As Variant)

Dim p As Integer

On Error Resume Next
    p = UBound(arr_var, 1)
If Err.Number = 0 Then
    Is_Var_Array_Empty = False
Else
    Is_Var_Array_Empty = True
End If

End Function

Results from testing if array is empty using ubound/lbound

StrPtr() function for a byte array

A byte array is nothing but a series or characters. A string can directly be assigned to a byte array. Two elements of an array are used to allocate space for a character from a string. The below code should help you understand further.

Sub byte_array_demo()

'declare a byte array and a string
Dim arr1() As Byte
Dim samplestr As String

'initiate the string
samplestr = "Coffee"

'Check if the array is empty. StrPtr(&amp;amp;amp;lt;arrname&amp;amp;amp;gt;) would return 0 if the array is empty.
Debug.Print StrPtr(arr1) = 0

'allocate the string directly to the byte array
arr1() = samplestr

'View what has been stored in the array
For i = LBound(arr1) To UBound(arr1)
Debug.Print arr1(i)
Next

'Check if the array is empty. StrPtr(&amp;amp;amp;lt;arrname&amp;amp;amp;gt;) would return 0 if the array is empty.
Debug.Print StrPtr(arr1) = 0

End Sub

Explaining the output:

Initially the array is empty , so StrPtr(arr1) returns true.

Ascii value of “C” is 67

Ascii null character

Ascii value of “o” is 111

Ascii null character

Ascii value of “f” is 102

Ascii null character

Ascii value of “f” is 102

Ascii null character

Ascii value of “e” is 101

Ascii null character

Ascii value of “e” is 101

Ascii null character

Finally the array is not empty , so StrPtr(arr1) returns false.

Results from checking array using strptr function.

Conclusion

In VBA, other than StrPtr() function for byte arrays , there are no direct methods to find if an array is empty or not. However our best friend, Magical VBA, offers flexible functions that can be combined with your own logic to check the size of an array or the existence or non-existence of data in an array of any datatype.

The meaning of “EMPTY” here lies with the user. It could either be an array that does not have a size defined or an array that has a specific size but no data in it.

Of the above methods, I recommend just grabbing a user-defined function that you can easily use to check if an array is empty or not.

If you’re looking to see how to check if a cell is empty, check out our article here.

Tagged with: Arrays, Concatenating, Lbound, Loop, redim, Size, Split, Strings, StrPtr, Ubound, VBA

Этот код не выполняет то, что вы ожидаете:

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

Если вы передадите пустую строку ("") или vbNullString в Dir, она вернет имя первого файла в текущем пути к каталогу (путь, возвращаемый CurDir$). Итак, если SigString пусто, ваше условие If будет оцениваться как True, потому что Dir вернет непустую строку (имя первого файла в текущем каталоге), а GetBoiler будет называется. И если SigString пуст, вызов fso.GetFile завершится с ошибкой.

Вы должны либо изменить свое условие, чтобы проверить, что SigString не пусто, либо использовать FileSystemObject.FileExists вместо Dir для проверки наличия файла. Dir сложно использовать именно потому, что он делает то, чего вы не ожидаете от него. Лично я использовал бы Scripting.FileSystemObject над Dir, потому что нет смешного бизнеса (FileExists возвращает True, если файл существует, и, ну, False, если он этого не делает). Что еще, FileExists выражает намерение вашего кода намного ясно, чем Dir.

Способ 1. Убедитесь, что SigString не является пустым первым

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

Метод 2: используйте метод FileSystemObject.FileExists

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

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

Этот код делает не то, что вы ожидаете:

Если вы передадите пустую строку (""") или vbNullString в Dir, он вернет имя первого файла в текущем пути к каталогу (путь, возвращаемый CurDir$). Таким образом, если SigString пуст, ваше условие If будет оценено как True, потому что Dir вернет непустую строку (имя первого файла в текущем каталоге), и будет вызван GetBoiler. Если же SigString будет пустым, вызов fso.GetFile завершится неудачей.

Вам следует либо изменить условие, чтобы проверить, что SigString не пуст, либо использовать метод FileSystemObject.FileExists вместо Dir для проверки существования файла. Метод Dir сложен в использовании именно потому, что он делает то, чего вы, возможно, не ожидаете от него. Лично я бы использовал Scripting.FileSystemObject вместо Dir, потому что здесь нет ничего смешного (FileExists возвращает True, если файл существует, и False, если не существует). Более того, FileExists выражает намерение вашего кода гораздо яснее, чем Dir.

Метод 1: Сначала проверьте, что SigString не является пустым.

Метод 2: Используйте метод FileSystemObject.FileExists.

Понравилась статья? Поделить с друзьями:
  • Excel vba как проверить существование файла
  • Excel vba как проверить существование листа
  • Excel vba как проверить наличие листа в книге
  • Excel vba как прервать цикл for
  • Excel vba как поставить фильтр