
Информатика
.pdf
71
30 |
trunc(ln(n)) |
|
|
|||
|
|
|
||||
f(x) = ∑ |
(-1) |
|
|
∙ n!∙x2∙n-1 |
||
3n |
2 |
n |
|
|
|
|
n = 0 |
|
∙ П (1 + k∙x) |
||||
|
|
|
k = 0 |
|
|
|
при х = 1 Mcd сообщает, что функция неопределена. Щелчок правой кнопкой мыши по "покрасневшему" изображению откроет меню выявления ошибки (рис. 13).
Выбор в нем "Trace Error" вызывает подменю выбора ошибки (рис. 14). Щелчок мышкой по
п. "First" высвечивает красным цветом n под знаком логарифма (логарифм нуля недопустим) с комментарием:
Меню
трассировки
ошибки
Рис. 13
"This function is undefined".
Установив начало суммирования с единицы, снова пытаемся вычислить значение f(1). Снова проблема с комментарием: "Encountered a floating point error" – переполнение, компилятор создал "плохую" программу. Запишем свою программу для вычисления бесконечной суммы (по аналогии с примером 13 из п. 1.6):
f(x) : = ε ← 0.00001, x2 ← x2, n ← 1, mn← 3
x
q ← 3∙(1 + x) , sum ← q while |q| > ε
n ← n + 1, mn← 9∙mn
q ← q∙x2∙n mn∙(1 + n∙x)
k ← if(mod(trunc(ln(n)), 2) = 0, 1, -1) sum ← sum + k∙q
sum
Программа легко справляется с задачей. Несложно представить эту функцию графически (меню "плоский график", рис. 15).
Рис. 15

72
В приведенной программе индексированная переменная – не элемент массива, здесь индекс – это "подпись", которая вводится нажатием точки после имени переменной, т.е. mn в данном случае единый символ одной переменной. К сожалению, визуального различия между индексом и "подписью" нет. Это иногда приводит к незаметным ошибкам.
Кроме указанных возможностей Mcd имеет окно трассировки (Trace Window в меню View) и панель инструментов отладки (Debug в меню Tools, см. рис. 16), а также
встроенные функции trace и pause. Аргументы этих функций позволяют выводить промежуточные значения в окно трассировки. Аналогично VBA имеется также оператор on error (на панели программирования, см. рис. 5). При вставке в программу он принимает вид:
▪ on error ▪,
где левый квадратик предполагает сообщение
об ошибке, правый содержит выражение с возможной ошибкой.
1.11.ОБЪЕКТНО-ОРИЕНТИРОВАННАЯ ИДЕОЛОГИЯ
Свозрастанием сложности программных пакетов появилась потребность внедрения т.н. структурной методологии, в которой всякий проект есть совокупность иерархических абстрактных уровней, которые позволяют четко структурировать программу, улучшая ее корректность и понимание. Основные ее принципы следующие:
1.принцип абстракции, умение до определенного уровня игнорировать детали,
2.принцип формальности – строгого методического подхода, подчинения правилам, определенной дисциплины,
3.принцип "разделяй и властвуй" – разбиение сложной проблемы на совокупность мелких, легко решаемых, с понятными взаимосвязями, каждая может быть реализована в виде отдельного модуля со своей структурой и поведением,
4.принцип иерархического упорядочения – связан с предыдущим,
определяет уровни независимости и подчиненности модулей.
Со временем оказалось возможным некоторые модули наделить дополнительными свойствами, превратив их в самостоятельный объект программирования.
73
Объект характеризуется совокупностью свойств, событий, происходящих при взаимодействии с ним, методов, которыми объект воздействует на окружающую среду (объединение в одном объекте таких качеств называют инкапсуляцией).
И структурная, и объектно-ориентированная методологии преследуют цель построения иерархического дерева взаимодействий объектов, при этом непременно отражается наследование родительских свойств (вышележащих объектов) дочерними (нижележащими) объектами. Многообразие форм проявления однотипных действий разными объектами называют полиморфизмом. Excel – прекрасный пример объектно-ориентированной методологии.
Объекты в Excel – это то, чем можно программно управлять, и с помощью чего можно управлять. Приложения в Ms Excel создаются путем объединения объектов с помощью VBA.
Самый верхний объект в иерархии – Application (приложение), который включает в себя Workbooks (Workbook – рабочая книга), а также связь с объектами Windows. Рабочая книга включает в себя Worksheets (Worksheet, рабочий лист, их может быть много). Рабочий лист содержит основные "кирпичики" конструкции приложения: Cells (ячейки), Range (диапазон ячеек), Chart (диаграммы), Shape (геометрические формы), CommandBars (элементы управления), и т.д. Каждый подчиненный объект можно отнести к свойствам родительского объекта. При ссылке или установлении свойств можно выписывать всю иерархию, отделяя дочерние объекты, свойства и методы от родительского точкой. Например, можно занести значение 1 в ячейку А1 первого рабочего листа в первой рабочей книге открытого приложения командой
Application.Workbooks(1).Worksheets(1).Range("A1").Value = 1
(здесь выписана вся иерархия – все родственники до последнего колена, каждый от другого отделен точкой – это признак подчинения). Можно поступить иначе: если предполагается работа с конкретным рабочим листом, то определить переменную типа Object инструкцией
Dim ‹имя› As Object,
присвоить переменной всех "родственников", после чего можно работать только с этой переменной, не нося за собой всю "родословную".
Нужно при этом помнить, что присваивание объектов выполняется с помощью служебного слова Set. В данном примере:
Dim W As Object
Set W = Application.Workbooks(1).Worksheets(1)
W.Range("A1").Value = 1 .

74
Аналогичным образом можно менять свойства объектов. Например, можно рабочему листу присвоить имя:
Worksheets(1).Name = "Graphics"
(теперь к рабочему листу можно обращаться по имени, это свойство наследуется и его подчиненными объектами, т.е. их тоже можно именовать).
Разумеется, если к объекту Excel обращаются внутри этого Excel, то ссылка на Application необязательна. Если в проекте только одна книга, то и в ссылке на Workbooks нет необходимости. Если программа имеет дело с одним активным рабочим листом, то и на него ссылаться необязательно. Если в одном рабочем листе требуются данные из другого листа (или книги), то ссылки на них необходимы.
Метод объекта является некоторой подпрограммой, часто с параметрами, поэтому и вызывается метод, как и всякая подпрограмма – по имени, за которым следуют фактические параметры (без скобок). Если в методе используются не все параметры (или с нарушением порядка), то ссылка на параметр должна состоять из трех элементов: имени параметра, знака присваивания ": =", значения параметра. Например, тре-
буется закрыть рабочую книгу с именем "Книга-1", сохранив изменения в ней, и сохранить ее в памяти под именем "TestBook". Строка соответствующего кода может выглядеть так:
Workbooks("Книга-1.xls").Close SaveChanges := True, _ FileName := "C:\Temp\TestBook.xls", RouteWorkbook := False
(пробел и подчеркивание – признак продолжения строки).
В конце этого пункта, в табл. 7, приведен краткий список некоторых свойств и методов базовых объектов изложенной иерархии.
Со всяким объектом, внедренным на рабочий лист, может быть связана запускаемая программа (макрос). Например, внедрив (с помощью панели "Рисование") на рабочий лист круг с надписью "Пуск", щелкнем по нему правой кнопкой мыши. В появившемся меню (рис.
17) выберем пункт "Назначить макрос". В открывшемся диалоговом говом окне (см. рис. 18) выберем пункт "Создать" (изменив, если необходимо, имя макроса). В результате в новом модуле появится заготовка кода макроса (в данном случае):
Рис. 17

75
Sub Овал1_Щелкнуть()
End Sub .
В теле этой подпрограммы может быть помещен произвольный код работы с приложением, вызов любых подпрограмм и функций.
Рис. 18
Таким образом легко решается вопрос о запуске различных программ с рабочего листа, доступ к редактору VBA, и пр. Готовые макросы мо-
жно запускать и прямо из меню: (разработчик) макросы макрос
(выбор) запуск, или в редакторе VBA, выделив его имя курсором и выбрав в меню команду Run (клавиша F5). Удобнее всего, конечно же, использовать специальные элементы управления. Но о них – в следующем разделе.
Поскольку произвольные события рабочего листа могут управляться программно, Excel (и другие пакеты, использующие VBA) имеет возможность автоматического создания макросов. Для этого доста-
точно войти в меню "Макросы", выбрать подменю "Начать запись" и, нажав кнопку "запись", выполнять необходимые действия. По окончании щелкнуть кнопку "остановить запись". Во вновь созданном модуле будет записана готовая программа, реализующая все действия. В общем, программа вполне работоспособная. Но, как всякий автоматический продукт, она может быть упрощена и улучшена. Во всяком случае, на ее основе можно (научиться) создавать вполне приличные рабочие приложения.
76
|
|
Таблица 7 |
|
|
|
|
|
Объект |
Свойства |
Методы |
|
Application |
Caption – надпись в заголовке, |
Calculate – вычисление всех |
|
Path – путь к каталогу Excel, |
формул, |
||
|
|||
|
WindowState – состояние окна |
Help – вывод справки, |
|
|
(нормальное, свернутое, развернутое) |
Quit – закрывает Excel, |
|
|
|
Run – запускает |
|
|
|
подпрограммы. |
|
Workbook |
Name – имя рабочей книги, |
Activate – активизация, |
|
Path – путь к файлу книги, |
Close – закрывает книгу, |
||
|
|||
|
Saved – сохранение изменений (да, |
Protect – защищает книгу, |
|
|
нет) |
Save – сохраняет книгу, |
|
|
SaveCopyAs – сохраняет в |
||
|
|
||
|
|
новом файле. |
|
Worksheet |
Index – номер листа, |
Activate – активизация, |
|
Name – имя листа, |
Calculate – вычисление всех |
||
|
|||
|
UsedRange – ссылка на дипазон |
формул, |
|
|
ячеек, |
Dilete – удаляет лист, |
|
|
Protect – защищает лист (аргу- |
||
|
Visible – отображение – скрытие. |
||
|
мент password). |
||
|
|
||
|
NumOfCells – количество ячеек, |
Calculate – вычисление всех |
|
Range |
Dependents – диапазон зависимых |
формул, |
|
ячеек, |
ClearContents – очищает |
||
Name – имя диапазона, |
содержимое, |
||
Value – значение в ячейках, |
|||
Copy – копирует значения в |
|||
|
Formula – строка формул, |
||
|
другой диапазон. |
||
|
Text – форматированный текст значений. |
||
|
|
1.12. КЛАССЫ
Класс – это некоторая таксономическая единица, характеризующая объекты с общими свойствами и поведением. Например, класс Кошачьих не определяет ни одну конкретную кошку, но характеризует всех их в общем, определяя их отличительные черты и поведение. Определив класс, мы можем далее создавать и использовать объекты с однотипными свойствами. Таким образом, класс удовлетворяет всем основополагающим принципам объектно-ориентированной идеологии. Как и любой объект, класс описывает свойства объектов, события, методы.
События – это способы управления классом, его реакцией на внешние воздействия. Отметим два специальных события, присущие всем классам: Initialize – возникает в момент создания нового объекта класса, Terminate – возникает в момент уничтожения объекта.
77
Методы класса – это функциональные "обязанности" объектов. Практически они представляют собой различные процедуры (Sub) и функции (Function) для "внутреннего" пользования, скрытые (определенные как Private) и (или) открытые (определенные как Public), образующие интерфейс класса.
По сути дела, пользовательский тип можно упрощенно рассматривать как (урезанный) пример класса. Класс элементов управления
CommandBars имеет свойства: Visible, Controls, Position, и др., поддерживает методы: Add, Delete, ShowPopUp, Reset, OnAction, и др.
Если, например, нужно добавить кнопки в новую панель, запускающие какие-то процедуры, можно воспользоваться кодом:
With Application.CommandBars.Add("Новая панель",False, True)
.Visible = True: .Position = msoBarleft With .Controls
With .Add(msoControlButton)
.Caption = "Кнопка1"
.OnAction = "‹имя процедуры›"
End With End With
End With .
1.12.1. Собственные классы
Для создания собственного класса нужно добавить в проект мо-
дуль класса: редактор VBA Insert Class Module Properties Window (или клавиша F4). В раскрывшейся панели можно изменить его имя (по умолчанию) Class1 на рабочее имя класса. В открывшемся листе редактора можно ввести все свойства класса (так же, как в типе пользователя) затем события и методы в виде подпрограмм и функций, в которых свойства обрабатываются без имени класса (и без точек).
Пример 1. Создадим класс автомобилей с именем Auto. В поле кода класса введем следующие свойства:
Public Num As Byte |
'***номер по порядку |
Public Model As String |
'***модель автомобиля |
Public Age As Byte |
'***возраст |
Public PetName As String |
'***кличка |
Public Price As Integer |
'***цена в тыс. евро |
Public Run As Single |
'***пробег (км.) |
Public Velocity As Byte |
'***скорость км./ч. |
Запишем событие инициализации (создания по умолчанию) объекта класса:
Public Sub Init()
Age = 30 * Rnd + 1: Velocity = 0 Model = "": PetName = "": Num = 0
78
Run = 100000 * Rnd: Price = 500 * Rnd
End Sub,
метод, возвращающий полную информацию об автомобиле:
Public Function Info() As String
Info = Format(Num) & ". " & Model & " - " & PetName & ": возраст " & _ Format(Age) & ", пробег " & Format(Run) & " км., цена " _
& Format(Price) & " тыс. евро" End Function.
Добавим также возможность изменять скорость конкретного автомобиля (если скорость превысит некоторую величину, автомобиль сломается):
Public Sub SpeedUp()
Randomize Timer
Velocity = Velocity + 10 '***увеличение скорости
If Velocity > 240 * Rnd Then
Velocity = 0: Model = ""
End If
End Sub .
Поместим на рабочий лист три надписи: "Добавить", "Показать" и "Поехали!". С каждй надписью свяжем одноименный запускаемый ей макрос (в модуле1).
Public n As Byte, k As Byte, AutoList(10) As Auto, a As Auto
Sub Добавить()
Randomize Timer |
|
n = n + 1: Set a = New Auto: a.Init |
'***создание объекта |
With a |
|
.Model = InputBox("Название модели", "", "") |
'***ввод данных |
.PetName = InputBox("Прозвище", "", "") |
|
.Num = n |
'***присвоение номера |
End With |
|
Set AutoList(n) = a |
'***занесение в массив |
Cells(n, 1) = a.Info |
'***и на рабочий лист |
End Sub |
|
Sub Показать()
k = Val(InputBox("Выберите номер автомобиля", "", 1)) If k > n Then
MsgBox "Слишком большой номер", vbCritical, "" Exit Sub
End If
Set a = AutoList(k): MsgBox "Вы выбрали" & Chr(13) & a.Info End Sub
Sub Поехали() |
|
|
Dim i As Byte |
|
|
With a |
'***вывод скорости |
|
.SpeedUp: Cells(11, 1) = "Скорость": Cells(11, 2) = .Velocity |
||
If .Velocity = 0 Then |
|
|
MsgBox "Ваш " & .PetName & " кончился!", vbExclamation |
||
Set AutoList(k) = Nothing |
'***уничтожение объекта |

|
79 |
For i = 1 To 10 |
'***обновление информации |
If i < k Then |
|
Cells(i, 1) = AutoList(i).Info
ElseIf i < n Then
Cells(i, 1) = AutoList(i + 1).Info
Else
Cells(i, 1) = ""
End If
Next
End If
End With
End Sub .
Теперь, несколько раз щелкнув по надписи "Добавить", введем инфор-
мацию: Ferrary, Jack, Volvo, Gerta, Jaguar, Kiddy, BMW, Satyr. В ячей-
ках С(1, 1) – С(4, 1) появится (например) текст:
1.Ferrary - Jack: возраст 4, пробег 60036,43 км., цена 338 тыс. евро
2.Volvo - Gerta: возраст 17, пробег 97644,75 км., цена 219 тыс. евро
3.Jaguar - Kiddy: возраст 26, пробег 57455,11 км., цена 241 тыс. евро
4.BMW - Satyr: возраст 30, пробег 35054,38 км., цена 132 тыс. евро
Щелкнув по надписи "Показать", выберем номер 3 из списка. Щелкая по надписи "Поехали!", будем увеличивать скорость авто. После скорости 50 появится сообщение "Ваш Kiddy кончился!".
Отметим для дальнейшего, что здесь большая часть переменных определена вне макросов. Эти переменные, таким образом, являются глобальными для этого модуля и сохраняют свои значения, пока не закончится работа модуля (в данном случае, проекта). Для принудительного сброса их значений в меню редактора VBA следует выбрать - пункт Reset (квадратик).
Класс, как подпрограмма или функция, допускает рекурсивное определение свойств. Это позволяет организовать динамическое рас-
пределение памяти явно, т. е. строить объекты, которые занимают память в зависимости от поступающей информации (напоминает конструкцию, аналогичную указателям в языке Pascal). Таким образом, при определении класса позволено указывать неявную ссылку на создаваемый объект (т. е. делается ссылка не на сам объект, которого еще нет, а на место в памяти, где этот объект будет находиться). При поступлении информации неявная ссылка делается явной и память, занимаемая объектами, динамически изменяется.
Пример 2. Пусть некоторое число человек, пересчитавшись по порядку, встали в круг (за последним идет снова первый) и, как в детской “считалке”, требуется удалить из круга каждого k-го по счету. Создадим пользовательский класс Circ (т.е. введем модуль класса и дадим ему имя Circ) со свойствами:
|
80 |
Option Explicit |
'***требование явного определения свойств |
Public Num As Long |
'***номер по порядку |
Public Pre As Circ |
' ***ссылка на предыдущего в круге |
Public Nxt As Circ |
'***ссылка на следующего в круге. |
На листе Excel поместим три надписи: “Initia” – инициализация класса переменных, “Add” – добавление в круг нового человека, “Delete” – удаление из круга очередного k-го по счету, и создадим в модуле1 одноименные макросы. с кодами:
Option Explicit |
|
|
Dim first As New Circ |
|
'*** первый в круге |
Dim last As New Circ |
|
'***последний в круге |
Dim cur As Circ |
'***текущий объект “считалки” |
|
Dim count As Long |
'***счетчик – количество участников |
|
Dim k As Integer |
|
'***модуль пересчета |
Private Initia() |
'***инициализация |
|
k = Val(InputBox("Какого по счету выбирать?", "", 2)) |
||
Set first.Nxt = last : first.Num = 1 |
|
|
Set first.Pre = last ; count = 2 |
|
'***формирование “круга” |
Set last.Pre = first : last.Num = 2 |
'***из двух человек |
|
Set last.Nxt = first |
|
|
Cells(1, 1) = "Содержание круга": Cells(2, 1) = "" |
||
Set cur = Nothing |
|
'***пустой объект |
End Sub |
|
|
Private Sub Add() |
'***добавление в круг |
|
Dim ncell As New Circ |
|
|
If count < 2 Then |
|
|
MsgBox "Начните с инициализации!" |
|
|
End If |
|
|
count = count + 1 |
|
|
ncell.Num = last.Num : last.Num = count |
|
|
Set ncell.Pre = last.Pre: Set ncell.Nxt = last |
|
|
Set last.Pre.Nxt = ncell : Set last.Pre = ncell |
|
|
Display |
'***вывод информации в ячейку А2 |
|
End Sub |
|
|
Private Sub Delete() |
'***удаление из круга k-го по счету |
|
Dim m As Long, i As Long |
|
|
If k < 2 Then Exit Sub |
|
|
If count = 1 then |
|
|
MsgBox “Счет закончен” : Exit Sub |
|
|
End If |
|
|
For i = 1 To k |
|
|
If cur Is Nothing And i = 1 Then |
|
|
Set cur = first |
|
|
Else |
|
|
Set cur = cur.Nxt : m = cur.Num |
'***переход по ссылке |
End if |
|
Next : MsgBox “Выбрали” & Format(m) & “-го” |
|
Set cur.Pre.Nxt = cur.Nxt |
|
Set cur.Nxt.Pre = cur.Pre |
'***изменение ссылки |