Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Microsoft Office и VBA программирование > Microsoft Office Excel
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.04.2011, 09:28   #1
hoza
Новичок
Джуниор
 
Регистрация: 13.04.2011
Сообщений: 6
По умолчанию Коллекции и пользовательские типы данных

Здравствуйте.
У меня такая проблема:
есть лист с некими данными. Требуется создать 4 коллекции (по количеству смен). Почему-то не получается "запихать" в коллекцию пользовательские типы данных.
Код:
Private Type record
    data As Date
    nom As String
    podr As String
    uch As String
    dol As String
    fio As String
    ktu As Double
    pai As Double
    otrab As Double
    prem As Double
    straf As Double
    ves As Double
    vyp As Double
    paichas As Double
    zp As Double
End Type
Public Sub fill()
Dim rec As record
Dim smena1 As New Collection
Dim smena2 As New Collection
Dim smena3 As New Collection
Dim smena4 As New Collection
    y = 5
    smena = Cells(y, 3)
    Do
        With rec
            .data = Cells(y, 1)
            .nom = Cells(y, 2)
            .podr = Cells(y, 3)
            .uch = Cells(y, 4)
            .dol = Cells(y, 5)
            .fio = Cells(y, 6)
            .ktu = Cells(y, 7)
            .pai = Cells(y, 8)
            .otrab = Cells(y, 9)
            .prem = Cells(y, 10)
            .straf = Cells(y, 11)
            .ves = Cells(y, 12)
            .vyp = Cells(y, 13)
            .paichas = .ktu * .pai * .otrab
        End With
        If smena = "áðèãàäà 1" Then smena1.Add (rec)
        y = y + 1
        smena = Cells(y, 3)
    Loop While smena <> ""
End Sub
В чём может быть дело?
hoza вне форума Ответить с цитированием
Старый 13.04.2011, 09:41   #2
EducatedFool
Программист VBA
СуперМодератор
 
Аватар для EducatedFool
 
Регистрация: 13.07.2008
Сообщений: 6,856
По умолчанию

Цитата:
Почему-то не получается "запихать" в коллекцию пользовательские типы данных.
Увы, не получится никак - VBA не позволит.

Вместо пользовательских типов данных используйте классы - а экземпляры класса помещайте в коллекцию.
EducatedFool вне форума Ответить с цитированием
Старый 13.04.2011, 09:45   #3
hoza
Новичок
Джуниор
 
Регистрация: 13.04.2011
Сообщений: 6
По умолчанию

А как этот код можно переписать с помощью классов? И как потом с ними работать?
hoza вне форума Ответить с цитированием
Старый 13.04.2011, 09:54   #4
EducatedFool
Программист VBA
СуперМодератор
 
Аватар для EducatedFool
 
Регистрация: 13.07.2008
Сообщений: 6,856
По умолчанию

Я в таких случаях сначала добавляю модуль класса примерно такого содержания:
(к примеру, назвал я этот класс NoticeFlat)

Код:
Public ДатаПубликации As Date
Public ТипНедвижимости As String, Город As String, Район As String
Public КоличествоКомнат As String, Этаж As Integer, Этажность As Integer
Public ВидДома As String, ТипДома As String, Адрес As String
Public ПлощадьОбщая As Double, ПлощадьЖилая As Double, ПлощадьКухня As Double
Public ОпцияБалкон As Boolean, ОпцияЛоджия As Boolean, ОпцияЛифт As Boolean, ОпцияТелефон As Boolean
Public Цена As Long

Public PublishInterval As String
Public Comment As String

Sub ReadFromRow(ByRef ro As Range)
    On Error Resume Next
    With ro
        ДатаПубликации = .Cells(1)
        ТипНедвижимости = .Cells(2)
        Город = .Cells(3)
        Район = .Cells(4)
        КоличествоКомнат = .Cells(5)
        Этаж = .Cells(6)
        Этажность = .Cells(7)
        ВидДома = .Cells(8)
        ТипДома = .Cells(9)
        Адрес = .Cells(10)
        ПлощадьОбщая = .Cells(11)
        ПлощадьЖилая = .Cells(12)
        ПлощадьКухня = .Cells(13)
        ОпцияБалкон = Len(Trim(.Cells(14))) > 0
        ОпцияЛоджия = Len(Trim(.Cells(15))) > 0
        ОпцияЛифт = Len(Trim(.Cells(16))) > 0
        ОпцияТелефон = Len(Trim(.Cells(17))) > 0
        Цена = .Cells(18)
        Comment = .Cells(19)
    End With
End Sub
А потом создаю экземпляры этого класса, и добавляю их в коллекции:
(кодом из стандартного модуля)

Код:
Sub SendNotices()
    Dim Notices As New Collection    ' создаём пустую коллекцию
    Dim Notice As NoticeFlat    ' имя созданного класса
    Set ra = Intersect(Selection.EntireRow, Selection.EntireRow, Range("3:65536"))

    For Each ro In ra.Rows  ' перебираем выделенные строки на листе
        
        Set Notice = New NoticeFlat    ' создаём экземпляр класса
        Notice.ReadFromRow ro    ' считываем данные из ячеек
        res = Notice.SendToWebsite(IE, 5)    ' делаем ещё что-то

        Notices.Add Notice ' добавляем очередной элемент в коллекцию
    Next ro
End Sub
EducatedFool вне форума Ответить с цитированием
Старый 13.04.2011, 09:57   #5
EducatedFool
Программист VBA
СуперМодератор
 
Аватар для EducatedFool
 
Регистрация: 13.07.2008
Сообщений: 6,856
По умолчанию

Цитата:
Требуется создать 4 коллекции (по количеству смен).
Обязательно коллекции? Чем массивы не устраивают?
К тому же, в вашем случае с массивами будет даже проще - либо используйте 4 двумерных массива, либо один 3-мерный.
(в массивы можно добавлять элементы пользовательского типа)
EducatedFool вне форума Ответить с цитированием
Старый 13.04.2011, 10:04   #6
hoza
Новичок
Джуниор
 
Регистрация: 13.04.2011
Сообщений: 6
По умолчанию

Цитата:
Сообщение от EducatedFool Посмотреть сообщение
Обязательно коллекции? Чем массивы не устраивают?
К тому же, в вашем случае с массивами будет даже проще - либо используйте 4 двумерных массива, либо один 3-мерный.
(в массивы можно добавлять элементы пользовательского типа)
Можно, конечно, и с массивами, но это не красиво и получается полная порнография - либо сначала нужно определить размерность массива, либо постоянно изменять его размеры.
У меня была похожая ситуация год назад, но код дома на компе, а дома буду только в пятницу вечером. Там, насколько я помню, ситуацию разрешил, но вот как я это сделал - уже не помню.
hoza вне форума Ответить с цитированием
Старый 13.04.2011, 10:22   #7
hoza
Новичок
Джуниор
 
Регистрация: 13.04.2011
Сообщений: 6
По умолчанию

Мне в Вашем коде не понятна строчка
Код:
Set ra = Intersect(Selection.EntireRow, Selection.EntireRow, Range("3:65536"))
Я так понимаю, что она задаёт на просмотр диапазон строк с 3 по 65536. Но у меня то строк гораздо меньше (за один месяц что-то около 6600), но не в этом суть. Хотелось бы что-то более универсальное, чтобы не "лопатить" пустые строки. Или это можно сделать проверкой в процедуре класса ReadFromRow?
hoza вне форума Ответить с цитированием
Старый 13.04.2011, 10:25   #8
EducatedFool
Программист VBA
СуперМодератор
 
Аватар для EducatedFool
 
Регистрация: 13.07.2008
Сообщений: 6,856
По умолчанию

Цитата:
Я так понимаю, что она задаёт на просмотр диапазон строк с 3 по 65536
нет
Это диапазон ВЫДЕЛЕННЫХ ПОЛЬЗОВАТЕЛЕМ строк, за исключением строк 1 и 2 (строк заголовка)

Цитата:
Хотелось бы что-то более универсальное, чтобы не "лопатить" пустые строки
Код:
Set ra = Range([A2], Range("A" & Rows.Count).End(xlUp))
это диапазон с ячейки A2 до последней заполненной
EducatedFool вне форума Ответить с цитированием
Старый 13.04.2011, 10:44   #9
hoza
Новичок
Джуниор
 
Регистрация: 13.04.2011
Сообщений: 6
По умолчанию

Получился следующий код:
Объявление класса Rec:
Код:
Public data As Date
Public nom As String
Public podr As String
Public uch As String
Public dol As String
Public fio As String
Public ktu As Double
Public pai As Double
Public otrab As Double
Public prem As Double
Public straf As Double
Public ves As Double
Public vyp As Double
Public paichas As Double
Public zp As Double

Sub ReadFromRow(ByRef ro As Range)
    On Error Resume Next
    With ro
        .data = .Cells(1)
        .nom = .Cells(2)
        .podr = .Cells(3)
        .uch = .Cells(4)
        .dol = .Cells(5)
        .fio = .Cells(6)
        .ktu = .Cells(7)
        .pai = .Cells(8)
        .otrab = .Cells(9)
        .prem = .Cells(10)
        .straf = .Cells(11)
        .ves = .Cells(12)
        .vyp = .Cells(13)
        .paichas = .ktu * .pai * .otrab
    End With
End Sub
Основная процедура:
Код:
Public Sub fill()
    Dim smena1 As New Collection
    Dim smena2 As New Collection
    Dim smena3 As New Collection
    Dim smena4 As New Collection
    Dim record As Rec
    Set ra = Range([A5], Range("A" & Rows.Count).End(xlUp))
    For Each ro In ra.Rows
        Set record = New Rec
        record.ReadFromRow ro
        If record.podr = "áðèãàäà 1" Then smena1.Add record
    Next ro
End Sub
Выдаёт ошибку:
ByRef argument type mismatch
hoza вне форума Ответить с цитированием
Старый 13.04.2011, 11:24   #10
EducatedFool
Программист VBA
СуперМодератор
 
Аватар для EducatedFool
 
Регистрация: 13.07.2008
Сообщений: 6,856
По умолчанию

Перед строкой Set ra = Range([A5], Range("A" & Rows.Count).End(xlUp))
добавьте строку
Код:
Dim ro as range, ra as range
EducatedFool вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Типы данных С++ werser Помощь студентам 1 13.03.2010 18:34
Типы данных psycho-coder Паскаль, Turbo Pascal, PascalABC.NET 6 04.02.2010 20:03
Типы данных nedden Помощь студентам 2 12.11.2008 17:18
Типы данных??? Рустам Общие вопросы Delphi 10 08.11.2007 08:03