
2 Курс Информатика VBA(ЗО) / Книги / В.Д.Хорев - Самоучитель программирования на VBA в Microsoft Office
.pdf
VBA — это очень просто! 31
Связывание данных в Excel
Связать два листа Excel в одной рабочей книге — смехотворно простая задача, если учитывать всю потенциальную мощь Office. Достаточно выделить в прайсе ту область, которую надо показать клиентам — столбцы A и B. Их можно выделить целиком или же в виде области под заголовками “Наименование” и “Цена”. Скопировать эту область в буфер обмена командой Правка | Копировать, а затем, открыв или создав новый лист, вставить и связать область при помощи коман-
ды Правка | Специальная вставка. При этом, открывшееся диалоговое окно Специальная вставка следует закрыть щелчком мыши на кнопке Вставить связь (см. рис. 1.4). В результате данные из “внутрифирменного” листа будут автоматически отображаться в листе “клиентском”.
Казалось бы, задача решена. Но устроит ли нас такое решение? Да, если на этом остановиться, и если дальнейшая автоматизация офиса больше не интересует. Нет, если достигнутого результата недостаточно, и надо усовершенствовать и облегчить работу по-настоящему радикальным образом.
Недостатки связывания листов Excel
В чем недостатки простого связывания клиентского листа с некоторой областью в листе “внутрифирменном”?
•В первую очередь в том, что область отображается “как есть”, без какого-либо отбора. Но позиции, товар по которым на складе в данный момент отсутствует, не должны попадать в “клиентский” прайс-лист.
•Кроме того, могут иметься и другие маркетинговые соображения, по которым отдельные позиции следует включать или не включать в список. Хорошее решение этой задачи должно давать возможность сотруднику отдела сбыта произвольно выбирать позиции товара для включения в прайс-лист. Иными словами, “клиентский” прайс-лист должен генерироваться по некоторым правилам из “внутрифирменного” листа.
Все это приводит к мысли, что дальнейшее развитие невозможно с использованием только лишь простейших средств MS Office и настала пора приступить у программированию на VBA….
VBA — это очень просто!
Многие люди, каждый день работающие в Word или Excel, считают, что VBA — это “что-то для программистов”. Напрасно они так думают. В рабочей среде MS Office есть множество сложных инструментов, которые, однако, обычные пользователи применяют, не задумываясь, и не пускаясь в рассуждения о том, насколько это сложно. Например, рядовой пользователь Word, который просто вводит текст и форматирует его по мере своего разумения, ужаснется, если узнает, насколько сложным может быть форматирование обычного текстового абзаца, и какие замысловатые механизмы можно в этом случае задействовать. Но вся эта потенциальная сложность не мешает ему просто ввести свой текст и отпечатать документ Word вполне пристойного вида, не постигая все “глубины” и тонкости, которые тут возможны. Точно так же дело обстоит и с VBA — программирование на VBA в некоторых случаях может быть очень сложной задачей. Но если сначала не очень усложнять задачу, и не увлекаться постижением “глубин”, то ничего особенно трудного в этом процессе нет.
Итак, VBA — Visual Basic для приложений, вот тот инструмент, который потребуется для дальнейшей автоматизации созданного в предыдущих разделах прайс-листа. Для первого знакомства с этим интереснейшим инструментом выберем несложную задачу: генерация клиентского прайс-листа с пропуском некоторых, произвольно выбранных позиций. Для этого необходимо предоставить пользователю возможность каким-то образом отмечать строки списка, который лежит в основе прайса.
ПРИМЕЧАНИЕ
Как можно сделать это вручную? С помощью диалогового окна Формат ячеек можно, как назначить для ячейки штриховку, так и отменить ее. Предполагается, что заштрихованное наименова-

32 Глава 1. Excel: cоздание прайс-листа
ние товара служит хорошим обозначением позиции, которую следует исключить. Давайте создадим макрос на VBA, который будет выполнять эти действия автоматически, по двойному щелчку мыши на ячейке.
Первое знакомство с Visual Basic
Если для читателя это первая встреча с Visual Basic, то многое может показаться ему сложным и пугающим. Ничего страшного, это всего лишь первое впечатление, не стоит ему поддаваться.
Запуск редактора Visual Basic
Итак, первый шаг заключается в том, чтобы открыть окно редактора Visual Basic. Для этого существует специальная команда в меню Сервис, однако не будем пока ее использовать. Для того чтобы кратчайшим путем попасть именно в ту точку редактора Visual Basic, которая требуется в данном примере, нужно расположить указатель мыши на ярлыке с названием рабочего листа в нижней части окна Excel и щелкнуть правой кнопкой мыши. Текущим должен быть именно тот лист рабочей книги, для которого создается макрос. В результате откроется контекстное меню (рис. 1.14) данного рабочего листа, в котором нужно выполнить команду Исходный текст. У всех листов рабочей книги контекстное меню выглядит одинаково, однако команда Исходный текст в меню разных листов приводит к отображению разных окон в редакторе Visual Basic.
Рис. 1.14. Создание макроса при помощи кон- |
Рис. 1.15. Окно кода рабочего листа, при от- |
текстного меню рабочего листа Excel |
крытии, автоматически создает заготовку тек- |
|
ста стандартной процедуры |
Создание процедуры VBA
В данном случае, на экране отобразится окно, показанное на рис. 1.15. Не стоит пугаться замысловатой структуры редактора Visual Basic — пока можно не обращать внимания на все остальное, кроме окна в центре экрана, служащего для ввода исходного текста процедур (программ VBA) выбранного рабочего листа. Автоматически в этом окне создается заготовка процедуры, содержащая ее заголовок и окончание. Но в этом случае нужен не этот макрос. В верхней части окна кода находятся два списка, определяющие конкретную процедуру (макрос).
Разверните левый список и выберите в нем пункт Worksheet. Затем, в правом списке выберите пункт BeforeDoubleClick, как показано на рис. 1.16.

Первое знакомство с Visual Basic 33
1 2
Рис. 1.16. При помощи списков Object и Procedure можно создать заготовку стандартной процедуры
В результате в окне кода будет создан заголовок нужной процедуры Work-
sheet_BeforeDoubleClick. Первая и последняя строки процедуры созданы автоматически, и теперь требуется ввести исходный текст процедуры (листинг 1.1). Или, как его еще называют, про-
граммный код.
ЛИСТИНГ 1.1
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Excel.Range, _
Cancel As Boolean)
With ActiveCell
If .Column = 1 Then
If .Interior.Pattern = xlPatternNone Then
.Interior.Pattern = xlPatternGray25
Else
.Interior.Pattern = xlPatternNone
End If
Cancel = True
End If
End With
End Sub
На рис. 1.17 показано, как в результате должно выглядеть окно кода.
Рис. 1.17. Процедура Worksheet_BeforeDoubleClick
Ввод исходного текста процедуры
Редактор Visual Basic анализирует вводимый пользователем текст на предмет ошибок. По мере ввода какого-нибудь слова редактор предлагает ближайший подходящий вариант синтаксически правильного выражения языка. Например, если начать ввод слова Pattern, редактор, рядом с

34 Глава 1. Excel: cоздание прайс-листа
курсором ввода, отобразит список, в котором будет найден и выделен ближайший подходящий вариант к уже введенной части слова. В этом случае можно продолжать вводить остальные буквы этого слова, не обращая внимания на поведение окна, или же ввести сразу символ, следующий за
этим словом, например “=”, тогда остаток слова Pattern будет введен автоматически (рис. 1.18).
Рис. 1.18. Редактор Visual Basic предлагает |
Рис. 1.19. Возврат в окно Excel |
свою помощь — рядом с курсором ввода появ- |
|
ляется список имен, которые допустимы в дан- |
|
ном выражении |
|
В следующей строке программного кода вспомогательное окно появится дважды — перед словом Interior и после него. При опечатках или даже просто попытках перевести курсор ввода с неоконченной строки редактор может раскрыть окно с предупреждением об ошибке (рис. 1.19) — в этом случае надо щелкнуть на кнопке OK этого окна и исправить ошибку. Ошибочно набранное слово будет выделено красным цветом.
Рис. 1.20. Возврат в окно Excel |
Рис. 1.21. Наименования товара, на которых выпол- |
|
нен двойной щелчок, заштрихованы |
Наконец, исходный текст макроса введен, и можно испытать его в деле. Для возврата в окно Excel можно воспользоваться кнопкой на панели задач или специальной кнопкой со значком Excel, расположенной в левом верхнем углу окна редактора Visual Basic (рис. 1.20).
Теперь попробуем выполнить двойной щелчок на одной из ячеек столбца “Наименование”.… Ура, работает! Ячейка заштрихована. Еще один двойной щелчок и штриховка исчезла. Теперь можем легко и просто отмечать позиции прайс-листа, которые не должны попасть в его версию для клиентов (рис. 1.21).
Возможные проблемы и методы их решения
При одновременной работе в среде редактора Visual Basic и Excel иногда возникают ситуации, которые могут поставить в тупик неопытного пользователя. Ничего страшного. Для того чтобы усвоить принципы работы с макросами VBA в приложениях MS Office, требуется всего лишь немного практики. Ниже описаны некоторые нештатные ситуации, которые могут возникнуть при создании и отладке макросов.

Первое знакомство с Visual Basic 35
•Если окно редактора Visual Basic закрывает весь экран и панель задач не видна, щелкните на кнопке максимизации окна в правом верхнем углу (средняя из трех кнопок).
•Если при вводе исходного текста появляется окно с сообщением об ошибке “Ошибка компиляции. Ожидалось...”, щелкните на кнопке OK или нажмите клавишу [Esc], а затем исправьте ошибку.
•Если при переходе из окна Excel в окно Visual Basic нельзя ввести текст при помощи клавиатуры или выбрать, какой-нибудь элемент окна мышью, вернитесь в окно Excel и нажмите клавишу [Esc]. Видимо, Excel был оставлен в состоянии редактирования ячейки, а в такой ситуации окно Visual Basic не реагирует на действия пользователя.
•Если при выполнении макроса возникла ошибка, то на экране появится окно с сообщением “Ошибка выполнения...”. Если щелкнуть на кнопке Завершить, то выполнение макроса прервется — выполняемые им операции не будут завершены.
•В случае, когда макрос не может завершить свою работу из-за логической ошибки в тексте программы (при этом Excel может не реагировать на действия пользователя), необходимо нажать сочетание клавиш [Ctrl]+[Break] или, что, то же самое, [Ctrl]+[Pause].
•Если выполнение программы прервано пользователем (см. выше), появится окно с сообщением “Выполнение программы прервано...”. В этом случае необходимо щелкнуть на кнопке Завершить.
•Если макрос “отказывается” стартовать, выдавая окно с сообщением “Невозможно выпол-
нение программы в режиме прерывания”, следует перейти в окно редактора Visual Basic и
выполнить команду Запуск | Сброс (Run | Reset).
Анализ стандартной процедуры обработки
события — двойного щелчка мышью на ячейке листа Excel
Посмотрим теперь на текст процедуры VBA, которая была создана в предыдущих разделах (листинг 1.1). Пользователю, не имевшему ранее дела с VBA, на первый взгляд, код может показаться сплошной “китайской грамотой”, однако на практике все не так сложно, как может показаться. Давайте разберемся.
В двух списках были выбраны пункты Worksheet и BeforeDoubleClick — в результате проце-
дура (Sub) стала называться Worksheet_BeforeDoubleClick. Здесь Worksheet — это стан-
дартный объект, для которого создавалась данная процедура — рабочий лист. BeforeDoubleClick — это стандартное событие рабочего листа, событие это происходит при каждом двойном щелчке на листе. Если бы в правом списке было выбрано другое событие, например, Activate, то код процедуры выполнялся бы при активации листа, то есть в момент, когда лист становится текущим. Но в нашем случае код будет выполняться при двойных щелчках мыши на любой ячейке данного листа.
Что же, собственно, делает код процедуры?
With ActiveCell
…
…
End With
Первая и последняя строчки определяют, что весь заключенный между ними код относится к объекту ActiveCell, то есть к текущей ячейке. Именно она-то нас и интересует. Поскольку любая ячейка, на которой выполнен двойной щелчок мыши, автоматически становится текущей.
Оператор
If .Column = 1 Then
…
…
End If

36 Глава 1. Excel: cоздание прайс-листа
означает “если−то” и ограничивает выполнение процедуры пределами столбца A. .Column — это свойство любой ячейки и указывает оно на номер столбца, к которому эта ячейка относится. Столбец “Наименование” расположен в рассматриваемой таблице первым по счету и если двойной щелчок выполнен на ячейке другого столбца, то .Column окажется не равным 1, и дальнейший код не будет выполнен.
см. также в приложении раздел “Операции сравнения”.
Следующий, самый внутренний оператор, выглядит сложнее. If–Then–Else означает “если−то−иначе” и в вольном переводе на обычный язык операторы
If .Interior.Pattern = xlPatternNone Then
.Interior.Pattern = xlPatternGray25
Else
.Interior.Pattern = xlPatternNone
End If
означают: если ячейка не заштрихована, то задать ей узор 25%-й серый, в противном случае, то есть, если она уже заштрихована узором 25%-й серый, отменить штриховку ячейки.
см. в приложении раздел “Конструкция If … Then … Else … End If”.
И, наконец, маленькая строка
Cancel = True
играет здесь вспомогательную роль. Переменная Cancel является параметром процедуры, и смысл этого параметра таков: присвоив ему логическое значение True (Истина), пользователь как бы сообщается рабочему листу Excel, что двойной щелчок отменяется, т.е. его не было. Поэтому Excel не перейдет по двойному щелчку к редактированию ячейки, как он это обычно делает.
ПРИМЕЧАНИЕ
Такой объект, как ячейка, обладает множеством свойств. Если, например, вместо
.Interior.Pattern = xlPatternGray25 использовать оператор .Value = 100, то по двойному щелчку на ячейке в нее будет помещаться число 100. Можно использовать такой оператор, как .Interior.ColorIndex = 3 — в этом случае ячейка будет окрашиваться в красный
цвет. Вернуть ей белый цвет можно оператором .Interior.ColorIndex = 2. Черному цвету соответствует значение 1, а серому — 15. Чтобы получить более подробную справку, достаточно выделить выражение ColorIndex и нажать клавишу [F1].
Можно использовать и другое событие, например, выбрав в списке Procedure выражение SelectionChange. Код, созданной процедуры менять не надо, должен измениться только ее заголовок. Это событие происходит каждый раз, когда текущей становится другая ячейка. В результате ячейки первого столбца можно будет выделять одиночным щелчком мыши, однако макрос будет выполняться и при простом перемещении по столбцу посредством клавиатуры. Какой вариант более удобен, но остается за разработчиком процедуры.
Еще одно событие — еще один маленький макрос
Чтобы закрепить достигнутого успеха в предыдущем разделе, выполним еще одно упражнение, которое, к тому же, позволит довести механизм выделения позиций в прайс-листе до совершенства. Пользователь может абсолютно произвольным образом решать, какие позиции необходимо включить в текущую версию “клиентского” прайс-листа, а какие — исключить. Но существует ряд позиций, по поводу которых нечего решать: позиции с закончившимся товаром все равно придется исключить. Пусть прайс выделяет такие позиции автоматически!

Первое знакомство с Visual Basic 37
Автоматическое выделение позиций в прайсе
Прежде чем приступить к созданию макроса, подумаем, в какой момент времени и каким образом он должен выполняться? Воспользуемся уже имеющимся небольшим опытом в обработке событий рабочего листа. Макрос можно связать с элементом управления, например, командной кнопкой, размещенной на листе или с каким-нибудь клавиатурным эквивалентом, однако наилучшим будет такое решение, при котором пользователю не придется предпринимать специальные шаги для вызова макроса — когда процедура выполняется в ответ на какое-то событие Excel. Среди событий рабочего листа уже упоминалось событие Activate, которое генерируется в момент, когда лист становится активным (текущим). Это может произойти в момент открытия книги, если книга открывается на данном листе или же при переключении между листами в уже открытой книге. Если выбрать какой-то другой лист, а потом вернутся к листу с прайсом, то для него будет генерироваться событие Activate. Этот момент и будет наилучшим для выполнения макроса, который вычеркивает позиции прайс-листа с закончившимся товаром. В этом случае как бы ни открывался лист, он предстанет перед пользователем в уже подготовленном виде.
Итак, необходимо создать макрос, который представляет собой процедуру обработки события Activate для рабочего листа. Для этого следует вновь вернуться в редактор Visual Basic, щелкнув правой кнопкой мыши на ярлыке с названием листа в нижней части окна, и выполнив в контекстном меню команду Исходный текст. В левом списке Object в верхней части окна кода выберите объект Worksheet (т.е. выбранный рабочий лист), а в правом Procedure — событие Activate. В результате будет создана заготовка процедуры Worksheet_Activate, в которую нужно ввести текст, приведенный на листинге 1.2.
ЛИСТИНГ 1.2
Private Sub Worksheet_Activate()
Dim N As Integer
For N = 5 To UsedRange.Rows.Count
If Cells(N, 5).Value = 0 Then
Cells(N, 1).Interior.Pattern = xlPatternGray25
End If
Next N
End Sub
Рис. 1.22. Процедура Worksheet_Activate в окне кода
При вводе строки Dim N As, объявляющей переменную N, редактор Visual Basic предложит выбрать тип переменной из списка, раскрывшегося рядом с курсором ввода. Можно просто ввести слово Integer, не обращая внимания на происходящее на экране, а можно воспользоваться предложенной подсказкой. В итоге окно программы должно приобрести вид, как на рис. 1.22.
см. в приложении разделе “Переменные”.
Вернувшись в окно Excel, можно проверить действие макроса: для этого достаточно ввести нулевые значения в произвольные позиции столбца “Нал.”, а затем закрыть и вновь открыть книгу

38 Глава 1. Excel: cоздание прайс-листа
или просто переключиться на другой лист, а затем вернуться к прайсу. Все обнуленные позиции буду заштрихованы.
Анализ стандартной процедуры обработки события — активизация рабочего листа Excel
Взглянем на исходный текст последней процедуры. В результате выполнения строки
Dim N As Integer
будет создана переменная N типа Integer — она предназначена для хранения целочисленных значений.
см. в приложении подраздел “Integer” в разделе “Типы данных”.
Конструкцию
For N = … To …
…
…
Next N
называют оператором цикла. Заключенный в нем код выполняется для всех значений переменной N, начиная с 5 и заканчивая числом…, которое возвращает выражение
UsedRange.Rows.Count. Что это за число? Макрос должен просмотреть все строки прайслиста до самого конца, но ведь количество строк в конкретном прайсе заранее неизвестно! Выражение UsedRange.Rows.Count возвращает число использованных строк рабочего листа. Если самой нижней строкой, куда “доходил” пользователь, будет, скажем, 500-я строка, то выражение
UsedRange.Rows.Count вернет значение 500.
см. в приложении раздел “Цикл For … Next”.
Наконец, условный оператор
If Cells(N, 5).Value = 0 Then
Cells(N, 1).Interior.Pattern = xlPatternGray25
End If
выполняет следующую операцию: если в текущей строке (ее номер задает переменная N) ячейка 5- го столбца содержит значение 0, то соответствующая ячейка первого столбца штрихуется узором “25%-й серый”. Вот и все, совершив эти действия поочередно для всех строк использованного диапазона, макрос тем самым выполнит свою задачу.
см. в приложении раздел “Конструкция If … Then … Else … End If”.
Генерация клиентского прайс-листа
Настала пора перейти к решению главной задачи. Как сгенерировать текущую клиентскую версию прайс-листа на основе внутрифирменного прайса. Программный код, способный выполнить эту операцию, будет несколько сложнее, чем те процедуры, с которые до сих пор былм рассмотрены. По этой причине эта задача будет решена в несколько этапов: вначале сделаем это в упрощенном варианте, немного этот вариант усовершенствуем и только затем перейдем к полноценному решению.
Прежде всего, необходимо решить вопрос запуска макроса. В данном случае нет смысла привязать его к какому-либо событию рабочего листа, поскольку пользователь может принять решение о генерации в произвольный момент времени. Поэтому лучше использовать элемент управления, при помощи которого можно было бы инициировать выполнение макроса. Самый простой способ снабдить лист Excel каким-нибудь элементом управления заключается в использовании

Генерация клиентского прайс-листа 39
панели инструментов Формы (рис. 1.23). Чтобы отобразить на экране эту панель, необходимо вы-
полнить команду Вид | Панели инструментов | Формы.
Рис. 1.23. Панель инструментов Формы содержит различные элементы управления, которые можно поместить на рабочий лист Excel
Элемент управления Кнопка наилучшим образом подходит для запуска макроса. Командная кнопка создана для того, чтобы подавать команду, она-то нам и нужна. Необходимо поместить на лист одну кнопку, снабдить ее надписью, скажем, “Копия” и связать с пустым макросомзаготовкой.
Как поместить на лист элемент управления
1.Если панель инструментов Формы не видна, выполните команду Вид | Панели инструмен-
тов | Формы.
2.Выберите щелчком мыши на панели Формы элемент управления Кнопка.
3.Поместите указатель мыши на лист Excel, в то место, где необходимо создать кнопку. Указатель мыши примет форму креста. Нажав левую кнопку мыши, растяните на экране, появившийся прямоугольник до необходимых размеров (рис. 1.24а). Отпустите кнопку мыши для завершения создания кнопки.
а
б
Рис. 1.24. Процесс создания кнопки на рабочем листе Excel
4.В указанном месте будет создана командная кнопка с надписью “Кнопка1” (рис. 1.24б).
5.На экране появится диалоговое окно Назначить макрос объекту (рис. 1.25).
Рис. 1.25. Диалоговое окно Назначить макрос объекту
6. Закройте диалоговое окно щелчком на кнопке Создать. В результате откроется окно Visual Basic с заготовкой макроса.

40 Глава 1. Excel: cоздание прайс-листа
7.Вернитесь в окно. Вновь созданная кнопка будет по-прежнему окружена двойной штриховкой, например, выполнив команду View | Microsoft Excel ([Alt]+[F11]) редактора Visual Basic.
8.Щелкните на кнопке один раз левой кнопкой мыши, при этом штриховка изменится на оди-
нарную.
9. Измените надпись на кнопке с “Кнопка1” на “Копия” (рис. 1.26) или другую надпись на свое усмотрение. При необходимости отформатируйте надпись, используя инструменты панели
Форматирование Microsoft Excel.
Рис. 1.26. Изменение свойств кнопки на рабочем листе Excel
10. Поместите указатель в любое место листа за пределами кнопки и щелкните левой кнопкой или же просто нажмите клавишу [Esc]. Штриховка исчезнет, и кнопка будет готова к работе.
Особенности изменения свойств элементов управляющих рабочим листом
Пока элемент управления (в данном примере — кнопка) окружен двойной штриховкой, его можно переместить в другое место или изменить его размеры. При обычной штриховке элемент управления (кнопка) позволяет изменить надпись на нем.
Необходимо, отличать надпись на объекте от его имени. Замена надписи никак не влияет на объект. Созданная в предыдущем разделе кнопка по-прежнему называется “Кнопка1”. Если вокруг объекта нет никакой штриховки, кнопка готова к работе. Указатель мыши над ней приобретает вид руки с вытянутым указательным пальцем, а щелчок левой кнопкой мыши приведет команд-
ную кнопку в действие — она выполнит макрос с именем Кнопка1_Щелкнуть. Пока что процедура, соответствующая этому макросу пуста, и состоит только из заголовка и окончания. Поэтому ее выполнение не приведет ни к какому действию.
Рис. 1.27. Диалоговое окно Назначить макрос объекту позволяет связать выбранный элемент управления с любым из доступных макросов, а также открыть окно кода с уже назначенным элементу управления макросом
Простейший вариант процедуры генерации прайса
Теперь можем заполнить заготовку процедуры программным кодом VBA. Для этого необходимо щелкнуть правой кнопкой мыши на созданной кнопке “Копия” и выбрать в контекстном меню команду Назначить макрос. В отобразившемся диалоговом окне Назначить макрос объекту (рис. 1.27) необходимо выделить название требуемого макроса (в данном случае “Кноп-