VBA. Практическое программирование
.pdf
Анализ текста
Таким образом, возникает необходимость программирования, и в программе должна быть предусмотрена возможность взаимодействия между текстовым редактором и электронной таблицей. Часть программы должна быть написана в Word, а вторая часть в Excel.
В силу определенной сложности предлагаемой программы рассмотрим еще раз некоторые этапы подробнее.
Подготовка данных к экспорту
На втором этапе при анализе текста предстоит просмотреть каждое слово, взять от него только первую букву и запомнить эти буквы так, что в конце этапа у нас должен получиться либо массив из первых букв всех слов, либо что-то еще, содержащее, необходимую для нас информацию. Здесь не зря мы останавливаемся на проблеме выбора (либо массив, либо...), потому что разработанный нами алгоритм должен учитывать способности исполнителя, то есть нужно подумать, а как эти данные передать в EXCEL, в какой форме возможен обмен данными между Word и электронной таблицей. Оказывается, что в VBA это возможно только через стандартный буфер обмена, а поместить в этот буфер можно только фрагмент текста. Таким образом, мы вынуждены формировать фразу, которая включает в себя только первые буквы всех слов. Но для VBA не существует понятие фразы, он принимает слова, предложения, абзацы и т. д., поэтому мы окончательно определимся, что формировать будем предложение.
Таким образом, в словесном описании алгоритм второго этапа будет выглядеть следующим образом. Сначала определим, сколько слов в нашем тексте, затем, используя цикл, просмотрим каждое слово и возьмем из него первую букву и присоединим ее к первым буква, взятых из других слов. При этом, используя конструкцию «if...then....else» будем рассматривать только те символы, цифровые коды которых соответствуют русским буквам, чтобы не допустить в обработку служебные символы, которыми богат текстовый редактор. Для того чтобы сформированная в цикле строка превратилась в предложение, мы добавим в конце символ точки, затем вставим это предложение в наш текст и уже оттуда вырежем этот текст в буфер обмена. Но на этом этап не заканчивается. Теперь для дальнейшей статистической обработки (на 3-м этапе) эту строку нужно вытащить из буфера, уже находясь в электронной таблице. А это значит, что необходимо отрыть новое приложение (Excel), в
91
3. Проекты на VBA
этом приложении открыть конкретную, в данном случае, книгу, сделать ее активной и перейти к работе в VBA уже внутри этой книги.
Об объектных переменных и подсчет числа букв
Для выполнения этих операций мы должны объявить две объектные переменные — одну для электронной таблицы, другую для конкретной, подготовленной заранее электронной книги, и затем установить соответствие между этими переменными и самими объектами. И лишь после того, как откроется электронная книга, можно считать второй этап завершенным.
Переходим к третьему этапу. Находясь в электронной таблице, мы из буфера обмена вытаскиваем сформированную строку и размещаем ее в какой-нибудь ячейке. Затем, определив число букв в этой строке, начинаем цикл, внутри которого, просматривая каждую буковку, вычисляем ее код и добавляем единичку в ту ячейку, которая «отвечает» именно за эту букву. При этом мы учитываем, что одна и та же буква может иметь два разных кода из-за того, что она бывает «большой» и «маленькой». Это реализуется с помощью конструкции «если код меньше 223 (верхний регистр) или иначе (нижний регистр)». В любом случае частота повторения одной и той же буквы будет отображена в одной ячейке. Также мы применим конструкцию «если код не менее 192» чтобы работать только с русскими буквами. После завершения цикла в электронной таблице будет построен столбец, в ячейках которого будут располагаться числа, указывающие, сколько раз та или иная буква выступает в роли первой в словах исследуемого текста. А слева от этого столбца можно заранее подготовить столбик из соответствующих букв и сам программный код писать соответственно с уче- том того, что напротив буквы «а» или «А» должно подсчитываться число «попаданий» для этой буквы и т. д. Понятно, что файл с такой программой должен быть подготовлен заранее, находиться в той директории (папке), где находится файл с исследуемым текстом и, мало того, чтобы иметь возможность работать с этой электронной книгой в дальнейшем, мы должны результаты исследования сохранить под другим именем. Это также решается на третьем этапе.
Четвертый этап — графическое представление данных может быть решен средствами ЭТ без программирования и поэтому здесь не рассматривается.
92
Анализ текста
Код программы
Сначала рассмотрим код программы для Word (2 этап проекта). Эта программа содержится в документе Word «Анализ текста». Этот документ и связанный с ним файл электронной таблицы «Test» должны быть расположены в одной папке!
Public MyXL As Object |
В этих строчках, размещенных в |
|
Dim xlApp As Object |
разделе General происходит |
|
объявление трех переменных, из |
||
Public n As Integer |
||
две объектные переменные — |
||
|
||
|
одна для приложения Excel |
|
|
(xlApp), другая для конкретной |
|
|
рабочей книги (MyXL). |
|
Private Sub CommandButton1_Click() |
Начало процедуры под щелчок по |
|
|
кнопке |
|
n = ThisDocument.Words.Count |
Определение числа слов в |
|
|
документе |
|
For k = 1 To n |
В цикле из каждого слова |
|
buk = Left(Words(k), 1) |
выбираем первую букву, и если, |
|
судя по ее числовому коду, она |
||
If Asc(buk) >= 192 Then slovo = slovo |
||
относится к кириллице, то |
||
+ buk |
||
добавляем ее к строковой |
||
|
||
Next |
переменной slovo. |
|
|
|
|
slovo = slovo + "." |
Превращаем slovo в предложение |
|
|
|
|
ThisDocument.Characters.Last.InsertA |
Вставляем получившееся |
|
fter (slovo) |
предложение в конец документа. |
|
|
|
|
ThisDocument.Sentences.Last.Cut |
Вырезаем это предложение в |
|
|
буфер обмена |
|
|
|
|
pat$ = ThisDocument.Path |
Определяем путь к папке, в |
|
|
которой хранится этот документ |
|
|
êàê ôàéë |
|
|
|
|
patex$ = pat$ + "\test.xls" |
К найденному пути добавляем |
|
|
имя заранее подготовленного |
|
|
файла рабочей книги ЭТ, |
|
|
расположенного в той же папке. |
|
|
|
|
MsgBox (patex$) |
Эта строчка для контроля |
|
|
|
|
Set xlApp = |
Открываем через объектную |
|
CreateObject("excel.application") |
переменную файл приложение |
|
|
Excel |
|
xlApp.Visible = True |
||
|
||
|
|
|
|
|
93
3. Проекты на VBA
Set MyXL = GetObject(patex$) |
Открываем через объектную |
|
MyXL.Application.Windows(1).Visible = |
переменную файл конкретной |
|
True |
рабочей книги («Test») и делаем |
|
ее активной. |
||
MyXL.Application.Windows(1).Activate |
||
|
||
End Sub |
Конец процедуры |
|
|
|
|
Теперь знакомимся с кодами 3 этапа проекта |
||
|
|
|
Private Sub CommandButton1_Click() |
Начало процедуры под щелчок по |
|
|
кнопке |
|
ActiveSheet.Paste |
Вставка содержимого буфера |
|
Destination:=Worksheets(1).Range("D |
обмена в ячейку D1. |
|
1") |
|
|
a$ = Cells(1, 4) |
Этому содержимому присваиваем |
|
|
èìÿ |
|
n = Len(a$) |
Определяем длину строковой |
|
|
переменной |
|
For i = 1 To n |
Поочередно в цикле в |
|
b$ = Mid(a$, i, 1) |
переменную b$ помещаем по |
|
одной букве, анализируем Asc-код |
||
cc = Asc(b$) |
||
каждой буквы и если она |
||
|
||
If cc >= 192 Then |
относится к кириллице, то в |
|
If cc <= 223 Then |
соответствующую ячейку таблицы |
|
добавляем единицу, независимо |
||
Cells(cc – 187, 4) = Cells(cc – 187, 4) |
||
от регистра буквы. Таким образом |
||
+ 1 |
||
в 4 колонке рабочего листа |
||
Cells(cc – 187, 5) = cc |
||
формируется число появлении той |
||
Else |
или иной буквы в качестве |
|
перовой. В 5 и 6 колонке для |
||
Cells(cc – 219, 4) = Cells(cc – 219, 4) |
||
контроля размещаются Asc-коды |
||
+ 1 |
||
|
||
Cells(cc – 219, 6) = cc |
|
|
End If |
|
|
End If |
|
|
Next |
|
|
mx$ = InputBox("Введите номер |
Просим пользователя дать |
|
файла для сохранеия", "Для |
какое-нибудь число |
|
сохранения файла") |
|
|
pat$ = ThisWorkbook.Path |
Определяем путь к папке, где |
|
|
хранится все наши файлы. |
|
|
|
|
94
|
Проект — игра «Теннис» |
|
|
|
|
polname$ = pat$ + "\rezalt" + mx$ + |
Формируем полное имя файла |
".xls" |
|
ThisWorkbook.SaveAs (polname$) |
И сохраняем его |
MsgBox ("Имя сохраненного файла - |
Сообщаем об этом пользователю |
" + polname$) |
|
End Sub |
Конец процедуры. |
|
|
И еще раз предупреждение — эта программа может не работать, если в фоновом режиме на компьютере работает антивирусная программа.
Проект — игра «Теннис»
Для иллюстрации возможностей VBA при работе с диаграммами предлагаем познакомиться с небольшим учебным проектом — игрой. Этот проект носит название учебного, потому что там многие элементы носят демонстрационный характер и вполне возможно усовершенствование этого проекта.
Цель этого проекта — создание небольшой игрушки, в которой по экрану движутся 4 снаряда, а задача игрока — не допустить попадание этих снарядов в человечка. Процесс создания игрушки умышленно описываем в произвольном плане, чтобы показать, что, несмотря на определенные требования к созданию проектов, принятые в среде программистов, язык VBA допускает определенную степень свободного творчества.
Создание изображений в диаграмме
В первую очередь необходимо создать изображения снарядов и заставить их двигаться. В своем рассказе для простоты мы будем говорить о создании одного изображения, читатель в примере увидит коды для 4 снарядов. Конечно, для этого используем диаграмму, и учитывая возможности диаграмм, выбираем пузырьковую. Для этой диаграммы в 5 строке в колонке A назначаем Х координату для снаряда — пузырька, в колонке B — Y — координату, и наконец в С — размеры пузырька. Заполним эти ячейки значениями 5, 5 и 1 соответственно. Это необходимо для первоначального создания изображения. Сразу же можно, используя 6, 7 и 8 строку добавить еще 3 изображения. Затем, используя различные свойства и параметры диаграммы получить необходимые изображения.
95
3. Проекты на VBA
То, что получилось у нас, Вы можете увидеть в примере Теннис Раскроем небольшую хитрость — у шкал обеих осей убрана галоч- ка «Авто».
Программирование движения
Следующий шаг — движение снаряда. Для этого, используя VBA, изменяем координату Х в ячейке А5. В цикле Do While (пока переменная sttop=0) увеличиваем значение в этой ячейке на вели- чину a. Заметим, что параметр a тоже со временем возрастает. Это приводит к возрастанию скорости движения. Кроме того, когда изображение достигнет левой части диаграммы, необходимо, чтобы оно начало свое движение опять с нуля, игрок получил одно очко (переменная kol возрастает на 1), и У —координата также поменялась (движение снаряда на другой высоте). Эти задачи реализуются в процедуре prov. Эта процедура написана для 4 снарядов и в качестве переменной, которую использует эта процедура, применяется номер строки, в которой находятся координаты того или иного снаряда. О самой процедуре поговорим позже, а сейчас приводим основные строчки кода для цикла.
Do While sttop = 0 Cells(5, 1) = Cells(5, 1) + a prov 5
Label1.Caption = kol a = a + 0.005
Loop
Поясним еще две строки кода — в одной из них в элемент управления Label1 посылается значение переменной kol, а в другой (DoEvents) программе дается инструкции о реализации различных событий, связанных с рабочим листом и диаграммой.
Вы, вероятно, заметили, что в заданном цикле совершенно ни- чего не делается с переменной sttop, и создается впечатление, что цикл бесконечен. На самом деле для остановки цикла (и программы) используется вторая кнопка с надписью «Стоп» (первая — это «Пуск»), в которой меняется значение этой переменной, доступной всем модулям блока.
Вернемся к коду. Перед запуском цикла необходимо задать на- чальные значения для переменных, «включить» генератор случайных чисел, расположить изображение на случайной высоте (координата У) и в начале шкалы Х. Все это делают следующие инструкции —
96
Проект — игра «Теннис»
sttop = 0 kol = 0 a = 0.1
Label1.Caption = kol Randomize Timer Cells(5, 1) = 0
Cells(5, 2) = Int(Rnd * 8) + 1
О человечке
Следующий шаг — создание на диаграмме изображения человечка и управление его перемещением. Сразу оговоримся — перемещение только вертикальное. Координаты этого изображения в 12 строке. На пузырьковой диаграмме мы должны были получить изображение шарика, но, изучив свойства этой диаграммы, Вы обнаружите, что вместо шарика можно поместить рисунок («Способы заливки»). Х-координату оставим неизменной (число 5) а вот У-координату будем менять. Для этого используем полосу прокрутки с размахом от 0 до 80, (устанавливаем свойства полосы min=0, max=80) и ячейкой связи — B11 (LinkedCell=B11). Чтобы перемещение ползунка и изображения на диаграмме визуально были синхронны, используем специальную формулу в ячейке В12, а размеры диаграммы и полосы подбираем вручную.
О работе процедуры prov
И, наконец, поговорим о процедуре prov. О задачах этой процедуры мы говорили чуть ранее, теперь сюда добавляем необходимость проверки попадания снаряда в человечка. Размеры снаряда и человечка принимаем равными единице, и будем считать, что они встретились, если разность их координат по вертикали равна единице, и при этом горизонтальная координата снаряд находится в диапазоне 4.5<X<5.5, то есть там где «гуляет» человечек.
Процедуру приводим с построчными комментариями
Public Sub prov(i) — i — это номер строки координат снарядов If Cells(i, 1) > 4.5 Then — åñëè Õ координата больше 4,5
If Cells(i, 1) < 5.5 Then — но меньше 5,5
If Abs(Cells(i, 2) – Cells(12, 2)) <= 1 Then sttop = 1 — и при этом координаты Y шарика и человечка отличаются менее чем на 1, тогда произошла «трагедия», игра останавливается.
Else — иначе (Õ>5,5)
If Cells(i, 1) > 10 Then è X>10, тогда
Cells(i, 1) = 0 X шарика обнуляем,
97
3. Проекты на VBA
Cells(i, 2) = (Rnd * 8) + 1 à Y — случайное число в диапазоне от 1 до 9
kol = kol + 1 — и игрок получает еще одно очко
End If
End If
End If End Sub
Óснарядов разные скорости
Èнаконец несколько слов об этих инструкциях
Cells(6, 1) = Cells(6, 1) + a – 0.02
Cells(7, 1) = Cells(7, 1) + a/2
Cells(8, 1) = Cells(8, 1) + a + 0.02
Здесь тоже происходит перемещение снарядов, но с разной скоростью. Самый быстрый снаряд — в строке 8, самый медленный — в строке 7.
Обработка социометрических исследований
Цель проекта
Рассмотрим ситуацию, которая может возникнуть при проведении социометрических исследований. В коллективе необходимо выявить лидеров и отстающих, антипатии и симпатии. Для этого членам коллектива задается вопрос типа «Кого бы Вы пригласили на день рождения», «С кем бы пошли в магазин» «Кого не хотели видеть за соседним столом» и т. д. Затем по полученным ответам (а каждый участник указывает не более 5-ти положительных и 5-ти отрицательных персон, меньше можно) составляется таблица и уже на основе этой таблицы проводится обработка данных. У нас в качестве испытуемых будет выступать лесной коллектив сказочных героев из фирмы «Тридевятое царство».
Структура таблицы
Таблица размещена на рабочем листе «Table». В верхней строке и в первой колонке размещены фамилии испытуемых. Причем наверху фамилии тех, кто выбирает, а сбоку — фамилии выбранных. Так сделано потому, что удобнее наверху выбрать столбик с фамилией Богатырь, и спускаясь по нему поставить «1» напротив его положительных выборов и «–1» — напротив его отрицательных
98
Обработка социометрических исследований
выборов. Количество участников опроса автоматически определяется в ячейке «B2». В этой ячейке расположена формула, которая подсчитывает число фамилий. По этому поводу мы сделаем сразу два замечания — во-первых, мы не будем комментировать смысл табличных формул и будем считать это Вашей самостоятельной несложной задачей, а во-вторых, все ячейки, где находятся формулы, и менять их нельзя, обозначим каким-нибудь образом, например двойной красной рамкой.
«нашем» коллективе 18 персон, но таблица рассчитана на 40 участников. Это видно из второй колонки и второго ряда, где расположены порядковые номера участников. За пределами этой зоны также расположены расчетные ячейки. В колонках AQ, AR, AS, AT для каждого участника подсчитывается количество «положительных» и «отрицательных» выборов в отдельности и в сумме. Кроме того, дублируется порядковый номер участника, а в колонке AU — его фамилия.
Â43 и 44 рядах также с помощью формул вычисляется, сколько положительных и отрицательных выборов сделал каждый участник. Причем, если участник «перебрал» в своих эмоциях (выбрал более пяти персон), то вследствие условного форматирования соответствующая ячейка будет выделена красным цветом.
Новые данные
Итак, таблица сформирована, фамилии распечатаны, формулы построены и теперь пора заняться кодом программы, чтобы понять, как обрабатывать эту таблицу. Проще всего код расположить под элементы управления «Кнопка». На рабочем листе расположены две кнопки. Сначала поговорим о кнопке «Новые данные». Как часто бывает в практике общения с компьютером пользователю удобнее и понятнее использовать уже знакомую программу со старыми данными, чтобы поместить туда новые значения. (действия по образцу). Но при этом нужно очистить таблицу от старых данных, покрасить диагональные ячейки в светло голубой цвет и сохранить файл под новым именем.
Вот соответствующий код
Private Sub |
|
CommandButton2_Click() |
|
|
|
Range("c3:ap42").Clear |
Очистка ячеек от предыдущих |
|
данных |
|
|
|
|
99
3. Проекты на VBA
For i = 3 To 42 |
Окрашивание диагональных ячеек |
|
|
в цикле |
|
Cells(i, i).Interior.ColorIndex = 33 |
||
|
||
|
|
|
Next |
|
|
|
|
|
Application.Dialogs(xlDialogSaveAs) |
Вызов диалогового окна для |
|
.Show |
сохранения файла под новым |
|
|
именем |
|
|
|
|
End Sub |
|
|
|
|
|
|
|
Сохранение под новым именем необходимо для того, чтобы под старым именем остался исходный файл с исходной программой (шаблон, другими словами), которым всегда можно было бы воспользоваться. Поэтому, если Вы нажмете на кнопку «Новые данные», то Вы сотрете все сведения про жителей «Тридевятого царства» и если не сохраните файл под новым именем, то уже не сможете их восстановить. В случае сохранения под новым именем Вы просто продолжите работу с другим файлом, а исходный, «образцовый» файл останется нетронутым.
Но сейчас нас интересуют не новые данные, а та часть программы, которая обрабатывает уже внесенные значения. На эту часть мы возлагаем следующие задачи
1.Определить пары (взаимный положительный выбор) и антипары (взаимный отрицательный выбор), раскрасить соответствующие ячейки таблицы соответственно в зеленый и желтый цвет, составить список пар и антипар на отдельном листе
2.Отсортировать список участников по положительному, отрицательному и суммарному рейтингу, оставить список на отдельном листе
3.Представить сведения для каждого участника, а именно его друзей и тех, кто его любит, а также его «врагов» и тех, кто его не любит. Подготовить распечатку для каждого участника с этими сведениями.
Использование массивов и циклов
Для решения первой задачи нам нужно знать общее число фамилий (переменная K), а затем, используя вложенный цикл, пройти по всем ячейкам таблицы, лежащим над главной диагональю. При этом, если в ячейке находится «1», проверить, нет ли «1», в ячейке, симметричной для данной ячейки по отношению к диаго-
100
