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