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