При переходе от ручного формирования отчетов к автоматическому (через регламентные задания) программисты часто сталкиваются с ситуацией, когда код, идеально работающий в обработке на клиенте, выдает ошибку на сервере. Особенно это актуально для конфигурации «Управление торговлей 10.3», где активно используется «Универсальный отчет» на базе обычных форм. Рассмотрим подробнее, почему возникает ошибка «Значение не является значением объектного типа (ДатаНачала)» и как правильно организовать выгрузку отчетов по расписанию.
Проанализируем ситуацию. В обычном приложении при сохранении настроек отчета в регистр сведений СохраненныеНастройки или системное хранилище, 1С упаковывает в ХранилищеЗначения структуру, содержащую различные объекты. Один из таких объектов — НастройкаПериода. Этот объект является чисто интерфейсным (клиентским). Он предназначен для работы с диалоговыми окнами выбора периода, которые мы видим на экране.
Когда регламентное задание запускается на сервере, происходит следующее:
ХранилищеЗначения методом Получить().НастройкаПериода не может быть корректно инициализирован.Неопределено.СохраненнаяНастройка.НастройкаПериода.ДатаНачала система закономерно сообщает, что значение не является объектным типом.Это классическое ограничение платформы: НастройкаПериода не доступна на сервере. Также стоит учитывать, что регламентные задания выполняются от имени специального пользователя или с пустым контекстом пользователя, что может влиять на доступ к настройкам, если они жестко привязаны к текущему авторизованному сотруднику.
Универсальный отчет в УТ 10.3 — это надстройка над объектом ПостроительОтчета. Чтобы отчет корректно формировался в фоновом задании, нам нужно отказаться от использования высокоуровневых интерфейсных свойств и перейти к управлению параметрами построителя напрямую. Разберем по шагам, как это реализовать.
Вместо того чтобы пытаться установить дату через НастройкаПериода, мы должны найти, как эти даты называются в параметрах самого построителя. Обычно это ДатаНач и ДатаКон.
Пример скорректированного кода для серверного модуля:
// Получаем настройку из хранилища
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
НастройкаСтруктура = Выборка.СохраненнаяНастройка.Получить();
// Создаем объект отчета программно (без формы!)
ОтчетОбъект = Обработки.УниверсальныйОтчет.Создать();
// Загружаем настройки в объект (имитируем логику типовой конфигурации)
// Важно: на сервере загрузка может не заполнить клиентские объекты
ОтчетОбъект.УстановитьНастройки(НастройкаСтруктура);
// Устанавливаем период напрямую в построитель, обходя НастройкаПериода
// Предположим, ПериодДата1 и ПериодДата2 рассчитаны заранее
ОтчетОбъект.ПостроительОтчета.Параметры.Вставить("ДатаНач", ПериодДата1);
ОтчетОбъект.ПостроительОтчета.Параметры.Вставить("ДатаКон", КонецДня(ПериодДата2));
// Если отчет использует стандартные переменные Универсального отчета:
ОтчетОбъект.ДатаНач = ПериодДата1;
ОтчетОбъект.ДатаКон = КонецДня(ПериодДата2);
// Выполняем формирование
ОтчетОбъект.СформироватьОтчет(ТабличныйДокумент);
КонецЕсли;
Если логика Универсального отчета в вашей конфигурации слишком сильно переплетена с методами формы (например, в процедуре СформироватьОтчет есть обращения к ЭлементыФормы), то переписывание кода под сервер может занять недели. В этом случае проанализируем альтернативный вариант — использование COM-соединения.
Суть метода заключается в том, что сервер 1С программно запускает «толстого клиента» в скрытом режиме. Поскольку это полноценный сеанс приложения, там будут доступны и НастройкаПериода, и все интерфейсные модули. Это позволит выполнить отчет ровно так же, как если бы его запустил пользователь вручную.
Рассмотрим пример логики:
V83.Application (или V83.COMConnector, но для обычных форм надежнее Application).Важный нюанс: Этот способ требует наличия лицензии на сеанс и может быть медленнее, чем прямое выполнение на сервере.
Часто проблема кроется не только в коде, но и в данных. Проверьте, под каким пользователем запускается регламентное задание. Если в запросе вы ищете настройки конкретного «Иванова», а фоновое задание работает под системной учетной записью, убедитесь, что у этой учетной записи есть права на чтение регистра СохраненныеНастройки.
Также проанализируем ситуацию с ПараметрыСеанса. В типовой УТ 10.3 многие функции (например, получение валюты учета или цен) опираются на глТекущийПользователь. В регламентном задании эта переменная может быть пустой. Перед формированием отчета обязательно инициализируйте глобальные переменные или установите нужные значения в параметры сеанса:
// Пример инициализации пользователя для корректной работы типовых механизмов
ТекущийПользователь = Справочники.Пользователи.НайтиПоНаименованию("Робот_Выгрузки");
ПараметрыСеанса.ТекущийПользователь = ТекущийПользователь;
// Инициализация глобальных переменных, если отчет на них завязан
УправлениеПользователями.УстановитьПараметрыСеанса();
Чтобы избежать ошибок в будущем, рекомендуем придерживаться следующих правил при автоматизации отчетов в «старых» конфигурациях:
ТипЗнч(Настройка.Свойство).НастройкаПериода, передавайте в отчет явные значения НачалоДня и КонецДня.Таким образом, основная проблема решается путем отказа от использования экранных объектов (таких как НастройкаПериода) в пользу прямой установки параметров в ПостроительОтчета или КомпоновщикНастроек (если используется СКД). Проанализировав контекст выполнения, вы сможете легко адаптировать любой отчет для работы по расписанию.