Как получить пустую ссылку в клиентском коде 1С 8.3
Содержание
Получить пустую ссылку на клиенте 1С проще всего так: ПредопределенноеЗначение("Справочник.Номенклатура.ПустаяСсылка"). Функция работает в тонком клиенте, веб-клиенте и в коде &НаКлиентеНаСервереБезКонтекста, поэтому её используют вместо Справочники.Номенклатура.ПустаяСсылка(), недоступной на клиенте.
Второй способ — получить пустое значение нужного типа через ОписаниеТипов. Он удобен, когда тип известен только во время выполнения. Ниже — оба метода с кодом, проверка на пустоту и подводные камни составных типов. Тема общая для платформы 8.3 и любой конфигурации на управляемых формах.
Почему менеджер справочника на клиенте не работает
Менеджеры объектов — Справочники, Документы, ПланыВидовХарактеристик и другие — живут на сервере. В модуле управляемой формы код с директивой &НаКлиенте к ним не обращается.
Если написать в клиентской процедуре:
&НаКлиенте
Процедура ОчиститьНоменклатуру(Команда)
Объект.Номенклатура = Справочники.Номенклатура.ПустаяСсылка();
КонецПроцедуры
модуль не пройдёт проверку: компилятор сообщит, что переменная Справочники не определена. В толстом клиенте обычного приложения такой код работал, поэтому старые примеры с форумов сбивают с толку.
Сами ссылки при этом на клиент передаются свободно. Реквизит формы типа СправочникСсылка.Номенклатура на клиенте доступен, его можно читать, сравнивать и присваивать. Нельзя только вызвать серверный менеджер, чтобы «сделать» значение.
Отсюда три рабочих пути:
- ✅
ПредопределенноеЗначение()— строка с именем, без серверного вызова в вашем коде; - ✅
Новый ОписаниеТипов(...).ПривестиЗначение()— пустое значение по типу; - ⚠️ серверная функция
&НаСервереБезКонтекста, которая вернётПустаяСсылка(), — работает, но стоит лишнего обращения к серверу.
Пустая ссылка через ПредопределенноеЗначение
Функция глобального контекста принимает строку вида "<Вид объекта>.<Имя>.ПустаяСсылка". Кроме имён предопределённых элементов, она понимает служебное имя ПустаяСсылка.
&НаКлиенте
Процедура ОчиститьНоменклатуру(Команда)
Объект.Номенклатура = ПредопределенноеЗначение("Справочник.Номенклатура.ПустаяСсылка");
КонецПроцедуры
Строки для разных видов объектов
| Вид объекта | Пример строки |
|---|---|
| Справочник | "Справочник.Контрагенты.ПустаяСсылка" |
| Документ | "Документ.РеализацияТоваровУслуг.ПустаяСсылка" |
| Перечисление | "Перечисление.СтавкиНДС.ПустаяСсылка" |
| План видов характеристик | "ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.ПустаяСсылка" |
| План счетов | "ПланСчетов.Хозрасчетный.ПустаяСсылка" |
Первое слово пишется в единственном числе: Справочник, а не Справочники. Это та же нотация, что в языке запросов внутри ЗНАЧЕНИЕ(...). Имена объектов в таблице взяты для примера — у вас они те, что заданы в метаданных вашей конфигурации.
Где удобнее всего
- 📌 в клиентских обработчиках формы: очистка поля, сброс отбора, начальное значение;
- 📌 в общих модулях с флагами «Клиент» и «Сервер» и в процедурах
&НаКлиентеНаСервереБезКонтекста— одна и та же строка работает по обе стороны; - 📌 в условиях сравнения:
Если Объект.Склад = ПредопределенноеЗначение("Справочник.Склады.ПустаяСсылка") Тогда.
Строка проверяется только при выполнении. Опечатка в имени справочника не подсветится при синтаксическом контроле модуля, а вызовет исключение в момент, когда пользователь нажмёт кнопку. Прогоните каждую ветку кода хотя бы раз руками.
Пустое значение по типу через ОписаниеТипов
Объект ОписаниеТипов создаётся на клиенте. Метод ПривестиЗначение() возвращает значение, приведённое к описанному типу. Если передать Неопределено и описание с одним ссылочным типом, получится пустая ссылка этого типа.
&НаКлиенте
Функция ПустаяСсылкаПоИмениТипа(ИмяТипа)
// ИмяТипа, например: "СправочникСсылка.Номенклатура"
Описание = Новый ОписаниеТипов(ИмяТипа);
Возврат Описание.ПривестиЗначение(Неопределено);
КонецФункции
Следите за нотацией: здесь нужно имя типа СправочникСсылка.Номенклатура, а не путь Справочник.Номенклатура.ПустаяСсылка. Путать эти две записи — частая причина ошибки «тип не определён».
Пустая ссылка того же типа, что и значение
Типичная задача универсального кода: есть значение произвольного ссылочного типа, нужно сбросить его в пустое, не меняя тип. Строку собирать не обязательно — достаточно массива типов.
&НаКлиенте
Функция ПустаяСсылкаТогоЖеТипа(Значение)
Типы = Новый Массив;
Типы.Добавить(ТипЗнч(Значение));
Описание = Новый ОписаниеТипов(Типы);
Возврат Описание.ПривестиЗначение(Неопределено);
КонецФункции
Если передать сюда ссылку на контрагента, вернётся пустая ссылка СправочникСсылка.Контрагенты. Если ссылку на документ — пустая ссылка этого вида документа.
Какой способ выбрать
| Способ | Когда подходит | Ограничения |
|---|---|---|
ПредопределенноеЗначение() | Тип известен на этапе написания кода | Опечатка в строке всплывает только при выполнении |
ОписаниеТипов по имени типа | Тип приходит параметром в виде строки | Нужна нотация СправочникСсылка.Имя |
ОписаниеТипов по ТипЗнч() | Нужно «обнулить» значение, сохранив его тип | Значение не должно быть Неопределено |
| Серверная функция | Пустую ссылку всё равно получают вместе с другими данными с сервера | Отдельный серверный вызов ради одной ссылки избыточен |
ПредопределенноеЗначение("Справочник.Имя.ПустаяСсылка"). Читается лучше всего, работает и в клиент-серверных модулях.Новый ОписаниеТипов(ИмяТипа) и вызовите ПривестиЗначение(Неопределено). Строка — в формате СправочникСсылка.Имя или ДокументСсылка.Имя.ТипЗнч(Значение), создайте по нему ОписаниеТипов и приведите Неопределено.Справочники.Имя.ПустаяСсылка(). Отдельного вызова не добавляйте.Как проверить ссылку на пустоту на клиенте
Получить пустую ссылку — полдела. Чаще её нужно распознать: заполнил ли пользователь поле, вернул ли выбор значение.
Метод Пустая()
У ссылок справочников, документов, перечислений и других ссылочных типов есть метод Пустая(). Он доступен в клиентском контексте и возвращает Истина для пустой ссылки.
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
Если Объект.Контрагент.Пустая() Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не указан контрагент";
Сообщение.Поле = "Объект.Контрагент";
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Ограничение одно, но серьёзное: метод есть только у ссылки. Если в переменной Неопределено, строка или число, вызов упадёт с ошибкой Метод объекта не обнаружен (Пустая).
Функция ЗначениеЗаполнено()
ЗначениеЗаполнено() — функция глобального контекста, она работает на клиенте и принимает значение любого типа. Для пустой ссылки, Неопределено, пустой строки, нуля и пустой даты она вернёт Ложь.
&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
Если Не ЗначениеЗаполнено(Объект.Контрагент) Тогда
Объект.Договор = ПредопределенноеЗначение("Справочник.ДоговорыКонтрагентов.ПустаяСсылка");
Возврат;
КонецЕсли;
// дальше — заполнение договора по контрагенту
КонецПроцедуры
Сравнение подходов к проверке
| Проверка | Безопасна для любого типа | Отличает пустую ссылку от Неопределено |
|---|---|---|
Значение.Пустая() | ❌ нет | только для ссылок |
ЗначениеЗаполнено(Значение) | ✅ да | ❌ нет, обе «незаполнены» |
Значение = ПредопределенноеЗначение("...ПустаяСсылка") | ✅ да | ✅ да, сравнивает с конкретным типом |
Значение = Неопределено | ✅ да | ловит только Неопределено |
Пустая ссылка не равна Неопределено. Условие Если Объект.Склад = Неопределено Тогда для незаполненного реквизита ссылочного типа вернёт Ложь, и ветка не выполнится.
Пустые ссылки в реквизитах составного типа
Реквизит составного типа — например, Субконто или «Документ основание», где допустимы несколько видов документов — ведёт себя иначе, чем реквизит с одним типом.
Пока такой реквизит не заполнен, в нём лежит Неопределено, а не пустая ссылка. Тип ещё не выбран, и платформа не знает, пустую ссылку какого вида хранить.
Что из этого следует на практике:
- 🔸
Объект.Основание.Пустая()упадёт на незаполненном реквизите — тамНеопределено; - 🔸 после выбора типа без выбора значения в реквизите может оказаться пустая ссылка конкретного вида, и проверка
= Неопределеноеё пропустит; - 🔸 единственная проверка, корректная для обоих случаев, —
ЗначениеЗаполнено().
Как сбросить значение составного реквизита
Здесь два варианта, и выбор зависит от смысла поля:
- Сбросить полностью, вместе с типом. Присвойте
Неопределено. Пользователь снова увидит выбор типа. - Оставить тип, очистить значение. Получите пустую ссылку того же типа функцией
ПустаяСсылкаТогоЖеТипа()из раздела проОписаниеТипови присвойте её.
&НаКлиенте
Процедура ОчиститьОснованиеСохранивТип(Команда)
Если ЗначениеЗаполнено(Объект.Основание) Тогда
Объект.Основание = ПустаяСсылкаТогоЖеТипа(Объект.Основание);
КонецЕсли;
КонецПроцедуры
Проверка ЗначениеЗаполнено() перед вызовом нужна: от Неопределено функция ТипЗнч() вернёт тип Неопределено, и «пустой ссылки того же типа» не получится.
Определить вид ссылки без серверного вызова
Для ветвления по виду объекта на клиенте сравнивайте тип, а не метаданные:
Если ТипЗнч(Объект.Основание) = Тип("ДокументСсылка.ПоступлениеТоваровУслуг") Тогда
// обработка поступления
КонецЕсли;
Метод Метаданные() у ссылки на клиенте недоступен, а Тип() и ТипЗнч() работают везде.
Лишние обращения к серверу и как их убрать
На клиенте каждая серверная процедура формы — это обмен по сети. В файловой базе на одном компьютере его не видно. В веб-клиенте или через интернет каждый вызов добавляет заметную задержку, а в цикле задержки складываются.
Чего избегать
// Плохо: серверный вызов ради одной пустой ссылки
&НаСервереБезКонтекста
Функция ПолучитьПустойСклад()
Возврат Справочники.Склады.ПустаяСсылка();
КонецФункции
Такая функция работает, но делает то, что на клиенте решается одной строкой без сервера. Если её вызвать в цикле по табличной части, сеть получит столько вызовов, сколько строк в таблице.
Что делать вместо этого
- ⚡ получите пустую ссылку один раз до цикла и сохраните в переменную;
- ⚡ строки для
ПредопределенноеЗначение()вынесите в общий клиент-серверный модуль, если одна и та же ссылка нужна во многих формах; - ⚡ если серверный вызов в процедуре всё равно есть, верните из него всё нужное сразу — структурой с несколькими полями.
&НаКлиенте
Процедура ОчиститьСкладыВТаблице(Команда)
ПустойСклад = ПредопределенноеЗначение("Справочник.Склады.ПустаяСсылка");
Для Каждого Строка Из Объект.Товары Цикл
Строка.Склад = ПустойСклад;
КонецЦикла;
КонецПроцедуры
Значения, подготовленные при открытии формы
Если форме постоянно нужны одни и те же значения по умолчанию, подготовьте их в ПриСозданииНаСервере. Этот обработчик и так выполняется на сервере при открытии, поэтому дополнительного вызова не будет.
Создайте реквизит формы нужного ссылочного типа и не заполняйте его: при открытии формы в нём будет пустая ссылка. На клиенте читайте его как обычную переменную. Способ удобен, когда рядом с пустой ссылкой нужны и другие данные с сервера — например, основной склад организации.
Отдельно про замер. Количество серверных вызовов показывает замер производительности в режиме отладки. Если после клика в списке видно несколько вызовов там, где ожидался один, ищите функции-обёртки вроде ПолучитьПустойСклад().
Ошибки при работе с пустой ссылкой на клиенте
Ниже — ошибки, которые не видны при беглом тестировании и проявляются уже у пользователей.
&НаКлиенте. Замените вызов Справочники.Имя.ПустаяСсылка() на ПредопределенноеЗначение("Справочник.Имя.ПустаяСсылка").Неопределено — обычно это незаполненный реквизит составного типа или пустая переменная. Используйте ЗначениеЗаполнено().Справочники. вместо Справочник.) или имя типа СправочникСсылка. вместо пути. Сверьте строку с именем объекта в дереве конфигурации.Неопределено, а в реквизите лежит пустая ссылка. Перейдите на ЗначениеЗаполнено() или сравнивайте с пустой ссылкой нужного типа.ПредопределенноеЗначение() не переименовываются вместе с объектом. Найдите старое имя глобальным поиском по конфигурации и исправьте все вхождения.Ещё одна ловушка — сравнение пустых ссылок разных типов. Пустая ссылка Справочник.Склады не равна пустой ссылке Справочник.Контрагенты: тип у них разный. Поэтому в универсальной процедуре сравнение с «какой-то» пустой ссылкой не работает
— проверяйте через ЗначениеЗаполнено().
Частые вопросы
Можно ли получить пустую ссылку в запросе, а не в коде?
ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Но запрос выполняется на сервере, так что для клиентского кода это не замена ПредопределенноеЗначение().Какой уникальный идентификатор у пустой ссылки?
00000000-0000-0000-0000-000000000000. Сравнивать ссылки по идентификатору ради проверки на пустоту не нужно — для этого есть Пустая() и ЗначениеЗаполнено().Как передать пустую ссылку в параметры открываемой формы?
ПараметрыФормы.Вставить("Склад", ПредопределенноеЗначение("Справочник.Склады.ПустаяСсылка")). Ссылки сериализуются и спокойно проходят между клиентом и сервером.Работает ли ПредопределенноеЗначение в веб-клиенте и мобильном клиенте?
Чем пустая ссылка отличается от ссылки на удалённый объект?
ЗначениеЗаполнено() для битой ссылки вернёт Истина, поэтому такие ссылки ищут на сервере, а не проверкой на пустоту.