При разработке отчетов в системе «1С:Предприятие 8.3» часто возникает необходимость настроить автоматическое заполнение параметров или реквизитов формы значениями по умолчанию. Например, при открытии отчета поле «Дата начала» должно автоматически заполняться первым числом текущего месяца или определенной фиксированной датой. На первый взгляд задача кажется тривиальной: достаточно написать одну строчку кода в процедуре инициализации формы. Однако на практике разработчики, особенно начинающие, сталкиваются с тем, что установленное значение «исчезает» или не отображается на форме. В рамках этой статьи мы подробно разберем, почему так происходит, изучим разницу между типами реквизитов, проанализируем жизненный цикл формы и рассмотрим правильные архитектурные подходы для платформы 1С.
Прежде чем писать код, нам необходимо четко понимать, с каким именно объектом данных мы работаем. В управляемом приложении 1С реквизиты, отображаемые на форме, могут принадлежать двум принципиально разным категориям:
Отчет. Путь к данным у таких элементов на форме выглядит как Отчет.ИмяРеквизита (например, Отчет.Дата1).Дата1).Рассмотрим разницу в обращении к ним в программном коде модуля формы. Если наш реквизит принадлежит отчету (объекту метаданных), то прямое обращение к нему по имени в модуле формы вызовет ошибку или создаст локальную переменную, которая уничтожится сразу после завершения процедуры. Для обращения к нему обязательно нужно использовать имя основного реквизита формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Если реквизит принадлежит отчету (объекту метаданных)
Отчет.Дата1 = '20190201';
КонецПроцедуры
Если же мы создали реквизит непосредственно на форме (вкладка «Реквизиты» формы), то обращаться к нему следует напрямую по его имени, без каких-либо префиксов:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Если это собственный реквизит формы
Дата1 = '20190201';
КонецПроцедуры
Обязательно проверим свойство элемента формы «ПутьКДанным». Именно оно определяет, куда записывается введенное пользователем значение. Всегда сверяйте написание переменной в коде с тем, что указано в этом свойстве.
Выясним причину, почему использование метода ЗначениеВРеквизитФормы() в данном контексте является ошибкой. Начинающие разработчики часто пытаются использовать следующую конструкцию:
ЗначениеВРеквизитФормы("01.02.2019", дата1); // Ошибка выполнения!
Давайте проанализируем, для чего на самом деле предназначены методы ЗначениеВРеквизитФормы() и РеквизитФормыВЗначение(). Эти системные функции используются исключительно для преобразования сложных прикладных типов данных (таких как справочники, документы, отчеты в виде объектов баз данных) в специальные типы данных управляемой формы (такие как ДанныеФормыСтруктура или ДанныеФормыКоллекция) и обратно. Это необходимо для того, чтобы на сервере выполнить методы объекта (например, заполнить документ по умолчанию по алгоритму модуля объекта), а затем вернуть результат обратно на форму.
Пытаться передать в этот метод простую строку или простую дату — бессмысленно и приведет к ошибке выполнения. Простые типы данных (числа, строки, даты, булево) присваиваются напрямую стандартным оператором присваивания =.
Часто разработчики пишут синтаксически верный код присвоения, например, Дата1 = '20190201';, но при запуске отчета поле на форме все равно остается пустым. Рассмотрим подробнее механизмы платформы 1С, которые могут приводить к такому поведению.
Основная причина кроется в механизме сохранения настроек пользователя и интеграции с Библиотекой стандартных подсистем (БСП). Жизненный цикл инициализации формы отчета выглядит следующим образом:
ПриСозданииНаСервере(). Здесь выполняется наш программный код, и реквизит действительно принимает значение '20190201'.Дата1 тем значением, которое было сохранено при последнем закрытии отчета пользователем. Если в прошлый раз это поле было пустым, то установленная нами дата будет затерта пустой датой.Для решения этой проблемы мы можем пойти несколькими путями, в зависимости от того, как спроектирован наш отчет.
Если наш отчет построен с использованием Схемы компоновки данных (СКД), то параметры дат обычно находятся внутри настроек компоновщика, а не просто в реквизитах формы. В этом случае правильнее всего инициализировать параметры напрямую в компоновщике настроек. Для этого в модуле формы отчета используются специализированные события.
Проанализируем пример использования события ПриЗагрузкеВариантаНаСервере(). Этот метод вызывается платформой в тот момент, когда происходит загрузка варианта отчета, что гарантирует сохранность установленных нами значений и исключает их затирание стандартными механизмами:
&НаСервере
Процедура ПриЗагрузкеВариантаНаСервере(НовыеНастройки)
// Получаем параметр "ДатаНачала" из схемы компоновки данных
ПараметрДата = НовыеНастройки.ПараметрыДанных.Элементы.Найти("ДатаНачала");
Если ПараметрДата <> Неопределено Тогда
ПараметрДата.Значение = '20190201';
ПараметрДата.Использование = Истина;
КонецЕсли;
КонецПроцедуры
Также мы можем использовать процедуру модуля объекта отчета ПриКомпоновкеРезультата(). Этот метод вызывается непосредственно перед формированием отчета, и в нем можно зафиксировать параметры по умолчанию, если пользователь их не заполнил на форме:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Установим значение параметра по умолчанию, если оно не задано
Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("Дата1"));
Если Параметр <> Неопределено И НЕ ЗначениеЗаполнено(Параметр.Значение) Тогда
Параметр.Значение = '20190201';
Параметр.Использование = Истина;
КонецЕсли;
КонецПроцедуры
В ходе обсуждения участники часто предлагают использовать функцию ДАТА("20190201"). Давайте разберем, почему в реальной разработке такой подход считается неоптимальным. Использование строковых функций преобразования заставляет платформу выполнять лишние вычисления для парсинга строки во внутренний формат даты при каждом выполнении кода.
В языке программирования 1С для явного указания дат существуют специальные синтаксические конструкции — литералы дат. Они записываются в одинарных кавычках в формате 'ГГГГММДД' или 'ГГГГММДДЧЧММСС'. Это позволяет компилятору сразу воспринимать значение как дату без каких-либо накладных расходов.
Посмотрим на примеры правильного и производительного написания дат в коде:
// Правильное использование литералов дат
Дата1 = '20190201'; // 1 февраля 2019 года (время 00:00:00 по умолчанию)
Дата2 = '2019-02-01'; // Альтернативный формат записи с дефисами
ДатаВремя = '20190201123000'; // 1 февраля 2019 года, 12 часов 30 минут
Использование литералов делает код чище, избавляет от потенциальных ошибок локализации при парсинге строк и повышает скорость работы системы.
В современной практике разработки жесткое прописание дат внутри самого отчета часто является признаком «плохого тона», если этот отчет должен открываться контекстно (например, из формы документа или списка с уже предопределенным периодом). Правильным архитектурным решением является передача параметров при открытии формы.
Рассмотрим, как реализовать этот механизм по шагам. Сначала в коде формы-отправителя (откуда мы открываем отчет) мы формируем структуру параметров и передаем ее в метод открытия формы:
&НаКлиенте
Процедура ОткрытьОтчетПоДате(Команда)
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("СформироватьПриОткрытии", Истина);
ПараметрыОткрытия.Вставить("Дата1", '20190201');
ОткрытьФорму("Отчет.Продажи.Форма.ФормаОтчета", ПараметрыОткрытия);
КонецПроцедуры
Затем в модуле формы самого отчета в процедуре ПриСозданииНаСервере() мы перехватываем переданные параметры и заполняем наш реквизит:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, был ли передан параметр "Дата1"
Если Параметры.Свойство("Дата1") Тогда
// Заполняем реквизит формы переданным значением
Дата1 = Параметры.Дата1;
Иначе
// Устанавливаем значение по умолчанию, если параметр не передан
Дата1 = ТекущаяДата();
КонецЕсли;
КонецПроцедуры
Если мы хотим упростить разработку, мы можем воспользоваться встроенным свойством реквизита формы в конфигураторе. В палитре свойств реквизита Дата1 найдем свойство «Параметр получения». Если установить там галочку, платформа 1С автоматически, без написания программного кода в ПриСозданииНаСервере(), свяжет переданный в параметрах открытия ключ "Дата1" с этим реквизитом формы при ее инициализации.
Подводя итог, составим краткий чек-лист, по которому мы всегда сможем быстро проверить, почему не заполняется дата на форме отчета:
Отчет.ИмяРеквизита, то в коде пишите Отчет.ИмяРеквизита = .... Если написано просто ИмяРеквизита, пишите ИмяРеквизита = ....'ГГГГММДД' вместо строковых функций ДАТА().ПриЗагрузкеВариантаНаСервере() модуля формы или ПриКомпоновкеРезультата() модуля объекта.Следуя этим правилам и понимая внутренние механизмы работы платформы 1С:Предприятие 8.3, вы сможете легко избегать ошибок при программном заполнении любых интерфейсных данных.