Информатика VBA. Учебное пособие по дисциплинам Информатика иИнформационные технологии
Скачать 1.05 Mb.
|
Next a End Sub 65 Рисунок 4.5 - Графики функции r=|20+a|cos 2 φ - sin 2 φ| | в виде «Точечной» диа- граммы 66 5 Обработка массивов данных Массив- это множество скалярных данных с одинаковыми па- раметрами типа, элементы которого упорядочены по прямоугольной схеме. Скалярные объекты, образующие массив, являются элемен- тами массива. Имя массива образуется в соответствии с общими правилами образования имен в VBA и определяет адрес первой ячей- ки участка памяти, хранящего числовые значения массива. Для ука- зания конкретного элемента массива используется переменная с ин- дексом. Индексированная переменная состоит из имени и списка ин- дексов, однозначно задающих местоположение элемента в массиве. Например, ALFA(3), X(3,5), MASSIV(L,M+2). Список индексов - это обычно целые числа или переменные, от- деленные друг от друга запятыми и заключенные в скобки. Допусти- мо также в качестве индекса использовать любое арифметическое выражение. Результат вычисления при наличии дробной части преоб- разуется к целому числу по законам алгебраического округления. На- пример: если в программе встречается ссылка на элемент массива A(R+T), то при R=2.3 и T=3.2 он будет рассматриваться как элемент A(6), а если T=3.1, то рассматриваться будет элемент A(5). Количество индексов в массиве определяет его размерность, и массивы могут быть, соответственно, одномерными, двумерными, трехмерными и т.д. Например: X(k), M2(ind), Primer(i+2*l) - обозна- чают элементы одномерных массивов; Mas(i, j), R(2, 5) обозначают элементы двумерных массивов. В VBA используются статические и динамические массивы. При определении статического массива указывается его количество эле- ментов. Размер резервируемой области памяти для хранения значения статического массива зависит от типа и количества элементов в мас- сиве. Для динамически размещаемых массивов место в оперативной памяти отводится в момент выполнения программы. 67 Тип элементов массива определяется теми же способами, что и тип простой переменной с помощью операторов Dim или Public. Но при объявлении статических массивов необходимо определить раз- мерность и количество элементов в массиве, для динамических мас- сивов объявляется только размерность массива, а количество элемен- тов определяется позже оператором ReDim. При объявлении количе- ства элементов массива можно в круглых скобках после имени ука- зать только верхнее значение индекса. Нижнее значение индекса бу- дет считаться нулевым. Так, оператор Dim Array(50) As Single, Var2() As Single, M(3,4) As Integer объявляет одномерный статический массив вещественного типа Array , содержащем 51 элемент (индексы элементов должны быть в диапазоне от 0 до 50), динамический массив вещественного типа с именем Var2 и двумерный массив М целого типа, содержащем 20 элементов (4 строки и 5 столбцов). Если нижней индекс массива отличается от нуля, то при объяв- лении массива необходимо указать диапазон индексов: Dim Array1(1 To 10) As Single, Mas(1 To 3 , 1 To 4) As Integer Этим оператором объявлены статические массивы Array1 веществен- ного типа из десяти элементов и целочисленный двумерный массив Mas из 12-ти элементов (3 строки и 4 столбца). При задании диапазо- на индексов допускается использование отрицательных констант. Ес- ли же первый индекс всех массивов должен быть равен единице, то перед первой процедурой модуля можно добавить следующее объяв- ление: Option Base l и при объявлении количества элементов массива не задавать нижнее значение индекса. Следует иметь в виду, что задавать размерность необходимо для всех массивов, используемых в программе, причем размерность ста- 68 тического массива может быть задана только один раз. Оператор объ- явления массива должен располагаться в начале программы до перво- го выполняемого оператора. Массив размещается в последовательно расположенных ячейках памяти. Если массив одномерный, то его элементы хранятся в памяти друг за другом, например, A(1), A(2), A(3), ... Количество элементов и размерность динамического массива объявляется внутри программы до первого его использования опера- тором ReDim, который имеет синтаксис, аналогичный оператору Dim. Для динамических массивов допустимо изменять как диапазон индек- сов, так и размерность массива. При этом, если изменяется только верхний индекс массива (для многомерных массивов только верхнее значение последнего индекса), то старые значения массива можно со- хранить добавлением в оператор ReDim опции Preserve. В приведен- ном ниже примере показаны различия в полученном результате для одинаковых программ с использованием опции Preserve и без нее. Пример 5.1. Вариант программы с опцией Preserve Вариант программы без опции Preserve Sub tt() Sub tt() Dim m() As Single Dim m() As Single ReDim m(1 To 3) ReDim m(1 To 3) m(1) = 1 : m(2) = 1.2 : m(3) = 1.3 m(1) = 1 : m(2) = 1.2 : m(3) = 1.3 ReDim Preserve m(1 To 5) ReDim m(1 To 5) m(4) = 1.4 : m(5) = 1.5 m(4) = 1.4 : m(5) = 1.5 For Each a In m For Each a In m Debug.Print a Debug.Print a Next Next End Sub End Sub 69 Результат, выведенный в окно отладки с опцией Preserve без опциии Preserve 1 1,2 1,3 1,4 1,5 0 0 0 1,4 1,5 5.1 Ввод-вывод массивов Задать значения элементам массива можно следующими спосо- бами: с помощью арифметического оператора присваивания (см. про- грамму предыдущего примера); из текстового файла оператором ввода Input; через диалоговые окна Excel; из ячеек активного листа рабочей книги Excel. Ввод значений элементов массива из текстового файла органи- зуют с использованием оператора ввода Input. При вводе (или выво- де) массивов используются два основных способа: ввод-вывод стати- ческого массива с заранее известным числом элементов и ввод-вывод динамического массива, число элементов в котором определяется в момент выполнения программы. Пример 5.2. Ввести и вывести в текстовый файл элементы мас- сива вещественного типа из 10-ти элементов. Исходные данные по- мещаются в текстовом файле с именем «dat.txt», а в файл вывода с именем «res.txt» выводим массив по пять чисел в строке. Предполага- ем, что в качестве разделителя целой и дробной части чисел в файле «dat.txt » используется символ «точка». Sub Пример_5_2() Dim Mas(1 To 10) As Single 70 Dim i As Integer Open "dat.txt" For Input As #1' открываем файла для ввода Open "res.txt" For Output As #2 ' открываем файла для вывода Print #2, " Введенный массив Mas(10)" For i = 1 To 10 If EOF(1) = True Then ' проверяем - достигли конца файла или нет ' конец файла достигнут, а данных меньше 10. Сообщаем об ошибке MsgBox "В файле ""dat.txt"" всего " & i-1 & " чисел - ОШИБКА" Exit For End If Input #1, Mas(i) ' считываем из файла очередное число Print #2, Mas(i), ' выводим число, но не заканчиваем строку вывода If Int(i/5)*5 = i Then Print #2, Chr(13) ' Заканчиваем вывод строки ' из 5-ти элементов Next Close ' оператор Close без параметров закрывает оба открытых файла End Sub Расположение данных в файле "dat.txt" 1.1 1.2 1.3 1.4 5 6 -7.7 -8 9 10 Расположение данных в файле "res.txt" Введенный массив Mas(10) 1,1 1,2 1,3 1,4 5 6 -7,7 -8 9 10 71 Результат работы программы не изменится, если в файле "dat.txt" данные расположить по пять чисел в строке: 1.1 1.2 1.3 1.4 5 6 -7.7 -8 9 10 . Однако если в файле исходных данных будут пустые строки, то эти строки будут восприняты как нулевые значения очередных эле- ментов. Символ «запятая» в данных воспринимается как разделитель между числами. Поэтому если задать числа с десятичной запятой ме- жду целой и дробной частью числа – будут прочитаны два целых чис- ла. При этом оператор Print выводит дробные числа с разделителем за- пятая. Если в файле «dat.txt» окажется меньше 10 чисел, то на актив- ный лист Excel будет выведено диалоговое окно с сообщением об ошибке, а в файле «res.txt» будут напечатаны прочитанные числа. Ес- ли же в файле будет больше 10 чисел, то будут обработаны только первые 10. Таких проблем можно избежать, если в программе использовать не статический, а динамический массив. Пример 5.3. Прочитать данные из файла в массив и определить количество элементов в массиве. Sub Пример_5_3() Dim Mas() As Single 'объявляем динамический массив вещественного типа Dim i As Integer ' рабочая переменная целого типа Dim kol As Integer ' переменная для определения количества чисел в файле Open "dat.txt" For Input As #1 ' открываем файла для ввода ' первое чтение файла для определения количества чисел в массиве kol = 0 ' обнуляем переменную Kol Do ' начинаем "бесконечный" цикл If EOF(1)=True Then Exit Do ' достигнут конец файла - выход из цикла kol = kol + 1 ' подсчитываем количество прочитанных данных ReDim Preserve Mas(1 To kol) ' увеличиваем размер динамического ' массива с сохранением ранее введенной информации 72 Input #1, Mas(kol) ' считываем из файла очередное число в массив Loop Close #1 ' закрываем файл dat.txt Open "res.txt" For Output As #2 ' открываем файла для вывода Print # 2, "Введенный массив содержит " & kol & " элементов" For i = 1 To kol Print #2, Mas(i), ' выводим число, но не заканчиваем строку вывода If Int(i / 5) * 5 = i Then Print #2, Chr(13) ' Если переменная i кратна пяти – выводим в строку вывода ' символ «конец строки» Next i Close #2 ' закрываем файл res.txt End Sub При чтении файла «dat.txt» из предыдущего примера располо- жение данных в файле «res.txt» будет следующим Введенный массив содержит 10 элементов 1,1 1,2 1,3 1,4 5 6 -7,7 -8 9 10 Одним из способов ввода данных в программу является ввод элементов массива с использованием диалоговых окон Excel. При ис- пользовании статического массива число его элементов должно быть заранее известно. Для динамического массива в начале работы про- граммы необходимо запросить количество элементов в массиве, а за- тем организовать ввод числовых данных. Пример 5.4. Ввести одномерный массив через диалоговое окно Excel. Вывести элементы массива в первый столбец активного листа рабочей книги Excel. Sub Пример_5_4() '********************************************** ' Ввод массива с клавиатуры '********************************************** Dim A() As Single ' объявляем динамический массив вещественного типа Dim N As Integer ' переменная для количества элементов в массиве 73 ' выводим в ячейку А1 заголовок Worksheets ("Лист1").Cells(1, 1) = "Массив А:" N = Val(InputBox( "Введите количество элементов массива")) ReDim A(1 To N) ' задаем размер массива А For i = 1 To N A(i) = Val(InputBox( "Введите A(" & i & ")", _ "Осталось ввести " & N - i + 1 & " элемент(ов/а)")) Cells(i + 1, 1) = A(i) Next End Sub Программа выводит в ячейку «А1» первого листа таблицы Excel заголовок «Массив А:», затем запрашивает количество элементов в массиве (рисунок 5.1). После определения количества элементов в массиве для данного сеанса работы, программа в цикле запрашивает ввод очередного числа, указывая в заголовке диалогового окна коли- чество элементов, которое осталось ввести (рисунок 5.2). При этом пользователь видит в первом столбце таблицы Excel ранее введенные значения. Рисунок 5.1 – Запрос на задание числа элементов в массиве Рисунок 5.2 – Запрос на ввод очередного элемента массива 74 Однако наиболее удобным способом ввода данных в VBA явля- ется ввод информации непосредственно из таблицы Excel, где и хра- нится сама программа. Обмен данными с таблицей выполняется ко- мандой Cells(i,j). Пример 5.5. Ввести массив данных их первого столбца активно- го листа рабочей книги Excel. Вывести полученные данные в тексто- вый файл. Sub Пример_5_5() Dim Mas() As Single 'объявляем динамический массив Dim i As Integer ' рабочая переменная целого типа Dim kol As Integer ' количество чисел в файле kol = 0 ' обнуляем переменную kol Do Until Cells(kol + 1, 1) = Empty ' выполняем цикл, пока есть данные kol = kol + 1 ' подсчитываем количество прочитанных данных ReDim Preserve Mas(1 To kol) ' увеличиваем размер массива ' с сохранением ранее введенной информации Mas(kol) = Cells(kol, 1) 'считываем из таблицы очередное число Loop Open "res.txt" For Output As #2 ' открываем файла для вывода Print # 2, "Введенный массив содержит " & kol & " элементов" For i = 1 To kol Print #2, Mas(i), ' выводим число, но не заканчиваем строку вывода If Int( i / 5) * 5 = i Then Print #2, Chr(13) ' Заканчиваем вывод ' строки из 5-ти элементов Next i If Int(kol / 5) * 5 = kol Then Print #2, Chr(13) ' заканчиваем строку, ' если kol не кратен пяти Close ' закрываем файл res.txt End Sub Программа просматривает первый столбец активного листа таб- лицы Excel. В данной программе при использовании метода Cells не используется объект Worksheets("Лист1"), что позволяет обращаться к активному листу, какое бы имя у него не было. Цикл, заданный оператором Do Until, продолжается до тех пор, пока в первом столб- 75 це таблицы не встретится пустая ячейка. Если необходимо обрабо- тать только часть таблицы Excel, следует использовать цикл вида For Each Элемент_массива In Selection , выделив предварительно нужную группу данных. Программа в таком варианте ввода может иметь следующий вид. Sub Пример_5_5б() Dim Mas() As Single 'объявляем динамический массив веществ. типа Dim Elem ' переменная для обозначения элемента выделенной группы Dim i As Integer ' рабочая переменная целого типа Dim kol As Integer ' переменная для количества чисел в массиве kol = 0 ' обнуляем переменную Kol For Each Elem In Selection kol = kol + 1 ' подсчитываем количество прочмтанных данных ReDim Preserve Mas(1 To kol) ' увеличиваем размер массива ' с сохранением ранее введенной информации Mas(kol) = Elem ' записываем в массив очередное число изгруппы Debug.Print "Mas(";kol;")=";Mas(kol) ' контрольный вывод в окно отладки Next . . . ' продолжение программы Следует отметить, что, если на активном листе таблицы Excel не будет выделена группа чисел, то будет прочитан массив из одного элемента с нулевым значением. 5.2 Программирование обработки одномерных массивов Обработка массивов может выполняться по следующей схеме: - ввод и контрольный вывод массива; - обработка элементов массива; - вывод полученного результата. Варианты ввода и контрольного вывода массива были рассмотрены выше. Обработка массива может выполняться по двум схемам - полная выборка элементов массива и частичная выборка элементов массива. 76 При полной выборке обрабатываются все элементы массива без ис- ключения. При частичной выборке – обрабатываются только элемен- ты массива, отвечающим заданным условиям. В полной выборке мас- сива всегда будет получен результат. В случае частичной выборки ре- зультат может быть не получен по той простой причине, что в масси- ве может не оказаться элементов, удовлетворяющих заданным требо- ваниям. Поэтому при частичной выборке перед выводом результата необходим дополнительный анализ – получен результат или нет. В задачах на частичную выборку последовательно анализирует- ся каждый элемент массива. Встречаются три вида анализа: 1. Проверка знака элемента массива – положительный, отрицатель- ный или нулевой элемент. Анализ осуществляется оператором If, в котором очередной элемент массива сравнивается с нулем If mas(i) < = > 0 Then Знаку «больше» соответствуют положительные числа, знаку «меньше» – отрицательные числа, знак «равно» определяет нуле- вые элементы массива. 2. Проверка наличия или отсутствия дробной части у элемента мас- сива. Оператор If, для такого анализа может использовать функ- цию int() – определения целой части числа If int(mas(i)) <> = mas(i) |