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