При разработке расширений для типовых конфигураций, таких как «Бухгалтерия предприятия 3.0», разработчики часто сталкиваются с ситуацией, когда привычный код, работающий в формах документов или справочников, отказывается функционировать в формах отчетов. Одной из самых частых задач является автоматическая подстановка счета (например, счета 60 или 70) в отчете Карточка счета при его открытии, а также ограничение доступа к этому полю для определенных пользователей. В этой статье мы подробно разберем, почему возникают ошибки «Переменная не определена (Объект)» или «Поле объекта недоступно для записи», и научимся правильно инициализировать данные в отчетах.
Первая и самая важная причина, по которой код Объект.Счет = ... выдает ошибку в форме отчета, заключается в архитектуре платформы 1С. Мы привыкли, что в формах документов, справочников или задач основным реквизитом является Объект. Однако формы отчетов устроены иначе.
В форме любого отчета (и «Карточка счета» не исключение) основным реквизитом выступает Отчет. Этот реквизит имеет тип, соответствующий объекту конфигурации «Отчет». Поэтому попытка обратиться к Объект приводит к тому, что система не находит такую переменную в контексте формы. Проанализируем правильное обращение: если вам нужно программно изменить значение счета на форме отчета, необходимо обращаться к Отчет.Счет.
Другой важный аспект — правильное использование директив компиляции. Рассмотрим ситуацию, когда процедура ПриОткрытии помечена директивой &НаСервере. Это грубая ошибка, так как событие ПриОткрытии является исключительно клиентским. Оно предназначено для взаимодействия с пользователем непосредственно перед тем, как форма станет доступна для ввода.
Если нам необходимо получить данные из базы (например, найти счет по его коду в плане счетов), мы должны разделить логику:
ПриОткрытии.ПриСозданииНаСервере для первоначальной инициализации данных.Часто начинающие разработчики пытаются присвоить значение непосредственно визуальному элементу: Элементы.Счет = ДайСчет(). Это приводит к ошибке «Поле объекта недоступно для записи». Разберем почему.
Коллекция Элементы содержит объекты типа «ПолеФормы», «КнопкаФормы» и так далее. У них есть свойства, отвечающие за внешний вид (Доступность, Видимость, ТолькоПросмотр), но они сами по себе не хранят данные. Данные хранятся в реквизитах формы. Чтобы изменить значение в поле ввода, нужно изменить значение реквизита, с которым это поле связано (свойство ПутьКДанным). В нашем случае это Отчет.Счет.
Рассмотрим правильную реализацию задачи: нам нужно при открытии отчета «Карточка счета» установить счет 70 для всех пользователей, кроме Ольги, и запретить им его редактирование.
Для поиска ссылки на счет нам потребуется обращение к базе данных, которое возможно только на сервере. Создадим вспомогательную функцию:
&НаСервере
Функция ПолучитьСсылкуНаСчет(КодСчета)
Возврат ПланыСчетов.Хозрасчетный.НайтиПоКоду(КодСчета);
КонецФункции
Теперь воспользуемся механизмом расширений и создадим обработчик &После("ПриОткрытии"). Обратите внимание на использование правильного пути к данным и работу с элементами формы.
&НаКлиенте
Процедура Расш1_ПриОткрытииПосле(Отказ)
// Проверяем имя пользователя (приводим к верхнему регистру для надежности)
ТекущийПользователь = ВРег(ИмяПользователя());
Если СтрНайти(ТекущийПользователь, "ОЛЬГА") = 0 Тогда
// Если это не Ольга, устанавливаем счет программно
СчетДляУстановки = ПолучитьСсылкуНаСчет("70");
// ВАЖНО: Присваиваем реквизиту Отчет.Счет, а не Элементу!
Отчет.Счет = СчетДляУстановки;
// Блокируем возможность редактирования для пользователя
Элементы.Счет.Доступность = Ложь;
Сообщить("Для вашего пользователя установлен предопределенный счет.");
Иначе
Сообщить("Добро пожаловать, Ольга. Поле выбора счета доступно для редактирования.");
КонецЕсли;
КонецПроцедуры
Проанализируем еще один важный момент. В современных конфигурациях, таких как БП 3.0, многие отчеты строятся с использованием Системы компоновки данных (СКД). В этом случае поле «Счет» может быть не просто реквизитом формы, а параметром компоновщика настроек.
Если после выполнения вышеуказанного кода счет на форме заполнился, но отчет при нажатии кнопки «Сформировать» все равно использует старое значение или выдает пустоту, значит, необходимо обновить параметры в КомпоновщикеНастроек. Рассмотрим, как это сделать на сервере:
&НаСервере
Процедура УстановитьСчетВКомпоновщике(ЗначениеСчета)
// Поиск параметра "Счет" в настройках компоновщика
Для Каждого Параметр Из Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы Цикл
Если Строка(Параметр.Параметр) = "Счет" Тогда
Параметр.Значение = ЗначениеСчета;
Параметр.Использование = Истина;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Наиболее корректным способом инициализации данных в расширениях считается использование события ПриСозданииНаСервере. Это позволяет избежать лишних вызовов между клиентом и сервером. Посмотрим на итоговый пример реализации через это событие:
&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
ТекущийПользователь = ВРег(ИмяПользователя());
Если СтрНайти(ТекущийПользователь, "ОЛЬГА") = 0 Тогда
// Находим счет сразу на сервере
Счет70 = ПланыСчетов.Хозрасчетный.НайтиПоКоду("70");
// Заполняем реквизит отчета
Отчет.Счет = Счет70;
// Управляем доступностью элемента формы
Элементы.Счет.Доступность = Ложь;
КонецЕсли;
КонецПроцедуры
Для успешной работы с расширением в отчете «Карточка счета» помните следующие правила:
Отчет.Счет для обращения к данным, а не Объект.Счет.Элементы.Счет.ПланыСчетов.Хозрасчетный.НайтиПоКоду) выполняйте только на сервере.Следуя этим рекомендациям, вы сможете гибко настраивать поведение типовых отчетов под нужды ваших пользователей, сохраняя чистоту кода и стабильность работы системы.