При разработке интерфейсов в 1С:Предприятии 8 часто возникает необходимость автоматически заполнять реквизиты формы. Например, при создании нового документа требуется подставить наименование, ИНН и юридический адрес собственной организации, а при выборе покупателя — сразу подтягивать его контактные данные. Разберем по шагам, с какими ошибками можно столкнуться при реализации этой задачи и как написать правильный, отказоустойчивый код.
Проанализируем типичную ошибку, которую часто допускают начинающие разработчики. Попытка обратиться к реквизитам напрямую через менеджер справочника приводит к аварийному завершению программы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Адрес = Справочники.Фирмы.ЮрАдрес;
Продавец = Справочники.Фирмы.Наименование;
ИННПродавца = Справочники.Фирмы.ИНН;
КонецПроцедуры
Выясним причину этой ошибки. Объект Справочники.Фирмы представляет собой менеджер справочника, а не конкретный элемент базы данных. У менеджера есть предопределенные методы (например, НайтиПоКоду, СоздатьЭлемент, Выбрать), но у него нет и не может быть реквизитов конкретного юридического лица. Реквизиты принадлежат конкретной ссылке или объекту.
Чтобы прочитать данные нашей фирмы, сначала необходимо получить ссылку на нужный элемент справочника. Простейший способ — поиск по уникальному коду:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
МояФирма = Справочники.Фирмы.НайтиПоКоду("000001");
Если ЗначениеЗаполнено(МояФирма) Тогда
Объект.Адрес = МояФирма.ЮрАдрес;
Объект.Продавец = МояФирма.Наименование;
Объект.ИННПродавца = МояФирма.ИНН;
КонецЕсли;
КонецПроцедуры
Обратите внимание на два важных нюанса:
Объект. (например, Объект.Адрес), иначе значения запишутся во временные переменные процедуры и на форме ничего не отобразится.НайтиПоКоду вернет не Неопределено, а пустую ссылку (Справочники.Фирмы.ПустаяСсылка()). Обращение через точку к пустой ссылке не вызовет ошибку, но вернет пустые значения. Поэтому всегда рекомендуется выполнять проверку через ЗначениеЗаполнено().Рассмотрим тонкость работы обработчика ПриСозданииНаСервере: эта процедура выполняется не только при создании нового документа, но и при каждом открытии ранее сохраненного объекта. Если не предусмотреть проверку, реквизиты уже проведенного документа будут перезаписываться значениями по умолчанию при каждом просмотре карточки.
Чтобы избежать нежелательной перезаписи данных, добавим проверку ключа объекта:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, что открывается новый, еще не записанный объект
Если Параметры.Ключ.Пустая() Тогда
МояФирма = Справочники.Фирмы.НайтиПоКоду("000001");
Если ЗначениеЗаполнено(МояФирма) Тогда
Объект.Продавец = МояФирма.Наименование;
Объект.Адрес = МояФирма.ЮрАдрес;
Объект.ИННПродавца = МояФирма.ИНН;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
С точки зрения стандартов разработки 1С, «зашивать» конкретный код элемента в текст модуля не рекомендуется. Оптимальным решением будет хранение основной организации в объекте метаданных Константа, в параметрах сеанса или использование предопределенного элемента справочника.
Теперь решим вторую задачу: как только пользователь выбирает покупателя в поле формы, должны автоматически заполниться его ИНН и юридический адрес. В управляемом приложении события элементов формы выполняются на клиенте, а чтение реквизитов объекта требует обращения к серверу.
Разберем по шагам правильную организацию связки «Клиент — Сервер»:
Клиент привязываем обработчик события ПриИзменении.
&НаКлиенте
Процедура КлиентПриИзменении(Элемент)
КлиентПриИзмененииНаСервере();
КонецПроцедуры
&НаСервере
Процедура КлиентПриИзмененииНаСервере()
Покупатель = Объект.Клиент;
Если ЗначениеЗаполнено(Покупатель) Тогда
Объект.АдресПокупателя = Покупатель.ЮрАдрес;
Объект.ИННПокупателя = Покупатель.ИНН;
Иначе
Объект.АдресПокупателя = "";
Объект.ИННПокупателя = "";
КонецЕсли;
КонецПроцедуры
Здесь не нужно выполнять поиск через НайтиПоНаименованию, поскольку реквизит Объект.Клиент уже содержит готовую ссылку на элемент справочника Контрагенты.
Обращение к реквизитам через точку (Покупатель.ЮрАдрес) приводит к неявному считыванию всех полей и табличных частей объекта из базы данных в память сервера. Если справочник содержит тяжелые данные, это замедляет работу системы. При промышленной разработке более производительным решением является чтение конкретных полей через запрос:
&НаСервере
Процедура КлиентПриИзмененииНаСервере()
Если НЕ ЗначениеЗаполнено(Объект.Клиент) Тогда
Объект.АдресПокупателя = "";
Объект.ИННПокупателя = "";
Возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.ЮрАдрес КАК ЮрАдрес,
| Контрагенты.ИНН КАК ИНН
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Объект.Клиент);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Объект.АдресПокупателя = Выборка.ЮрАдрес;
Объект.ИННПокупателя = Выборка.ИНН;
КонецЕсли;
КонецПроцедуры
Если реквизиты контрагента (ИНН, адрес) не требуется сохранять непосредственно в самом документе, а нужно только выводить их для информации пользователю, программный код вообще писать не требуется.
В редакторе формы достаточно добавить элемент Поле надписи или Поле ввода (свойство «Только просмотр») и в свойстве ПутьКДанным указать цепочку реквизитов: Объект.Клиент.ЮрАдрес или Объект.Клиент.ИНН. Платформа будет автоматически обновлять эти данные на клиенте при любом изменении контрагента.
При работе с реквизитами ИНН и КПП часто возникает необходимость объединить их в единую строку формата «ИНН/КПП». Если реквизиты в конфигурации ошибочно созданы с типом Число, простая конкатенация через знак плюс может привести к математическому сложению или добавлению лишних пробелов.
При неявном преобразовании числа к строке платформа 1С автоматически разделяет тысячи пробелами (например, «77 012 345 67»). Чтобы выполнить склеивание корректно, следует использовать функцию Формат() с отключением группировки разрядов:
СтрокаИНН = Формат(Объект.ИНН, "ЧГ=0");
СтрокаКПП = Формат(Объект.КПП, "ЧГ=0");
ИННКПП = СтрокаИНН + "/" + СтрокаКПП;
Тем не менее, лучшей практикой является использование типа данных Строка для хранения кодов ИНН и КПП, так как числовой тип приводит к безвозвратной потере лидирующих нулей в реквизитах.