Excel проверка данных макросом

 

Ronin751

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

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

Доброго времени суток уважаемые жители планеты!
Заранее прошу прощения за создание темы ( её начало

тут

) немного условия поменялись, но проблема та же.
Взываю к Вашей помощи ибо не знаю, что делать с текущей проблемой и как из неё выйти.
  Есть книга с двумя листами. На первом листе таблица (примерно 200 строк, но может меняться).В таблицу, исходя из условий поставленных пользователем, макросом вносятся начальные данные (каждой ячейке или буква, или цифра). Далее пользователь корректирует таблицу уже по фактическим данным. Но при этом есть условия:
1.Буквенные значения ограничены перечнем (именованный диапазон на Листе2) и не заменяются на цифры ( это я решил );
2. Ячейки с исходно числовыми значениями (могут быть целыми или с десятыми), меняются только на буквы или же на изначально (внесенную макросом) цифру.
  Все эти задачи с легкостью решает стандартная «Проверка». Но… Оказывается,при создании Проверки макросом, Экселю тяжело понять, что я от него хочу. (НУ ИЛИ Я СКОРЕЕ НЕ ПРАВИЛЬНО ЕМУ ОБЪЯСНЯЮ)
В файле в ячейке А1 установлена проверка вручную. А в В1 поместить проверку макросом не могу.
Прошу Вашей помощи в решении второго пункта. Заранее огромное спасибо всем за помощь!

 

Пытливый

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

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

Здравствуйте.
Я (честно) пытался понять критерии проверки ячейки, которые вы описываете. Про числа — вообще не понял как.
Пока нашел только то, что счетесли надо писать СЧЁТЕСЛИ (чрез Ё) — функция пишется именно так.
Не знаю, решит это проблему, или нет.
Опять же — проверки у вас — все в процедурах, которые не срабатывают автоматом (не привязаны к событию на листе, изменению значения ячейки там, или еще какому), а написаны в отдельных процедурах, которые надо запускать. Т.е. чтобы макрос начал работать — его надо запустить. Вы меняете значение в нужной ячейке — как макрос поймет, что «уже пора, Коля!»?

Кому решение нужно — тот пример и рисует.

 

Ronin751

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

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

#3

06.05.2016 13:36:08

Здравствуйте Пытливый! Спасибо, что обратили внимание на тему.

Цитата
как макрос поймет, что «уже пора, Коля!»?

Это же я для образца, сделал.  Весь файл очень большой. Вот я только проблемный участок и показал. В реальном файле дело идет так: пользователь, в UserForm отбирает нужные позиции, их количество и подчиненность, нажимает ОК и макрос составляет полную таблицу начальных данных ( если хотите, назовем её неким ГРАФИКОМ или ПЛАНОМ ). Как только таблица составлена, макрос выставляет проверку. А далее пользователь редактирует данные в таблице.
Проблема в том, что цифры, которые изначально проставляет макрос, предугадать нельзя. Но и другие ставить пользователю тоже запрещено. Цифры можно заменять только на буквы из именованного диапазона.
Буду рад любому совету.

 

Пытливый

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

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

#4

06.05.2016 13:47:34

Ну… тогда у вас уже все сделано, т.е. надо определить конкретную ячейку, для которой стараемся (у вас в коде это все для АсtiveCell).
А так я вон макрорекордером записал:

Код
Sub Макрос1()
'
' Макрос1 Макрос
'

'
    With Selection.Validation
        .Delete
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
        xlBetween, Formula1:="=исходник"
        .IgnoreBlank = True
        .InCellDropdown = True
        .InputTitle = ""
        .ErrorTitle = ""
        .InputMessage = ""
        .ErrorMessage = ""
        .ShowInput = True
        .ShowError = True
    End With
End Sub

Потом выделил В2, запустил — все гуд.

Кому решение нужно — тот пример и рисует.

 

Ronin751

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

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

Да! Ваш пример только на случай замены цифр на букву. Но если пользователь изменил цифру на букву, а через время снова захотел поставить прежнюю цифру, то столкнется с ошибкой. Вот по этому, в примере я использовал другую формулу. Задача составить проверку, которая будет позволять наличие только букв из именованного диапазона или исходной цифры.

Изменено: Ronin75106.05.2016 14:01:11

 

Пытливый

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

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

#6

06.05.2016 13:57:27

Ну добавьте в именованный список значение изначальное и все…

Код
ActiveWorkbook.Names("ИСХОДНИК").Delete 'удаляем именованный диапазон
'копируем из В1 листа 1 в первую пустую столбца А на листе 2
Worksheets("Лист1").Range("B1").copy Worksheets("Лист2").Range("A" & Worksheets("Лист2").Range("A1").CurrentRegion.Rows.Count +1)
'делаем новый именованный диапазон
ActiveWorkbook.Names.Add Name:="ИСХОДНИК", RefersToR1C1:="=Лист2!R1C1:R" & Worksheets("Лист2").Range("A1").CurrentRegion.Rows.Count & "C1"

Изменено: Пытливый06.05.2016 14:14:21

Кому решение нужно — тот пример и рисует.

 

Ronin751

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

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

#7

06.05.2016 14:05:18

Цитата
Ну добавьте в именованный список значение изначальное и все…

С радостью, но я их сам не знаю. Их рассчитывает  макрос. Да и если представить, что в именованом диапазоне будут допустим еще и 5,6,8,9… То, что в этом случае будет мешать пользователю изменить изначальную 9 на 5?!
Но за предложение спасибо!

 

Sanja

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

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

#8

06.05.2016 14:21:41

Цитата
Ronin751 написал: цифры, которые изначально проставляет макрос, предугадать нельзя. Но и другие ставить пользователю тоже запрещено.

Такое не то что макросу не объяснить, тут и человеку-то надо столько выпить, что бы понять… ;)
Не отчаивайтесь, попытайтесь еще раз объяснить.
На сколько я понял на текущий момент — По событию Change нужной ячейке добавляйте значение Target.Value к Списку Проверки данных

Согласие есть продукт при полном непротивлении сторон.

 

Пытливый

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

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

Развивая мысль ув.Sanja, по событию Change
1. сохраняете буквенный массив из диапазона проверки куда-нить
2. очищаете имя с массивом
3. вставляете сохраненные буквы «взад»
4. добавляете нужное значение из ячейки к массиву
5. формируете новый именованный диапазон
6. Ставите проверку на ячейку по этому диапазону.

Ничего не забыл? :)

Кому решение нужно — тот пример и рисует.

 

Sanja

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

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

#10

06.05.2016 14:46:38

«Растекаемся» мыслью дальше

Цитата
Пытливый написал:
5. формируете новый именованный диапазон
6. Ставите проверку на ячейку по этому диапазону.

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

Код
With Selection.Validation
        .Delete
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
        xlBetween, Formula1:="1,2,3,4,5,6,7,8,9"
        ....
    End With

Изменено: Sanja06.05.2016 14:51:52

Согласие есть продукт при полном непротивлении сторон.

 

Ronin751

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

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

#11

06.05.2016 15:56:00

Цитата
Не отчаивайтесь, попытайтесь еще раз объяснить

С помощью макроса составляется таблица и заносятся начальные данные. Следующий ход макроса — установить проверку эти ячейки. Условием для устанавки проверки является: если в ячейке текст -значит, при редактировании этой ячейки, допускаются только буквенные значения из именованного диапазона (на листе2); если в ячейке число(допустим 7) — то, при редактировании этой ячейки, допускаются только буквенные значения из именованного диапазона (на лист2) и это число (то есть 7). Фух! Вроде так.
Желтым выделил ячейки в которых уже установил проверку вручную.
Прошу помощи!

Прикрепленные файлы

  • Проверка.xls (47.5 КБ)

 

Sanja

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

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

#12

06.05.2016 16:13:39

?

Код
Sub ПРОВЕРКА()
   Dim j As String, i As Long, w As Long
    j = 14: Do While Cells(j, 4) > "": j = j + 3: Loop: j = j + 1
    For i = 14 To j Step 3
        For w = 5 To 35
            a = Cells(i, w)
            With Cells(i, w).Validation
                .Delete
                If Not IsNumeric(Cells(i, w)) Then
                    S = "А,Б,У,О,ПР,К"
                    errS = "Допускаются только буквенные значения"
                Else
                    X = "=или(счётесли(ИСХОДНИК;" & Cells(i, w).Address & ");счетесли(" & Cells(i, w).Address & ";" & a & "))"
                    S = "А,Б,У,О,ПР,К," & Replace(Cells(i, w), ",", ".")
                    errS = "Допускаются только буквенные значения или " & Replace(Cells(i, w), ",", ".")
                End If
                    .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:=S
                    .InCellDropdown = True: .ErrorMessage = errS
                    .ErrorTitle = "Отклонение от условий ": .ShowInput = False: .ShowError = True
            End With
        Next w
    Next i
End Sub

Согласие есть продукт при полном непротивлении сторон.

 

Ronin751

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

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

#13

06.05.2016 17:35:31

Вроде и проверку выполнило но…

Цитата
S = «А,Б,У,О,ПР,К,» & Replace(Cells(i, w), «,», «.»)

В ячейках, где числовое значение записано через запятую, эту самую запятую превращаем в точку. Только проблема возникает при попытке изменить, допустим 4,5 на 4.5. Все равно пишет, что значение не допустимое. И сумма получается уже другая.
Но за мысль и за Ваше внимание спасибо!

 

Sanja

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

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

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

Согласие есть продукт при полном непротивлении сторон.

 

Ronin751

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

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

Я это тоже делал, только немного иначе. Сейчас думаю как число с запятой загнать в кавычки (как текст). Тогда проверка, по идее, должна воспринять его.  

 

Sanja

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

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

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

Согласие есть продукт при полном непротивлении сторон.

 

Sanja

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

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

#17

07.05.2016 09:02:38

Проверил на практике идею Пытливый,
После этого пункта

Цитата
5. формируете новый именованный диапазон

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

Согласие есть продукт при полном непротивлении сторон.

 

Ronin751

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

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

#18

07.05.2016 13:30:45

Именно об этом я говорил в посте № 7

Цитата
…да и если представить, что в именованном диапазоне будут допустим еще и 5,6,8,9… То, что в этом случае будет мешать пользователю изменить изначальную 9 на 5?!

И с кавычками у меня не получается. Эксель все равно интерпретирует число с запятой, как два разных. (((
Видимо реально проблема получается?!  :cry:  

 

Sanja

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

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

#19

07.05.2016 13:44:52

Цитата
Ronin751 написал: Именно об этом я говорил в посте № 7

Нет, мы говорим про разные вещи. Но все равно решения нет. Пока
Может более опытные коллеги помогут.
Сузим вопрос.
Как к Списку Проверки данных добавить число с запятой с помощью макроса?
Конкретно — как в нижеприведенном коде добавить к переменной S(строка кода 13) число с запятой в качестве разделителя дробной части?

Или может какое другое решение будет?

Код
Sub ПРОВЕРКА()
   Dim j As String, i As Long, w As Long
    j = 14: Do While Cells(j, 4) > "": j = j + 3: Loop: j = j + 1
    For i = 14 To j Step 3
        For w = 5 To 35
            a = Cells(i, w)
            With Cells(i, w).Validation
                .Delete
                If Not IsNumeric(a) Then
                    S = "А,Б,У,О,ПР,К"
                    errS = ""
                Else
                    S = "А,Б,У,О,ПР,К," & Trim(Str(a))
                    errS = " или " & a
                End If
                    .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:=S
                    .InCellDropdown = True: .ErrorMessage = "Допускаются только буквенные значения" & errS
                    .ErrorTitle = "Отклонение от условий ": .ShowInput = False: .ShowError = True
            End With
        Next w
    Next i
End Sub

Прикрепленные файлы

  • Проверка макросом.xls (42.5 КБ)

Изменено: Sanja07.05.2016 13:51:14

Согласие есть продукт при полном непротивлении сторон.

 

Ronin751

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

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

   Вообще, конечно странно… Но видимо приходится констатировать тот факт, что любое (даже текстовое значение) которое записано через запятую в ячейке, с помощью ВБА не возможно добавить в стандартную проверку. Просто потому, что эксель, в этом случае,  не воспринимает запятую как десятичный разделитель, а упорно думает, что это перечисление последовательных (или не последовательных) пунктов.  :cry:
   Но тут появляется вопрос: почему когда в проверку добавляешь значение через запятую, то всё нормально?

 

JeyCi

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

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

#21

08.05.2016 15:18:54

Цитата
Ronin751 написал: с помощью ВБА не возможно добавить в стандартную проверку. Просто потому, что эксель, в этом случае,  не воспринимает запятую как десятичный разделитель, а упорно думает, что это перечисление последовательных

мне кажется не xl, а vba

Цитата
Ronin751 написал: Но тут появляется вопрос: почему когда в проверку добавляешь значение через запятую, то всё нормально?

а тут не vba, а xl
(думаю в вашем вопросе и есть этот ответ)

Изменено: JeyCi08.05.2016 15:19:39

чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах)

 

Ronin751

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

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

Как то странно получается не правда ли? Эксель не понимает ВБА. хм-м.

 

JeyCi

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

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

#23

08.05.2016 16:28:15

Цитата
Ronin751 написал: Эксель не понимает ВБА.

расхождения бывают в рус.яз xl (именно по трактовке запятой и точки-с-запятой в формулах, а также десятичного разделителя)

Изменено: JeyCi08.05.2016 16:30:52

чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах)

 

Ronin751

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

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

Поскольку при попытке создать проверку макросом эксель не воспринимает запятую как десятичный разделитель, решил пойти нахрапом: сменил десятичный разделитель с запятой на точку (меню пуск — панель управления — пункт «Языки и региональные стандарты»). Но эффект тот же (даже если формат ячейки перевести в текстовый).  :evil:  Получается, что с помощью ВБА вообще не возможно передать в проверку значение с любым разделителем?! И это очень прискорбно.  :cry:

 

Юрий М

Модератор

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

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

Вариант: создать именованный динамический (если размер меняется) диапазон и его скармливать Проверке данных.

 

Ronin751

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

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

#26

09.05.2016 18:28:00

Цитата
Вариант: создать именованный динамический

Если я правильно понимаю, то в этом случае придется добавлять новые значения (с разделителями) в именованный динамический диапазон и  в итоге все эти значения будут доступны для каждой ячейки. Но этот вариант не подходит, так как необходимо чтоб список проверки был наполнен значениями (буквенными) из именованного списка и значением самой ячейки ( к примеру «3,5»). Или можно как то это менять?
 

 

Юрий М

Модератор

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

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

Не понимаю проблемы (вопроса): что будет в ячейках, то и увидите в выпадающем списке.

 

Sanja

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

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

#28

09.05.2016 19:51:11

Цитата
Юрий М написал: Не понимаю проблемы

Юрий М, я тоже не сразу воткнулся. Тут не все так просто. Диапазон не просто динамический. Проблема в том, что в Диапазон необходимо добавлять значение, если оно НЕ из Диапазона, но находится в ячейке на момент добавления в нее Проверки данных. А таким значением может быть число с десятичной запятой, которая Списком Проверки данных расценивается как разделитель списка. Теоретически таких РАЗНЫХ Списков может быть 31 (кол-во столбцов) * кол-во строк в таблице. Хотелось это обойти (назначение КАЖДОЙ ячейке СВОЕГО Списка (см. код в #19), но из-за запятой не выходит. С целыми числами проблем нет.
Как-то так  

Согласие есть продукт при полном непротивлении сторон.

 

Юрий М

Модератор

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

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

#29

09.05.2016 19:53:47

Цитата
Sanja написал:
если оно НЕ из Диапазона, но находится в ячейке

Вот это не могу переварить: если находится в ячейке диапазона, то уже в диапазоне ))
Может какой простенький пример? :-)

 

Sanja

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

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

#30

09.05.2016 20:16:23

Цитата
Юрий М написал: Может какой простенький пример? :-)

Так там-же в #19. Находиться не в ячейке Диапазона, а в ячейке, в которую Проверка вставляется. Т.е. на момент вставки ячейка НЕ пустая и вот это значение нужно добавить к Списку Проверки

Согласие есть продукт при полном непротивлении сторон.

Проверка переменных и выражений с помощью встроенных функций VBA Excel: IsArray, IsDate, IsEmpty, IsError, IsMissing, IsNull, IsNumeric, IsObject.

Проверка переменных и выражений

Встроенные функции VBA Excel — IsArray, IsDate, IsEmpty, IsError, IsMissing, IsNull, IsNumeric, IsObject — проверяют значения переменных и выражений на соответствие определенному типу данных или специальному значению.

Синтаксис функций для проверки переменных и выражений:

Expression — выражение, переменная или необязательный аргумент для IsMissing.

Все функции VBA Excel для проверки переменных и выражений являются логическими и возвращают значение типа Boolean — True или False.

Функция IsArray

Описание функции

Функция IsArray возвращает значение типа Boolean, указывающее, является ли переменная массивом:

  • True — переменная является массивом;
  • False — переменная не является массивом.

Пример с IsArray

Sub Primer1()

Dim arr1(), arr2(1 To 10), arr3

    Debug.Print IsArray(arr1)  ‘Результат: True

    Debug.Print IsArray(arr2)  ‘Результат: True

    Debug.Print IsArray(arr3)  ‘Результат: False

arr3 = Array(1, 2, 3, 4, 5)

    Debug.Print IsArray(arr3)  ‘Результат: True

End Sub

Как показывает пример, функция IsArray возвращает True и в том случае, если переменная только объявлена как массив, но еще не содержит значений.

Функция IsDate

Описание функции

Функция IsDate возвращает логическое значение, указывающее, содержит ли переменная значение, которое можно интерпретировать как дату:

  • True — переменная содержит дату, выражение возвращает дату, переменная объявлена с типом As Date;
  • False — в иных случаях.

Пример с IsDate

Sub Primer2()

Dim d1 As String, d2 As Date

    Debug.Print IsDate(d1)  ‘Результат: False

    Debug.Print IsDate(d2)  ‘Результат: True

d1 = «14.01.2023»

    Debug.Print IsDate(d1)  ‘Результат: True

    Debug.Print IsDate(Now)  ‘Результат: True

End Sub

Функция IsEmpty

Описание функции

Функция IsEmpty возвращает значение типа Boolean, указывающее, содержит ли переменная общего типа (As Variant) значение Empty:

  • True — переменная содержит значение Empty;
  • False — переменной присвоено значение, отличное от Empty.

Пример с IsEmpty

Sub Primer3()

Dim s As String, v As Variant

    Debug.Print IsEmpty(s)  ‘Результат: False

    Debug.Print IsEmpty(v)  ‘Результат: True

v = 125

    Debug.Print IsEmpty(v)  ‘Результат: False

Range(«A1»).Clear

    Debug.Print IsEmpty(Range(«A1»))  ‘Результат: True

Range(«A1») = 123

    Debug.Print IsEmpty(Range(«A1»))  ‘Результат: False

End Sub

Как видно из примера, функцию IsEmpty можно использовать для проверки ячеек на содержание значения Empty (пустая ячейка общего формата).

Функция IsError

Описание функции

Функция IsError возвращает логическое значение, указывающее, является ли аргумент функции значением ошибки, определенной пользователем:

  • True — аргумент функции является значением ошибки, определенной пользователем;
  • False — в иных случаях.

Пользователь может определить одну или несколько ошибок для своей процедуры или функции с рекомендациями действий по ее (их) исправлению. Возвращается номер ошибки с помощью функции CVErr.

Пример с IsError

Допустим, пользователь определил, что ошибка №25 означает несоответствие аргумента функции Vkuba числовому формату:

Function Vkuba(x)

    If IsNumeric(x) Then

        Vkuba = x ^ 3

    Else

        Vkuba = CVErr(25)

    End If

End Function

Sub Primer4()

    Debug.Print Vkuba(5)  ‘Результат: 125

    Debug.Print IsError(Vkuba(5))  ‘Результат: False

    Debug.Print Vkuba(«пять»)  ‘Результат: Error 25

    Debug.Print IsError(Vkuba(«пять»))  ‘Результат: True

End Sub

Функция IsMissing

Описание функции

Функция IsMissing возвращает значение типа Boolean, указывающее, был ли необязательный аргумент типа данных Variant передан процедуре:

  • True — если в процедуру не было передано значение для необязательного аргумента;
  • False — значение для необязательного аргумента было передано в процедуру.

Пример с IsMissing

Function Scepka(x, Optional y)

    If Not IsMissing(y) Then

        Scepka = x & y

    Else

        Scepka = x & » (а необязательный аргумент не подставлен)»

    End If

End Function

Sub Primer5()

    Debug.Print Scepka(«Тропинка», » в лесу»)  ‘Результат: Тропинка в лесу

    Debug.Print Scepka(«Тропинка»)  ‘Результат: Тропинка (а необязательный аргумент не подставлен)

End Sub

Функция IsNull

Описание функции

Функция IsNull возвращает логическое значение, указывающее, является ли Null значением переменной или выражения:

  • True — значением переменной или выражения является Null;
  • False — в иных случаях.

Пример с IsNull

Функция IsNull особенно необходима из-за того, что любое условие с выражением, в которое входит ключевое слово Null, возвращает значение False:

Sub Primer6()

Dim Var

Var = Null

    If Var = Null Then Debug.Print Var  ‘Результат: «»

    If Var <> Null Then Debug.Print Var  ‘Результат: «»

    If IsNull(Var) Then Debug.Print Var  ‘Результат: Null

End Sub

Функция IsNumeric

Описание функции

Функция IsNumeric возвращает значение типа Boolean, указывающее, можно ли значение выражения или переменной рассматривать как число:

  • True — если аргумент функции может рассматриваться как число;
  • False — в иных случаях.

Пример с IsNumeric

Sub Primer7()

Debug.Print IsNumeric(«3,14»)  ‘Результат: True

Debug.Print IsNumeric(«четыре»)  ‘Результат: False

End Sub

Функция IsObject

Описание функции

Функция IsObject возвращает логическое значение, указывающее, является ли переменная объектной:

  • True — переменная содержит ссылку на объект или значение Nothing;
  • False — в иных случаях.

Функция IsObject актуальна для переменных типа Variant, которые могут содержать как ссылки на объекты, так и значения других типов данных.

Пример с IsObject

Sub Primer8()

Dim myObj As Object, myVar As Variant

    Debug.Print IsObject(myObj)  ‘Результат: True

    Debug.Print IsObject(myVar)  ‘Результат: False

Set myVar = ActiveSheet

    Debug.Print IsObject(myVar)  ‘Результат: True

End Sub


Ошибки пользователей при вводе данных – одна из самых распространенных проблем в ExcelВ результате ошибочных данных ячейки с формулами на разных листах друг за другом могут заполниться ошибками #ЗНАЧ, #H/Д и т.п. Поиск ошибок может занимать длительное время, потому что непонятен первоначальный источник ошибки. С чего начинать?  Но появление ячеек с ошибками это даже хорошо. 

Гораздо хуже, когда внешне все выглядит нормально, но при этом в данных есть ошибки. В таких случаях пользователь даже не догадываться о наличии ошибок и формирует недостоверные отчеты. А в результате принимаются ошибочные управленческие решения. Что же делать?

НЕДОСТАТКИ СТАНДАРТНЫХ ИНСТРУМЕНТОВ EXCEL

Как вы наверняка знаете, в Excel существует стандартный функционал для контроля вводимых в ячейки данных. Он устанавливается через меню Данные -> Проверка данных. В результате появляется диалоговое окно Проверка вводимых значений c тремя закладками.

На закладке Параметры в поле Тип данных можно выбрать тип данных. В зависимости от введенного типа становятся доступными для заполнения другие поля, например: 

  • для типа Число, Дата, Время можно задать границы – от и до и проверять на соблюдение условий между, меньше, больше и т.д.;
  • для типа Список можно задать список доступных значений;
  • для типа Другой можно задать свою собственную формулу, которая будет проверять вводимое значение на соблюдение каких либо условий, в том числе в зависимости от значений в других ячейках. 

На закладках Сообщение для ввода и Сообщение об ошибке можно задать текст соответствующего сообщения, чтобы подсказать пользователю в чем он ошибся.

Внешне сервис проверки данных кажется очень эффективным.  Особенно удобно  выбирать значение из выпадающего списка, а не вводить его вручную. Тем не менее стандартный функционал Excel позволяет решить проблему контроля вводимых данных лишь частично и у него есть существенные недостатки:

1. Стандартные средства контроля введенных данных могут создать у пользователя вредную иллюзию защищенности от ошибок. Особенно если данные вводили не вы, а кто-то другой, и вы рассчитываете что там все нормально, система отловила ошибки. Ведь проверка работает только при ручном вводе данных, но не работает при внесении данных другими способами! 

Например, если данные вводятся в ячейку с использованием команд Копировать->Вставить, Копировать->Специальная вставка-Значения или путем «растаскивания» от соседних ячеек, то проверка данных не осуществляется. Также значения в ячейках не контролируются, если они введены в ячейку с помощью макроса (если только контроль не осуществляется в самом макросе).

Таким образом, неверные данные могут попасть в ячейки, многократно тиражированы и Excel это не отследит! 

Часто это бывает, когда вы выгружаете данные в таблицы из других программ, например, 1С. Но особенно неприятно когда ошибки незаметны или малозаметны. Например:

  • Значение в ячейке выглядит как число и дата, а на самом деле оно является текстом. Например потому, что перед или после цифр есть пробел или другие непечатные (невидимые) символы.
  • Ячейка выглядит пустой, а на самом деле там есть непечатные символы.
  • В качестве разделителя целой и дробной части использована точка вместо запятой.
  • Введено значение, которое отсутствует в «привязанном» к ячейке выпадающем списке.

Последняя ситуация достаточно распространена. Например, вы ведете реестр платежей от контрагентов, и вводите наименование контрагентов с помощью выпадающего списка, связанного со справочником контрагентов. Спустя некоторое время вы обнаруживаете в наименовании контрагента ошибку и исправляете ее в справочнике. При этом Excel никак не отреагирует на то, что в реестре есть записи со старым (ошибочным) наименованием контрагента. То есть Excel при изменении элементов списка не отлавливает уже введенные данные типа «Список». 

2. Стандартные способы проверки могут «тормозить»

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

В этом случае часто используются «тяжелые» функции СЧЕТЕСЛИ, СЧЕТЕСЛИМН, которые подсчитывают количество или сумму по уже введенным ранее данным и сравнивают, не превысит ли вводимое значение какой-то предел.
Всякий раз, когда вы вводите или изменяете значение в ячейке, отрабатывает эта «тяжелая» формула. Если при этом с ячейкой связано много других ячеек, будут пересчитываться и они. Когда вы это делаете и тестируете в таблицах мало данных и задержек не ощущается.

Но по мере роста таблиц Excel может начать «залипать» при вводе данных, иначе говоря не успевать за руками пользователя. И это очень раздражает.
Поэтому, использовать проверку вводимых данных с использованием типа Другой и «тяжелыми» формулами нужно очень обдуманно. Я советую вообще исключить использование подобных приемов.

 3. Бесполезный инструмент «Обвести неверные данные»

Для проверки правильности введенных значений в Excel есть встроенный инструмент «Обвести неверные данные», который вызывается через пункты меню — Данные -> Проверка данных -> Обвести неверные данные.

Команда доступна только на незащищенном листе, а результатом ее работы будет обведение неверных по мнению Excel данных красным овалом как на рисунке выше. 

На мой взгляд, это функция практически бесполезна по трем причинам: 

  • Будут признаны ошибочными и обведены пустые ячейки с типом «Список допустимых значение», если для них при настройке была снята галочка в поле «игнорировать пустые ячейки» (она снята в большинстве случаев). Но согласитесь — неверные значения и пустые значения это разные вещи. 
  • Помечаются только первые 255 недопустимых значения.
    Если в вашей таблице десятки колонок и тысячи строк, то придется много раз повторять одни и те же действия – исправлять ошибки и снова запускать обводку неверных данных. 
  • Она не всегда работает корректно. На вышеприведенном рисунке не были обведены значения в колонке ЦУ  — Объект «Сколково» — хотя эти значения ошибочные, т.к. их нет в списке. 

4. «Подсвечивание» ячеек с ошибочными данными

Еще одним распространенным способом проверки наличия неверных данных является выделение ячеек, в которых обнаружены некорректные данные, ярким цветом фона или шрифта с помощью условного форматирования

Я считаю это способ неэффективным. Ну  «подсветили» вы некорректные данные в таблице, а что дальше? 

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

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

Мало того, что из-за правил условного форматирования Excel будет «тормозить», так пользователи еще и усложняют систему совсем необязательными макросами. 

КАК ПРАВИЛЬНО ОРГАНИЗОВАТЬ ПРОВЕРКУ ВВЕДЕННЫХ ДАННЫХ

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

Этот способ может быть дополнением к стандартному функционалу проверки вводимых данных, или применяться самостоятельно. Суть способа в следующем. 

Любую проверку вводимых значений можно делать и обычными функциями Excel, такими как ЕСЛИ, ЕТЕКСТ, ЕНЕТЕКСТ, ЕЧИСЛО, ПОИСКПОЗ. Поэтому в таблице можно создать служебную колонку  в ячейках которой задать формулу, которая будет проверять корректность введенных данных по заданным условиям во всех ячейках строки, предназначенных для ввода и сообщать об этом пользователю. Расчет формулы сделать включаемым/ выключаемым в зависимости от положения «тумблера». Что такое тумблеры и зачем они, написано здесь.

Это не предотвратит некорректный ввод данных, но предупредит об этом пользователя.
Зато формула будет отрабатывать не при ручном вводе данных, а по вашему требованию. 
Таким образом, пользователь может свободно вводить данные и Excel не будет «тормозить». Перед формированием управленческих отчетов пользователь запускает проверку, выявляет все ошибки и исправляет их. 

Как это устроено проще всего понять это на примере (см. рисунок ниже) 

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

2. В таблице создается служебная колонка (удобней если она будет крайней слева), в ячейках которой вводится формула, проверяющие корректность введенных в строке таблицы значений.

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

Блоки могут быть такие:

  • Ячейки, в которых должна вводиться дата или число проверяется такой конструкцией

ЕСЛИ(ЕТЕКСТ(проверяемое_значение);номер_столбца&».»;»») 

  • Ячейки, в которых значение вводится из выпадающего списка проверяется такой конструкцией: 

EСЛИ(ЕСЛИОШИБКА(ПОИСКПОЗ(искомое_значение; просматриваемый_массив;0);-1)>0;””;номер_столбца) 

  • Если вам нужно проверять даты на вхождение в определенный период времени используйте обычные функции ЕСЛИ, >=,<= и т.д. Аналогично для чисел. 

Не забудьте всю эту конструкцию поместить внутрь функции ЕСЛИ:     =ЕСЛИ(НаТ1;ваша_цепочка_блоков;””), где НаТ1 это имя ячейки-тумблера, которая включает/выключает расчет формулы.  Это позволит не вычислять формулу при всяком изменении в ячейках, а делать это по необходимости. 

В результате в служебной колонке, в тех строках, где будут обнаружены ошибки, отобразятся номера колонок с некорректными данными, разделенные точками. В шапке таблицы можно подсчитать количество строк с ошибками следующей формулой:
=ЧСТРОК(A$5:A$677)-СЧЁТЕСЛИ(A$5:A$677;»») , где A$5:A$677 – диапазон служебного столбца в котором выводятся признаки ошибок. 

В результате вы всегда видите сколько, в каких строчках и в каких столбцах у вас ошибки и можете быстро их исправить, используя стандартные возможности Excel — фильтр, растаскивание и т.д. 

Ваша программа будет еще удобнее если вы соберете данные о количестве ошибок на одном листе (в моих решениях это лист Настройки как на рисунке ниже) и там же разместите кнопку для запуска формул проверки ошибок. В этом случае вам не нужно метаться между листами рабочей книги. Достаточно нажать одну кнопку – макрос включит «тумблер» — все листы будут проверены на наличие ошибок, данные о количестве ошибок будут выведены в таблице. Если ошибок не обнаружено ячейка останется пустой. Если ошибки обнаружены вам нужно перейти на соответствующий лист и исправить их.

Все просто и удобно, никаких «тормозов» и экономия времени!

Cookie-файлы

Настройка cookie-файлов

Детальная информация о целях обработки данных и поставщиках, которые мы используем на наших сайтах

Аналитические Cookie-файлы
Отключить все

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


Подробнее


Понятно

Перейти к содержимому

Макрос проверки заполнения ячеек.

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

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

Рассмотрим несколько вариантов VBA алгоритмов:Макро VBA Excel

Алгоритм для строго определенной ячейки с применением её адреса.

Пример для ячейки с адресом B6:

  •     Private Sub CommandButton1_Click() ‘наименование алгоритма
  •      If IsEmpty(Range(«B6»)) = True Then  ‘условие, если ячейка пустая, то
  •      MsgBox («В ячейке нет данных») ‘вывод сообщения, что в ячейке нет данных
  •      Else  ‘в противном случае
  •      MsgBox («Данные внесены в ячейку»)  ‘вывод сообщения, что в ячейке есть данные
  •      End If  ‘конец блока «если»
  •     End Sub ‘конец алгоритма

Алгоритм для выделенной (активной)  ячейки :

    • Private Sub CommandButton1_Click() ‘наименование алгоритма    
    • If IsEmpty(ActiveCell) = True Then ‘условие, если активная ячейка (ActiveCell)  пустая, то
    •      MsgBox («В ячейке нет данных»)  ‘вывод сообщения, что в ячейке нет данных
    •      Else  ‘в противном случае
    •      MsgBox («Данные внесены в ячейку»)  ‘вывод сообщения, что в ячейке есть данные
    •      End If  ‘конец блока «если»
    •     End Sub ‘конец алгоритма

    Еще один способ определения в примере для активной ячейки, но можно использовать  и для конкретной ячейки с адресом.

      • Private Sub CommandButton1_Click() ‘наименование алгоритма    
      • If Len(ActiveCell) Then ‘если активная ячейка заполнена данными (имеет объем информации)
      • MsgBox («Данные внесены в ячейку»)  ‘вывод сообщения, что в ячейке есть данные
      • Else  ‘в противном случае
      • MsgBox («Ячейка пустая») ‘вывод сообщения, что в ячейке нет данных
      • End If  ‘конец блока «если»
      •  End Sub  ‘конец алгоритма

      На чтение 19 мин. Просмотров 24.4k.

      VBA If Statement

      Пьер Корнель

      Угадай, если сможешь, и выбери, если посмеешь

      Содержание

      1. Краткое руководство по VBA If Statement
      2. Что такое IF  и зачем оно тебе?
      3. Тестовые данные
      4. Формат операторов VBA If Then
      5. Простой пример If Then
      6. Условия IF
      7. Использование If ElseIf
      8. Использование If Else
      9. Используя If And/If Or
      10. Функция IIF
      11. Использование Select Case
      12. Попробуйте это упражнение

      Краткое руководство по VBA If Statement

      Описание Формат Пример
      If Then If [условие верно] 
      Then [действие]
      End If
      If score = 100 
      Then Debug.Print
      «Отлично» 
      End If
      If Else If [условие верно]
      Then [действие]
      Else [действие]
      End If
      If score = 100 
      Then Debug.Print 
      «Отлично» 
      Else Debug.Print 
      «Попробуй снова» 
      End If
      If ElseIf If [1 условие верно] 
      Then [действие]
      ElseIf [2 условие
      верно] 
      Then [действие]
      End If
      If score = 100 
      Then Debug.Print 
      «Отлично» 
      ElseIf score > 50 
      Then Debug.Print 
      «Пройдено» 
      ElseIf score <= 50 
      Then Debug.Print 
      «Попробуй снова» 
      End If
      Else и ElseIf
      (Else должно
      идти
      после ElseIf’s)
      If [1 условие верно] 
      Then [действие]
      ElseIf [2 условие
      верно] 
      Then [действие]
      Else [действие]
      End If
      If score = 100 
      Then Debug.Print 
      «Отлично» 
      ElseIf score > 50 
      Then Debug.Print 
      «Пройдено» 
      ElseIf score > 30 
      Then Debug.Print 
      «Попробуй снова» 
      Else Debug.Print 
      «Ой» 
      End If
      If без Endif
      (Только одна
      строка)
      If [условие верно] 
      Then [действие]
      If value <= 0 
      Then value = 0

      В следующем коде показан простой пример использования
      оператора VBA If

      If Sheet1.Range("A1").Value > 5 Then
          Debug.Print "Значение больше 5."
      ElseIf Sheet1.Range("A1").Value < 5 Then
          Debug.Print "Значение меньше 5."
      Else
          Debug.Print "Значение равно 5."
      End If
      

      Что такое IF  и зачем оно тебе?

      Оператор VBA If используется, чтобы позволить вашему коду
      делать выбор, когда он выполняется.

      Вам часто захочется сделать выбор на основе данных, которые
      читает ваш макрос.

      Например, вы можете захотеть читать только тех учеников, у
      которых оценки выше 70. Когда вы читаете каждого учащегося, вы можете
      использовать инструкцию If для проверки отметок каждого учащегося.

      Важным словом в последнем предложении является проверка. Оператор
      If используется для проверки значения, а затем для выполнения задачи на основе
      результатов этой проверки.

      Тестовые данные

      Мы собираемся использовать следующие тестовые данные для
      примеров кода в этом посте.

      VBA If Sample Data

      Формат операторов VBA If Then

      Формат оператора If Then следующий

      За ключевым словом If следуют условие и ключевое слово Then

      Каждый раз, когда вы используете оператор If Then, вы должны использовать соответствующий оператор End If.

      Когда условие оценивается как истинное, обрабатываются все
      строки между If Then и End If.

      If [условие верно] Then
          [строки кода]
          [строки кода]
          [строки кода]
      End If
      

      Чтобы сделать ваш код более читабельным, рекомендуется
      делать отступы между операторами If Then и End If.

      Отступ между If и End If

      Отступ означает просто переместить строку кода на одну вкладку вправо. Правило большого пальца состоит в том, чтобы сделать отступ между начальным и конечным операторами, такими как:

      Sub … End Sub
      If Then … End If
      If Then… ElseIf … Else … Endif
      For … Next
      Do While … Loop
      Select Case … End Case

      Для отступа в коде вы можете выделить строки для отступа и нажать клавишу Tab. Нажатие клавиш Shift + Tab сделает отступ кода, т.е. переместит его на одну вкладку влево.

      Вы также можете использовать значки на панели инструментов Visual Basic для отступа кода.

      VBA If

      Если вы посмотрите на примеры кода на этом сайте, вы увидите, что код имеет отступ.

      Простой пример If Then

      Следующий код выводит имена всех студентов с баллами более 50.

      Sub ChitatOcenki()
          
          Dim i As Long
          ' Пройдите столбцы отметок
          For i = 2 To 11
              ' Проверьте, больше ли баллов,чем 50
              If Sheet1.Range("C" & i).Value > 50 Then
                  ' Напечатайте имя студента в «Immediate Window» (Ctrl + G)
                  Debug.Print Sheet1.Range("A" & i).Value & " " & Sheet1.Range("B" & i).Value
              End If
          
          Next
          
      End Sub
      

      Результаты:

      • Василий Кочин
      • Максим Бородин
      • Дмитрий Маренин
      • Олеся Клюева
      • Евгений Яшин

      Поэкспериментируйте с этим примером и проверьте значение или знак > и посмотрите, как изменились результаты.

      Условия IF

      Часть кода между ключевыми словами If и Then называется условием. Условие — это утверждение, которое оценивается как истинное или ложное. Они в основном используются с операторами Loops и If. При создании условия вы используете такие знаки, как «>, <, <>,> =, <=, =».

      Ниже приведены примеры условий:

      Условие Это верно, когда
      x < 5 x меньше,чем 5
      x <= 5 x меньше, либо равен 5
      x > 5 x больше, чем 5
      x >= 5 x больше, либо равен 5
      x = 5 x равен 5
      x <> 5 x не равен 5
      x > 5 And x < 10 x больше, чем 5 И x меньше, чем 10
      x = 2 Or x >10 x равен 2 ИЛИ x больше,чем 10
      Range(«A1») = «Иван» Ячейка A1 содержит текст «Иван»
      Range(«A1») <> «Иван» Ячейка A1 не содержит текст «Иван»

      Вы могли заметить x = 5, как условие. Не стоит путать с х = 5, при использовании в качестве назначения.

      Когда в условии используется «=», это означает, что «левая сторона равна правой стороне».

      В следующей таблице показано, как знак равенства используется
      в условиях и присваиваниях.

      Использование «=» Тип Значение
      Loop Until x = 5 Условие Равен ли x пяти
      Do While x = 5 Условие Равен ли x пяти
      If x = 5 Then Условие Равен ли x пяти
      For x = 1 To 5 Присваивание Установите значение х = 1, потом = 2 и т.д.
      x = 5 Присваивание Установите х до 5
      b = 6 = 5 Присваивание и
      условие
      Присвойте b
      результату условия
      6 = 5
      x = MyFunc(5,6) Присваивание Присвойте х
      значение,
      возвращаемое
      функцией

      Последняя запись в приведенной выше таблице показывает
      оператор с двумя равными. Первый знак равенства — это присвоение, а любые
      последующие знаки равенства — это условия.

      Поначалу это может показаться странным, но подумайте об этом
      так. Любое утверждение, начинающееся с переменной и равно, имеет следующий
      формат

      [переменная] [=] [оценить эту часть]

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

      [x] [=] [5]

      [b] [=] [6 = 5]

      [x] [=] [MyFunc (5,6)]

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

      Инструкция ElseIf позволяет вам выбирать из нескольких вариантов. В следующем примере мы печатаем баллы, которые находятся в диапазоне.

      Sub IspElseIf()
          
          If Marks >= 85 Then
              Debug.Print "Высший балл"
          ElseIf Marks >= 75 Then
              Debug.Print "Отлично"
          End If
          
      End Sub
      

      Важно понимать, что порядок важен. Условие If проверяется
      первым.

      Если это правда, то печатается «Высший балл», и оператор If заканчивается.

      Если оно ложно, то код переходит к следующему ElseIf и
      проверяет его состояние.

      Давайте поменяемся местами If и ElseIf из последнего
      примера. Код теперь выглядит так

      Sub IspElseIfNeverno()
          
          ' Этот код неверен, так как ElseIf никогда не будет верным
          If Marks >= 75 Then
              Debug.Print "Отлично"
          ElseIf Marks >= 85 Then
              ' код никогда не достигнет здесь
              Debug.Print "Высший балл"
          End If
          
      End Sub
      

      В этом случае мы сначала проверяем значение более 75. Мы никогда не будем печатать «Высший балл», потому что, если значение больше 85, это вызовет первый оператор if.

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

      If marks >= 75 And marks < 85 Then
          Debug.Print "Отлично"
      ElseIf marks >= 85 And marks <= 100 Then
          Debug.Print "Высший балл"
      End If
      

      Давайте расширим оригинальный код. Вы можете использовать столько операторов ElseIf, сколько захотите. Мы добавим еще несколько, чтобы учесть все наши классификации баллов.

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

      Утверждение Else используется, как ловушка для всех. Это в основном означает «если бы не было условий» или «все остальное». В предыдущем примере кода мы не включили оператор печати для метки сбоя. Мы можем добавить это, используя Else.

      Sub IspElse()
          
          If Marks >= 85 Then
              Debug.Print "Высший балл"
          ElseIf Marks >= 75 Then
              Debug.Print "Отлично"
          ElseIf Marks >= 55 Then
              Debug.Print "Хорошо"
          ElseIf Marks >= 40 Then
              Debug.Print "Удовлетворительно"
          Else
              ' Для всех других оценок
              Debug.Print "Незачет"
          End If
          
      End Sub
      

      Так что, если это не один из других типов, то это провал.

      Давайте напишем некоторый код с помощью наших примеров
      данных и распечатаем студента и его классификацию.

      Sub DobClass()
          
          ' получить последнюю строку
          Dim startRow As Long, lastRow As Long
          startRow = 2
          lastRow = Sheet1.Cells(Sheet1.Rows.Count, 1).End(xlUp).Row
          
          Dim i As Long, Marks As Long
          Dim sClass As String
      
          ' Пройдите столбцы отметок
          For i = startRow To lastRow
              Marks = Sheet1.Range("C" & i).Value
              ' Проверьте отметки и классифицируйте соответственно
              If Marks >= 85 Then
                  sClass = "Высший балл"
              ElseIf Marks >= 75 Then
                  sClass = "Отлично"
              ElseIf Marks >= 55 Then
                  sClass = "Хорошо"
              ElseIf Marks >= 40 Then
                  sClass = "Удовлетворительно"
              Else
                  ' Для всех других оценок
                  sClass = "Незачет"
              End If
          
              ' Запишите класс в столбец E
              Sheet1.Range("E" & i).Value = sClass
          Next
          
      End Sub
      

      Результаты выглядят так: в столбце E — классификация баллов

      VBA If ElseIf Class

      Используя If And/If Or

      В выражении If может быть несколько условий. Ключевые слова VBA And и Or позволяют использовать несколько условий.

      Эти слова работают так же, как вы используете их на
      английском языке.

      Давайте снова посмотрим на наши примеры данных. Теперь мы
      хотим напечатать всех студентов, которые набрали от 50 до 80 баллов.

      Мы используем Аnd, чтобы добавить дополнительное условие. Код гласит: если оценка больше или равна 50 и меньше 75, напечатайте имя студента.

      Sub ProverkaStrokiOcenok()
      
          Dim i As Long, marks As Long
          For i = 2 To 11
              
              ' Хранить оценки для текущего студента
              marks = Sheet1.Range("C" & i).Value
              
              ' Проверьте, если отметки больше 50 и меньше 75
              If marks >= 50 And marks < 80 Then
                   ' Напечатайте имя и фамилию в Immediate window (Ctrl+G)
                   Debug.Print Sheet1.Range("A" & i).Value & Sheet1.Range("B" & i).Value
              End If
          
          Next
      
      End Sub
      

      Вывести имя и фамилию в результаты:

      • Дмитрий Маренин
      • Олеся Клюева
      • Евгений Яшин

      В нашем следующем примере мы хотим знать, кто из студентов сдавал историю или геометрию. Таким образом, в данном случае мы говорим, изучал ли студент «История» ИЛИ изучал ли он «Геометрия» (Ctrl+G).

      Sub ChitatObektOcenki()
          
          Dim i As Long, marks As Long
          
          ' Пройдите столбцы отметок
          For i = 2 To 11
              marks = Sheet1.Range("D" & i).Value
              ' Проверьте, если отметки больше 50 и меньше 80
              If marks = "История" Or marks = "Геометрия" Then
                  ' Напечатайте имя и фамилию в Immediate window (Ctrl+G)
                  Debug.Print Sheet1.Range("A" & i).Value & " " & Sheet1.Range("B" & i).Value
              End If
          
          Next
          
      End Sub
      

      Результаты:

      • Василий Кочин
      • Александр Грохотов
      • Дмитрий Маренин
      • Николай Куликов
      • Олеся Клюева
      • Наталия Теплых
      • Дмитрий Андреев

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

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

      And работает следующим образом:

      Условие 1 Условие 2 Результат
      ИСТИНА ИСТИНА ИСТИНА
      ИСТИНА ЛОЖЬ ЛОЖЬ
      ЛОЖЬ ИСТИНА ЛОЖЬ
      ЛОЖЬ ЛОЖЬ ЛОЖЬ

      Что вы заметите, так это то, что And верно только тогда, когда все условия выполняются.

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

      Ключевое слово OR работает следующим образом

      Условие 1 Условие 2 Результат
      ИСТИНА ИСТИНА ИСТИНА
      ИСТИНА ЛОЖЬ ИСТИНА
      ЛОЖЬ ИСТИНА ИСТИНА
      ЛОЖЬ ЛОЖЬ ЛОЖЬ

      Что вы заметите, так это то, что OR ложно, только когда все условия ложны.

      Смешивание And и Or может затруднить чтение кода и привести к ошибкам. Использование скобок может сделать условия более понятными.

      Sub OrSAnd()
          
       Dim subject As String, marks As Long
       subject = "История"
       marks = 5
          
       If (subject = "Геометрия" Or subject = "История") And marks >= 6 Then
           Debug.Print "ИСТИНА"
       Else
           Debug.Print "ЛОЖЬ"
       End If
          
      End Sub
      

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

      Также есть оператор NOT. Он возвращает противоположный результат условия.

      Условие Результат
      ИСТИНА ЛОЖЬ
      ЛОЖЬ ИСТИНА

      Следующие две строки кода эквивалентны.

      If marks < 40 Then 
      If Not marks >= 40 Then
      

      так же, как и

      If True Then 
      If Not False Then 
      

      и

      If False Then 
      If Not True Then 
      

      Помещение условия в круглые скобки облегчает чтение кода

      If Not (marks >= 40) Then
      

      Распространенное использование Not — при проверке, был ли установлен объект. Возьмите Worksheet для примера. Здесь мы объявляем рабочий лист.

      Dim mySheet As Worksheet
      ' Некоторый код здесь
      

      Мы хотим проверить действительность mySheet перед его использованием. Мы можем проверить, если это Nothing.

      If mySheet Is Nothing Then
      

      Нет способа проверить, является ли это чем-то, поскольку есть много разных способов, которым это может быть что-то. Поэтому мы используем NOT с Nothing.

      If Not mySheet Is Nothing Then
      

      Если вы находите это немного запутанным, вы можете использовать круглые скобки, как здесь

      If Not (mySheet Is Nothing) Then
      

      Функция IIF

      VBA имеет функцию, аналогичную функции Excel If. В Excel вы часто используете функцию If следующим образом:

      = ЕСЛИ (F2 =»»,»», F1 / F2)

      Формат

      = If (условие, действие, если ИСТИНА, действие, если ЛОЖЬ).

      VBA имеет функцию IIf, которая работает так же. Давайте посмотрим на примере. В следующем коде мы используем IIf для проверки значения переменной val. Если значение больше 10, мы печатаем ИСТИНА, в противном случае мы печатаем ЛОЖЬ.

      Sub ProveritVal()
       
          Dim result As Boolean
          Dim val As Long
          
          ' Печатает ИСТИНА
          val = 11
          result = IIf(val > 10, ИСТИНА, ЛОЖЬ)
          Debug.Print result
          
          ' печатает ЛОЖЬ
          val = 5
          result = IIf(val > 10, ИСТИНА, ЛОЖЬ)
          Debug.Print result
          
      End Sub
      

      В нашем следующем примере мы хотим распечатать «Удовлетворитеьно» или «Незачет» рядом с каждым студентом в зависимости от их баллов. В первом фрагменте кода мы будем использовать обычный оператор VBA If, чтобы сделать это.

      Sub ProveritDiapazonOcenok()
      
          Dim i As Long, marks As Long
          For i = 2 To 11
              
              ' Хранить оценки для текущего студента
              marks = Sheet1.Range("C" & i).Value
              
              ' Проверьте, прошел ли студент или нет
              If marks >= 40 Then
                   ' Запишите имена для столбца F
                   Sheet1.Range("E" & i) = "Удовлетворительно"
              Else
                   Sheet1.Range("E" & i) = "Незачет"
              End If
          
          Next
      
      End Sub
      

      В следующем фрагменте кода мы будем использовать функцию IIf. Код здесь намного аккуратнее.

      Sub ProveritDiapazonOcenok ()
      
          Dim i As Long, marks As Long
          For i = 2 To 11
              
              ' Хранить оценки для текущего студента
              marks = Sheet1.Range("C" & i)
              
              ' Проверьте, прошел ли студент или нет
              Sheet1.Range("E" & i).Value = IIf(marks >= 40,"Удовлетворительно","Незачет")
          
          Next
      
      End Sub
      

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

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

      Вы также можете вкладывать IIf-операторы, как в Excel. Это означает использование результата одного IIf с другим. Давайте добавим еще один тип результата в наши предыдущие примеры. Теперь мы хотим напечатать «Отлично», «Удовлетворительно» или «Незачетт» для каждого студента.

      Используя обычный VBA, мы сделали бы это так

      Sub ProveritRezultatiTip2()
      
          Dim i As Long, marks As Long
          For i = 2 To 11
              
              ' Хранить оценки для текущего студента
              marks = Sheet1.Range("C" & i).Value
              
              If marks >= 75 Then
                   Sheet1.Range("E" & i).Value = "Отлично"
              ElseIf marks >= 40 Then
                   ' Запишите имена для столбца F
                   Sheet1.Range("E" & i).Value = "Удовлетворительно"
              Else
                   Sheet1.Range("E" & i).Value = "Незачет"
              End If
          
          Next
      
      End Sub
      

      Используя вложенные IIfs, мы могли бы сделать это так

      Sub IspNestedIIF()
      
      Dim i As Long, marks As Long, result As String
      For i = 2 To 11
          
      marks = Sheet1.Range("C" & i).Value
      result = IIf(marks >= 55,"Хорошо",IIf(marks >= 40,"Удовлетворительно","Незачет"))
      
      Sheet1.Range("E" & i).Value = result
      
      Next
      
      End Sub
      

      Использование вложенного IIf хорошо в простых случаях, подобных этому. Код прост для чтения и, следовательно, вряд ли вызовет ошибки.

      Чего нужно остерегаться

      Важно понимать, что функция IIf всегда оценивает как
      Истинную, так и Ложную части выражения независимо от условия.

      В следующем примере мы хотим разделить по баллам, когда он не равен нулю. Если он равен нулю, мы хотим вернуть ноль.

      marks = 0
      total = IIf(marks = 0, 0, 60 / marks)
      

      Однако, когда отметки равны нулю, код выдаст ошибку «Делить на ноль». Это потому, что он оценивает как Истинные, так и Ложные утверждения. Здесь ложное утверждение, т.е. (60 / Marks), оценивается как ошибка, потому что отметки равны нулю.

      Если мы используем нормальный оператор IF, он будет
      запускать только соответствующую строку.

      marks = 0
      If marks = 0 Then
          'Выполняет эту строку только когда отметки равны нулю
          total = 0
      Else
          'Выполняет только эту строку, когда отметки не равны нулю
          total = 60 / marks
      End If
      

      Это также означает, что если у вас есть функции для ИСТИНА и ЛОЖЬ, то обе будут выполнены. Таким образом, IIF будет запускать обе функции, даже если он использует только одно возвращаемое значение. Например:

      ' Обе функции будут выполняться каждый раз
      total = IIf(marks = 0, Func1, Func2)
      

      IF против IIf

      Так что лучше?

      В этом случае вы можете видеть, что IIf короче для написания и аккуратнее. Однако если условия усложняются, вам лучше использовать обычное выражение If. Недостатком IIf является то, что он недостаточно известен, поэтому другие пользователи могут не понимать его так же, как и код, написанный с помощью обычного оператора if.

      Кроме того, как мы обсуждали в последнем разделе, IIF всегда оценивает части ИСТИНА и ЛОЖЬ, поэтому, если вы имеете дело с большим количеством данных, оператор IF будет быстрее.

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

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

      Оператор Select Case
      — это альтернативный способ написания статистики If с большим количеством ElseIf. Этот тип операторов
      вы найдете в большинстве популярных языков программирования, где он называется
      оператором Switch. Например,
      Java, C #, C ++ и Javascript
      имеют оператор switch.

      Формат

      Select Case [переменная]
          Case [условие 1]
          Case [условие 2]
          Case [условие n]
          Case Else
      End Select
      

      Давайте возьмем наш пример DobClass сверху и перепишем его с помощью оператора Select Case.

      Sub DobavitClass()
          
          ' получить последнюю строку
          Dim startRow As Long, lastRow As Long
          startRow = 2
          lastRow = Sheet1.Cells(Sheet1.Rows.Count, 1).End(xlUp).Row
          
          Dim i As Long, Marks As Long
          Dim sClass As String
      
          ' Пройдите столбцы отметок
          For i = startRow To lastRow
              Marks = Sheet1.Range("C" & i).Value
              ' Проверьте отметки и классифицируйте соответственно
              If Marks >= 85 Then
                  sClass = "Высший балл"
              ElseIf Marks >= 75 Then
                  sClass = "Отлично"
              ElseIf Marks >= 55 Then
                  sClass = "Хорошо"
              ElseIf Marks >= 40 Then
                  sClass = "Удовлетворительно"
              Else
                  ' Для всех других оценок
                  sClass = "Незачет"
              End If
          
              ' Запишите класс в столбец E
              Sheet1.Range("E" & i).Value = sClass
          Next
          
      End Sub
      

      Ниже приведен тот же код с использованием оператора Select Case. Главное, что вы заметите, это то, что мы используем “Case 85 to 100” rather than “marks >=85 And marks <=100”. , а не “marks >=85 And marks <=100”.

      Sub DobavitClassSSelect()
          
          ' получить первую и последнюю строки
          Dim firstRow As Long, lastRow As Long
          firstRow = 2
          lastRow = Cells(Cells.Rows.Count, 1).End(xlUp).Row
          
          Dim i As Long, marks As Long
          Dim sClass As String
      
          ' Пройдите столбцы отметок
          For i = firstRow To lastRow
              marks = Sheet1.Range("C" & i).Value
              ' Проверьте отметки и классифицируйте соответственно
              Select Case marks
              Case 85 To 100
                  sClass = "Высший балл"
              Case 75 To 84
                  sClass = "Отлично"
              Case 55 To 74
                  sClass = "Хорошо"
              Case 40 To 54
                  sClass = "Удовлетворительно"
              Case Else
                  ' Для всех других оценок
                  sClass = "Незачет"
              End Select
              ' Запишите класс в столбец E
              Sheet1.Range("E" & i).Value = sClass
          Next
          
      End Sub
      

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

      Вы можете переписать оператор select в том же формате, что и оригинальный ElseIf. Вы можете использовать Is с Case.

      Select Case marks
          Case Is >= 85
               sClass = "Высший балл"
          Case Is >= 75
              sClass = "Отлично"
          Case Is >= 55
              sClass = "Хорошо"
          Case Is >= 40
              sClass = "Удовлетворительно"
          Case Else
              ' Для всех других оценок
              sClass = "Незачет"
      End Select
      

      Вы можете использовать Is для проверки нескольких значений.
      В следующем коде мы проверяем, равны ли оценки 5, 7 или 9.

      Sub TestNeskZnach()
          
          Dim marks As Long
          marks = 7
          
          Select Case marks
              Case Is = 5, 7, 9
                  Debug.Print True
              Case Else
                  Debug.Print False
          End Select
          
      End Sub
      

      Попробуйте это упражнение

      В этой статье много рассказывали о выражении If. Хороший способ помочь вам понять — это попытаться написать код, используя темы, которые мы рассмотрели. В следующем упражнении используются тестовые данные из этой статьи. Ответ на упражнение ниже.

      Мы будем использовать ячейку G1, чтобы написать имя
      субъекта.

      В колонках от H до L запишите всех студентов, которые имеют оценки по этому предмету. Мы хотим классифицировать их результат как успешный или неудачный. Оценка ниже 40 — неудача, оценка 40 или выше — Зачет.

      Колонка H: Имя

      Колонка I: Фамилия

      Колонка J: Баллы

      Колонка H: Предмет

      Столбец I: Тип результата — Зачет или Незачет

      Если ячейка G1 содержит «Геометрия», то ваш результат должен выглядеть следующим образом:

      VBA If Statement

      Ответ на упражнение

      Следующий код показывает, как выполнить вышеупомянутое упражнение.

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

      Sub ZapisatRezultat()
           
          ' Получить тему
          Dim subject As String
          subject = Sheet1.Range("G1").Value
           
          If subject = "" Then
              Exit Sub
          End If
           
          ' Получить первый и последний ряд
          Dim firstRow As Long, lastRow As Long
          firstRow = 2
          lastRow = Cells(Cells.Rows.Count, 1).End(xlUp).Row
           
          ' Очистить любой существующий вывод
          Sheet1.Range("H:L").ClearContents
           
          ' Отслеживать выходной ряд
          Dim outRow As Long
          outRow = 1
           
          Dim i As Long, marks As Long, rowSubject As String
          ' Прочитать данные
          For i = firstRow To lastRow
              marks = Sheet1.Range("C" & i).Value
              rowSubject = Sheet1.Range("D" & i).Value
              If rowSubject = subject Then
                  ' Запишите данные студента, если предмет Геометрия
                  Sheet1.Range("A" & i & ":" & "D" & i).Copy
                  Sheet1.Range("H" & outRow).PasteSpecial xlPasteValues
                   
                  ' Запишите Зачет или Незачет
                  If marks < 40 Then
                      Sheet1.Range("L" & outRow).Value = "Незачет"
                  ElseIf marks >= 40 Then
                      Sheet1.Range("L" & outRow).Value = "Зачет"
                  End If
                  ' Переместить вывод в следующую строку
                  outRow = outRow + 1
              End If
               
          Next i
           
      End Sub
      

      Понравилась статья? Поделить с друзьями:
    • Excel проверка данных для формулы
    • Excel проверка данных двссыл
    • Excel проверка данных в диапазоне
    • Excel проверка вхождения числа в диапазон
    • Excel проверка вхождения строки в строку