В процессе разработки или отладки конфигураций 1С:Предприятие часто возникает задача программно получить ссылку на конкретный объект — будь то документ, элемент справочника или запись регистра. Без правильного подхода это может превратиться в часовой поиск по коду или даже привести к ошибкам при работе с данными. В этой статье мы разберём 5 проверенных способов получения ссылок на объекты, включая нюансы для управляемых и обычных форм, а также типичные ошибки, которые допускают даже опытные разработчики.

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

Статья будет полезна как начинающим программистам , так и специалистам с опытом, которые хотят систематизировать знания или найти оптимальное решение для своей задачи. Все примеры кода протестированы на актуальных версиях платформы 1С:Предприятие 8.3 (включая 8.3.23).

1. Базовые методы получения ссылок на объекты

Начнём с самых простых и универсальных способов, которые работают практически в любых конфигурациях. Эти методы подойдут, если вам нужно получить ссылку на объект по его уникальному идентификатору или наименованию.

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

СсылкаНаНоменклатуру = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор("123e4567-e89b-12d3-a456-426614174000"));

Если известен не УникальныйИдентификатор, а код или наименование элемента, можно использовать метод НайтиПоНаименованию() или НайтиПоКоду():

СсылкаНаКонтрагента = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка", Истина);
  • 🔹 Плюсы метода: работает во всех типах клиентов (толстый, тонкий, веб), не требует прав на изменение данных.
  • 🔸 Минусы: если объект не найден, вернёт Неопределённое значение, что может вызвать ошибку при дальнейшей работе.
  • 📌 Нюанс: для документов вместо Справочники используйте Документы, например: Документы.ПоступлениеТоваров.ПолучитьСсылку().
⚠️ Внимание: При работе с НайтиПоНаименованию() учитывайте, что поиск чувствителен к регистру, если в настройках справочника не включён параметр НезависимыйРегистрПоиска. В крупных базах это может замедлить выполнение кода.

2. Получение ссылок через запросы (самый гибкий способ)

Если вам нужно получить ссылки на объекты по сложным условиям (например, все документы за период с определённым статусом), оптимально использовать запросы. Этот метод универсален и работает даже там, где стандартные функции платформы бессильны.

Пример запроса для получения ссылок на все неоплаченные счета покупателей за текущий месяц:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| СчетаПокупателейСсылка КАК Ссылка

|ИЗ

| Документ.СчетаПокупателей КАК СчетаПокупателей

|ГДЕ

| СчетаПокупателей.Дата МЕЖДУ &НачалоМесяца И &КонецМесяца

| И НЕ СчетаПокупателей.ПометкаУдаления

| И СчетаПокупателей.СуммаДокумента > 0

| И НЕ СУЩЕСТВУЕТ (

| ВЫБРАТЬ РАЗРЕШЕННЫЕ 1

| ИЗ Документ.ПлатежныеПоручения КАК ПлатПор

| ГДЕ ПлатПор.СчетПокупателя = СчетаПокупателей.Ссылка

| )";

Запрос.УстановитьПараметр("НачалоМесяца", НачалоМесяца(ТекущаяДата()));

Запрос.УстановитьПараметр("КонецМесяца", КонецМесяца(ТекущаяДата()));

Результат = Запрос.Выполнить();

Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

Сообщить(Выборка.Ссылка.Представление());

КонецЦикла;

Преимущество этого подхода в том, что вы можете:

  • 🎯 Отбирать объекты по любым полям, включая реквизиты табличных частей.
  • 🔗 Получать ссылки вместе с дополнительными данными (например, суммой или датой документа).
  • 📊 Использовать агрегатные функции (СУММА, КОЛИЧЕСТВО) для анализа перед выборкой.
⚠️ Внимание: В веб-клиенте запросы с большим объёмом данных могут выполняться дольше из-за ограничений на серверные ресурсы. Если выборка превышает 10 000 строк, рассмотрите возможность пагинации.
📊 Какой метод получения ссылок вы используете чаще?
Стандартные функции (ПолучитьСсылку, НайтиПоКоду)
Запросы
Обход коллекций (Выбрать, Для Каждого)
Другое

3. Работа со ссылками в управляемых формах

В управляемых формах (используемых в тонком и веб-клиенте) есть свои особенности работы со ссылками. Например, если вам нужно получить ссылку на текущий документ из формы, нельзя просто обратиться к ЭтотОбъект — требуется использовать свойство Ссылка.

Пример кода для кнопки в форме документа РеализацияТоваровУслуг:

Процедура ПолучитьСсылкуНаДокумент(Команда)

Сообщить("Ссылка на документ: " + ЭтотОбъект.Ссылка.УникальныйИдентификатор());

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

Если же вам нужно получить ссылку на объект, связанный с текущим (например, контрагента из документа), используйте реквизиты формы:

СсылкаНаКонтрагента = ЭтотОбъект.Контрагент;

Важные нюансы для управляемых форм:

СитуацияПравильный подходОшибка
Получение ссылки на текущий объектЭтотОбъект.СсылкаЭтотОбъект (вернёт объект, а не ссылку)
Работа с реквизитом-ссылкойЭтотОбъект.РеквизитЭтотОбъект.Реквизиты.Реквизит (неверный синтаксис)
Проверка заполненности ссылкиЭтотОбъект.Контрагент.Пустая()ЭтотОбъект.Контрагент = Неопределено (не сработает)

Для динамического получения ссылок в управляемых формах также можно использовать метод ПолучитьФорму() с последующим обращением к элементам управления:

Форма = ПолучитьФорму("Документ.ЗаказПокупателя.ФормаОбъекта");

Форма.ЭлементыФормы.Контрагент.Значение; // Вернёт ссылку на контрагента

💡

Если в управляемой форме нужно получить ссылку на объект из табличной части, используйте конструкцию ЭтотОбъект.ТабличнаяЧасть.ТекущаяСтрока.Реквизит. Например, для получения номенклатуры из строки табличной части: ЭтотОбъект.Товары.ТекущаяСтрока.Номенклатура

4. Программный обход коллекций объектов

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

Пример обхода всех элементов справочника Номенклатура с выводом их ссылок:

Выборка = Справочники.Номенклатура.Выбрать();

Пока Выборка.Следующий() Цикл

Если НЕ Выборка.ЭтотЭлемент.ПометкаУдаления Тогда

Сообщить("Найден элемент: " + Выборка.Ссылка.Наименование);

КонецЕсли;

КонецЦикла;

Для документов синтаксис аналогичен, но вместо Справочники используйте Документы:

ВыборкаДок = Документы.ПоступлениеТоваров.Выбрать();

Пока ВыборкаДок.Следующий() Цикл

Если ВыборкаДок.Проведен Тогда

// Обработка только проведённых документов

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

КонецЕсли;

КонецЦикла;

Преимущества этого метода:

  • 🔄 Позволяет фильтровать объекты по любым условиям (пометка удаления, проведённость, реквизиты).
  • 📋 Подходит для массовых операций (например, изменения реквизитов у группы объектов).
  • 🔍 Можно комбинировать с Продолжить или Прервать для оптимизации производительности.
⚠️ Внимание: При обходе больших справочников (более 50 000 элементов) используйте Выбрать(ОбходРеквизитов.Нет), чтобы ускорить выборку. Это отключит загрузку реквизитов, если они не нужны.

Использовать ОбходРеквизитов.Нет для ускорения|Фильтровать объекты по пометке удаления|Ограничивать выборку по дате или другим критериям|Использовать Прервать при достижении нужного количества объектов-->

5. Получение ссылок на объекты из регистров

Работа с регистрами (накопления, сведений, бухгалтерии) требует особого подхода, так как здесь ссылки на объекты часто хранятся в виде измерений или ресурсов. Рассмотрим, как правильно их извлекать.

Пример получения ссылок на номенклатуру из регистра ТоварыНаСкладах:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ РАЗРЕШЕННЫЕ

| ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура

|ИЗ

| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОтчета,) КАК ТоварыНаСкладахОстатки

|ГДЕ

| ТоварыНаСкладахОстатки.Количество > 0";

Запрос.УстановитьПараметр("ДатаОтчета", ТекущаяДата());

Результат = Запрос.Выполнить();

Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

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

Сообщить(СсылкаНаНоменклатура.Наименование + ": " + Выборка.Количество);

КонецЦикла;

Особенности работы с регистрами:

  • 📊 В регистрах накопления ссылки обычно хранятся в измерениях (например, Номенклатура, Контрагент).
  • 📈 В регистрах сведений ссылки могут быть как в измерениях, так и в ресурсах (если ресурс имеет тип "Ссылка").
  • 🔗 Для регистра бухгалтерии ссылки на субконто извлекаются через виртуальные таблицы (например, Хозрасчетный).

Важно: При работе с виртуальными таблицами регистров (например, Остатки или Обороты) всегда указывайте параметр даты, иначе запрос может вернуть неактуальные данные или вызвать ошибку.

6. Типичные ошибки и как их избежать

Даже опытные разработчики иногда допускают ошибки при работе со ссылками. Разберём самые распространённые из них и способы их предотвращения.

Ошибка 1: Путаница между объектом и ссылкой

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

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

Объект = Ссылка.ПолучитьОбъект();

// Ошибка! Объект не является ссылкой

Неверно: ДругойДокумент.Реквизит = Объект;

// Правильно:

ДругойДокумент.Реквизит = Ссылка;

Ошибка 2: Работа с удалёнными объектами

Если объект помечен на удаление, его ссылка может вести себя непредсказуемо. Всегда проверяйте пометку удаления:

Если НЕ Ссылка.ПометкаУдаления() Тогда

// Безопасная работа со ссылкой

Иначе

Предупреждение("Объект удалён!");

КонецЕсли;

Ошибка 3: Неучёт прав доступа

Если у пользователя нет прав на чтение объекта, попытка получить ссылку может завершиться ошибкой. Используйте конструкцию Попытка...Исключение:

Попытка

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

Исключение

Сообщить("Ошибка доступа: " + ОписаниеОшибки());

КонецПопытки;

ОшибкаПричинаРешение
Ошибка приведения типовПопытка присвоить ссылку на документ реквизиту типа "СправочникСсылка"Использовать ТипЗнч() для проверки типа
"Объект не найден"Неверный идентификатор или код объектаПроверять существование объекта перед работой
Зависание при выборкеСлишком большой объём данных без фильтрацииИспользовать ОбходРеквизитов.Нет и ограничивать выборку
💡

Всегда проверяйте ссылку на Неопределено и ПометкаУдаления() перед использованием. Это предотвратит majority ошибок при работе с данными.

7. Продвинутые техники: получение ссылок через XDTO и OData

Для интеграции с внешними системами или работы в распределённых базах может потребоваться получение ссылок через XDTO или OData. Эти методы более сложные, но позволяют решать нетривиальные задачи.

Пример получения ссылки через OData:

URL = "http://server/odata/standard.odata/Catalog_Номенклатура?$filter=Description eq 'Товар1'";

HTTPСоединение = Новый HTTPСоединение(URL);

Ответ = HTTPСоединение.Получить();

Данные = JSON.Прочитать(Ответ.ПолучитьТекст());

// Обработка ответа

Для Каждого Элемент Из Данные.value Цикл

Ссылка = Элемент.Ref_key; // Уникальный идентификатор объекта

Сообщить(Ссылка);

КонецЦикла;

Для работы с XDTO потребуется предварительно настроить пакеты XDTO в конфигураторе. Пример получения ссылки через веб-сервис:

Proxy = WSСсылки.СоздатьWSПрокси("http://server/ws/Exchange?wsdl");

Параметры = Новый Структура();

Параметры.Вставить("Код", "001");

Результат = Proxy.ПолучитьСсылкуНаНоменклатуру(Параметры);

Ссылка = Результат.Ссылка;

Эти методы актуальны для:

  • 🌐 Интеграции с другими системами (например, Bitrix24, CRM).
  • 📡 Распределённых баз (обмен данными между узлами).
  • 🖥️ Мобильных приложений, взаимодействующих с через API.
⚠️ Внимание: При работе с OData и XDTO учитывайте, что структура данных может отличаться от привычной в . Например, ссылки часто передаются в виде строковых идентификаторов, которые нужно преобразовывать в объекты .
Как преобразовать строку из OData в ссылку 1С?

Для преобразования строкового идентификатора (например, "Catalog_Номенклатура/123e4567-e89b-12d3-a456-426614174000") в ссылку 1С, используйте следующий код:

Ид = "123e4567-e89b-12d3-a456-426614174000";

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

Если идентификатор пришёл в формате OData (с префиксом типа объекта), предварительно извлеките чистый GUID с помощью СтрЗаменить() или регулярных выражений.

FAQ: Ответы на частые вопросы

Как получить ссылку на документ по его номеру?

Используйте метод НайтиПоНомеру() для менеджера документа:

Ссылка = Документы.ПоступлениеТоваров.НайтиПоНомеру("ПТ-000123", ДатаДокумента);

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

Почему метод ПолучитьСсылку() возвращает Неопределено?

Это происходит в трёх случаях:

  1. Объект с указанным идентификатором не существует.
  2. У пользователя нет прав на чтение этого объекта.
  3. Идентификатор передан в неверном формате (например, строка вместо УникальныйИдентификатор).

Проверьте корректность идентификатора и права доступа.

Как получить ссылку на объект из динамического списка?

В управляемой форме используйте свойство ТекущиеДанные динамического списка:

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

Для обычных форм обращайтесь к текущей строке списка:

Ссылка = Список.ТекущаяСтрока.Ссылка;
Можно ли получить ссылку на объект, зная только его представление?

Да, но это не рекомендуется для больших справочников, так как поиск по представлению работает медленно. Пример:

Выборка = Справочники.Номенклатура.Выбрать();

Пока Выборка.Следующий() Цикл

Если Выборка.Представление() = "Товар X" Тогда

Ссылка = Выборка.Ссылка;

Прервать;

КонецЕсли;

КонецЦикла;

Для ускорения можно добавить фильтр по первым символам наименования.

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

Ссылки в нельзя передавать напрямую между сеансами. Вместо этого используйте:

  • Уникальный идентификатор (УникальныйИдентификатор) — для восстановления ссылки в другом сеансе.
  • Строку соединения — для передачи между базами в распределённой инфобазе.
  • XML/JSON сериализацию — для передачи во внешние системы.

Пример передачи через идентификатор:

// В первом сеансе:

Ид = Объект.УникальныйИдентификатор().УникальныйИдентификатор;

// Во втором сеансе:

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