Получить ссылку в 1С приходится почти в каждой доработке: загрузить прайс из Excel, принять заказ с сайта, подставить склад по умолчанию, проверить статус документа в коде. Ссылка — это не текст «Молоко 3,2%», а указатель на конкретную запись базы: тип объекта плюс уникальный идентификатор. Строку из файла или из обмена в реквизит не запишешь, сначала по ней нужно найти элемент. Ниже — все способы получить ссылку программно в 1С 8.3: НайтиПоКоду, НайтиПоНаименованию, НайтиПоРеквизиту, НайтиПоНомеру для документов, предопределённые значения, ПолучитьСсылку по уникальному идентификатору и запрос.
Менеджеры Справочники и Документы со всеми методами поиска доступны на сервере (а также в толстом клиенте обычного приложения и во внешнем соединении). В управляемой форме обработчик команды выполняется на клиенте, поэтому поиск выносят в серверную функцию и возвращают на клиент уже готовую ссылку — ссылочные значения передаются между клиентом и сервером без ограничений.
// АртикулДляПоиска и Товар — реквизиты формы
&НаКлиенте
Процедура НайтиТовар(Команда)
Товар = НайтиТоварПоАртикулу(АртикулДляПоиска);
Если Не ЗначениеЗаполнено(Товар) Тогда
Сообщить("Товар с артикулом " + АртикулДляПоиска + " не найден");
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция НайтиТоварПоАртикулу(Артикул)
Возврат Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", СокрЛП(Артикул));
КонецФункции
&НаСервереБезКонтекста лучше, чем &НаСервере: данные формы функции не нужны, и они не передаются на сервер.
Чтобы получить ссылку на элемент справочника по коду, у менеджера есть метод НайтиПоКоду(Код, ПоискПоПолномуКоду, Родитель, Владелец). Он возвращает ссылку или пустую ссылку, если ничего не нашёл. Исключения при неудачном поиске нет, поэтому результат проверяют всегда.
// Код передаём строкой целиком: с префиксом и ведущими нулями
Товар = Справочники.Номенклатура.НайтиПоКоду("00-00000123");
Если Товар.Пустая() Тогда
ВызватьИсключение "Не найдена номенклатура с кодом 00-00000123";
КонецЕсли;
// Подчинённый справочник, коды уникальны в пределах владельца:
// третий параметр (родитель) пропускаем, четвёртым передаём владельца
Договор = Справочники.ДоговорыКонтрагентов.НайтиПоКоду("00-000045", Ложь, , Контрагент);
На чём спотыкаются:
"123" вместо "00-00000123" вернёт пустую ссылку.Найти по наименованию в 1С соблазнительно: в файле поставщика часто есть только название товара. Сигнатура похожая: НайтиПоНаименованию(Наименование, ТочноеСоответствие, Родитель, Владелец).
// Опасно: второй параметр по умолчанию Ложь, совпадение может быть частичным
Товар = Справочники.Номенклатура.НайтиПоНаименованию("Молоко");
// Точнее: только полное совпадение. Дубли наименований это не решает
Товар = Справочники.Номенклатура.НайтиПоНаименованию(СокрЛП(НаименованиеИзФайла), Истина);
Проблем три. Первая — второй параметр по умолчанию равен Ложь, и тогда совпадение ищется по началу строки: по «Молоко» можно получить «Молоко 3,2% 1 л». Вторая — наименование не уникально: два элемента «Болт М8» в разных группах для платформы нормальны, метод вернёт первый попавшийся. Третья — пользователи переименовывают элементы, и загрузка, которая работала вчера, сегодня перестаёт находить товары. Поэтому НайтиПоНаименованию годится для разовой обработки под присмотром человека, но не для регулярного обмена. Для обмена нужен устойчивый ключ: код, артикул, ИНН или идентификатор внешней системы.
У документов нет кода и наименования, зато есть номер: НайтиПоНомеру(Номер, ДатаИнтервала). Номера обычно уникальны только в пределах периода (свойство документа «Периодичность», чаще всего — год), поэтому вторым параметром передают любую дату из нужного периода.
// Номера уникальны в пределах года: вторым параметром — любая дата этого года
Заказ = Документы.ЗаказКлиента.НайтиПоНомеру("ТД00-000045", Дата(2026, 3, 15));
Если Заказ.Пустая() Тогда
Сообщить("Заказ не найден");
КонецЕсли;
Номер указывают полностью, с префиксом организации или информационной базы. Если нужен поиск по номеру без префикса или по номеру и контрагенту сразу — это уже работа для запроса.
Когда ключ хранится в обычном реквизите, найти ссылку помогает НайтиПоРеквизиту(ИмяРеквизита, Значение, Родитель, Владелец).
Контрагент = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", "7700000000");
Если Контрагент.Пустая() Тогда
// создаём нового или пишем в протокол загрузки
КонецЕсли;
Метод возвращает первый найденный элемент и не сообщает, были ли другие. Для ИНН это критично: в базе легко оказываются организация и её обособленное подразделение с одним ИНН и разными КПП. Второй момент — скорость. По коду и наименованию у справочника есть индексы, а обычный реквизит индексируется, только если в конфигураторе у него свойство «Индексирование» не равно «Не индексировать». Без индекса каждый вызов на большом справочнике — просмотр всей таблицы. Искать по реквизиту-строке неограниченной длины и по реквизитам табличных частей этот метод не умеет.
Элементы, которые нужны коду всегда (основной склад, статус «Выполнен», служебный вид цены), в конфигурации делают предопределёнными или выносят в перечисление. Искать их по коду или наименованию не нужно — к ним обращаются по имени.
// Сервер: через менеджеры (имена условные)
Склад = Справочники.Склады.ОсновнойСклад;
Статус = Перечисления.СтатусыЗаказов.Выполнен;
// Клиент или сервер: по строковому пути
Статус = ПредопределенноеЗначение("Перечисление.СтатусыЗаказов.Выполнен");
ПустойТовар = ПредопределенноеЗначение("Справочник.Номенклатура.ПустаяСсылка");
На сервере пишут через менеджер: Справочники.Склады.ОсновнойСклад. На клиенте менеджеров нет, там работает ПредопределенноеЗначение("Перечисление.СтатусыЗаказов.Выполнен") — функция доступна и на клиенте, и на сервере. Через неё же получают пустую ссылку нужного типа. Подробнее про значения перечислений — в статье как создать перечисление 1С и получить его значение.
Имена в примерах условные. Опечатка в строке ПредопределенноеЗначение обнаружится только при выполнении кода.
Если внешняя система хранит GUID элемента (сайт, мобильное приложение, другая база 1С), ссылку восстанавливают без поиска методом менеджера ПолучитьСсылку(УникальныйИдентификатор).
&НаСервереБезКонтекста
Функция НоменклатураПоИдентификатору(СтрокаИдентификатора)
Идентификатор = Новый УникальныйИдентификатор(СтрокаИдентификатора);
Ссылка = Справочники.Номенклатура.ПолучитьСсылку(Идентификатор);
// ПолучитьСсылку не проверяет, есть ли объект в базе, — проверяем сами
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА КАК Найден
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Если Запрос.Выполнить().Пустой() Тогда
Возврат Справочники.Номенклатура.ПустаяСсылка();
КонецЕсли;
Возврат Ссылка;
КонецФункции
Метод не обращается к базе: он собирает ссылку из типа и идентификатора. Поэтому он самый быстрый — и единственный из перечисленных, который вернёт ссылку на объект, которого нет. Если такую ссылку записать в документ, в поле появится <Объект не найден>. Существование проверяют запросом, как в примере, или функцией ОбщегоНазначения.СсылкаСуществует из БСП, если конфигурация на ней построена.
Тот же результат даёт XMLЗначение(Тип("СправочникСсылка.Номенклатура"), СтрокаИдентификатора), а чтобы сохранить идентификатор как текст — XMLСтрока(Ссылка) или Строка(Ссылка.УникальныйИдентификатор()). Вызов ПолучитьСсылку() без параметра создаёт ссылку с новым идентификатором: так ссылку назначают объекту заранее, до записи, через УстановитьСсылкуНового.
Каждый вызов метода менеджера — отдельное обращение к базе. В цикле по 20 000 строкам прайса это 20 000 запросов, и загрузка идёт минутами там, где хватило бы секунд. Правильнее собрать ключи в массив и получить все ссылки одним запросом. Заодно запрос умеет то, чего не умеют методы: отсечь помеченные на удаление элементы и группы и показать дубли.
// Серверный общий модуль (или модуль объекта обработки загрузки).
// Имена объектов условные: справочник Номенклатура с реквизитом Артикул
// и иерархией групп и элементов.
// Приводит артикул к виду для сравнения: без пробелов по краям, в верхнем регистре.
// Этой же функцией нормализуют артикул из файла перед поиском в соответствии.
Функция КлючАртикула(Артикул) Экспорт
// Excel может отдать числовой артикул. Формат без ЧГ=0
// добавил бы разделитель разрядов и ключ не совпал бы с "12345".
Если ТипЗнч(Артикул) = Тип("Число") Тогда
Артикул = Формат(Артикул, "ЧГ=0");
КонецЕсли;
Возврат ВРег(СокрЛП(Строка(Артикул)));
КонецФункции
// Находит ссылки на номенклатуру по списку артикулов одним запросом.
// Параметры:
// Артикулы - Массив - строки артикулов из файла или из обмена.
// Дубли - Массив - (возвращаемый) ключи артикулов, найденных у нескольких элементов.
// Возвращаемое значение:
// Соответствие - ключ: КлючАртикула(...), значение: СправочникСсылка.Номенклатура.
// Ненайденные и неоднозначные артикулы в соответствие не попадают.
Функция СсылкиНоменклатурыПоАртикулам(Артикулы, Дубли) Экспорт
Результат = Новый Соответствие;
Дубли = Новый Массив;
Ключи = Новый Массив;
Для Каждого Артикул Из Артикулы Цикл
Ключ = КлючАртикула(Артикул);
Если ЗначениеЗаполнено(Ключ) Тогда
Ключи.Добавить(Ключ);
КонецЕсли;
КонецЦикла;
Если Ключи.Количество() = 0 Тогда
Возврат Результат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул В (&Артикулы)
| И НЕ Номенклатура.ПометкаУдаления
| И НЕ Номенклатура.ЭтоГруппа";
Запрос.УстановитьПараметр("Артикулы", Ключи);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Ключ = КлючАртикула(Выборка.Артикул);
Если Результат[Ключ] = Неопределено Тогда
Результат.Вставить(Ключ, Выборка.Ссылка);
ИначеЕсли Дубли.Найти(Ключ) = Неопределено Тогда
Дубли.Добавить(Ключ);
КонецЕсли;
КонецЦикла;
// Неоднозначный артикул не подставляем: пусть решит пользователь
Для Каждого Ключ Из Дубли Цикл
Результат.Удалить(Ключ);
КонецЦикла;
Возврат Результат;
КонецФункции
Вызов при загрузке таблицы из файла:
// Если функции лежат в серверном общем модуле РаботаСНоменклатурой,
// укажите имя модуля. В модуле самой обработки префикс не нужен.
Дубли = Неопределено;
Найденные = РаботаСНоменклатурой.СсылкиНоменклатурыПоАртикулам(
ТаблицаФайла.ВыгрузитьКолонку("Артикул"), Дубли);
Для Каждого СтрокаФайла Из ТаблицаФайла Цикл
Товар = Найденные[РаботаСНоменклатурой.КлючАртикула(СтрокаФайла.Артикул)];
Если Товар = Неопределено Тогда
// нет в базе или артикул неоднозначный — в протокол
Продолжить;
КонецЕсли;
// дальше работаем с найденной ссылкой
КонецЦикла;
Разбор ключевых мест:
Номенклатура.Артикул В (&Артикулы) — в параметр передаётся массив, платформа сама подставляет его как список значений.НЕ Номенклатура.ПометкаУдаления И НЕ Номенклатура.ЭтоГруппа — фильтры, которых нет у НайтиПоКоду и НайтиПоРеквизиту. Условие на ЭтоГруппа пишут только для справочника с иерархией групп и элементов, иначе запрос не выполнится.ВРег(СокрЛП(...)). Запрос сравнивает строки без учёта регистра, а соответствие — строго. Без нормализации «ab-15» из файла найдётся запросом, но не найдётся в соответствии, где лежит «AB-15».Функцию удобно держать в серверном общем модуле или в модуле внешней обработки загрузки. Если коды внешней системы не совпадают ни с одним реквизитом, заведите регистр сведений «внешний код → ссылка» и ищите тем же способом по нему.
| Способ | Обращение к базе | Надёжность | Когда использовать |
|---|---|---|---|
| НайтиПоКоду | один запрос по индексу | высокая при уникальных кодах | коды из этой же базы, обмен между базами 1С |
| НайтиПоНаименованию | один запрос по индексу | низкая: частичное совпадение, дубли, переименования | разовые обработки под контролем человека |
| НайтиПоРеквизиту | один запрос; без индекса — просмотр таблицы | средняя: берёт первый найденный | артикул, ИНН, внешний код в единичных вызовах |
| НайтиПоНомеру | один запрос | высокая, если передана дата периода | документ по номеру |
| Предопределённые значения | минимальное | высокая | статусы, виды, служебные элементы; на клиенте — только ПредопределенноеЗначение |
| ПолучитьСсылку(УИД) | нет | ссылка может вести на несуществующий объект | внешняя система хранит GUID из 1С |
| Запрос | один запрос на весь набор | высокая: фильтры и контроль дублей | загрузки и пакетная обработка |
Короткое правило: на клиенте — ПредопределенноеЗначение или вызов сервера; для одного значения по устойчивому ключу — метод менеджера; для списка значений — запрос; наименование — только когда другого ключа нет, и с ручной проверкой результата.
&НаКлиенте. Поиск переносят в серверную функцию, а для предопределённых значений на клиенте используют ПредопределенноеЗначение.ПолучитьОбъект() и обратились к свойству: для пустой ссылки объект не получить, метод возвращает Неопределено.<Объект не найден> в поле документа — ссылка получена через ПолучитьСсылку по идентификатору, которого в этой базе нет: GUID из другой базы или удалённого элемента.СтрРазделить (платформа 8.3.6 и выше). При грязных данных вызов оборачивают в Попытка…Исключение.Если Товар = "Молоко" Тогда — ошибки нет, условие просто всегда ложно.В форме документа — Объект.Ссылка. У нового, ещё не записанного документа она пустая. Если ссылка нужна до записи, получите её через Документы.Имя.ПолучитьСсылку() и назначьте объекту методом УстановитьСсылкуНового (в управляемой форме — у параметра ТекущийОбъект в обработчике ПередЗаписьюНаСервере). В форме списка текущая строка динамического списка с основной таблицей — это и есть ссылка: Элементы.Список.ТекущаяСтрока.
Для одного значения разницы практически нет: и там и там один запрос к СУБД по индексу. Разница появляется на объёме: тысяча вызовов метода — тысяча обращений к базе, запрос по массиву — одно.
Справочники.Имя.ПолучитьСсылку(Новый УникальныйИдентификатор(Строка)) и обязательная проверка существования. Если сайт хранит собственные идентификаторы, а не GUID из 1С, храните соответствие в регистре сведений и ищите запросом по нему.
Коллекция менеджеров индексируется по имени: Справочники[ИмяСправочника].НайтиПоКоду(Код). Для полного имени вида «Справочник.Номенклатура» в конфигурациях на БСП есть ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени.
Найти элемент по коду — пять минут работы. Но если ссылки нужно сопоставлять при регулярной загрузке прайсов, обмене с сайтом или маркетплейсами, а в данных дубли, опечатки и чужие идентификаторы, это уже задача на правила сопоставления и протокол ошибок. Такие доработки 1С можно отдать программистам площадки: разместите задачу бесплатно — оценка бесплатная, ответ в течение рабочего дня.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.