Модераторы: mihanik

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Передача массива в качестве аргумента подпрограммы, Не удается передать пользовательский тип 
V
    Опции темы
НеуФазендник
Дата 25.2.2012, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 9.5.2006

Репутация: нет
Всего: 2



Есть процедура, которая обрабатывает массивы произвольных данных.
Массивы передаются вовнутрь через переменную variant
C предопределенными типами данных проблем нет
конструкция типа:
Код

dim a(100) as byte
dim b

b=a

Прекрасно работает. Так же, нет проблем при передаче во внутрь подпрограммы массива предопределенного типа.
Но вот если элементы массива  A будут представителя пользовательского типа, то при попытке присвоения (равно - попытке передачи параметров) возникает ошибка компиляции:
"Only public user defined types defined in public object modules can be used as parameters or return types for public procedures of class modules or as fields of public user defined types"
Естественно, что я попробовал описывать соответствующий пользовательский тип и в этом же модул, и в отдельном , и с public и без.
Не фурычит никак.
Что делать?
Процедура может вызываться с неограниченным числом пользовательских типов. Поэтому я не могу под каждый пользовательский тип заложить отдельный параметр, ответственный за передачу элементов именно этого типа. Передача различных массивов данных через одну и ту же переменную, это тот универсализм, который мне требуется сохранить, чтобы не усложнять код. Но как передать различные пользовательские данные через один и тот же параметр или заголовок процедуры?
PM MAIL   Вверх
Akina
Дата 25.2.2012, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 26
Всего: 454



Цитата(НеуФазендник @  25.2.2012,  15:02 Найти цитируемый пост)
Что делать?

Set


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
НеуФазендник
Дата 25.2.2012, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 9.5.2006

Репутация: нет
Всего: 2



Akina, Подробнее, пожалуйста.
Я пробовал и Set использовать, но, видимо, что-то не так делал. Лезут ошибки. Не работает.

Это сообщение отредактировал(а) НеуФазендник - 25.2.2012, 23:53
PM MAIL   Вверх
Вождь
Дата 26.2.2012, 06:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 4.1.2012

Репутация: нет
Всего: нет



Цитата(НеуФазендник @ 25.2.2012,  14:02)
...Only public user defined types defined in public object modules can be used as parameters or return types for public procedures of class modules or as fields of public user defined types...

В сообщении об ошибке речь не о массивах (array), а о типах (type). Вам надо объявить тип, куда и включить описание массива. Хорошо бы видеть ошибочный код. Пример:
Код
Option Explicit

Public Type myTYPE
    A(0 To 9) As String
    B As Variant
End Type

Function P1(ByRef X As myTYPE) As myTYPE
    P1.A(0) = "bbbb"
    P1.B = Array(100, 200, 300, 400)
End Function

Sub P2()
Dim Z1 As myTYPE, Z2 As myTYPE
    Z1.A(0) = "aaaa"
    Z1.B = Array(1, 2, 3)
    Z2 = P1(Z1)
End Sub

PM MAIL WWW ICQ   Вверх
НеуФазендник
Дата 26.2.2012, 08:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 9.5.2006

Репутация: нет
Всего: 2



Вождь
Цитата(НеуФазендник @  25.2.2012,  14:02 Найти цитируемый пост)
Процедура может вызываться с неограниченным числом пользовательских типов. Поэтому я не могу под каждый пользовательский тип заложить отдельный параметр, ответственный за передачу элементов именно этого типа. 


В приведенном Вами примере Function P1(ByRef X As myTYPE) As myTYPE
Имеет в качестве параметра переменную пользовательского типа mytype.

Я не могу воспользоваться Вашим примером по изложенной выше причине. Или же я Вас недопонимаю.

Пример 
Код

Public Type t1
  v1 As Byte
  v2 As String
  End Type
  
Public v4() As Integer
Public v5() As String
Public v6() As t1

Sub s1(v7)
ReDim v7(50)
End Sub

Sub s2()
  Call s1(v4) ' работает
  Call s1(v5) 'работает
  Call s1(v6) ' не работает
End Sub
кода таков:

PM MAIL   Вверх
Вождь
Дата 26.2.2012, 09:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 4.1.2012

Репутация: нет
Всего: нет



Цитата(НеуФазендник @ 26.2.2012,  07:51)
Код
Public Type t1
  v1 As Byte
  v2 As String
  End Type

Такое передать не удастся, о чем и говорится в сообщении об ошибке.  Как альтернатива: вместо типа использовать класс, что может оказаться даже удобнее и гибче, и решится проблема с передачей.
PM MAIL WWW ICQ   Вверх
НеуФазендник
Дата 26.2.2012, 21:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 9.5.2006

Репутация: нет
Всего: 2



Фигово. Было три массива с общей индексацией. String, String, и Byte. Чтобы сделать код более читаемым и , особенно, более понятным передачу этих (наряду с кучей прочих скалярных)   параметров в обрабатывающие процедуры, оформил их в отдельный тип.
Но вот еще сделать их классом, как-то уж совсем больно громоздкая городулька выходит вместо трех массивов.
Получилось, хотел упростить, в итоге создал еще один модуль, набросал на целый экран кода и задействовал дополнительный массив объектных переменных! Не айс. Не очень люблю ООП в подобных вещах. Громоздко.

Это сообщение отредактировал(а) НеуФазендник - 26.2.2012, 21:20
PM MAIL   Вверх
Вождь
Дата 26.2.2012, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 4.1.2012

Репутация: нет
Всего: нет



Цитата(НеуФазендник @ 26.2.2012,  20:07)
Фигово...Громоздко

Спорные аргументы smile По-другому универсальности не добиться, по-моему. Либо одна процедура + variant и class, либо отдельная процедура под каждый тип.
PM MAIL WWW ICQ   Вверх
НеуФазендник
Дата 26.2.2012, 22:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 9.5.2006

Репутация: нет
Всего: 2



Цитата(Вождь @  26.2.2012,  22:17 Найти цитируемый пост)
Либо одна процедура + variant и class,

Да в том то и дело, что под каждый пользовательский тип еще и класс рисовать вместо процедуры. Легче, но все равно убого выходит.
Но, я так понял, что правда ваша - другого выбора кроме побочного эффекта VBA не предлагает.
PM MAIL   Вверх
НеуФазендник
Дата 1.3.2012, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 9.5.2006

Репутация: нет
Всего: 2



Еще несколько дней думал над задачей, пробуя разные варианты. Делаю вывод, что самым разумным решением является добавлять при необходимости каждый новый пользовательский тип в виде optional параметра в заголовок процедур. Поскольку при вызове подпрограммы все равно передается лишь одна переменная, то optional - параметров в описании процедуры может быть сколько хочешь, и, одновременно, нет раздувания заголовка при вызовах процедуры. В общем - то, это почти то, что нужно. Остается лишь код для распознавания типа передаваемого параметра в самой процедуре разместить. Но все это куда менее громоздко, чем "рисовать" классы под передачу пользовательских типов.
PM MAIL   Вверх
Вождь
Дата 1.3.2012, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 4.1.2012

Репутация: нет
Всего: нет



Цитата(НеуФазендник @ 1.3.2012,  11:56)
...менее громоздко, чем "рисовать" классы под передачу пользовательских типов.

Тоже вариант. Вам судить. Мне задача целиком не видна, а то можно все затолкать в один класс.
PM MAIL WWW ICQ   Вверх
НеуФазендник
Дата 6.3.2012, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 9.5.2006

Репутация: нет
Всего: 2



Очередная засада!
Компилятор не пропускает optional параметра в виде динамического массива пользовательского типа.

Общая Задача такова:
Есть база данных в excel под управлением VBA.
Отображение информации в этой базе происходит на отдельных worksheet. Каждый из которых я называю контекстом.
Любой контекст имеет набор событий, которые могут породить вложеный контекст. Тот в свою очередь может породить еще более вложенный. Ну, к примеру первым был контекст со списком телефонов. Вторым - информация о владельце конкретного номера телефона. Третьим - информация о месте работы этого человека. Четвертым - информация о тех должностях, которые известны в организации, котоой мы заинтересованы. 
В тот момент, когда пользователь дает команду создания дочернего контекста нам требуется некоторые параметры, которые определят содержимое будущего контекста передать универсальной подпрограмме заполнения нового worksheet. В то же время, после того, как дочерний контекст отработал, в ряде случаев он тоже должен вернуть в материнский какие-либо данные. Для подобного обмена данными между дочерним и материнским контекстами есть ряд массивов и отдельных переменных. Например, есть массивы А(), B(), C(), D() c единой индексацией. 
А - название графы дочернего контекста, из которой нужно будет извлечь параметр, выбранный пользователем.
B - название графы материнского контекста, в которую вернуть выбранный параметр.
C - тип\назначение передаваемого параметра
D (variant) - сам передаваемый параметр.

Вся база работает под управлением почти 1 Mb код, с основной логикой без ООП. Массивы, массивы, и еще раз массивы, подобные A-D. Переделать постепенно на ООП не реально. Проще все сделать заново, когда уже стала понятна структура. 
Я решил расширить возможности базы. Сделать так, чтобы была возможность работать не только с единственной цепочкой взаимосвязанных (дочерний-материнский) контекстов, а чтобы параллельно таких цепочек могло быть несколько.
Я понял, что без структурирования мой мозг такую задачу уже не потянет.
Создал первый класс - цепочка контекстов.
Создал первый пользовательский тип - как раз для хранения структуры массивов A-D
И вот тут то меня и настигли беды.
В логике межконтекстного обмена данными зарезервировано более сотни параметров межконтекстного обмена.
Эти параметры нужно передавать на временное хранение в мой класс и обратно. Вроде бы  все складно. Бери да передавай. Но внутри класса, алгоритм передачи параметра на хранение и выборки его связан с тем, какой контекст и какому что отправлял и какой теперь от какого требует.  Это снова структура данных и не 2 строки кода. Один и тот же, не зависимо от параметра. Не хочу подробно описывать его суть. Я не готов психологически для каждого из сотни передаваемых параметров рисовать свойства Property Let и Property Set  на 2 экрана каждое, причем по одному и тому же алгоритму. Я пытаюсь запихнуть во внутрь класса переменные через один из методов. И выкидывать нужную информацию так же.  Но столкнулся с проблемой, что заголовок этого метода тоже не удается сделать универсальным. Вот и ищу выход, как один и тот же алгоритм распространить на обработку сотни разных по структуре данных. Самым разумным было бы обьявить классом отдельный контекст. Но это уже переделка основы базы. Слишком много затрагивается. Точнее, затрагивается ввесь код, который создавался постепенно около 5 лет. Я уже оговорился, что проще тогда все начинать с ноля переделывать. Но тогда уж вообще не на VBA.  идея уже просто выросла из пространства VBA а глобальной переделкой ее заниматься не планирую.

Это сообщение отредактировал(а) НеуФазендник - 6.3.2012, 10:13
PM MAIL   Вверх
FINANSIST
Дата 6.3.2012, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Статус: Жив
**


Профиль
Группа: Участник
Сообщений: 526
Регистрация: 11.4.2008
Где: Москва

Репутация: 13
Всего: 23



Стало интересно, а зачем при наличии готовых и проверенных временем продуктов ПЫТАТЬСЯ создавать средствами VBA Excel движок СУБД?
Мазохизм? Спортивный интерес? Или на спор?


Это сообщение отредактировал(а) FINANSIST - 6.3.2012, 15:05


--------------------
“...Брали корову рыжую одну, отдавать будем корову рыжую одну, чтобы не нарушать отчетности”
Эдуард Успенский, “Каникулы в Простоквашино”
PM MAIL ICQ   Вверх
НеуФазендник
Дата 7.3.2012, 00:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 108
Регистрация: 9.5.2006

Репутация: нет
Всего: 2



FINANSIST, болталка находится в другой ветке, но из всех предложенных Вами ответов на Ваш вопрос мне больше всего нравится "Мазохист".

Это сообщение отредактировал(а) НеуФазендник - 7.3.2012, 00:40
PM MAIL   Вверх
FINANSIST
Дата 7.3.2012, 07:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Статус: Жив
**


Профиль
Группа: Участник
Сообщений: 526
Регистрация: 11.4.2008
Где: Москва

Репутация: 13
Всего: 23



Цитата(НеуФазендник @  7.3.2012,  00:19 Найти цитируемый пост)
болталка находится в другой ветке

Ладно, прозрачный намек не услышан.
Исходя из: 
Цитата(НеуФазендник @  6.3.2012,  09:55 Найти цитируемый пост)
Есть база данных в excel под управлением VBA.

А так же из:
Цитата(НеуФазендник @  6.3.2012,  09:55 Найти цитируемый пост)
Любой контекст имеет набор событий, которые могут породить вложеный контекст. Тот в свою очередь может породить еще более вложенный. Ну, к примеру первым был контекст со списком телефонов. Вторым - информация о владельце конкретного номера телефона. Третьим - информация о месте работы этого человека. Четвертым - информация о тех должностях, которые известны в организации, котоой мы заинтересованы. В тот момент, когда пользователь дает команду создания дочернего контекста нам требуется некоторые параметры, которые определят содержимое будущего контекста передать универсальной подпрограмме заполнения нового worksheet. В то же время, после того, как дочерний контекст отработал, в ряде случаев он тоже должен вернуть в материнский какие-либо данные. Для подобного обмена данными между дочерним и материнским контекстами есть ряд массивов и отдельных переменных.

Можно сделать вывод что основная работа с данными предполагает выборку по различным критериям, с различными аналитическими срезами и  с различной степенью агрегации данных.
Так же предполагается судя по всему, возврат в основные запросы результаты действия подзапросов.
Помимо этого (возможно) необходимы некие манипуляции с выбранными данными (update, delete, insert).
Задачи типичные и удобоваримые для любой СУБД.
Помимо этого делаю предположение что необходим некий юзверский интерфейс, а так же какая -то вложенная бизнес-логика обработки массивов помимо средств sql (которая уже прописана Вами на VBA)
ИМХО: наименее безболезненный   и эффективный переход  был бы на  Access, или  на [sql server+ADP проект] 
На то и намекал:)


Это сообщение отредактировал(а) FINANSIST - 7.3.2012, 07:43


--------------------
“...Брали корову рыжую одну, отдавать будем корову рыжую одну, чтобы не нарушать отчетности”
Эдуард Успенский, “Каникулы в Простоквашино”
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Программирование, связанное с MS Office"
mihanik staruha

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами



  • Несанкционированная реклама на форуме запрещена
  • Пожалуйста, давайте своим темам осмысленный, информативный заголовок. Вопль "Помогите!" таковым не является.
  • Чем полнее и яснее Вы изложите проблему, тем быстрее мы её решим.
  • Оставляйте свои записи в "Книге отзывов о работе администрации"
  • А вот тут лежит FAQ нашего подраздела


Если Вам понравилась атмосфера форума, заходите к нам чаще!
С уважением mihanik и staruha.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Программирование, связанное с MS Office | Следующая тема »


 




[ Время генерации скрипта: 0.0975 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.