При написании программного кода в 1С:Предприятие 8 начинающие разработчики часто сталкиваются с ситуацией, когда система выдает ошибку «Переменная не определена (Ссылка)». Эта проблема особенно актуальна при переходе от обычных форм к управляемым или при написании кода в модулях, где контекст объекта не доступен напрямую. Рассмотрим подробнее, почему возникает эта ошибка, как правильно передавать параметры в запрос и какие нюансы работы с базой данных необходимо учитывать.
Проанализируем ситуацию, представленную в вопросе. Разработчик пытается выполнить запрос к табличной части справочника и передать текущую ссылку в качестве параметра. Ошибка Переменная не определена (Ссылка) означает, что в той процедуре или функции, где исполняется код, платформа не видит переменную с именем Ссылка. Выясним, почему это происходит:
Объект. Напрямую обратиться к полю Ссылка нельзя, необходимо использовать конструкцию Объект.Ссылка.Ссылка (а также другие реквизиты) были доступны напрямую без префиксов.Для исправления ошибки в контексте управляемой формы (серверный вызов) нам необходимо изменить строку установки параметра. Вместо Ссылка укажем путь к данным через реквизит формы.
Посмотрим на исправленный пример кода:
&НаСервере
Процедура ЗаполнитьТабличнуюЧастьНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КомплектацияКомплектующие.Номенклатура КАК Номенклатура,
| КомплектацияКомплектующие.Цена КАК Цена,
| КомплектацияКомплектующие.Количество КАК Количество,
| КомплектацияКомплектующие.Сумма КАК Сумма
|ИЗ
| Справочник.Комплектация.Комплектующие КАК КомплектацияКомплектующие
|ГДЕ
| КомплектацияКомплектующие.Ссылка = &Ссылка";
// Обращаемся к ссылке через основной реквизит формы "Объект"
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Объект.Комплектующие.Загрузить(РезультатЗапроса);
КонецПроцедуры
Рассмотрим ситуацию, которая часто следует за исправлением синтаксической ошибки: код выполняется без ошибок, но табличная часть остается пустой. Почему так происходит? Важно понимать фундаментальное различие между данными «в памяти» (в форме) и данными «в базе» (в таблицах SQL).
Запрос (Запрос.Выполнить()) всегда обращается к таблицам базы данных. Если вы создали новый элемент справочника, заполнили его табличную часть на форме, но еще не нажали кнопку «Записать», то в базе данных этого объекта еще не существует. Поле Объект.Ссылка при этом может быть пустым или содержать временную ссылку, по которой запрос ничего не найдет.
Вывод: Запрос к табличной части текущего объекта сработает только в том случае, если объект уже был предварительно записан в информационную базу. Если данные еще не записаны, а вам нужно их обработать, следует использовать методы работы с коллекциями в памяти, например:
// Вместо запроса обходим ТЧ в цикле или выгружаем в таблицу значений
ТаблицаДанных = Объект.Комплектующие.Выгрузить();
// Далее работаем с переменной ТаблицаДанных как с объектом типа ТаблицаЗначений
Проанализируем сообщение автора о том, что ему нужна «ссылка только на табличную часть». В архитектуре 1С:Предприятие 8 не существует понятия ссылки на табличную часть как отдельного типа данных. Ссылочный тип (UUID) имеют только сами объекты: справочники, документы, бизнес-процессы.
Табличная часть — это зависимая структура. В запросе поле Ссылка внутри таблицы Справочник.Комплектация.Комплектующие — это всегда ссылка на владельца этой табличной части (т.е. на сам элемент справочника «Комплектация»). Чтобы получить строки конкретного документа, мы всегда фильтруем всю таблицу строк по ссылке их родителя.
Для улучшения читаемости кода и избегания путаницы, рекомендуется давать параметрам запроса осмысленные имена. Вместо того чтобы называть параметр &Ссылка, лучше использовать имя, отражающее суть объекта.
Рассмотрим пример хорошего тона в кодировании:
Запрос.Текст =
"ВЫБРАТЬ ... ИЗ ... ГДЕ Ссылка = &ТекущаяКомплектация";
// Использование более понятного имени параметра
Запрос.УстановитьПараметр("ТекущаяКомплектация", Объект.Ссылка);
Это помогает избежать логических ошибок, когда в одном запросе участвуют несколько ссылок на разные объекты (например, ссылка на документ и ссылка на контрагента).
Чтобы ваш код был отказоустойчивым, перед выполнением запроса полезно проверять, не является ли ссылка пустой. Если ссылка пустая (объект не выбран или не создан), запрос выполнится, но вернет пустой результат, что может привести к неверной логике работы программы.
Разберем, как добавить проверку:
Если Объект.Ссылка.Пустая() Тогда
Сообщить("Действие невозможно: сначала необходимо записать объект!");
Возврат;
КонецЕсли;
// Если проверка пройдена, выполняем запрос
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
Использование метода Пустая() позволяет вовремя остановить выполнение кода и уведомить пользователя о необходимости записи данных. Это стандарт качества при разработке профессиональных решений на платформе 1С.