При разработке в среде 1С:Предприятие 8.3 на управляемых формах разработчики нередко сталкиваются с необходимостью повторить интерактивные действия пользователя из фоновых процессов, подписок на события или регламентных заданий. Типичный пример — необходимость пересчитать строки документа ТабельУчетаРабочегоВремени при проведении или записи сопутствующих документов (например, регистраций переработок или сверхурочных часов).
Попытка обратиться к форме через серверный код приводит к ошибкам платформы. Разберем, почему возникает такое поведение, почему нельзя обращаться к контексту формы на сервере и как правильно реализовать программное заполнение данных объекта.
Проанализируем типовую ошибочную конструкцию, с которой часто начинают разработку:
// Ошибочный подход в серверном контексте
сс = Документы.ТабельУчетаРабочегоВремени.НайтиПоНомеру("0А00-000015", Источник.Дата);
об = сс.ПолучитьОбъект();
ЭтаФорма = об.ПолучитьФорму(); // Вызовет исключение на сервере
Выясним причину такого поведения платформы 1С:
ПолучитьФорму() предназначен для клиентского контекста или работы в режиме обычного приложения. На стороне сервера без активного сеанса взаимодействия с пользователем формы физически не существует. Сервер выполняет чистую бизнес-логику и транзакции базы данных.Формы (например, УчетРабочегоВремениРасширенныйФормы) оперируют исключительно визуальными структурами. Они ожидают на вход параметры типа УправляемаяФорма, ДанныеФормыКоллекция, ДанныеФормыСтруктура и обращаются к элементам интерфейса (например, Форма.Элементы.ДанныеОВремени.ТекущаяСтрока). У объекта ДокументОбъект таких свойств нет.Рассмотрим правильный подход. Вся логика расчета, получения данных из регистров и заполнения табличных частей в типовых конфигурациях (включая «1С:Зарплата и управление персоналом 3») вынесена в серверные модули — модули менеджеров, модули объектов и общие серверные модули учета времени.
Разберем по шагам, как организовать программный пересчет и обновление данных без обращения к интерфейсу:
ДокументОбъект через метод ПолучитьОбъект().ТабельУчетаРабочегоВремени (например, ТаблицаДанныхДляЗаполнения) или функции серверного общего модуля УчетРабочегоВремениРасширенный.ДанныеОВремени объекта.Записать() в необходимом режиме.Посмотрим на пример серверного кода обновления строк документа:
// Серверный алгоритм пересчета табеля
ТабельОбъект = СсылкаНаТабель.ПолучитьОбъект();
Если ТабельОбъект <> Неопределено Тогда
Для Каждого СтрСотрудник Из Источник.Сотрудники Цикл
Отбор = Новый Структура("Сотрудник", СтрСотрудник.Сотрудник);
НайденныеСтроки = ТабельОбъект.ДанныеОВремени.НайтиСтроки(Отбор);
// Модифицируем показатели времени в табличной части объекта
Для Каждого СтрокаТабеля Из НайденныеСтроки Цикл
// Вызываем серверный расчет показателей по регистрам учета времени
// и обновляем реквизиты строки (Часы, ВидВремени и т.д.)
КонецЦикла;
КонецЦикла;
// Записываем документ
ТабельОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецЕсли;
Если логика заполнения была изначально написана разработчиком внутри модуля формы и отсутствует в модуле менеджера, её необходимо отрефакторить. Перенесем расчетные процедуры из модуля формы в модуль объекта или менеджер документа.
Проанализируем разницу в типах данных при адаптации кода:
ДанныеФормыКоллекция работаем с обычной ТабличнаяЧасть объекта или ТаблицаЗначений.Идентификатор через интерфейсную коллекцию используем поиск по реквизитам через Найти() или НайтиСтроки() у табличной части объекта.Элементы, ТекущаяСтрока и ЭтаФорма, передавая конкретную строку или ссылку в качестве явного параметра процедуры.Посмотрим на пример процедуры, адаптированной для работы на сервере:
// В модуле менеджера или модуле объекта
Процедура ЗаполнитьДанныеПоСотрудникуСервер(ТабельОбъект, СотрудникСсылка) Экспорт
Отбор = Новый Структура("Сотрудник", СотрудникСсылка);
СтрокиВремени = ТабельОбъект.ДанныеОВремени.НайтиСтроки(Отбор);
Для Каждого Строка Из СтрокиВремени Цикл
// Серверный алгоритм заполнения реквизитов строки времени
КонецЦикла;
КонецПроцедуры
Если пересчет вызывается из подписки на события ПриЗаписи или ОбработкаПроведения другого документа, важно учитывать следующие особенности платформы: