Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
EDO_VBA.doc
Скачиваний:
3
Добавлен:
11.08.2019
Размер:
494.08 Кб
Скачать

5.3. Оператор GoTo

Оператор GoTo — це оператор безумовного переходу, коли хід виконання програми без перевірки яких-небудь умов перестрибує на мітку в коді.

Приклад використання GoTo може виглядати так:

GoTo EngineNotStarted

...

EngineNotStarted:

MsgBox "Їдемо на метро"

...

Тут EngineNotStarted: — це мітка, для неї використовується ім'я (вибиране за правилами призначення імен для змінних), яке закінчується двокрапкою. Ця мітка може знаходитися як до, так і після оператора GoTo.

У будь-якому випадку, при виконанні оператора GoTo хід виконання "перестрибне" на вказану в GoTo мітку.

Іноді використання GoTo дуже зручно, наприклад, коли нам потрібне добиватися від користувача введення правильного значення невідоме число разів.

Проте використовувати GoTo категорично не рекомендується, тому що код стає непрозорим. Частіше усього GoTo можна замінити на конструкцію Do While...Loop на виклик функції з самої себе.

6. Робота з циклами

Цикли використовуються в ситуаціях, коли нам треба виконати яку-небудь дію кілька разів. Перша ситуація — ми знаємо, скільки разів треба виконати певну дію, в цьому випадку використовується конструкція

For...Next:

For iCounter = 1 to 10

MsgBox "Лічильник: " & iCounter

Next

Щоб вказати, наскільки повинне приростати значення лічильника, використовується ключове слово Step :

For iCounter = 1 to 10 Step 2

MsgBox "Лічильник: " & iCounter

Next

Можна і зменшувати початкове значення лічильника :

For iCounter = 10 to 1 Step - 2

MsgBox "Лічильник: " & iCounter

Next

Для безумовного виходу з конструкції For...Next використовується команда Exit For:

VStop = InputBox("Введіть значення зупину")

VInput = CInt(VStop)

For iCounter = 1 to 10

MsgBox "Лічильник: " & iCounter

If iCounter =VInput Then Exit For

Next

Дуже часто в VBA вимагається зробити яку-небудь дію з усіма елементами колекції або масиву — перебрати усі відкриті документи, усі комірки в певному діапазоні і т. д. Для того, щоб пройти циклом по усіх елементах колекції, використовується команда

For Each...Next:

For Each oWbk in Workbooks

MsgBox oWbk.Name

Next

При використанні цього прийому можна дуже просто знайти і отримати посилання на потрібний нам об'єкт:

For Each oWbk in Workbooks

If oWbk.Name = "Зведення.xls" Then

Set oMyWorkBook = oWbk

Exit For

End If

Next

В цьому випадку ми проходимо циклом по усіх елементах колекції Workbooks (тбт. по відкритих робочих книгах в Excel), для кожної книги перевіряємо її ім'я і, якщо знайшли книгу з ім'ям "Зведення.xls", отримуємо на неї посилання і виходимо з циклу.

Ще одна ситуація: коли ми не знаємо точно, скільки разів має бути виконана та або інша команда — це залежить від якої-небудь умови. У цьому випадку використовуються конструкції Do While...Loop і Do Until...Loop.

Конструкція Do While...Loop означає: виконувати яку-небудь дію тих пір, поки умова істинна:

Do While MyVar < 10

MyVar = MyVar + 1

MsgBox "MyVar = " & MyVar

Loop

Якщо ви випадково запустили у своїй програмі нескінченний цикл, натисніть на клавіші <Ctrl>+<Break>.

Другий варіант — Do Until...Loop. Усе виглядає так само, за одним исключением: цикл виконуватиметься до тих пір, поки умова помилкова.

Do Until MyVar >= 10

MyVar = MyVar + 1

MsgBox "MyVar = " & MyVar

Loop

Можна переписати цикл так, щоб умова перевірялася після завершення циклу:

Do

MyVar = MyVar + 1

WScript.Echo "MyVar = " & MyVar

Loop While MyVar < 10

В цьому випадку цикл буде виконаний, принаймні, один раз.

Негайний вихід з циклу можна зробити по команді Exit Do.

У VBA є також конструкція While...Wend. Це ще один варіант циклу, який залишений для зворотної сумісності з першими версіями

Visual Basic. Функціональні можливості — ті ж, що і у конструкції Do While...Loop:

While My Var < 10

MyVar = MyVar + 1

WScript.Echo "MyVar = " & MyVar

Wend

Приклад 3 Проаналізуйте роботу програми:

Sub Counter()

Dim i, count As Integer, member As String

i = 2

count = 0

Do

member = Cells(i, 1)

If member <> "" Then

count = count + 1

End If

i = i + 1

Loop While member <> ""

Cells(i - 1, 1) = "Ви ввели " & count & " учасників"

End Sub

7. Масиви

Масиви використовуються для зберігання в пам'яті безлічі значень. Замість того щоб оголошувати множину схожих один на одного змінних, часто набагато зручніше скористатися масивом.

Оголошення масиву робиться дуже просто:

Dim MyArray(2) As Integer

Тут 2 — це верхня межа масиву (upper bound). За умовчанням нижньою межі масиву (lower bound) відповідає елемент з номером 0. Кількість елементів, яку може зберігати масив, — від 0 до верхньої межі включно. Наш масив може зберігати три цілочисельні елементи.

Якщо вам хочеться, щоб нижня межа масиву (і, відповідно, нумерація елементів) починалася з 1, то в розділ оголошень модуля треба записати команду:

Option Base 1

В принципі, тип даних для масиву можна не оголошувати:

Dim MyArray(2)

В цьому випадку для елементів масиву буде використаний тип Variant. Такий масив зможе зберігати в собі елементи різних типів даних, але вимоги до пам'яті у нього будуть вищі і працювати він буде трохи повільніший в порівнянні з масивом, для якого тип даних вказаний явно (наприклад, Integer чи String).

Присвоїти значення окремому елементу масиву (в нашому випадку — першому) можна дуже просто:

MyArray(0) = 100

А потім це значення можна буде витягнути:

MsgBox MyArray(0)

Масиви можуть бути багатовимірними, зокрема, двовимірними:

Dim MyArray(4, 9)

У кожному рядку багатовимірного масиву зручно зберігати дані, що відносяться до одного об'єкту (наприклад, ім'я співробітника, унікальний номер, номер телефону). У VBScript в одному багатовимірному масиві може бути до 60 вимірів.

Часто необхідно використовувати динамічні масиви, розмір яких можна змінювати в ході виконання. Динамічний масив оголошується наступним чином:

Dim MyArray() ' оголошуємо масив без верхньої межі

ReDim MyArray(4) ' змінюваний розмір масиву

Команда ReDim не лише змінює розмір масиву, але і видаляє з нього усі старі значення. Щоб старі значення збереглися, використовується ключове слово Preserve :

ReDim Preserve MyArray(7)

Проте якщо новий розмір масиву менший, ніж кількість поміщених в його елементів, слово Preserve не допоможе — частина даних все одно буде втрачена. Масиви можна створювати і заповнювати одночасно:

Dim MyArray

MyArray = Array(100, 200, 300, 400, 500)

Вказувати розмір масиву необов'язково — він буде автоматично налаштований відповідно до кількості передаваних елементів.

Очистити масив можна командою Erase : Erase MyArray

Масив фіксованої довжини просто очищається, динамічний масив розініціалізується — його доведеться ініціалізувати (визначати розмір) наново.

У динамічних масивах часто не відомо, скільки елементів в масиві.

Для визначення кількості елементів використовується функція UBound() (якщо масив одновимірний або вас цікавить розмір першого виміру, то вимір передавати не потрібно) :

UBound(ім'я_Масиву [, вимір])

Як не дивно, але при програмуванні в VBA вам рідко припаде стикатися з масивами. Замість них в об'єктних моделях додатків Office зазвичай використовуються колекції. Колекції — це спеціальні об’єкти, які призначені для зберігання наборів однакових елементів.

Наприклад, в Word передбачена колекція Documents для зберігання элементів Document, т. е. усіх відкритих документів, в Excel — колекції Workbooks (відкриті книги) і Worksheets (листи в книзі) і т. д. Колекції зазвичай зручніші, ніж масиви : вони спочатку безрозмірні і в них передбачений стандартний набір властивостей і методів: (метод Add() для додавання нового елементу, властивість Count для отримання інформації про кількість елементів, метод Item() для отримання посилання на потрібний елемент). Для багатьох коллекцій в об'єктних моделях окрім стандартних передбачений ще і набір специфічних властивостей і методів.

Приклад 4. Проаналізуйте роботу програм вводу масивів:

Sub InputFree()

Dim N, x() As Integer, inp As String

Range("a1:a100") = ""

N = 1

ReDim x(N)

Cells(1, 1) = "Введено вектор:"

Do

inp = InputBox("Елемент вектора (" _

& i & ")=?", "Ввід вектора")

If inp = "" Then Exit Do

x(N) = val(inp)

Cells(N + 1, 1) = x(N)

N = N + 1

ReDim x(N)

Loop While True

End Sub

Sub Vvid()

Dim N, i, x() As Integer, inp As String

Range("a1:a100") = ""

inp = InputBox("Кількість елементів в векторі ?", _

"Ввід розмірності вектора")

If inp = "" Then Exit Sub

N = val(inp)

ReDim x(N)

Cells(1, 1) = "Введено вектор:"

For i = 1 To N

inp = val(InputBox("Елемент вектора (" _

& i & ")=?", "Ввід вектора"))

'If inp = "" Then Exit Sub

x(i) = val(inp)

Cells(i + 1, 1) = x(i)

Next

End Sub

Приклад 5

Дано два цілі числа А і B (А < B). Вивести в порядку спадання всі цілі числа, розташовані між А і B, а також кількість N цих чисел.

Sub diap_zrost()

'опис змінних

Dim A, B As Single, x, Row, i As Integer

'ввід даних без прив'язки до конфігурації листка

A = Range("A") ' нижня межа

B = Range("B") ' верхня межа

' цикл значень x

Row = 5 'вибір початкової стрічки виводу

i = 0 'початковий номер значення аргументу

x = A ' початкове значення аргументу

Do While x <= B

i = i + 1 'встановлення номера побудованого значення

Cells(Row, 1) = "x" & i & "=" 'вивід повідомлення про знач. x

Cells(Row, 2) = x 'вивід значення x

Row = Row + 1 ' зміна стрічки виводу

x = x + 1

Loop

Cells(Row, 1) = "Кількість елементів=" & i

End Sub

Sub diap_spad()

'опис змінних

Dim A, B As Single, x, Row, i As Integer

'ввід даних без прив'язки до конфігурації листка

A = Range("A") ' нижня межа

B = Range("B") ' верхня межа

' цикл значень x

Row = 5 'вибір початкової стрічки виводу

i = 0 'початковий номер значення аргументу

x = B ' початкове значення аргументу

Do While x >= A

i = i + 1

Cells(Row, 1) = "x" & i & "=" 'вивід повідомлення про значення x

Cells(Row, 2) = x 'вивід значення x

Row = Row + 1 ' зміна стрічки виводу

x = x - 1

Loop

Cells(Row, 1) = "Кількість елементів=" & i

End Sub

Sub Och()

'очищення форми виводу

Range("A4:D100") = ""

End Sub

Sub diap()

'опис змінних

Dim A, B As Single, x, Row, i As Integer

'ввід даних

'перевірка коректності даних

A = Range("A")

B = Range("B")

If A > B Then

MsgBox "А має бути менше ніж В"

Else

' вхідні дані коректні

' цикл значень x

' виділення цілої частини числа В

x = B \ 1

' при округленні B до більшого зменшуємо x

If x > B Then x = x - 1

i = 0

Row = 5

'очищення форми виводу

Range("A4:D100") = ""

' цикл по значеннях аргументу

Do While x > A

Cells(Row, 1) = "x" & i & "="

Cells(Row, 2) = x

' зміна стрічки виводу

Row = Row + 1

' зміна номеру та значення аргументу

i = i + 1

x = x - 1

Loop

End If

Cells(Row, 1) = "Кількість елементів=" & i

End Sub

Приклад 6

Даний масив розміру N. Знайти його середнє значення

Sub Factor()

Dim N, i As Integer

Dim F0, F1 As Double

' ввід розмірності масиву

N = Range("N")

' очищення області виводу

For i = N + 4 To 40

Cells(i, 1) = ""

Cells(i, 2) = ""

Next

F0 = 1 'попереднє значення факторіала

For i = 1 To N

F1 = F0 * i

F0 = F1

Next

'вивід значення факторіала

Cells(5 + N, 1) = "N! = "

Cells(5 + N, 2) = F1

End Sub

Sub Dobutok()

Dim A(), N, i, D As Integer

' ввід розмірності масиву

N = Range("N")

' відведення пам'яті під масив

ReDim A(N)

' очищення області виводу

For i = N + 4 To 40

Cells(i, 1) = ""

Cells(i, 2) = ""

Next

' присвоєння значень елементам масиву

For i = 0 To N - 1

A(i) = Cells(4 + i, 1)

Next

D = 1 'попереднє значення добутку

For i = 0 To N - 1

D = D * A(i)

Next

'вивід значення добутку

Cells(5 + N, 1) = "Добуток елементів масиву = "

Cells(5 + N, 2) = D

End Sub

Sub SumMas()

Dim A(), i, S As Integer

' ввід розмірності масиву

N = Range("N")

' відведення пам'яті під масив

ReDim A(N)

' очищення області виводу

For i = N + 4 To 40

Cells(i, 1) = ""

Cells(i, 2) = ""

Next

' присвоєння значень елементам масиву

For i = 0 To N - 1

A(i) = Cells(4 + i, 1)

Next

' сума елементів масиву

S = 0

For i = 0 To N - 1

S = S + A(i)

Next

Cells(5 + N, 1) = "Cума елементів массиву="

Cells(5 + N, 2) = S

End Sub

Sub SumKvElMas()

Dim A(), i, El, S As Integer

' ввід розмірності масиву

N = Range("N")

' відведення пам'яті під масив

ReDim A(N)

' очищення області виводу

For i = N + 4 To 40

Cells(i, 1) = ""

Cells(i, 2) = ""

Next

' присвоєння значень елементам масиву

For i = 0 To N - 1

A(i) = Cells(4 + i, 1)

Next

' сума елементів масиву

S = 0

For i = 0 To N - 1

El = A(i)

S = S + El * El

Next

Cells(5 + N, 1) = "Cума квадр. елем. массиву="

Cells(5 + N, 2) = S

End Sub

Sub AvgMas()

Dim A(), i, S As Integer, AvgMas As Single

' ввід розмірності масиву

N = Range("N")

' відведення пам'яті під масив

ReDim A(N)

' очищення області виводу

For i = N + 4 To 40

Cells(i, 1) = ""

Cells(i, 2) = ""

Next

' присвоєння значень елементам масиву

For i = 0 To N - 1

A(i) = Cells(4 + i, 1)

Next

' сума елементів масиву

S = 0

For i = 0 To N - 1

S = S + A(i)

Next

' середнє значення елементів масиву

AvgMas = S / N

Cells(5 + N, 1) = "Середнє значення массиву="

Cells(5 + N, 2) = AvgMas

End Sub

Приклад 7

Даний масив розміру N. Знайти його максимальний елемент

Sub MaksElMas()

Dim A(), i, kmax, Amax As Integer

N = Range("N")

ReDim A(N)

For i = N + 4 To 40

Cells(i, 1) = ""

Cells(i, 2) = ""

Next

For i = 0 To N - 1

A(i) = Cells(4 + i, 1)

Next

kmax = 0

Amax = A(0)

For i = 0 To N - 1

If A(i) > Amax Then

Amax = A(i)

kmax = i

End If

Next

Cells(5 + N, 1) = "Максимальний елемент=" & Amax

Cells(6 + N, 1) = "Номер максимального елемента=" & kmax + 1

End Sub

Sub MaksParElMas()

Dim A(), i, kmax, Amax As Integer

N = Range("N")

ReDim A(N)

For i = N + 4 To 40

Cells(i, 1) = ""

Cells(i, 2) = ""

Next

For i = 0 To N - 1

A(i) = Cells(4 + i, 1)

Next

kmax = 0

i = 0

Do

If kmax = 0 Then

If A(i) Mod 2 = 0 Then

Amax = A(i)

kmax = i

End If

Else

If A(i) Mod 2 = 0 Then

If A(i) > Amax Then

Amax = A(i)

kmax = i

End If

End If

End If

i = i + 1

Loop While i < N

Cells(5 + N, 1) = "Максимальний елемент=" & Amax

Cells(6 + N, 1) = "Номер максимального елемента=" & kmax + 1

End Sub

Приклад 8

Даний масив розміру N. Знайти кількість його проміжків монотонності (тобто ділянок, на яких його елементи зростають або убувають )

Sub FindInterval()

Dim A(), i, kZrost, kSpad As Integer, fZrost, fSpad As Boolean

' ввід розмірності масиву

N = Range("N")

' відведення пам'яті під масив

ReDim A(N)

' очищення області виводу

For i = N + 4 To 40

Cells(i, 1) = ""

Cells(i, 2) = ""

Next

' присвоєння значень елементам масиву

For i = 0 To N - 1

A(i) = Cells(4 + i, 1)

Next

' присвоєння початкових значень ознакам та кількостям інтервалів монотонності

fZrost = False

kZrost = 0

fSpad = False

kSpad = 0

For i = 0 To N - 2

If A(i) < A(i + 1) And Not fZrost Then

'відкриття інтервалу зростання

fZrost = True

kZrost = kZrost + 1

fSpad = False

ElseIf A(i) > A(i + 1) And Not fSpad Then

'відкриття інтервалу спадання

fSpad = True

kSpad = kSpad + 1

fZrost = False

Else

' значення лементів масиву рівні

' закриття ынтервалів зростання та спадання

fSpad = False

fZrost = False

End If

Next

Cells(5 + N, 1) = "Кількість інтервалів монотонності"

Cells(6 + N, 1) = "K зростання="

Cells(6 + N, 2) = kZrost

Cells(7 + N, 1) = "K спадання="

Cells(7 + N, 2) = kSpad

End Sub

Приклад 9 розв’язання задачі на VBA.

Дано дійсне числа А<B,H і ціле число N (> 0). Знайти значення виразу X - X3/(3!) + X5/(5!) - . + (-1)N·X2·N+1/((2·N+1)!) для в порядку убуваня значень x з кроком H.

План розв’язання задачі.

Необхідно організувати цикл по умові для обчислення значень Х, для кожного з яких здійснювати вивід значення виразу. Для обчислення значення виразу необхідно організувати цикл сумування. Оскільки сумуються вирази із степенями та факторіалами для їх обчислення необхідно побудувати рекурентні формули.

Відкриваємо нову книгу в Excel і зберігаємо її.

Створюємо шаблон макросу (Сервіс – макрос – макроси – ім’я макросу – IND_test (наприклад) - создать

Формуємо сторінку інтерфейсу програми та іменуємо поля вводу:

Призначаємо кнопці обчислень створений макрос.

Копіюємо в макрос схему його виконання у вигляді коментарів.

Будуємо рекурентну формулу обчислень елементів суми

Формуємо текст програми

Sub IND_test()

'опис змінних

Dim A, B, H, x, S, AA As Single, N, i As Integer

'ввід даних

'перевірка коректності даних

A = Range("A")

B = Range("B")

H = Range("H")

N = Range("N")

'MsgBox "A=" & A

'MsgBox " B=" & B

'MsgBox " H=" & H

'MsgBox " N=" & N

If A > B Then

MsgBox "А має бути менше ніж В"

ElseIf H < 0 Then

MsgBox "H має бути > 0"

ElseIf N < 0 Then

MsgBox "N має бути > 0"

Else

' вхідні дані коректні

' цикл значень x

x = B

i = 0

Row = 8

'очищення форми виводу

Range("A8:D100") = ""

' цикл по значеннях аргументу

Do While x > A

Cells(Row, 1) = "x" & i & "="

Cells(Row, 2) = x

'формування і вивід результату

'початкове значення суми

S = x

' початкове значення доданку

AA = 1

For j = 1 To N

' рекурентне обчислення доданку

AA = AA * (-x ^ 2) / ((2 * j + 2) * (2 * j + 3))

' поновлення значення суми

S = S + AA

Next

' вивід результату для даного аргументу

Cells(Row, 3) = "y" & i & "="

Cells(Row, 4) = S

' зміна стрічки виводу

Row = Row + 1

' зміна номеру та значення аргументу

i = i + 1

x = x - H

Loop

End If

End Sub

8. Процедури і функції

8.1. Види процедур

Процедури — це найважливіші функціональні блоки мови VBA. У VBA ви можете виконати тільки той програмний код, який міститься в якій-небудь процедурі (звичайній в стандартному модулі, подієвій для елементу управління на формі і т. п.). Іноді початкуючі користувачі пробують записати команди прямо в область оголошень стандартного модуля і не можуть зрозуміти, чому вони не виконуються (повідомлення про помилку при цьому не видається — просто цей код стає "невидимий" для компілятора).

Причина проста: в розділі оголошень модуля (коли у верхніх списках редактора кода показуються значення General і Declarations) можуть бути тільки оголошення змінних рівня модуля і деякі спеціальні інструкції для компілятора. Увесь інший програмний код повинен знаходитися усередині процедур.

У VBA передбачені наступні типи процедур :

ˆ процедура типу Sub (підпрограма) — універсальна процедура для виконання деяких дій :

Sub Farewell()

MsgBox "Goodbye"

End Sub

Макрос в VBA — це процедура типу Sub, що не має параметрів. Тільки макроси можна викликати по імені з редактора VBA або з додатка Office. Усі інші процедури треба викликати або з інших процедур, або спеціальними способами, про які буде розказано далі; ˆ процедура типу Function (функція) — набір команд, які повинні бути виконані. Принципова відмінність тільки одно: функція повертає програмі (чи процедурі), що викликала її, якесь значення, яке буде там використано. Приклад функції :

Function Tomorrow()

Tomorrow = DateAdd("d", 1, Date())

End Function

і приклад її виклику :

Private Sub Test1()

Dim dDate

dDate = Tomorrow()

MsgBox dDate

End Sub

У тексті функції необхідно передбачити оператор, який присваи-вает їй яке-небудь значення. У нашому випадку це рядок:

Tomorrow = DateAdd("d", 1, Date())

В принципі, процедури типу Sub теж можуть повертати значення — при допомозі змінних, що передаються по посиланню. Навіщо ж тоді потрібні функції? Усе дуже просто: функцію можна вставляти практично в будь-яке місце програмного коду. Наприклад, наш останній приклад може виглядати набагато простіше:

Private Sub Test1()

MsgBox Tomorrow()

End Sub

У VBA передбачені сотні вбудованих функцій (і набагато більшу кількість функцій передбачено в об'єктних моделях додатків Office). Навіть у нашому прикладі використовуються дві вбудовані функції: Date(), яка повертає поточну дату по годиннику комп'ютера, і DateAdd(), яка уміє додавати до поточної дати певну кількість днів, тижнів, місяців, років і т. д. У VBA є також процедури обробки подій (event procedure) процедури типу Sub спеціального призначення, які виконується у випадку виникнення певної події, наприклад, при відкритті форми або натисненні на ній кнопки.

Є ще процедури типу Property (процедури властивості). Вони потрібні для визначення властивостей створюваного вами класу.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]