Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Воробьева.Приемы_программирования_в среде_VBfor...doc
Скачиваний:
5
Добавлен:
01.03.2025
Размер:
1.58 Mб
Скачать

Работа с листами книги

Мы познакомились с основными приемами работы в среде программирования VBA. Теперь познакомимся с приемами управления данными книги. Данные приемы можно использовать только в подпрограммах (Sub), так как при обращении к данным листа при выполнении функции происходит пересчет всех данных, что может зациклить систему.

Для получения данных с листа и переноса результатов на лист можно прямо обращаться к ячейкам листа по их адресам через объект .Range(“A1”) или по номерам строки и столбца через объект .Cells(1,1). Обе записи ссылаются на первую ячейку активного листа. Для работы с различными листами надо данные объекты привязать к нужным листам, добавив объект .Sheets(“Лист1”) с нужным именем листа. Так же можно продолжить цепочку объектов и работать с различными книгами, добавив коллекцию открытых книг объектом Workbooks("Имя_книги”). Существуют специальные объекты, которые позволяют обращаться к активным (открытым в данные момент листам, книгам и ячейкам), они имеют следующие имена: ActiveWorkBook – активная (видимая в данный момент) книга Excel; ActiveSheet – активный лист; ActiveCell – выделенная ячейка (в ней в данный момент находится курсор ввода). Пользуясь этими объектами, мы можем попадать в объекты, которые мы только что активировали. Например, новая открытая книга всегда становится – ActiveWorkBook. Если нам надо выполнить какие-либо действия на листе, мы можем написать программный код с использованием объекта ActiveSheet и запускать его на исполнение после выбора нужного листа и т.п. Часто надо бывает работать с двумя книгами – одна содержит сам код программы, а в другой находятся данные, которые надо оттуда забрать, обработать и сохранить в основной книге, где записан код программы. В этом случае мы может использовать два объекта: ThisWorkBook – книга с программным кодом и ActiveWorkBook – книга, которую мы открываем, обрабатываем и снова закрываем. В результате мы можем обработать несколько книг, которые мы будем открывать и закрывать друг за другом, все они будут отвечать объекту ActiveWorkBook.

Иногда бывает удобно не вносить данные непосредственно в активную ячейку, что снижает мерцание экрана, а пользоваться смещением от активной ячейки на ячейку, куда надо поместить данные – .OffSet(2,4) указывает на ячейку, которая лежит на 2 строки ниже и на 4 столбца правее от активной ячейки.

Рассмотрим несколько примеров реализации этих задач:

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

Сначала готовим лист, с которым мы будем работать. Для этого создаем новую книгу, переименовываем первый лист на «Данные» и заполняем следующую информацию на нем (рис.26.). Светло-зеленым цветом отмечены ячейки, куда будет вводиться информация о интервале графика. В ячейку функции записываем формулу, например =SIN(B4). Заполняем любыми данными таблицу в 10 строк, которая является исходным материалом для графика, и после на отдельном листе с именем «График» строим сам график, и настраиваем его параметры.

Рис.26. Лист «Данные»

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

Теперь все готово для создания программы. Открываем редактор VBA (Alt+F11), создаем модуль (InsertModule) и в него вставляем подпрограмму (InsertProcedure) с именем «Make_Graf» и записываем следующий код:

Public Sub MakeGraf()

Sheets("Данные").Activate

ActiveSheet.Range("A1").Activate

N = 10: Ir = 6

For i = 0 To N

ActiveCell.Offset(Ir + i, 0) = ""

ActiveCell.Offset(Ir + i, 1) = ""

Next i

xl = ActiveCell.Offset(1, 1)

xr = ActiveCell.Offset(1, 3)

H = (xr - xl) / N

For i = 0 To N

ActiveCell.Offset(3, 1) = xl + H * i

y = ActiveCell.Offset(3, 3)

ActiveCell.Offset(Ir + i, 0) = xl + H * i

ActiveCell.Offset(Ir + i, 1) = y

Next i

Sheets("График").Activate

End Sub

В двух первых строках определяем активный лист и активную ячейку. Потом задаем число интервалов (N) и смещение (Ir) для таблицы данных. Потом очищаем таблицу, считываем границы интервалов, определяем шаг (H) и далее в цикле вычисляем значения (Y) и помещаем их в таблицу для графика. Для вычисления функции мы сначала помещаем текущее значение параметра в ячейку «В4» командой ActiveCell.Offset(3, 1) = xl + H * i, потом получаем значение функции командой y = ActiveCell.Offset(3, 3), полученные данные заносим в таблицу. Последняя команда делает активным лист графика. Результаты работы показаны на (рис.27).

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

Рис.27. Результаты работы программы: лист данных и сам график

Ч

Рис.28. Пример оформления ячеек с данными

тобы выполнить последнее действие, надо на графике выделить нужные заголовки для редактирования, перейти в строку редактирования и вписать туда формулу вида «=Адрес_Ячейки». В представленном выше примере ячейки с текстами заголовков находятся в столбце «G» с 3 по 5 строки. Для них формулы будут иметь следующий вид «=Данные!$G$3», «=Данные!$G$4» и «=Данные!$G$5». Для ввода этих формул достаточно в строке формулы при выделении нужного заголовка написать «=» и потом с помощью мышки выбрать нужную ячейку на листе «Данные».

  1. Реализуем вариант программы для сбора данных из других книг Excel. Например, предположим, что мы проводим эксперименты на установке, которая записывает результаты на первый лист книги Excel. Нам надо указать программе нужную книгу, открыть ее, считать два столбца данных до первой пустой ячейки в любом из двух столбцов. Затем эти данные мы должны сохранить в книге Excel на листе «Эксперименты» по следующей схеме: находим первый свободный столбец, в первой строке заносим текущие дату и время получения данных, во второй – имя файла данных, который был открыт для чтения данных, в третьей – число пар данных и далее сами данные.

Сначала определим основные этапы программы:

  • на первом этапе мы должны получить файл для обработки, здесь можно воспользоваться стандартным диалоговым окном «Открыть файл…»;

  • если файл указан и открыт, проверяем наличие данных на первом листе в открытом файле, если они есть тогда:

    • готовим место для сохранения данных – записываем текущие дату, время и имя файла, находим свободный столбец на листе «Эксперимент»;

    • начинаем считывать и сохранять данные, иначе просто выходим из программы;

    • заносим число пар данных в третью строку;

    • закрываем файл с данными.

  • иначе просто завершаем программу.

Теперь начнем создавать саму книгу. Нам нужна новая книга с одним листом с именем «Эксперименты». Создаем ее, удаляем лишние листы и переименовываем первый с «Лист1» на «Эксперимент». Теперь переходим в редактор VBA (Alt+F11) и начинаем писать саму программу.

Создаем модуль и вставляем в него процедуру «Sub Get_Dates».

Теперь вызываем стандартный диалог

R = Application.Dialogs(xlDialogOpen).Show

Для этого определяем переменную, которая вернет нам результат операции, т.е. при открытии файла переменная R будет иметь значение True. После знака равенства вводим служебное слово Application, которое определят саму программу Excel. Ставим точку и выбираем из появившегося списка Dialogs. В этот момент можно начинать вводить данное слово, пока курсор сам не найдет нужную позицию списка. Вводим скобку и в следующем списке находим тип окна диалога. Ставим точку и выбираем метод «Show». После можно задать набор дополнительных аргументов типа маски файла, типа файла и т.п.

В следующей строке проверяем, открыт ли файл, если нет, сообщаем в окне «MsgBox» об этом

MsgBox "Для работы укажите файл с данными", _

vbInformation + vbOKOnly

Если файл открыт, определяем два объекта для упрощения записей в коде программы для листа с данными и листа экспериментов соответственно

Set AW = ActiveWorkbook.Sheets(1)

Set TW = ThisWorkbook.Sheets("Эксперимент")

Теперь проверяем наличие данных в первой строке открытого файла

If Not IsEmpty(AW.Cells(1, 1)) And _

Not IsEmpty(AW.Cells(1, 2)) Then

Если их (данных) нет, то выводим сообщение об этом и закрываем книгу без сохранения сделанных изменений

MsgBox "На листе открытой книги данных нет", _

vbInformation + vbOKOnly

ActiveWorkbook.Close False

Иначе подготавливаем место для сохранения данных на листе «Эксперимент». Для этого определяем переменную ic = 1 (номер первого столбца на листе «Эксперимент») и ищем свободный столбец с приращением в 2 столбца:

ic = 1

Do While Not IsEmpty(TW.Cells(1, ic))

ic = ic + 2

Loop

Теперь вносим начальные данные по серии – дату, время и имя файла

TW.Cells(1, ic) = Date

TW.Cells(1, ic + 1) = Time

TW.Cells(2, ic) = ActiveWorkbook.Name

Остается перенести сами данные, и сосчитать их количество. Для этого используем две переменные ir = 1 – текущий номер строки в файле данных и ke = 0 – число экспериментов в серии. Хотя можно воспользоваться и одной переменной с прибавлением или отниманием 1. Потом в цикле с предусловием переносим данные:

ir = 1: ke = 0

Do While Not IsEmpty(AW.Cells(ir, 1)) Or _

Not IsEmpty(AW.Cells(ir, 2))

TW.Cells(ir + 3, ic) = AW.Cells(ir, 1)

TW.Cells(ir + 3, ic + 1) = AW.Cells(ir, 2)

ir = ir + 1: ke = ke + 1

Loop

Строки в листе «Эксперимент» будут отличаться от строк на листе с исходными данными на 3 из-за наличия дополнительной информации в 3-х первых строках. Если возникнут другие требования, то можно просто изменить это число и добавить или уменьшить число строк с дополнительными данными. После переноса всех данных остается только закрыть файл с данными, и внести в третью строку данных на листе «Эксперимент» число пар данных в серии:

ActiveWorkbook.Close False

TW.Cells(3, ic) = ns

В полном виде программа показана ниже:

Public Sub Get_Dates()

R = Application.Dialogs(xlDialogOpen).Show

If R Then

Set AW = ActiveWorkbook.Sheets(1)

Set TW = ThisWorkbook.Sheets("Эксперимент")

If Not IsEmpty(AW.Cells(1, 1)) And _ Not IsEmpty(AW.Cells(1, 2)) Then

ic = 1

Do While Not IsEmpty(TW.Cells(1, ic))

ic = ic + 2

Loop

TW.Cells(1, ic) = Date

TW.Cells(1, ic + 1) = Time

TW.Cells(2, ic) = ActiveWorkbook.Name

ir = 1: ke = 0

Do While Not IsEmpty(AW.Cells(ir, 1)) Or _ Not IsEmpty(AW.Cells(ir, 2))

TW.Cells(ir + 3, ic) = AW.Cells(ir, 1)

TW.Cells(ir + 3, ic + 1) = AW.Cells(ir, 2)

ir = ir + 1: ke = ke + 1

Loop

ActiveWorkbook.Close False

TW.Cells(3, ic) = ns

Else

MsgBox "На первом листе книги данных нет", _ vbInformation + vbOKOnly

End If

Else

MsgBox "Для работы укажите файл с данными", _ vbInformation + vbOKOnly

End If

End Sub

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

  • Activate – происходит в момент активации листа. В этот момент мы может настроить вид листа (выбрать масштаб просмотра, определить активную ячейку, вывести определенную область листа на экран и т.п.);

  • Deactivate – противоположное событие, происходящее перед выбором другого листа. Здесь можно проверить правильность введенных данных, и при выявленных ошибках вернуть пользователя для их исправления, выполнить какие-либо расчеты, которые требуют времени и были деактивированы при вводе данных на листе, и другие операции;

  • Change – в момент изменения данных в ячейках листа. Здесь обычно проводят проверки правильности ввода данных;

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

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

Свои события имеют и книги. Чаще всего используются события управления книгой:

  • Open – в момент открытия книги. Здесь настраиваются вид оболочки Excel, запускаются пользовательские формы, выполняются первоначальные расчеты и подготовка памяти для дальнейших работ;

  • Группа событий Before… Close, Save, Print и другие. В них можно выполнить действия перед выполнением указанных выше операций закрытия книги, печати и сохранения или проверить правомочность этих действий и отказаться от их выполнения;

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

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

Для программы построения графиков добавим событие Open, в котором запишем проверку на открытие листа «Данные». Для события листа «Данные» в событие SelectionChange введем контроль ввода данных только в разрешенные ячейки. И последняя проблема – поставить элемент управления для построения графика. Посмотрим, как выполнить эти исправления. Для этого открываем файл «VBA_График.xls», входим в редактор VBA, и открываем модуль «ЭтаКнига» (рис.29). В окне модуля (слева) выбираем в левом выпадающем списке объект –WorkBook и в правом событие Open.

Рис.29. Выбор модуля «ЭтаКнига» и ввод кода в событие Open

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

ThisWorkbook.Sheets("Данные").Activate

Теперь переходим к «Лист2(Данные)», выбираем объект WorkSheet и событие SelectionChange (Рис.30). Здесь надо подумать об алгоритме работы программы. Нам надо сделать так, чтобы программа могла проверить разрешен ввод данных в эту ячейку или нет.

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

Рис.30. Выбор модуля «Лист2(Данные)» и событие SelectionChange

Реально нам надо искать нужные ячейки в области от «B2:G4». Попробуем записать макрос, который будет искать нужные нам ячейки. Для этого выполняем все необходимые операции в режиме записи макроса, как было показано выше.

Вызываем команду СервисМакросыНачать запись, соглашаемся с предложенным именем макроса и начинаем записывать саму программу:

  • Выделяем диапазон от ячейки B2 до G4;

  • Вызываем команду поиска ПравкаНайти…;

  • На панели Найти и заменить нажимаем кнопку Параметры;

  • На открывшейся расширенной панели поиска нажимаем кнопку Формат;

  • В открывшемся окне Найти формат открываем закладку Вид и выбираем необходимый нам цвет;

  • Подтверждаем выбор цвета кнопкой Ok и нажимаем кнопку Найти далее;

  • Завершаем запись макроса.

Переходим в редактор VBA и видим там новый модуль «Модуль2», в нем созданный нами макрос.

Range("B2:G4").Select

Application.FindFormat.Interior.ColorIndex = 35

Selection.Find(What:="", After:=ActiveCell, _ LookIn:=xlFormulas, LookAt:=xlPart, _ SearchOrder:=xlByRows, _ SearchDirection:=xlNext, _ MatchCase:=False, SearchFormat:=True).Activate

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

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

If Target.Interior.ColorIndex = 35 Then Exit Sub

Ok = False

If Target.Row < 2 Then

r = 2: Ok = True

ElseIf Target.Row > 4 Then

r = 4: Ok = True

Else

r = Target.Row

End If

If Target.Column < 2 Then

c = 2: Ok = True

ElseIf Target.Column > 7 Then

c = 7: Ok = True

Else

c = Target.Column

End If

If Ok Then Cells(r, c).Activate

Range("B2:G4").Find(What:="", _ After:=ActiveCell, _ LookIn:=xlFormulas, _ LookAt:=xlPart, _ SearchOrder:=xlByRows, _ SearchDirection:=xlNext, _ MatchCase:=False, _ SearchFormat:=True).Activate

End Sub

Разберем его более подробно. В первой строке проверяем, удовлетворяет нас ячейка, которая в данный момент выбрана, и выходим из программы, если это так. Дальше проверяем, находится ли активная ячейка внутри диапазона поиска. Если это не так, выбираем ближайшую к ней ячейку внутри диапазона, и делаем эту ячейку активной. Переменная Ok сообщает о необходимости перемещения активной ячейки внутри диапазона. Теперь можно выполнять поиск необходимой ячейки.

Ясно, что для полнофункциональной версии работы программы надо вывести на лист элемент управления, который будет вызывать подпрограмму построения графика. Воспользуемся формами для управления объектами. Вызовем стандартную панель инструментов Формы, и выберем кнопку. Нарисуем ее на листе ниже заголовков для графика. Как только мы завершаем рисование кнопки, открывается меню выбора макроса, который будет привязан к этой кнопке, и выбираем MakeGraf. После этого предлагается изменить заголовок кнопки. Пишем «Строим график», и получаем кнопку вида . Можно настроить и ряд других параметров, если вызвать с помощью контекстного меню свойства этого объекта.