Работа с коллекциями классов
Одна из самых замечательных идей (правил) в объектно-ориентированном программировании является абстрагирование. При соблюдении этого правила, мы отдаляемся от кода и работаем с объектами, их свойствами, методами, как будто они существуют в нашем, физическом мире. Главное, что отличает класс от процедуры – возможность одновременного запуска нескольких экземпляров класса. Например, на основе класса «Cat» (Кот) можно создать несколько объектов и задать различные значения свойствам «Name» (Имя) и «Color» (Окраска). Для простой демонстрации создадим класс Cat с перечисленными ранее свойствами: Код класса: view plainprint? 1. Option Explicit 2. Private NValue As String 3. Private CValue As String 4. 5. Property Let Name(NameValue As String) 6. NValue = NameValue 7. End Property 8. 9. Property Get Name() As String 10. Name = NValue 11. End Property 12. 13. Property Let Color(ColorValue As String) 14. CValue = ColorValue 15. End Property 16. 17. Property Get Color() As String 18. Color = CValue 19. End Property Код вызова класса в модуле: view plainprint? 1. Sub TestCat() 2. Dim Kity As Cat 3. Set Kity = New Cat 4. Kity.Color = "Рыжий" 5. Kity.Name = "Барсик" 6. Debug.Print Kity.Color, Kity.Name 7. End Sub В примере выше создан объект Kity на основе класса Cat. Свойствам объекта задали значения. Создадим массив объектов на основе класса Cat (стаю котов): view plainprint? 1. Sub ManyCats() 2. Dim Cats(1 To 3) As Cat’объявляем массив типа Cat 3. Dim i As Integer 4. For i = 1 To 3 5. Set Cats(i) = New Cat’создаем объект и присваиваем значению массива 6. Next i 7. Cats(1).Color = "Белый"’задаем значения свойства 8. Cats(2).Color = "Рыжий" 9. Cats(3).Color = "Серый" 10. For i = 1 To 3 11. Debug.Print Cats(i).Color’читаем свойство 12. Next i 13. End Sub Никто не запрещает создать многомерный массив… Все отлично. Мы создали стаю котов из 3 штук, читаем и задаем их свойства по индексу массива. Но чтобы добавить еще одного кота, необходимо переобъявлять массив, а для удаления кота присвоить значение Nothing. Добавление объекта в массив будет выглядеть так: view plainprint? 1. Dim Cats() As Cat 'обратите внимание, объявляем массив без размера 2. Dim i As Integer 3. ReDim Cats(1 To 3) As Cat 'меняем размер первый раз 4. For i = 1 To 3 5. Set Cats(i) = New Cat 'заполняем 6. Next i 7. Cats(1).Color = "Рыжий" 'задаем свойства 8. Cats(2).Color = "Серый" 9. Cats(3).Color = "Белый" 10. ReDim Preserve Cats(1 To 4) As Cat 'меняем размер второй раз 11. Set Cats(4) = New Cat 'заполняем 12. Cats(4).Color = "Дымчатый" 'задаем свойства 13. For i = 1 To 4 14. Debug.Print Cats(i).Color 'читаем 15. Next i А при удалении объекта из массива нужно быть осторожным: view plainprint? 1. Dim Cats(1 To 3) As Cat 'объявляем массив 2. Dim i As Integer 3. For i = 1 To 3 4. Set Cats(i) = New Cat 'заполняем 5. Next i 6. Cats(1).Color = "Рыжий" 'задаем свойства 7. Cats(2).Color = "Серый" 8. Cats(3).Color = "Белый" 9. Set Cats(2) = Nothing 'удаляем объект из массива 10. Debug.Print Cats(1).Color 'читаем по отдельности 11. ' Debug.Print Cats(2).Color потому что здесь будет ошибка. Объекта нет... 12. Debug.Print Cats(3).Color В данном случае мы не изменяем размерность массива, просто присваиваем объекту значение Nothing. Если нужно пройти по всем объектам массива и прочитать их свойства, можно воспользоваться циклом For Each…Next. view plainprint? 1. Dim Cats(1 To 3) As Cat 'объявляем массив 2. Dim i As Integer 3. For i = 1 To 3 4. Set Cats(i) = New Cat 'заполняем 5. Next i 6. Cats(1).Color = "Рыжий" 'задаем свойства 7. Cats(2).Color = "Серый" 8. Cats(3).Color = "Белый" 9. Dim c As Variant 'объявляем переменную как вариант (как cat не пройдет) 10. For Each c In Cats 'проходим по массиву 11. Debug.Print c.Color 'читаем свойство 12. Next c Однако не следует забывать, что переменная, с помощью которой проходим по массиву должна иметь тип Variant. Хороший способ использования нескольких одинаковых объектов, это объединить их в коллекцию. Коллекция это объект, построенный на основе класса Collection, предназначенный для хранения данных (в том числе и других объектов). Он очень похож на одномерный массив. Индекс коллекции всегда начинается с 1. Свойства объекта Collection: Count – содержит число элементов (Item) коллекции. Item(index) – возвращает значение элемента (объект) по его индексу. Свойство также может вернуть значение по ключу. Об этом ниже… Методы: Add(Item, [Key], [Before], [After]) – Добавляет элемент в коллекцию. Параметр Item должен содержать добавляемое значение или объект. Это обязательный параметр. Остальные параметры не являются обязательными: Key – строковый ключ для элемента. Он должен быть уникальным. After и Before – выражение, указывающее перед каким или после какого элемента вставить новый. Если параметры числовые, они могут принимать значения от 1 до Count и вставка пройдет по индексу элементов, если параметры строковые, они должны содержать существующие названия ключей, и вставка будет происходить по ключам. Нельзя указывать два этих параметра сразу, только по отдельности. Ну как тут не вспомнить о коллекции Sheets… Вот пример создания коллекции и добавление элементов: view plainprint? 1. Dim i As Integer 2. Dim Cats As Collection 'объявляем коллекцию 3. Set Cats = New Collection 'создаем коллекцию 4. For i = 1 To 3 5. Cats.Add Item:=New Cat, Key:="Cat_" & i 'добавляем в коллекцию объекты 6. Next i 7. 8. Cats(1).Color = "Рыжий" 'задаем свойства 9. Cats(2).Color = "Белый" 10. Cats(3).Color = "Черный" 11. 12. Debug.Print Cats.Item("Cat_1").Color 'читаем свойства 13. Debug.Print Cats.Item(2).Color 14. Debug.Print Cats("Cat_1").Color 15. 16. Dim c As Cat 'еще способ читать свойства 17. For Each c In Cats 18. Debug.Print c.Color 19. Next c Очень интересная вещь: при использовании конструкции For Each…Next, переменная c объявлена как Cat, а это означает ,что при написании кода, нам доступен просмотр свойств и методов класса cat. Это удобно. Вот пример удаления объекта из коллекции: view plainprint? 1. Dim i As Integer 2. Dim Cats As Collection 'объявляем коллекцию 3. Set Cats = New Collection 'создаем коллекцию 4. For i = 1 To 3 5. Cats.Add Item:=New Cat, Key:="Cat_" & i 'добавляем в коллекцию объекты 6. Next i 7. 8. Cats(1).Color = "Рыжий" 'задаем свойства 9. Cats(2).Color = "Белый" 10. Cats(3).Color = "Черный" 11. 12. Cats.Remove 2 'Удаляем второй объект из коллекции 13. ' Cats.Remove ("Cat_2") 'по ключу удалять так же можно 14. Dim c As Cat 'еще способ читать свойства 15. For Each c In Cats 16. Debug.Print c.Color 17. Next c 18. Debug.Print Cats("Cat_3").Color 'число объектов изменилось и обращаться к ним лучше по ключам При удалении объектов из коллекции меняется свойство Count. В работе с коллекциями мне больше всего нравиться использование ключей. view plainprint? 1. Dim i As Integer 2. Dim c As Cat 3. Dim Cats As Collection 'объявляем коллекцию 4. Set Cats = New Collection 'создаем коллекцию 5. Set c = New Cat 6. c.Name = "Барсик" 7. Cats.Add Item:=c, Key:=c.Name 'добавляем в коллекцию объекты 8. Set c = New Cat 9. c.Name = "Дымок" 10. Cats.Add Item:=c, Key:=c.Name 11. Set c = New Cat 12. c.Name = "Ушлепок" 13. Cats.Add Item:=c, Key:=c.Name 14. 15. Cats("Дымок").Color = "Дымчатый" 'обращаемся к элементу коллекции по ключу 16. Debug.Print Cats("Дымок").Color То есть даже, если число элементов изменится, всегда можно достучаться до нужного элемента по его ключу. Создание класса со свойством, содержащим коллекцию В файле csvDataLoader.zip предложено практическое применение вышеописанной теории с котиками. Только вместо котиков ячейки. Некоторые программы создают в результате своей деятельности файлы *.csv, которые содержат строки, в которых данные разделены запятыми. Я не нашел способа доступа к данным по номеру строки и столбца в vba, пришлось сделать самому. В примере создано подобие объектной модели для таких файлов, то есть адаптер для доступа к данным. Можно получать доступ к данным по номеру строки и столбца. Более того, в объектную модель можно загрузить несколько файлов и доступ будет осуществляться по имени файла (индексу), номеру строки и столбца. То есть получается фактически аналог книги Excel. Конечно, пример только учебный, в нем нет обработки ошибок, проверки многих исключений, не реализован поиск. Хорошо бы реализовать запись данных по индексам. Но пример этот хорошо демонстрирует способы работы с коллекциями и массивами объектов, построенных на основе собственных классов. Так же демонстрирует способ разработки внятной объектной модели, которая не реализована в Excel изначально. Подобные адаптеры для доступа к данным можно создать для любых типов файлов, в том числе и для пользовательских бинарных форматов, особенно, если планируется часто работать с ними. Кстати вот поиск для нашего адаптера: view plainprint? 1. Public Function SearchFirstCell(Data As String, Optional Column As Long = 0) As Cell 2. Dim r As Long 3. Dim c As Long 4. Dim cl As Cell 5. Select Case Column 6. Case 0 7. For r = 1 To UBound(DataArray, 1) 8. For c = 1 To UBound(DataArray, 2) 9. If DataArray(r, c).Value = Data Then 10. Set SearchFirstCell = DataArray(r, c) 11. Exit Function 12. End If 13. Next c 14. Next r 15. Case Else 16. For r = 1 To UBound(DataArray, 1) 17. If DataArray(r, Column).Value = Data Then 18. Set SearchFirstCell = DataArray(r, Column) 19. Exit Function 20. End If 21. Next r 22. End Select 23. Set cl = New Cell 24. cl.Value = "Указанное значение не найдено" 25. Set SearchFirstCell = cl 26. End Function Метод осуществляет точный поиск первой ячейки. Требует указания искомого значения. Параметр столбец является необязательным. При его указании поиск осуществляется только по указанному столбцу. Метод возвращает объект. Пример использования: view plainprint? 1. Debug.print DataReader. SearchFirstCell("202”).Row Найдет ячейку, содержащую значение 202 и вернет ее номер строки. |
Скачано с www.znanio.ru
Материалы на данной страницы взяты из открытых источников либо размещены пользователем в соответствии с договором-офертой сайта. Вы можете сообщить о нарушении.