Excel Analysis Blog
BETA
Придется немного поработать


Макросы. Урок третий

Типы данных

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

  • Byte — может содержать цифры от 0 до 255 (1)
  • Boolean — логическая переменная. TRUE или FALSE. (Истина или ложь) (2)
  • Integer — может содержать цифры от -32768 до 32768 (2)
  • Long — может содержать цифры от -2 147 483 648 до 2 147 483 648 (4)
  • Single — дробные числа (4)
  • Double — дробные числа, большего размера (8)
  • Currency — дробные числа еще большего размера (8)
  • Date — дату и время (8)
  • String — текст (в зависимости от длинны текста)
  • Variant —все, что угодно (22+)

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

Первое. Разницу между Single, Double и Currency я описал так, как знаю. Лично я никогда не пользовался последними двумя, Single поддерживает числа с 3-мя знаками после запятой, а мне больше и не надо.

Теперь второе. Для чего это вообще все нужно.

Как я уже в одном уроке говорил, в настоящих языках программирования, переменные выделяются особо. Там определить ее тип нужно обязательно. А вот vba это дело прощает, но просто потому, что если вы сами не создали тип переменной, то он, по умолчанию, становится Variant. Вы также можете на все это забить, и пусть будет Variant, но есть две вещи:

  1. Скорость. Чем меньше байт занимает ваша переменная в коде, тем быстрее он будет выполняться. Лично я одни раз проверил. Мой макрос выполнялся порядка 40 минут, после того, как я задал типы переменных, выполнился за 25. Т.е. прирост скорости был ощутимый.
  2. Помощь в обработке ошибок. Об этом в этом же уроке, но чуть позже.

Из минусов, использования типов, НЕ Variant, то что на них налагаются соответствующие ограничения. Я не могу, объявить, что A — это Byte и загнать в нее «Привет мир». Потому что текст может содержаться только в String.

По правилам, переменные мы задаем в начале кода. Делается это через оператор Dim

Sub test()
    Dim a As String
	
    a = "Привет мир"
    MsgBox (a)
End Sub

К сожалению, сам не знаю почему, vba не дает возможности задавать тип переменных для нескольких сразу. Dim только можно задать один раз, но для каждого типа свой. Пример как нельзя:

Dim a, b As String

Как можно:

Dim a As String, b As String

Если переменные разным типов, то Dim для каждого свой

Sub test()
    Dim a As String, b As String
    Dim c As Byte
    
    a = "Мне "
    b = "сейчас "
    c = 26
    MsgBox (a & b & c)
End Sub

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

Хорошим тоном, среди макрописцев, считается объявлять все переменные без исключения. Если уж надо, то прямо словами и писать, что A — это Variant, хотя мне так приходилось делать очень редко.

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

Option Explicit

Эта команда распространится на весь используемые модуль. В этом случае макросы не будут выполняться, если хоть одна переменная не объявлена.

Теперь о второй пользе:

В файле, с примерами, найдите модуль Primer_kosyka и попробуйте его выполнить. Кто догадается, в чем ошибка?

Добавьте в начало модуля Option Explicit. Пробуем еще раз и вываливается ошибка

Говорит, что мол у нас не объявлена переменная, еще и выделяет ее. Ну что, логично, косяк наш. Объявите A и B любыми типами. Попробуйте выполнить еще раз. Все равно ругается, так ведь? Вот только выделят вам не первую A и ту, которая используется в вычислениях.

Все дело в том, что первая буква написана на латинской раскладке, а вторая в русской. Выглядят они абсолютно одинаково, но для компьютера это разные буквы. И вот ведь какая засада получилась, что если ли бы не стоял Option Explicit, то код выполнялся бы. Ошибок никаких не было. А вот итоговые данные, считались бы неправильно. Это простой код, и ошибка тут видна сразу. Но вот макрос, которые выполняется полчаса и перебирает миллионы строк, в каждом свои данные. Да фиг когда вы догадаетесь, что в расчетах у вас ошибка, только если на калькулятора проверять станете. Поэтому рекомендую, не играйте с судьбой. Ставьте Option Explicit, он защитит вас от подобных косяков. И когда вы в расчетах переменную не так назовете, и когда вы вообще что-то новое сделаете, которое и не планировали. Он сразу все упорядочет. Плюс 100% будете объявлять все типы, и коды будут выполняться быстрее. Когда, какой тип объявлять, это уже персонально. Вы знаете, что будете там хранить. Лично у меня, для подсчета ВЫСШЕГО РУКОВОДСТВА используется только Byte, не думаю, что когда-то их будет больше 256. Integer можете использовать для подсчета строк. Если таблица небольшая и не на всю страницу (в Excel более миллиона строк).

Для удобства, эту функцию можно включить на постоянной основе. Зайдите Tools→Options. Ставьте галочку на Require Variable Declaration. Теперь, когда вы создаете новый модуль, в начале его будет гордо находиться необходимая нам операция (правда можно удалить руками).

Передача данных в переменную

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

Sub test2()
    Dim a As String
	
    a = InputBox(1, 2, 3)   
End Sub

Сразу определяем где, что пишем. Как вы поняли, сам InputBox вызывает диалоговое окно, в которое можно вносить данные. После нажатия кнопки ОК переменная приобретет указанное значение. Цифры, внутри скобок указаны в качестве примера. Смотрим и отслеживаем

С 1 и 2 думаю все ясно. 3 — это дефолтное значение, которое ставится сразу, при активизации формы. Есть такая функция в VBA DATE. Она ставит сегодняшнюю дату. В нашем случае, большинство отчетов в моей организации начинаются с появления этой формы, где в коде указано DATE-1, т.е. предлагает мне сделать отчет за вчерашний день, но я могу это поле редактировать. Вот как у меня все написано в моем дашборде.

Repdate = InputBox("Дата, за которую формируем отчет", "VM", My_Date + 1)

Теперь попрошу выполнить ваш код:

 Sub test2()
    Dim a As String
    a = InputBox(1, 2, 3)
End Sub
по шагам. Напоминаю, что для выполнения кода по шагам, нужно в VBA-редакторе нажимать F8. И остановитесь на End Sub.

Наведите курсор на переменную, посмотрите, какое значение она приобрела после ваших действий. Видите, что цифра обрамлена в кавычки. Это из-за того, что мы указали переменную A, как String. И макрос записал вашу цифру как текст, а не число. Это важно понимать, потому что, например, теперь нельзя ее использовать в вычислениях. Нельзя помножить что-то на текст, это билиберда. Также если бы я указал переменную Integer, и ввел число 1 000 000. Такая переменная не может хранить столь большие числа и макрос выдал бы такую ошибку:

Обработчик ошибок

Кстати, что касательно окна обработки ошибок. Здесь видно четыре кнопки:

  1. Continue. Она будет активна только в том случае, если вы прекратили выполнение макроса, по своему желанию (это делается путем нажатия CTRL+Break). После нажатия на нее, макрос продолжит работу.
  2. End. Макрос завершит работу
  3. Debug. Макрос только приостановит работу и выбросит вас в окно редактора, где подстветить строку, которую он не может выполнить. Вы можете прямо там исправить (если возможно) эту ошибку и продолжить выполнение кода дальше.
  4. Help. Требуется подлючение интернет для офиса. Там справка по программированию, но она очень скромная и полностью на английском.

Самостоятельная работа

Сделайте «Калькулятор сложения». Чтобы нам предлагалось сначала ввести одно число, затем второе. А в конце нам бы через MsgBox выдавали сумму этих чисел.

Скачать примеры урока