Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/15: Рейтинг темы: голосов - 15, средняя оценка - 4.80
2 / 3 / 0
Регистрация: 19.01.2018
Сообщений: 11
Excel

Составной/вложенный тип + словарь

03.08.2020, 22:40. Показов 3062. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер.

Помогите, пожалуйста, написать код для следующей задачи: есть Завод1, Завод2...и т.д., у каждого завода набор количественных характеристик (отгрузка по жд план/факт, отгрузка на авто план/факт).
Можно, не используя массивы, организовать следующую структуру данных?:
Zavod("Завод1").ZhD.Plan
Zavod("Завод1").ZhD.Fact
Zavod("Завод1").Auto.Fact
Zavod("Завод2").ZhD.Plan и т.д.

Вот, что у меня получается:
Модуль класса clsZavods
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Option Explicit
 
Private tID As String
Private tPlan As Double
Private tFact As Double
 
Public Property Get ZavodID() As String
    ZavodID = tID
End Property
 
Public Property Let ZavodID(value As String)
    tID = value
End Property
 
Public Property Get Plan() As Double
    Plan = tPlan
End Property
 
Public Property Let Plan(value As Double)
    tPlan = value
End Property
 
Public Property Get Fact() As Double
    Fact = tFact
End Property
 
Public Property Let Fact(value As Double)
    tFact = value
End Property
Основной модуль
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Sub DefineZavod()
 
Dim Zavod As Object
Dim tempZavod As clsZavods
 
    Set tempZavod = New clsZavods
    Set Zavod = CreateObject("Scripting.Dictionary")
   
    tempZavod.ZavodID = "Завод1"
    tempZavod.Plan = 100
    tempZavod.Fact = 200
 
    Zavod.Add tempZavod.ZavodID, tempZavod
    
    Set tempZavod = New clsZavods
 
    tempZavod.ZavodID = "Завод2"
    tempZavod.Plan = 10
    tempZavod.Fact = 20
 
    Zavod.Add tempZavod.ZavodID, tempZavod
 
    Debug.Print Zavod("Завод1").Plan
    Debug.Print Zavod("Завод2").Fact
 
End Sub
А как сделать вложенность, типа пользовательского класса?:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Public Type Values
    Plan As Double
    Fact As Double
End Type
 
Public Type Transport
    ZhD As Values
    Auto As Values
End Type
 
Sub CompositeType()
 
    Dim Zavod As Transport
 
    Zavod.ZhD.Fact = 100
    Zavod.Auto.Fact = 300
 
End Sub
Нужно, чтобы было:
Visual Basic
1
2
Zavod("Завод1").ZhD.Fact = 100
 Zavod("Завод2").Auto.Fact = 300
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.08.2020, 22:40
Ответы с готовыми решениями:

Вложенный словарь и как его изменить
Нужно создать базу данных по примеру Ее вид примерно следующий: ...

Составной тип, проверка на ссылочность
всем привет имеется задача, найти все ссылочные значения в поле ВЫБРАТЬ первые 10 ...

Составной тип данных в запросе
имеется запрос: ВЫБРАТЬ ХранилищеДополнительнойИнформации.ИмяФайла КАК ИмяФайла, ...

11
6998 / 2896 / 555
Регистрация: 19.10.2012
Сообщений: 8,804
04.08.2020, 11:47
Можно сделать словарь словарей.
Можно массив словарей.
Можно словарь с массивом.
Можно словарь с коллекцией.
И всё это без классов, я их как-то и не применяю, зачем усложнять?
Словарь с массивом здесь вроде как вполне бы подошёл, но Вы против массивов

Добавлено через 1 минуту
Ну тогда словарь словарей.
0
2 / 3 / 0
Регистрация: 19.01.2018
Сообщений: 11
04.08.2020, 19:31  [ТС]
Hugo121, спасибо, что обратили внимание на мое сообщение.
Цитата Сообщение от Hugo121 Посмотреть сообщение
И всё это без классов, я их как-то и не применяю, зачем усложнять?
Пытаюсь разобраться, как работают классы + код более понятный.
Если есть возможность, подскажите, как сделать еще одно вложение в класс?
0
6998 / 2896 / 555
Регистрация: 19.10.2012
Сообщений: 8,804
04.08.2020, 20:28
Я же написал, я без классов обхожусь. Когда прижмёт - тогда и буду вникать.

Добавлено через 55 минут
Если у всех заводов известное количество этих характеристик, то словарь+массив вполне достаточно. И в массиве можно собирать хоть суммы, хотя по коду это и не нужно.
А если не нужно - то проще словарь+коллекция, в которой храним строки типа "Plan = 10"
Хотя в принципе достаточно одного словаря с ключами типа "Завод1.План", "Завод1.Факт" и т.д.
Тем более что этот словарь уже используете, а всё остальное выкинуть
И суммы собирать нет проблем
0
 Аватар для anton-sf
128 / 64 / 14
Регистрация: 29.03.2015
Сообщений: 265
04.08.2020, 20:57
Цитата Сообщение от pvapower Посмотреть сообщение
Можно, не используя массивы, организовать следующую структуру данных?:
Zavod("Завод1").ZhD.Plan
Zavod("Завод1").ZhD.Fact
Zavod("Завод1").Auto.Fact
Zavod("Завод2").ZhD.Plan и т.д.
где то в главном модуле расположить глобальный список заводов:
Visual Basic
1
Public Заводы As Collection
В первом (стартовом) макросе инициировать глобальный список заводов:
Visual Basic
1
Set Заводы = New Collection
В тех макросах, в который нужно добавить завод в глобальную коллекцию:
Visual Basic
1
Заводы.Add Item:=НовыйЗавод, Key:=НовыйЗавод.Название
Вот когда объект в коллекцию добавлен с ключем (Key), тогда и можно делать обращение
Visual Basic
1
Set ТекущийЗавод = Заводы(НазваниеЗавода)
А вообще создавать такую систему - значит дублировать эксель в экселе, ведь есть ячейки, чем не коллекция ?
Как ранее писал Hugo121 - использовать массивы, вот, ячейки это тоже массивы

Добавлено через 19 минут
Цитата Сообщение от pvapower Посмотреть сообщение
А как сделать вложенность, типа пользовательского класса?
Объявить в классе Заводы переменные класса Завод
Visual Basic
1
2
3
Dim Завод1 As Завод
Dim Завод2 As Завод
'...
И можно обращаться как:
Visual Basic
1
Заводы.Завод1.План = 100
Но это фиксированный список!

А для динамики нужно в класс Заводы добавить Collection
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
'Class Заводы
    Private Коллекция As Collection
 
    '....
 
    Public Function Добавить(НазваниеЗавода) As Завод
        'Тут нужно замутить проверку: а не содержится ли уже в коллекции такой ключ (переданное название)
        Dim Завод As New Завод
        Set Завод.Название = НазваниеЗавода
        Коллекция.Add Item:=Завод, Key:=Завод.Название
        Set Добавить = Завод
    End Function
 
    Public Function Элемент(НазваниеЗавода) As Завод
        'Тут нужно замутить проверку: а есть ли в коллекции такой ключ (переданное название)
        Dim Завод As Завод
        Set Завод = Коллекция(НазваниеЗавода)
        Set Элемент = Завод
    End Function
'End Class
Тогда можно обращаться таким образом:
Visual Basic
1
Заводы.Элемент(НазваниеЗавода).План = 100
Добавлено через 4 минуты
Цитата Сообщение от pvapower Посмотреть сообщение
Нужно, чтобы было:
Visual Basic
1
2
Zavod("Завод1").ZhD.Fact = 100
 Zavod("Завод2").Auto.Fact = 300
Такое только по первому варианту (глобальная коллекция без вложения её в класс)
0
6998 / 2896 / 555
Регистрация: 19.10.2012
Сообщений: 8,804
04.08.2020, 21:00
Цитата Сообщение от anton-sf Посмотреть сообщение
Заводы.Элемент(НазваниеЗавода).План = 100
С словарём, без всякой мути с классами:
Visual Basic
1
2
3
словарь("НазваниеЗавода.План") = 100
'и извлечь например факт для завод10:
MsgBox словарь("завод10.Факт")
1
2 / 3 / 0
Регистрация: 19.01.2018
Сообщений: 11
04.08.2020, 21:00  [ТС]
Всем спасибо за помощь.
Сделал, что хотел. Возможно, кому-нибудь пригодится:
создаем два класса clsZavods (внешний) и clsTransports (внутренний)
Класс clsZavods
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Option Explicit
 
Private tID As String
Private tZhD As New clsTransports
Private tAuto As New clsTransports
 
Public Property Get ZavodID() As String
    ZavodID = tID
End Property
 
Public Property Let ZavodID(Value As String)
    tID = Value
End Property
 
Public Property Get ZhD() As clsTransports
    Set ZhD = tZhD
End Property
 
Public Property Let ZhD(Value As clsTransports)
    Set ZhD = tZhD
End Property
 
Public Property Get Auto() As clsTransports
    Set Auto = tAuto
End Property
 
Public Property Let Auto(Value As clsTransports)
    Set Auto = tAuto
End Property
Класс clsTransports
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Option Explicit
 
Private tPlan As Double
Private tFact As Double
 
Public Property Get Plan() As Double
    Plan = tPlan
End Property
 
Public Property Let Plan(Value As Double)
    tPlan = Value
End Property
 
Public Property Get Fact() As Double
    Fact = tFact
End Property
 
Public Property Let Fact(Value As Double)
    tFact = Value
End Property
И основной модуль
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Option Explicit
 
Sub DefineZavod()
 
Dim Zavod As Object
Dim tempZavod As clsZavods
 
    Set tempZavod = New clsZavods
    Set Zavod = CreateObject("Scripting.Dictionary")
   
    tempZavod.ZavodID = "Завод1"
    tempZavod.ZhD.Plan = 100
    tempZavod.ZhD.Fact = 200
 
    Zavod.Add tempZavod.ZavodID, tempZavod
    
    Set tempZavod = New clsZavods
 
    tempZavod.ZavodID = "Завод2"
    tempZavod.Auto.Plan = 10
    tempZavod.Auto.Fact = 20
 
    Zavod.Add tempZavod.ZavodID, tempZavod
 
    Debug.Print Zavod("Завод1").ZhD.Plan
    Debug.Print Zavod("Завод1").ZhD.Fact
    Debug.Print Zavod("Завод2").Auto.Plan
    Debug.Print Zavod("Завод2").Auto.Fact
 
End Sub
1
 Аватар для anton-sf
128 / 64 / 14
Регистрация: 29.03.2015
Сообщений: 265
04.08.2020, 21:27
Мой вариант по объектному запросу
Цитата Сообщение от Hugo121 Посмотреть сообщение
С словарём, без всякой мути с классами:
А до этого понимания надо дорасти, всё приходит с опытом через сложные дебри (я ещё не дорос)

Добавлено через 4 минуты
Hugo121, кстати, в вашем варианте хорошо хранить, но как быть с вычисляемыми параметрами ?

Добавлено через 4 минуты
Я имею ввиду, например, рассчитать изделие производства, там куча параметров, и куча вычислений, а на выходе всего то строка с названием и ценой

Добавлено через 12 минут
Цитата Сообщение от pvapower Посмотреть сообщение
Visual Basic
1
Public Property Let ZhD(Value As clsTransports)
Тут надо применять Property Set

Цитата Сообщение от pvapower Посмотреть сообщение
создаем два класса clsZavods (внешний) и clsTransports (внутренний)
Ну да, вы сделали по первому варианту, через коллекцию

Добавлено через 3 минуты
Ага, я врубился, проблема была вот в этом обращении
Visual Basic
1
2
3
4
.ZhD.Plan
.ZhD.Fact
.Auto.Plan
.Auto.Fact
Ок, вы молодец, решили
0
6998 / 2896 / 555
Регистрация: 19.10.2012
Сообщений: 8,804
04.08.2020, 21:54
Кто-нибудь может мне прояснить в чём преимущество тех 79 строк кода с классами перед моими прогнозирую 11-ю на два завода (с объявлением и созданием объектов)?
Про вычисления вообще не понял, в чём может быть проблема например выяснить
Visual Basic
1
Отставание = словарь("завод10.План") - словарь("завод10.Факт")
0
 Аватар для anton-sf
128 / 64 / 14
Регистрация: 29.03.2015
Сообщений: 265
04.08.2020, 22:02
Цитата Сообщение от Hugo121 Посмотреть сообщение
в чём преимущество
Как минимум в выпадающем списке с процедурами/свойствами, их может быть +100500, что б не запоминать все. Да и не писать их а выбирать, intellisense вроде как
0
6998 / 2896 / 555
Регистрация: 19.10.2012
Сообщений: 8,804
04.08.2020, 22:04
Ну так понятно, оно там нужно, для такого-то монстра
0
2 / 3 / 0
Регистрация: 19.01.2018
Сообщений: 11
04.08.2020, 22:42  [ТС]
Цитата Сообщение от anton-sf Посмотреть сообщение
Как минимум в выпадающем списке с процедурами/свойствами, их может быть +100500, что б не запоминать все. Да и не писать их а выбирать, intellisense вроде как
Да, удобство в написании кода. Если использовать массивы, нужно запоминать (комментировать) под каким индексом "сидит" то или иное свойство.
Еще удобно расширять код, например, нужно добавить дельту (Факт-План). Для этого в класс clsTransports добавляем
Visual Basic
1
2
3
4
5
Private tDelta As Double
 
Public Property Get Delta() As Double
    Delta = tFact - tPlan
End Property
И всё....у вас есть разница по всем заводам, по всем видам трансорта
Visual Basic
1
2
3
4
    For Each key In Zavod.Keys
        Debug.Print Zavod(key).ZhD.Delta
        Debug.Print Zavod(key).Auto.Delta
    Next key
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.08.2020, 22:42
Помогаю со студенческими работами здесь

Отчет. Группы. составной тип
1С 8.1 УТ 10.3 В отчете Валовая Прибыль используется регистр накопления Продажи Себестоимость. В нем реквизит Документ оприходования...

Составной тип данных для реквизита
Всем доброй ночи!:) Как в документе создать тип данных составной?.. Чтобы я могла выбрать несколько элементов в один реквизит?..

Управляемые формы, составной тип данных
на упр. форме настройки отчета имеется поле содержащее составной тип данных допустим два справочника или просто справочник.ссылка() ...

Составной тип данных в табличной части
Использую у реквизита таб части составной тип данных(док ссылка и док ссылка), но в режиме предприятия почему то реквизит нельзя выбрать,...

Составной тип данных в табличной части документа
День добрый. Возник следующий вопрос. Управляемая конфигурация. Есть типовой документ, в этом документе нужно создать табличную часть с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru