Пара получила в качестве дополнений к двум уже опубликованным исключительным ответам:
Доступ к полям набора записей в формах и отчетах
Элементом по умолчанию объектов формы в Access является объединение коллекции Controls формы и коллекции Fields набора записей формы. Если имя элемента управления конфликтует с именем поля, я не уверен, какой объект на самом деле возвращается. Поскольку свойство по умолчанию как поля, так и элемента управления равно их .Value
, часто это «различие без разницы». Другими словами, обычно не волнует, что это потому, что значения поля и элемента управления часто совпадают.
Остерегайтесь конфликтов имен!
Эта ситуация усугубляется тем, что конструктор форм и отчетов Access по умолчанию именует связанные элементы управления так же, как поле набора записей, к которому они привязаны. Я лично принял соглашение о переименовании элементов управления с префиксом их типа (например, tbLastName
для текстового поля, связанного с полем LastName ).
Поля набора записей отчета отсутствуют!
Ранее я уже говорил, что элемент по умолчанию для объекта Form представляет собой набор элементов управления и полей. Тем не менее, элемент по умолчанию объекта отчета является только его коллекция элементов управления. Поэтому, если кто-то хочет обратиться к полю набора записей, используя оператор взрыва, ему нужно включить это поле в качестве источника для (скрытого, при желании) элемента управления с привязкой.
Остерегайтесь конфликтов с явными свойствами формы / отчета
Когда кто-либо добавляет элементы управления в форму или отчет, Access автоматически создает свойства, которые ссылаются на эти элементы управления. Например, элемент управления с именем tbLastName
будет доступен из модуля кода формы, ссылаясь на Me.tbLastName
. Однако Access не будет создавать такое свойство, если оно конфликтует с существующей формой или свойством отчета. Например, предположим, что один добавляет элемент управления с именем Pages. Ссылка на Me.Pages
в модуле кода формы возвращает свойство Pages формы, а не элемент управления с именем "Pages".
В этом примере можно получить доступ к элементу управления «Страницы» явно, используя Me.Controls("Pages")
или неявно используя оператор взрыва, Me!Pages
. Однако имейте в виду, что использование оператора взрыва означает, что Access может вместо этого вернуть поле с именем «Страницы», если оно существует в наборе записей формы.
А как. Значение?
Хотя эта тема не упоминается явно, эта тема возникла в приведенных выше комментариях. По умолчанию свойство для объектов поля и большинства «привязываемых к данным» ¹ управляющих объектов - .Value
. Так как это свойство по умолчанию, обычно считается ненужным многословным всегда включать его явно. Таким образом, это стандартная практика:
Dim EmployeeLastName As String
EmployeeLastName = Me.tbLastName
Вместо:
EmployeeLastName = Me.tbLastName.Value
Остерегайтесь тонкой ошибки. Значение при вводе словарей
Есть несколько случаев, когда это соглашение может вызвать незначительные ошибки. Наиболее заметный - и, если память служит только - один, с которым я на самом деле сталкивался на практике, - это использование значения поля / элемента управления в качестве ключа словаря.
Set EmployeePhoneNums = CreateObject("Scripting.Dictionary")
Me.tbLastName.Value = "Jones"
EmployeePhoneNums.Add Key:=Me.tbLastName, Item:="555-1234"
Me.tbLastName.Value = "Smith"
EmployeePhoneNums.Add Key:=Me.tbLastName, Item:="555-6789"
Можно ожидать, что приведенный выше код создает две записи в словаре EmployeePhoneNums
. Вместо этого он выдает ошибку в последней строке, потому что мы пытаемся добавить дубликат ключа. То есть сам объект управления tbLastName
является ключом, а не значением элемента управления. В этом контексте значение элемента управления даже не имеет значения.
На самом деле, я ожидаю, что адрес памяти объекта (ObjPtr(Me.tbLastName)
), скорее всего, используется за кулисами для индексации словаря. Я сделал быстрый тест, который, кажется, подтверждает это.
'Standard module:
Public testDict As New Scripting.Dictionary
Sub QuickTest()
Dim key As Variant
For Each key In testDict.Keys
Debug.Print ObjPtr(key), testDict.Item(key)
Next key
End Sub
'Form module:
Private Sub Form_Current()
testDict(Me.tbLastName) = Me.tbLastName.Value
Debug.Print ObjPtr(Me.tbLastName); "..."; Me.tbLastName
End Sub
При запуске приведенного выше кода ровно один элемент словаря добавляется при каждом закрытии и повторном открытии формы. Переход от записи к записи (и, следовательно, вызывающий несколько обращений к подпрограмме Form_Current) не добавляет новые элементы словаря, поскольку это сам объект Control, индексирующий словарь, а не значение элемента управления.
Мои персональные рекомендации / условные обозначения
За эти годы я принял следующие практики YMMV:
- Префикс имени элемента формы / отчета с индикаторами типа элемента управления (например,
tbTextBox
, lblLabel
и т. Д.)
- См. Элементы управления формы / отчета в коде с использованием обозначения
Me.
(например, Me.tbLastName
)
- Избегайте создания полей таблицы / запроса с проблемными именами в первую очередь
- Используйте обозначение
Me!
при возникновении конфликтов, например, с устаревшими приложениями (например, Me!Pages
)
- Включение скрытых элементов управления отчетом для получения доступа к значениям поля Recordset *
- Явно включать
.Value
только в том случае, если ситуация требует добавленного многословия (например, словарные ключи)
¹ Что такое «привязываемый к данным» элемент управления?
По сути, элемент управления со свойством ControlSource
, например TextBox или ComboBox. Не привязываемый элемент управления будет что-то вроде Label или CommandButton. Свойство по умолчанию для TextBox и ComboBox: .Value
; Метки и кнопки CommandButton не имеют свойства по умолчанию.