К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как получить ссылку из табличной части 1С

Способы получить ссылку на объект из строки табличной части 1С: через реквизит строки, владельца, запрос и поиск. Примеры кода и типичные ошибки.

Табличная часть в 1С — это коллекция строк, подчинённая объекту-владельцу (документу или справочнику). Сама строка табличной части не является самостоятельным объектом базы данных и не имеет собственной ссылки. Поэтому под фразой «получить ссылку из табличной части» обычно понимают одну из трёх задач: взять значение ссылочного реквизита строки (например, «Номенклатура» в таблице «Товары»), получить ссылку на документ-владелец, которому принадлежит табличная часть, или найти объект по данным строки.

Конкретный способ зависит от того, где выполняется код: в модуле объекта, в модуле формы на клиенте или на сервере, во внешней обработке. Также имеет значение, работаете вы с управляемыми или обычными формами — от этого зависит, как обратиться к текущей строке таблицы на форме.

Ниже разобраны все основные сценарии с примерами кода на встроенном языке 1С, а также типичные ошибки, из-за которых вместо ссылки возвращается «Неопределено» или пустая ссылка.

Что именно можно получить из строки табличной части

Прежде чем писать код, определите, какая именно ссылка нужна. Строка табличной части — это структура данных внутри объекта, у неё нет уникального идентификатора в базе. Зато в реквизитах строки могут храниться ссылки на справочники, документы, перечисления и другие объекты.

Типовые варианты того, что требуется получить:

  • ссылку на элемент справочника из реквизита строки (Номенклатура, Контрагент, Склад);
  • ссылку на документ, указанный в реквизите строки (например, «ЗаказПокупателя» в табличной части реализации);
  • ссылку на объект-владелец табличной части;
  • ссылку на объект, который нужно найти по данным строки (по коду, наименованию, артикулу).

Получение ссылки из реквизита строки в модуле объекта или на сервере

Самый частый случай — перебор строк табличной части в модуле документа, в процедуре проведения или в серверной функции. Доступ к строкам выполняется через коллекцию с именем табличной части, а к значению реквизита — через точку.

Для Каждого СтрокаТовары Из Товары Цикл

СсылкаНаТовар = СтрокаТовары.Номенклатура;

// СсылкаНаТовар имеет тип СправочникСсылка.Номенклатура

Если Не ЗначениеЗаполнено(СсылкаНаТовар) Тогда

Продолжить;

КонецЕсли;

КонецЦикла;

Через полученную ссылку можно читать реквизиты объекта без вызова метода ПолучитьОбъект(): например, СтрокаТовары.Номенклатура.Артикул или СтрокаТовары.Номенклатура.ВидНоменклатуры. Это безопасно для чтения и не блокирует объект.

Если нужно изменить сам объект, на который указывает ссылка, тогда вызывайте СсылкаНаТовар.ПолучитьОбъект(), меняйте реквизиты и записывайте. Но делайте это только при реальной необходимости: ПолучитьОбъект() загружает весь объект в память и при записи устанавливает блокировку.

Получение ссылки из текущей строки таблицы на форме

На управляемой форме табличная часть представлена элементом формы «ТаблицаФормы», а данные хранятся в реквизите типа «ДанныеФормыКоллекция». Получить ссылку из текущей строки можно двумя способами: через ТекущиеДанные элемента формы или через идентификатор строки.

&НаКлиенте

Процедура ТоварыПриАктивизацииСтроки(Элемент)

ТекущиеДанные = Элементы.Товары.ТекущиеДанные;

Если ТекущиеДанные = Неопределено Тогда

Возврат;

КонецЕсли;

СсылкаНаТовар = ТекущиеДанные.Номенклатура;

КонецПроцедуры

Обратите внимание: ТекущиеДанные возвращает объект типа «ДанныеФормыЭлементКоллекции», а не строку табличной части в привычном серверном смысле. Ссылочные реквизиты доступны напрямую, но методы объекта-владельца из клиентского контекста недоступны. Если нужна серверная логика, передавайте полученную ссылку в серверную функцию.

На обычных формах (толстый клиент) подход похожий: ЭлементыФормы.Товары.ТекущиеДанные.Номенклатура, но там текущие данные — это настоящая строка табличной части, поэтому доступен и владелец, и методы коллекции.

Получение ссылки на владельца табличной части

Если под «ссылкой из табличной части» нужна ссылка на сам документ или справочник, которому принадлежит таблица, то в модуле объекта достаточно свойства Ссылка:

СсылкаНаДокумент = Ссылка; // в модуле объекта

// или для произвольного объекта:

СсылкаНаДокумент = ДокументОбъект.Ссылка;

В запросах у табличной части есть виртуальное поле «Ссылка», которое содержит ссылку на владельца. Это удобно, когда нужно выбрать документы по условиям на строки:

ВЫБРАТЬ РАЗЛИЧНЫЕ

Товары.Ссылка КАК Документ,

Товары.Номенклатура КАК Товар

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК Товары

ГДЕ

Товары.Номенклатура = &Номенклатура

Учтите, что у нового, ещё не записанного объекта ссылка пустая. Если код должен работать и до записи, используйте ПолучитьСсылкуНового() или сначала записывайте объект.

bsl
Если Объект.Ссылка.Пустая() Тогда
    НоваяСсылка = Документы.РеализацияТоваровУслуг.ПолучитьСсылку();
    Объект.УстановитьСсылкуНового(НоваяСсылка);
КонецЕсли;

Поиск объекта и получение ссылки по данным строки

Иногда в строке табличной части хранятся не ссылки, а строковые данные — артикул, код, наименование. Чтобы получить ссылку на соответствующий элемент справочника, используйте методы поиска менеджера объекта:

СсылкаНаТовар = Справочники.Номенклатура.НайтиПоКоду(СтрокаТовары.КодТовара);

Если СсылкаНаТовар.Пустая() Тогда

СсылкаНаТовар = Справочники.Номенклатура.НайтиПоНаименованию(СтрокаТовары.НаименованиеТовара, Истина);

КонецЕсли;

Методы НайтиПоКоду и НайтиПоНаименованию возвращают ссылку, а не объект — это быстрый способ. Если элемент не найден, возвращается пустая ссылка, которую обязательно нужно проверить через Пустая() или ЗначениеЗаполнено(), иначе дальнейшее обращение к реквизитам даст ошибку или неверные данные.

Для сложных условий поиска (по нескольким полям, по реквизитам) используйте запрос с выбором поля Ссылка — это гибче и при пакетной обработке множества строк значительно быстрее, чем поиск в цикле по одному элементу.

Маршрут решения

Как выбрать способ

В строке уже есть ссылочный реквизитОбратитесь к нему напрямую: СтрокаТовары.Номенклатура
Нужна ссылка на сам документ-владелецИспользуйте Ссылка в модуле объекта или поле Ссылка табличной части в запросе
В строке только код или наименованиеИспользуйте НайтиПоКоду / НайтиПоНаименованию или запрос
Нужно обработать много строк с поискомСоберите данные в один запрос вместо поиска в цикле

Работа со ссылкой из табличной части во внешних обработках и COM/HTTP-интеграции

При выгрузке данных во внешние системы ссылку обычно преобразуют в строку уникального идентификатора: XMLСтрока(СсылкаНаТовар) или Строка(СсылкаНаТовар.УникальныйИдентификатор()). Обратное преобразование выполняется через XMLЗначение(Тип("СправочникСсылка.Номенклатура"), СтрокаGUID).

При обмене через COM-соединение помните, что ссылка одной базы не имеет смысла в другой: передавайте GUID и восстанавливайте ссылку на стороне приёмника. Получить ссылку по GUID в другой базе через COM можно методом менеджера объекта ПолучитьСсылку(Новый УникальныйИдентификатор(GUID)).

Также проверяйте, что полученная по GUID ссылка реально существует в базе: метод ПолучитьОбъект() у «битой» ссылки вернёт Неопределено. Это типичная ситуация после удаления объектов без контроля ссылочной целостности.

Типичные ошибки
01
Обращение к ТекущиеДанные.Номенклатура без проверки на Неопределено — ошибка при пустой таблице
02
Попытка получить ссылку на саму строку табличной части — у строки нет ссылки, только у реквизитов и владельца
03
Обращение к реквизитам через пустую ссылку после неудачного поиска — получение нулевых значений или ошибки
04
Использование ПолучитьОбъект() в цикле ради чтения одного реквизита — падение производительности
05
Сравнение ссылок через оператор = смешанных типов без приведения — ложный результат сравнения

Проверка результата и отладка

После получения ссылки убедитесь, что она корректна. Минимальный набор проверок: значение не равно Неопределено, ссылка не пустая, тип соответствует ожидаемому. Для проверки типа используйте ТипЗнч(СсылкаНаТовар) = Тип("СправочникСсылка.Номенклатура").

В отладчике удобно смотреть значение ссылки в табло: там отображается представление объекта и его тип. Если вместо представления виден текст «Объект не найден» с идентификатором — это битая ссылка, объект был удалён из базы.

Контрольные точки

Как проверить результат

Значение переменной
Норма

СправочникСсылка или ДокументСсылка с представлением объекта

Тревожный признак

Неопределено или пустая ссылка

Тип значения через ТипЗнч
Норма

Совпадает с ожидаемым типом

Тревожный признак

Другой тип — значит, взят не тот реквизит строки

Представление в отладчике
Норма

Наименование или номер объекта

Тревожный признак

«Объект не найден» — битая ссылка

Для массовой обработки полезно выводить в журнал регистрации или в сообщения номер строки и полученную ссылку — так проще локализовать строку, в которой данные не заполнены или не найдены.

Итог

Что важно запомнить

Строка табличной части ссылки не имеет. Получайте либо значение ссылочного реквизита строки (СтрокаТовары.Номенклатура), либо ссылку на владельца (Ссылка в модуле объекта или поле Ссылка в запросе к табличной части). Всегда проверяйте результат на Неопределено и пустую ссылку, а для чтения реквизитов обращайтесь через ссылку без ПолучитьОбъект().

Частые вопросы

Можно ли получить ссылку на саму строку табличной части?

Нет. Строка табличной части хранится как часть объекта-владельца и не имеет собственного уникального идентификатора в базе. Идентифицировать строку можно по номеру строки, ключу уникальности (если он есть в конфигурации) или по идентификатору строки в данных формы, но это не ссылка в смысле встроенного языка.

Почему ТекущиеДанные.Номенклатура возвращает ошибку?

Чаще всего потому, что ТекущиеДанные равны Неопределено: таблица пуста или фокус не на ней. Добавьте проверку «Если ТекущиеДанные = Неопределено Тогда Возврат». Вторая причина — колонка «Номенклатура» не добавлена в элемент формы, хотя реквизит в табличной части существует.

Как получить ссылку на документ, зная только его табличную часть в запросе?

В запросе к табличной части доступно поле Ссылка — это и есть ссылка на документ-владелец. Например: ВЫБРАТЬ Товары.Ссылка ИЗ Документ.РеализацияТоваровУслуг.Товары КАК Товары. Дополнительно доступны поля НомерСтроки и все реквизиты табличной части.

Чем отличается Ссылка от ПолучитьОбъект()?

Ссылка — это лёгкий указатель на объект, через неё можно читать реквизиты и сравнивать значения. ПолучитьОбъект() загружает весь объект в память, позволяет его изменять и вызывает блокировку при записи. Для чтения данных достаточно ссылки — это быстрее и безопаснее.

Как передать ссылку из табличной части во внешнюю систему?

Преобразуйте её в строку GUID: Строка(Ссылка.УникальныйИдентификатор()) или XMLСтрока(Ссылка). На стороне приёмника восстановите ссылку через XMLЗначение или ПолучитьСсылку с новым УникальныйИдентификатор, а затем проверьте, что объект существует.

Почему НайтиПоНаименованию вернул не тот элемент?

Наименования в справочнике могут повторяться — поиск возвращает первый найденный элемент. Если точность критична, ищите по уникальному реквизиту (код, артикул) или используйте запрос с дополнительными условиями, например по владельцу или пометке удаления.