Как восстановить несколько настроек Построителя отчета из файлов и правильно отобразить результаты

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на платформе 1С:Предприятие (особенно в рамках обычного приложения на базе механизма ПостроительОтчета) программисты часто сталкиваются с задачей автоматизации. Одна из таких задач — последовательное применение нескольких файлов настроек (например, с расширением .set или .xml) для автоматического формирования нескольких вариантов отчета.

Типичная проблема выглядит следующим образом: код обходит в цикле файлы настроек, восстанавливает их в построителе и запускает генерацию отчета. Однако на форме отображается только самый последний отчет, а предыдущие результаты бесследно исчезают. Выясним причину этой проблемы, детально разберем ошибки в коде и рассмотрим правильные архитектурные решения.

Анализ исходных ошибок и причин «исчезновения» отчетов

Для начала проанализируем, почему у автора оригинального вопроса в цикле «срабатывал» только один файл, хотя отладчик показывал успешное прохождение всех итераций. Здесь кроются сразу две важные проблемы платформы 1С.

1. Логическая ошибка при загрузке настроек из файла

В первом варианте кода автора содержалась классическая опечатка невнимательности. Настройки считывались в одну переменную, а применялись из совершенно другой:


// ОШИБКА: Считали данные в СтруктураЭлементов...
СтруктураЭлементов = ЗначениеИзФайла(ФайлПутьКФайлу);

// ...а применили из старой переменной СохраненныеНастройки!
ПостроительОтчета.УстановитьНастройки(СохраненныеНастройки.НастройкиПостроителя);

Эту проблему быстро выявили участники обсуждения. Данные необходимо извлекать непосредственно из того объекта, который был только что прочитан из файла с диска.

2. Блокировка потока отрисовки интерфейса (UI-потока)

Основная причина, почему пользователь не видел промежуточных результатов генерации отчетов в цикле — физические особенности работы графического движка платформы 1С. Когда выполняется длительный цикл на клиенте, интерфейс программы временно «замораживается». Все манипуляции с табличным документом происходят исключительно в оперативной памяти компьютера.

Отрисовка изменений на экране монитора происходит только тогда, когда выполнение встроенного языка полностью завершается и управление передается обратно платформе. Таким образом, на каждой итерации цикла происходило следующее:

  1. Загружалась первая настройка.
  2. Очищался табличный документ на форме.
  3. Строился первый отчет (в памяти).
  4. Тут же загружалась вторая настройка.
  5. Табличный документ на форме снова очищался.
  6. Строился второй отчет (в памяти).
  7. Цикл завершался, интерфейс разблокировался, и пользователь видел только результат второй итерации.

Для решения этой проблемы необходимо изменить саму логику обработки результатов. Рассмотрим три практических сценария реализации этой задачи.

---

Вариант 1. Последовательный вывод отчетов в один табличный документ (один под другим)

Если ваша задача — показать пользователю результаты всех настроек одновременно в одном окне, необходимо отказаться от полной очистки поля табличного документа на каждой итерации цикла. Вместо этого мы будем последовательно дописывать новые данные в конец существующего документа.

Разберем этот процесс по шагам в следующем примере кода:


Процедура ВосстановитьИОбъединитьНастройки() Экспорт
    
    КаталогНастроек = "\\tsclient\E\1С\Прайс";
    НайденныеФайлы = НайтиФайлы(КаталогНастроек, "*.set");
    
    // Получаем прямую ссылку на табличный документ на форме
    ТабДок = ЭлементыФормы.РезультатОтчета; 
    
    // Очищаем результирующий документ ОДИН раз перед началом цикла
    ТабДок.Очистить();
    
    Для Каждого ТекущийФайл Из НайденныеФайлы Цикл
        
        Попытка
            // Извлекаем настройки построителя из файла
            НастройкиПостроителя = ЗначениеИзФайла(ТекущийФайл.ПолноеИмя);
            
            Если НастройкиПостроителя = Неопределено Тогда
                ВызватьИсключение "Файл поврежден или имеет неверный формат.";
            КонецЕсли;
            
            // Инициализируем построитель (восстанавливаем структуру запроса)
            ИнициализироватьПостроительОтчета();
            
            // Применяем новые настройки
            ПостроительОтчета.УстановитьНастройки(НастройкиПостроителя);
            
            // Выполняем запрос построителя
            ПостроительОтчета.Выполнить();
            
            // Выводим результат, дописывая его в конец нашего ТабДок
            ПостроительОтчета.Вывести(ТабДок);
            
            // Добавляем визуальный разделитель между отчетами для удобства чтения
            ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
            
        Исключение
            Сообщить("Не удалось обработать файл: " + ТекущийФайл.Имя + ". Ошибка: " + ОписаниеОшибки(), СтатусСообщения.Внимание);
        КонецПопытки;
        
    КонецЦикла;
    
    Сообщить("Пакетное построение отчетов завершено успешно!");
    
КонецПроцедуры

В данном сценарии метод ПостроительОтчета.Вывести(ТабДок) не затирает предыдущее содержимое, а аккуратно присоединяет новые секции снизу. Метод ВывестиГоризонтальныйРазделительСтраниц() позволяет визуально разграничить прайсы с разными настройками отборов и колонок.

---

Вариант 2. Программное открытие каждого отчета в отдельном окне

Если для каждого файла настроек требуется открыть собственное независимое диалоговое окно, чтобы пользователь мог работать с каждым отчетом отдельно (сворачивать, разворачивать, сравнивать), нам потребуется динамическое создание форм.

Рассмотрим, как это реализовать программно:


Процедура ОткрытьОтчетыВРазныхОкнах() Экспорт
    
    КаталогНастроек = "\\tsclient\E\1С\Прайс";
    НайденныеФайлы = НайтиФайлы(КаталогНастроек, "*.set");
    
    Для Каждого ТекущийФайл Из НайденныеФайлы Цикл
        
        Попытка
            // Читаем индивидуальные настройки
            НастройкиПостроителя = ЗначениеИзФайла(ТекущийФайл.ПолноеИмя);
            
            // Программное создание НОВОГО экземпляра формы отчета
            ИмяОтчета = "МойОтчетПоЦенамНоменклатуры";
            ФормаНовогоОтчета = Отчеты[ИмяОтчета].ПолучитьФорму("ФормаОтчета");
            
            // Открываем форму на экране (теперь у нее свой собственный контекст и UI-поток)
            ФормаНовогоОтчета.Открыть();
            
            // Задаем настройки в построитель созданной формы
            ФормаНовогоОтчета.ПостроительОтчета.УстановитьНастройки(НастройкиПостроителя);
            
            // Запускаем обновление данных конкретно в этой форме
            ФормаНовогоОтчета.ОбновитьОтчет();
            
            // Опционально: меняем заголовок окна для информативности
            ФормаНовогоОтчета.Заголовок = "Отчет: " + ТекущийФайл.БазовоеИмя;
            
        Исключение
            Сообщить("Ошибка инициализации формы для файла " + ТекущийФайл.Имя + ": " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЦикла;
    
КонецПроцедуры

При таком подходе платформа создаст в памяти изолированные объекты форм. Вызов метода Открыть() зарегистрирует их в операционной системе, а последующий вызов процедур построения заполнит индивидуальные табличные документы.

---

Вариант 3. Автоматическое сохранение результатов в файлы (пакетный экспорт)

Зачастую перед разработчиком стоит задача не выводить отчеты на экран пользователя, а выгружать их на диск в различных форматах (например, Excel или PDF) по расписанию или по кнопке «Выгрузить всё». В этом случае нам вообще не нужны экранные элементы формы.

Посмотрим на пример реализации фоновой генерации файлов:


Процедура ПакетныйЭкспортВExcel() Экспорт
    
    КаталогНастроек = "\\tsclient\E\1С\Прайс";
    КаталогЭкспорта = "\\tsclient\E\1С\Прайс\Экспорт";
    НайденныеФайлы = НайтиФайлы(КаталогНастроек, "*.set");
    
    Для Каждого ТекущийФайл Из НайденныеФайлы Цикл
        
        Попытка
            НастройкиПостроителя = ЗначениеИзФайла(ТекущийФайл.ПолноеИмя);
            
            ИнициализироватьПостроительОтчета();
            ПостроительОтчета.УстановитьНастройки(НастройкиПостроителя);
            ПостроительОтчета.Выполнить();
            
            // Создаем скрытый табличный документ исключительно в оперативной памяти
            ВременныйТабДок = Новый ТабличныйДокумент;
            ПостроительОтчета.Вывести(ВременныйТабДок);
            
            // Формируем имя результирующего Excel-файла
            ИмяВыходногоФайла = КаталогЭкспорта + "\" + ТекущийФайл.БазовоеИмя + ".xlsx";
            
            // Записываем документ на диск в формате XLSX
            ВременныйТабДок.Записать(ИмяВыходногоФайла, ТипФайлаТабличногоДокумента.XLSX);
            
            Сообщить("Файл успешно сформирован: " + ИмяВыходногоФайла);
            
        Исключение
            Сообщить("Ошибка экспорта по настройке " + ТекущийФайл.Имя + ": " + ОписаниеОшибки(), СтатусСообщения.Важное);
        КонецПопытки;
        
    КонецЦикла;
    
КонецПроцедуры

---

Важные технические правила работы с настройками Построителя

Чтобы программное сохранение и восстановление настроек работало стабильно и не вызывало труднодиагностируемых ошибок времени выполнения, обязательно соблюдайте следующие технические регламенты:

Современная альтернатива: Переход на СКД (Систему компоновки данных)

Механизм ПостроительОтчета является устаревшим наследием платформы 1С ранних версий (8.0/8.1) для обычного приложения. Если перед вами стоит задача разработки новых отчетов, настоятельно рекомендуется использовать Систему компоновки данных (СКД).

В СКД механизмы сохранения и переключения вариантов отчетов реализованы на уровне ядра платформы. Пользователю и разработчику больше не требуется вручную писать код работы с файлами на диске. Платформа самостоятельно управляет настройками, позволяет хранить их в системных таблицах базы данных, передавать между пользователями, гибко модифицировать структуру вывода в режиме "1С:Предприятие" и автоматически перерисовывать отчеты на управляемых формах без зависания интерфейса.

← На главную