Словарь VBA как свойство класса

У меня есть этот упрощенный класс с именем clsWarehouseSum.

Option Compare Database
Option Explicit

Private wh_units As Scripting.Dictionary    

Public Function availableUnits(warehouse As String) As Long
    'Debug.Print wh_units(warehouse)
    If wh_units Is Nothing Then Set wh_units = New Scripting.Dictionary
    
    If Not wh_units.Exists(warehouse) Then
    
        Dim SQL As String
        Dim RS As DAO.Recordset
        SQL = "SELECT sum(units) as tot_units " _
            & "FROM warehouse " _
            & "WHERE warehouse = '" & warehouse & "' "   
    
        Set RS = CurrentDb.OpenRecordset(SQL)
       
        wh_units.Add (warehouse), RS("tot_units")
        
    End If
    
    availableUnits = wh_units(warehouse)
    
    

End Function

Я пытаюсь использовать это так:

Sub test()

Dim wh As New clsWarehouseSum    
Debug.Print wh.availableUnits("Cohasset")
Debug.Print wh.availableUnits("Cohasset")

End Sub

В то время как первый Debug.Print печатает то, что ожидается, второй выдает ошибку: Run time error 3420, Object Invalid or no longer set. Когда я выполняю код, он правильно оценивает оба утверждения if как false. Тем не менее, последняя строка функции дает мне упомянутую выше ошибку. Что я делаю не так? Почему?

Он отлично работает для меня, используя ваш точный код (сокращение SQL, чтобы просто добавить 5). Обновлено: я также изменил dict на объект и использовал CreateObject("Scripting.Dictionary"), потому что мне лень добавлять ссылку.

SSlinky 09.01.2023 15:27

Поскольку словарь является частным для класса, пусть класс управляет своим состоянием. Это означает, что словарь должен быть создан в методе конструктора Class_Initialize() и ничего не установлен в методе деструктора Class_Terminate().

Kostas K. 09.01.2023 16:56

Кристиан, ты был прав. Тип был Field3. Почему это было? Обобщаемое поле — Long. Но в любом случае функция CLng решила проблему. Пожалуйста, вставьте это в ответ, чтобы я мог вознаградить вас правильным ответом

user2395238 09.01.2023 21:36

Словарь может содержать несколько типов вещей, поэтому, когда вы добавляете RS(“tot units”), вы добавляете объект Field, а не значение этого поля. Вам нужно быть более явным и использовать RS(“tot units”).Value

Tim Williams 10.01.2023 01:22

@user2395238 user2395238 Возможно, Field3 — это просто оболочка или, что еще более вероятно, вы используете позднее связывание, что вызывает проблемы с получением правильных интерфейсов. Я удалил комментарий и разместил его как ответ. Рад, что вы решили это.

Cristian Buse 10.01.2023 10:17

Ошибка Object Invalid or no longer set звучит для меня так, как будто RS("tot_units") будет не само значение, а ссылка. Поэтому во второй раз, когда вы вызываете wh.availableUnits("Cohasset"), эта ссылка не устанавливается (поскольку RS является локальной переменной и становится недоступной, когда выходит за рамки). Так что проверяйте, что вы на самом деле добавляете с помощью RS("tot_units"). Вам нужно добавить само значение Long ... которое вы, вероятно, и так знаете :).

Daniel Dušek 13.01.2023 16:27
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
6
90
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Добавьте Debug.Print TypeName(wh_units(warehouse)) перед строкой availableUnits = wh_units(warehouse), и если в окне Immediate будет напечатано что-то еще, кроме Long, вы можете захотеть выполнить приведение к Long с помощью CLng, хотя у вас также есть какой-то обработчик ошибок.

Или вы можете убедиться, что строка wh_units.Add (warehouse), RS("tot_units") добавляет Long в ваш словарь, поэтому вам следует проверить тип, прежде чем добавлять.

Как правило, когда вы возвращаете определенный тип данных из словаря или коллекции, у вас всегда должны быть проверки либо при добавлении данных в dict/coll, либо при их возврате, чтобы избежать несовместимости типов и ошибок времени выполнения. .

Другие вопросы по теме