При работе с платформой 1С:Предприятие, особенно в клиент-серверном варианте, мы можем столкнуться с неприятной ситуацией: отчет, который прекрасно работает в файловой базе или на небольших объемах данных, на сервере выдает сообщение "Не удалось сформировать отчет (пустой результат)". При этом видимых ошибок в коде нет, запрос в консоли отрабатывает корректно, а кэш очищен.
Эта проблема часто связана не с логикой запроса, а с особенностями работы фоновых заданий, правами доступа на уровне ОС Windows Server или объемом выводимых данных (в частности, картинок). Разберем подробно основные причины и способы их решения, опираясь на опыт сообщества.
В клиент-серверной архитектуре тяжелые отчеты формируются в фоновом задании. Результат формирования отчета (временные файлы) сохраняется в рабочую директорию кластера серверов. Если у пользователя, от имени которого запущена служба агента сервера 1С (обычно это USR1CV8), нет прав на запись в эту папку, формирование отчета прервется, и мы получим "пустой результат".
Симптомы:
Решение:
Нам необходимо проверить и настроить права доступа на уровне файловой системы сервера, а также выполнить анализ прав и ролей пользователя в самой базе — для этого есть детальный анализ прав доступа, ролей и ограничений RLS.
C:\Program Files\1cv8\srvinfo (или путь, указанный при установке службы).reg_1541.USR1CV8 или другой доменный пользователь), имеет права "Полный доступ" (Full Control) на эту папку и все вложенные объекты.После назначения прав, проблема с сохранением временных результатов фонового задания должна уйти.
Вторая распространенная причина — наличие в отчете изображений (фотографий товаров), которые хранятся в высоком разрешении. Система компоновки данных (СКД) при попытке вывести в табличный документ большое количество картинок (или одну, но очень "тяжелую", например, более 2 Мб) может не справиться с выделением памяти или передачей данных с сервера на клиент, что приведет к пустому результату. Для этой задачи подойдёт контроль размера и массовое сжатие изображений номенклатуры.
Решение: Программный вывод и сжатие картинок
Если простое формирование отчета падает, нам придется отказаться от стандартного автоматического вывода и переопределить процедуру вывода (используя инструменты для упрощения программного создания СКД (поможет инструменты для анализа метаданных и отладки СКД)), добавив механизм сжатия картинок "на лету".
Рассмотрим код, который необходимо разместить в модуле объекта отчета (для внешнего отчета) или в модуле менеджера, перехватив событие ПриКомпоновкеРезультата.
Логика следующая:
Разберем готовый пример кода:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Отключаем стандартный механизм вывода, так как будем выводить программно
СтандартнаяОбработка = Ложь;
// 1. Получаем настройки и макет
НастройкаКомпоновки = КомпоновщикНастроек.ПолучитьНастройки();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, НастройкаКомпоновки, ДанныеРасшифровки);
// 2. Инициализируем процессор компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
// 3. Выводим результат в документ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// 4. Постобработка: поиск и сжатие картинок
// Проверяем, включено ли поле "ФайлКартинки" в настройках
ЭлементыВыбранныеПоля = НастройкаКомпоновки.Выбор.Элементы;
ВывестиИзображение = Ложь;
Для каждого ЭлементВыбранногоПоля Из ЭлементыВыбранныеПоля Цикл
// Здесь "ФайлКартинки" - имя поля в вашем наборе данных, содержащего путь к файлу
Если Строка(ЭлементВыбранногоПоля.Поле) = "ФайлКартинки" И ЭлементВыбранногоПоля.Использование Тогда
ВывестиИзображение = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
// Если картинки нужны, проходим по табличному документу и обрабатываем их
Если ВывестиИзображение Тогда
КоличествоСтрок = ДокументРезультат.ВысотаТаблицы;
КоличествоКолонок = ДокументРезультат.ШиринаТаблицы;
Для СтрокаДокумента = 1 По КоличествоСтрок Цикл
Для КолонкаДокумента = 1 По КоличествоКолонок Цикл
Область = ДокументРезультат.Область(СтрокаДокумента, КолонкаДокумента);
Расшифровка = Область.Расшифровка;
// Проверяем расшифровку, чтобы найти нужные данные
Если ТипЗнч(Расшифровка) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
ПоляРасшифровки = ДанныеРасшифровки.Элементы.Получить(Расшифровка).ПолучитьПоля();
НайденноеПоле = ПоляРасшифровки.Найти("ФайлКартинки");
Если НайденноеПоле <> Неопределено Тогда
Если ЗначениеЗаполнено(НайденноеПоле.Значение) Тогда
// Предполагается, что в поле хранится структура с Томом и Путем (как в 1С:УТ/ERP)
// Если у вас хранилище значения, код получения данных будет иным
Если ЗначениеЗаполнено(НайденноеПоле.Значение.Том) И ЗначениеЗаполнено(НайденноеПоле.Значение.ПутьКФайлу) Тогда
ПутьККартинке = НайденноеПоле.Значение.Том.ПолныйПутьWindows + НайденноеПоле.Значение.ПутьКФайлу;
Если ЗначениеЗаполнено(ПутьККартинке) Тогда
Фото = Новый Файл(ПутьККартинке);
Если Фото.Существует() Тогда
Картинка = Новый Картинка(ПутьККартинке);
// Создаем рисунок в ячейке
Изображение = ДокументРезультат.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
// СЖАТИЕ КАРТИНКИ
// Вызываем вспомогательную функцию сжатия
СжатаяКартинка = ПолучитьСжатуюКартинку(Картинка, 60);
Изображение.Картинка = СжатаяКартинка;
Изображение.РазмерКартинки = РазмерКартинки.АвтоРазмер;
Область.АвтоВысотаСтроки = Ложь;
Изображение.Расположить(Область);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Также нам понадобится вспомогательная функция для сжатия. Она проверяет размер файла или высоту картинки и при необходимости уменьшает её качество.
Функция ПолучитьСжатуюКартинку(Крт, ВысотаКартинки, РазмерФайлаПоУмолчаниюКБ = 300) Экспорт
Крт_ = Крт;
// Если файл больше заданного лимита (например, 300 КБ) или слишком высокий
Если (Крт_.РазмерФайла() > РазмерФайлаПоУмолчаниюКБ * 1024) ИЛИ (Крт_.Высота() > ВысотаКартинки) Тогда
Попытка
// Используем объект ОбрабатываемаяКартинка (доступен в новых платформах)
ОбрКрт = Новый ОбрабатываемаяКартинка(Крт, Истина); // Истина - формат сохраняется
// Устанавливаем новые параметры
ОбрКрт.УстановитьРазмер(, ВысотаКартинки);
ОбрКрт.УстановитьПлотность(96, 96);
ОбрКрт.УстановитьГлубинуЦвета(ГлубинаЦвета.БитНаПиксел24);
// Можно принудительно установить формат, например PNG или JPEG
ОбрКрт.УстановитьФормат(ФорматКартинки.PNG);
Крт_ = ОбрКрт.ПолучитьКартинку();
Возврат Крт_;
Исключение
// Если обработка не удалась, возвращаем оригинал
Возврат Крт;
КонецПопытки;
Иначе
Возврат Крт;
КонецЕсли;
КонецФункции
Важные замечания по коду:
ХранилищеЗначения, вам нужно будет получить двоичные данные из хранилища и создать объект Картинка из них.ВысотаКартинки подбирайте экспериментально.ОбрабатываемаяКартинка доступна начиная с платформы 8.3.14.Часто бывает, что ошибка происходит внутри фонового задания, но платформа просто "проглатывает" её, выдавая пользователю пустой отчет вместо текста ошибки. Если отчёт запускает фоновое задание, в просмотре фоновых заданий можно проверить сохранившийся статус, длительность и текст ошибки. Список фоновых задач не хранит полную долговременную историю, поэтому параллельно проверьте журнал регистрации.
Как диагностировать:
/DebugMode или /РежимОтладки — для этого подойдёт инструмент для пошаговой отладки кода в режиме 1С:Предприятие. В этом режиме сообщения об ошибках фоновых заданий могут отображаться более явно.Если вы подключаете внешний отчет через справочник "Дополнительные отчеты и обработки", обратите внимание на настройку "Безопасный режим".
В безопасном режиме запрещены некоторые операции:
Попробуйте отключить "Безопасный режим" в карточке дополнительного отчета и сформировать его снова.