Как получить пустую ссылку в клиентском коде 1С 8.3

· 9 мин

Содержание

Получить пустую ссылку на клиенте 1С проще всего так: ПредопределенноеЗначение("Справочник.Номенклатура.ПустаяСсылка"). Функция работает в тонком клиенте, веб-клиенте и в коде &НаКлиентеНаСервереБезКонтекста, поэтому её используют вместо Справочники.Номенклатура.ПустаяСсылка(), недоступной на клиенте.

Второй способ — получить пустое значение нужного типа через ОписаниеТипов. Он удобен, когда тип известен только во время выполнения. Ниже — оба метода с кодом, проверка на пустоту и подводные камни составных типов. Тема общая для платформы 8.3 и любой конфигурации на управляемых формах.

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

Менеджеры объектов — Справочники, Документы, ПланыВидовХарактеристик и другие — живут на сервере. В модуле управляемой формы код с директивой &НаКлиенте к ним не обращается.

Если написать в клиентской процедуре:

&НаКлиенте
Процедура ОчиститьНоменклатуру(Команда)
	Объект.Номенклатура = Справочники.Номенклатура.ПустаяСсылка();
КонецПроцедуры

модуль не пройдёт проверку: компилятор сообщит, что переменная Справочники не определена. В толстом клиенте обычного приложения такой код работал, поэтому старые примеры с форумов сбивают с толку.

Сами ссылки при этом на клиент передаются свободно. Реквизит формы типа СправочникСсылка.Номенклатура на клиенте доступен, его можно читать, сравнивать и присваивать. Нельзя только вызвать серверный менеджер, чтобы «сделать» значение.

Отсюда три рабочих пути:

  • ✅ ПредопределенноеЗначение() — строка с именем, без серверного вызова в вашем коде;
  • ✅ Новый ОписаниеТипов(...).ПривестиЗначение() — пустое значение по типу;
  • ⚠️ серверная функция &НаСервереБезКонтекста, которая вернёт ПустаяСсылка(), — работает, но стоит лишнего обращения к серверу.

Пустая ссылка через ПредопределенноеЗначение

Функция глобального контекста принимает строку вида "<Вид объекта>.<Имя>.ПустаяСсылка". Кроме имён предопределённых элементов, она понимает служебное имя ПустаяСсылка.

&НаКлиенте
Процедура ОчиститьНоменклатуру(Команда)
	Объект.Номенклатура = ПредопределенноеЗначение("Справочник.Номенклатура.ПустаяСсылка");
КонецПроцедуры

Строки для разных видов объектов

Вид объектаПример строки
Справочник"Справочник.Контрагенты.ПустаяСсылка"
Документ"Документ.РеализацияТоваровУслуг.ПустаяСсылка"
Перечисление"Перечисление.СтавкиНДС.ПустаяСсылка"
План видов характеристик"ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.ПустаяСсылка"
План счетов"ПланСчетов.Хозрасчетный.ПустаяСсылка"

Первое слово пишется в единственном числе: Справочник, а не Справочники. Это та же нотация, что в языке запросов внутри ЗНАЧЕНИЕ(...). Имена объектов в таблице взяты для примера — у вас они те, что заданы в метаданных вашей конфигурации.

Где удобнее всего

  • 📌 в клиентских обработчиках формы: очистка поля, сброс отбора, начальное значение;
  • 📌 в общих модулях с флагами «Клиент» и «Сервер» и в процедурах &НаКлиентеНаСервереБезКонтекста — одна и та же строка работает по обе стороны;
  • 📌 в условиях сравнения: Если Объект.Склад = ПредопределенноеЗначение("Справочник.Склады.ПустаяСсылка") Тогда.

Строка проверяется только при выполнении. Опечатка в имени справочника не подсветится при синтаксическом контроле модуля, а вызовет исключение в момент, когда пользователь нажмёт кнопку. Прогоните каждую ветку кода хотя бы раз руками.

Пустое значение по типу через ОписаниеТипов

Объект ОписаниеТипов создаётся на клиенте. Метод ПривестиЗначение() возвращает значение, приведённое к описанному типу. Если передать Неопределено и описание с одним ссылочным типом, получится пустая ссылка этого типа.

&НаКлиенте
Функция ПустаяСсылкаПоИмениТипа(ИмяТипа)
	// ИмяТипа, например: "СправочникСсылка.Номенклатура"
	Описание = Новый ОписаниеТипов(ИмяТипа);
	Возврат Описание.ПривестиЗначение(Неопределено);
КонецФункции

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

Пустая ссылка того же типа, что и значение

Типичная задача универсального кода: есть значение произвольного ссылочного типа, нужно сбросить его в пустое, не меняя тип. Строку собирать не обязательно — достаточно массива типов.

&НаКлиенте
Функция ПустаяСсылкаТогоЖеТипа(Значение)
	Типы = Новый Массив;
	Типы.Добавить(ТипЗнч(Значение));
	Описание = Новый ОписаниеТипов(Типы);
	Возврат Описание.ПривестиЗначение(Неопределено);
КонецФункции

Если передать сюда ссылку на контрагента, вернётся пустая ссылка СправочникСсылка.Контрагенты. Если ссылку на документ — пустая ссылка этого вида документа.

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

СпособКогда подходитОграничения
ПредопределенноеЗначение()Тип известен на этапе написания кодаОпечатка в строке всплывает только при выполнении
ОписаниеТипов по имени типаТип приходит параметром в виде строкиНужна нотация СправочникСсылка.Имя
ОписаниеТипов по ТипЗнч()Нужно «обнулить» значение, сохранив его типЗначение не должно быть Неопределено
Серверная функцияПустую ссылку всё равно получают вместе с другими данными с сервераОтдельный серверный вызов ради одной ссылки избыточен
Что у вас есть на клиенте?

Как проверить ссылку на пустоту на клиенте

Получить пустую ссылку — полдела. Чаще её нужно распознать: заполнил ли пользователь поле, вернул ли выбор значение.

Метод Пустая()

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

&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
	Если Объект.Контрагент.Пустая() Тогда
		Сообщение = Новый СообщениеПользователю;
		Сообщение.Текст = "Не указан контрагент";
		Сообщение.Поле = "Объект.Контрагент";
		Сообщение.Сообщить();
		Отказ = Истина;
	КонецЕсли;
КонецПроцедуры

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

Функция ЗначениеЗаполнено()

ЗначениеЗаполнено() — функция глобального контекста, она работает на клиенте и принимает значение любого типа. Для пустой ссылки, Неопределено, пустой строки, нуля и пустой даты она вернёт Ложь.

&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
	Если Не ЗначениеЗаполнено(Объект.Контрагент) Тогда
		Объект.Договор = ПредопределенноеЗначение("Справочник.ДоговорыКонтрагентов.ПустаяСсылка");
		Возврат;
	КонецЕсли;
	// дальше — заполнение договора по контрагенту
КонецПроцедуры

Сравнение подходов к проверке

ПроверкаБезопасна для любого типаОтличает пустую ссылку от Неопределено
Значение.Пустая()❌ неттолько для ссылок
ЗначениеЗаполнено(Значение)✅ да❌ нет, обе «незаполнены»
Значение = ПредопределенноеЗначение("...ПустаяСсылка")✅ да✅ да, сравнивает с конкретным типом
Значение = Неопределено✅ даловит только Неопределено

Пустая ссылка не равна Неопределено. Условие Если Объект.Склад = Неопределено Тогда для незаполненного реквизита ссылочного типа вернёт Ложь, и ветка не выполнится.

Пустые ссылки в реквизитах составного типа

Реквизит составного типа — например, Субконто или «Документ основание», где допустимы несколько видов документов — ведёт себя иначе, чем реквизит с одним типом.

Пока такой реквизит не заполнен, в нём лежит Неопределено, а не пустая ссылка. Тип ещё не выбран, и платформа не знает, пустую ссылку какого вида хранить.

Что из этого следует на практике:

  • 🔸 Объект.Основание.Пустая() упадёт на незаполненном реквизите — там Неопределено;
  • 🔸 после выбора типа без выбора значения в реквизите может оказаться пустая ссылка конкретного вида, и проверка = Неопределено её пропустит;
  • 🔸 единственная проверка, корректная для обоих случаев, — ЗначениеЗаполнено().

Как сбросить значение составного реквизита

Здесь два варианта, и выбор зависит от смысла поля:

  1. Сбросить полностью, вместе с типом. Присвойте Неопределено. Пользователь снова увидит выбор типа.
  2. Оставить тип, очистить значение. Получите пустую ссылку того же типа функцией ПустаяСсылкаТогоЖеТипа() из раздела про ОписаниеТипов и присвойте её.
&НаКлиенте
Процедура ОчиститьОснованиеСохранивТип(Команда)
	Если ЗначениеЗаполнено(Объект.Основание) Тогда
		Объект.Основание = ПустаяСсылкаТогоЖеТипа(Объект.Основание);
	КонецЕсли;
КонецПроцедуры

Проверка ЗначениеЗаполнено() перед вызовом нужна: от Неопределено функция ТипЗнч() вернёт тип Неопределено, и «пустой ссылки того же типа» не получится.

Определить вид ссылки без серверного вызова

Для ветвления по виду объекта на клиенте сравнивайте тип, а не метаданные:

Если ТипЗнч(Объект.Основание) = Тип("ДокументСсылка.ПоступлениеТоваровУслуг") Тогда
	// обработка поступления
КонецЕсли;

Метод Метаданные() у ссылки на клиенте недоступен, а Тип() и ТипЗнч() работают везде.

Лишние обращения к серверу и как их убрать

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

Чего избегать

// Плохо: серверный вызов ради одной пустой ссылки
&НаСервереБезКонтекста
Функция ПолучитьПустойСклад()
	Возврат Справочники.Склады.ПустаяСсылка();
КонецФункции

Такая функция работает, но делает то, что на клиенте решается одной строкой без сервера. Если её вызвать в цикле по табличной части, сеть получит столько вызовов, сколько строк в таблице.

Что делать вместо этого

  • ⚡ получите пустую ссылку один раз до цикла и сохраните в переменную;
  • ⚡ строки для ПредопределенноеЗначение() вынесите в общий клиент-серверный модуль, если одна и та же ссылка нужна во многих формах;
  • ⚡ если серверный вызов в процедуре всё равно есть, верните из него всё нужное сразу — структурой с несколькими полями.
&НаКлиенте
Процедура ОчиститьСкладыВТаблице(Команда)
	ПустойСклад = ПредопределенноеЗначение("Справочник.Склады.ПустаяСсылка");
	Для Каждого Строка Из Объект.Товары Цикл
		Строка.Склад = ПустойСклад;
	КонецЦикла;
КонецПроцедуры

Значения, подготовленные при открытии формы

Если форме постоянно нужны одни и те же значения по умолчанию, подготовьте их в ПриСозданииНаСервере. Этот обработчик и так выполняется на сервере при открытии, поэтому дополнительного вызова не будет.

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

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

Ошибки при работе с пустой ссылкой на клиенте

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

Диагностика: выберите симптом

Ещё одна ловушка — сравнение пустых ссылок разных типов. Пустая ссылка Справочник.Склады не равна пустой ссылке Справочник.Контрагенты: тип у них разный. Поэтому в универсальной процедуре сравнение с «какой-то» пустой ссылкой не работает — проверяйте через ЗначениеЗаполнено().

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

Можно ли получить пустую ссылку в запросе, а не в коде?
Да. В тексте запроса пишут ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Но запрос выполняется на сервере, так что для клиентского кода это не замена ПредопределенноеЗначение().
Какой уникальный идентификатор у пустой ссылки?
Нулевой: 00000000-0000-0000-0000-000000000000. Сравнивать ссылки по идентификатору ради проверки на пустоту не нужно — для этого есть Пустая() и ЗначениеЗаполнено().
Как передать пустую ссылку в параметры открываемой формы?
Как любое другое значение: положите её в структуру параметров, например ПараметрыФормы.Вставить("Склад", ПредопределенноеЗначение("Справочник.Склады.ПустаяСсылка")). Ссылки сериализуются и спокойно проходят между клиентом и сервером.
Работает ли ПредопределенноеЗначение в веб-клиенте и мобильном клиенте?
Да, функция относится к глобальному контексту и доступна во всех клиентских приложениях платформы 8.3. Ограничения те же: строка должна точно совпадать с именем объекта в конфигурации.
Чем пустая ссылка отличается от ссылки на удалённый объект?
Пустая ссылка ни на что не указывает изначально. «Битая» ссылка указывает на объект, которого больше нет в базе. ЗначениеЗаполнено() для битой ссылки вернёт Истина, поэтому такие ссылки ищут на сервере, а не проверкой на пустоту.