Не работает раннее связывание для объекта TableDef, Access.

Весь MS Office, программирование на Visual Basic for Applications и MS VB

Модератор: Naeel Maqsudov

Ответить
ALMOST_DEAD
Сообщения: 7
Зарегистрирован: 30 окт 2006, 16:45

01 ноя 2006, 17:14

Код: Выделить всё

Dim CUR_TBL As TableDef
Set CUR_TBL = CurrentDb.TableDefs(CUR_TBL_NAME)
Не работает - в вотче пишет о несуществующем объекте, на свойстве Name, к примеру, выдает ошибку, но к QueryDefs я спокойно могу линковаться - почему???
Аватара пользователя
Naeel Maqsudov
Сообщения: 2551
Зарегистрирован: 20 фев 2004, 19:17
Откуда: Moscow, Russia
Контактная информация:

01 ноя 2006, 23:51

Единственное, что в соответствии с предоставленной информацией приходит в голову - это невеное имя таблицы в переменной CUR_TBL_NAME.

Дайте точный текст ошибки, и лучше побольше кода. С указанием где именно происходтит ошибка.

Совет:
При возникновении ошибки всегда пользуйтесь отладчиком. Добавьте в список Watches переменные, а также подозрительные выражения и посмотрите чему они равны. Выясните, какая часть выражения чему равна. Часто это на 100% позволяет понять проблему.
ALMOST_DEAD
Сообщения: 7
Зарегистрирован: 30 окт 2006, 16:45

02 ноя 2006, 09:31

Спасибо, что взялись решать мою проблему!Често говоря много кода тут и не надо - падает уже на таком:

Код: Выделить всё

Function TableCompare(CUR_TBL_NAME As String, ORIG_TBL_NAME As String, Optional Silent As Boolean = True) As Boolean
Dim CUR_TBL As TableDef
Set CUR_TBL = CurrentDb.TableDefs(CUR_TBL_NAME)
msgbox Currentdb(CUR_TBL_NAME).name 'нормально
msgbox CUR_TBL.Name 'ошибка
№ 3420 - "Указан недопустимый объект или объект более не задан"
В вотче все свойства CUR_TBL (после связи, естесственно) = "Указан недопустимый объект или объект более не задан".
Просто в МсгБоксах удобнее писать CUR_TBL.name, чем ...
Аватара пользователя
Naeel Maqsudov
Сообщения: 2551
Зарегистрирован: 20 фев 2004, 19:17
Откуда: Moscow, Russia
Контактная информация:

02 ноя 2006, 23:24

Вот. Поступаем точно так как я советовал, т.е. добавляем переменную CUR_TBL в Watch, выполняем макрос по шагам, "и тупо смотрим что к чему" (с) Стругацкие.

Под отладчиком видно, что переменна CUR_TBL сначала = Nothing, а потом (после Set) становися действительным указателем, но в процессе выполнения ЛЮБОГО следующего оператора (Даже если после Set поставить X=1) перестает быть действительным. Экспериментально установлено, что объект TableDef прекращает свое существование к началу выполнения следующего оператора (составные операторы рассматриваются как несколько).

ФАНТАСТИКА! Я этого не знал! Т.е. работать с экземпляром объекта TableDef можно только в пределах одного оператора. Потом он разрушается, а указатель на него перестает быть действительнывм. Аналогично обстоит дело с объектами лежащими глубже (Например, ссылка на TableDef(...).Fields ведет себя также). Могу только предположить, что TableDef - это лишь логическое отражение некой физической реальности, которая потенциально может быть изменена другим пользователем (или даже просто другим потоком текущего приложения), и поэтому оно не является, например, потокозащищенным, а посему срок его жизни ограничен одним оператором, который в VBA выполняется в одном потоке в CriticalSection (но это только догадки)

Увы ничего тут не поделаешь! Придется писать громоздкий и неэффективный код!!!

Например цикл

Код: Выделить всё

For Each t In CurrentDb.TableDefs
  MsgBox t.Name
Next
РАБОТАЕТ
А цикл

Код: Выделить всё

For Each f In CurrentDb.TableDefs(CUR_TBL_NAME).Fields
  MsgBox f.Name
Next
Уже не работает, так как при вхождении в цикл переменная f ссылается на объект Field, но уже на первоой же итерации (т.е. к началу выполнения MsgBox f.Name) оказывается ссылкой на недействительный объект!

Увы....
Ответить