Как открыть форму из серверного кода и отладить сложные запросы с временными таблицами в 1С

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

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

Почему нельзя открыть форму напрямую с сервера?

Прежде всего, проанализируем причину ограничения. Платформа 1С строго разделяет контексты выполнения. Сервер отвечает за работу с данными и бизнес-логику, у него нет «экрана», на который можно вывести форму. Клиент отвечает за взаимодействие с пользователем. Когда мы находимся внутри серверной процедуры (например, в общем модуле или модуле менеджера), попытка вызвать ОткрытьФорму() приведет к ошибке, так как сервер «не знает», в каком сеансе и на каком мониторе нужно отобразить это окно.

Способ 1: Использование возможностей встроенного отладчика (Платформа 8.3.8+)

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

Рассмотрим ситуацию: у нас есть объект Запрос, в котором уже инициализирован МенеджерВременныхТаблиц и выполнены промежуточные части пакета. Чтобы посмотреть содержимое конкретной временной таблицы в режиме отладки, выполним следующие шаги:

  1. Установим точку останова после выполнения части запроса.
  2. Вызовем окно «Вычислить выражение» (Shift+F9).
  3. Введем выражение для получения данных конкретной таблицы:

// Где "ВТ_ДанныеСотрудников" - имя вашей временной таблицы
Запрос.МенеджерВременныхТаблиц.Таблицы.Найти("ВТ_ДанныеСотрудников").ПолучитьДанные().Выгрузить()

Платформа выполнит неявный запрос к менеджеру временных таблиц и вернет ТаблицуЗначений. Нажав на кнопку «Показать значения в отдельном окне» (лупа), мы увидим содержимое таблицы в виде таблицы. Это избавляет от необходимости открывать какие-либо формы программно.

Способ 2: Создание отладочного общего модуля

Если временных таблиц много (как это часто бывает в регламентированной отчетности ЗУП), просматривать их по одной в отладчике неудобно. Рассмотрим вариант автоматизации, предложенный участниками сообщества. Мы можем создать общий модуль (например, НТХ_Отладка) с признаком «Сервер» и «Вызов сервера».

Создадим функцию, которая будет собирать все временные таблицы в одну структуру:


Функция ВыгрузитьВсеВременныеТаблицы(МенеджерВременныхТаблиц) Экспорт
    
    РезультатСтруктура = Новый Структура;
    
    Для Каждого Элемент Из МенеджерВременныхТаблиц.Таблицы Цикл
        
        ТекстЗапроса = "ВЫБРАТЬ * ИЗ " + Элемент.ПолноеИмя;
        ЗапросДебаг = Новый Запрос(ТекстЗапроса);
        ЗапросДебаг.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
        
        Попытка
            РезультатСтруктура.Вставить(Элемент.ПолноеИмя, ЗапросДебаг.Выполнить().Выгрузить());
        Исключение
            // Обработка случая, если таблица пуста или еще не инициализирована
            Продолжить;
        КонецПопытки;
        
    КонецЦикла;
    
    Возврат РезультатСтруктура;
    
КонецФункции

Теперь в любой момент отладки в окне «Вычислить выражение» достаточно написать НТХ_Отладка.ВыгрузитьВсеВременныеТаблицы(Запрос.МенеджерВременныхТаблиц). Мы получим структуру, где ключи — это названия таблиц, а значения — их содержимое. Это гораздо нагляднее при анализе цепочки сложных расчетов.

Способ 3: Передача данных на клиент через временное хранилище

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

Разберем алгоритм реализации:

  1. На сервере выгружаем данные в ТаблицуЗначений.
  2. Помещаем таблицу во Временное хранилище и получаем адрес.
  3. Возвращаем этот адрес в вызывающую клиентскую процедуру.
  4. На клиенте вызываем ОткрытьФорму(), передавая адрес хранилища в параметрах.

Пример кода на сервере:


АдресХранилища = ПоместитьВоВременноеХранилище(ТаблицаСДанными, ЭтаФорма.УникальныйИдентификатор);
Возврат АдресХранилища;

Пример кода на клиенте:


Адрес = ПодготовитьДанныеНаСервере(); // Вызов серверной функции
ПараметрыФормы = Новый Структура("АдресДанных", Адрес);
ОткрытьФорму("ОбщаяФорма.МояФормаПросмотраВТ", ПараметрыФормы);

Способ 4: Сохранение данных в файл (метод для фоновых заданий)

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

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


ТабДок = Новый ТабличныйДокумент;
// ... Заполнение ТабДок данными из ВТ ...
ТабДок.Записать("C:\Debug\Result.mxl", ТипФайлаТабличногоДокумента.MXL);

Способ 5: Метод ВыполнитьПакетСПромежуточнымиДанными()

Выясним, какой еще штатный инструмент есть у объекта Запрос. Метод ВыполнитьПакетСПромежуточнымиДанными() возвращает массив результатов выполнения всех запросов в пакете, включая временные таблицы. Это самый «чистый» способ получить данные всех ВТ одним вызовом, не перебирая менеджер вручную.

Рассмотрим пример:


МассивРезультатов = Запрос.ВыполнитьПакетСПромежуточнымиДанными();
// МассивРезультатов содержит РезультатЗапроса для каждого запроса в пакете
Для Каждого ТекРезультат Из МассивРезультатов Цикл
    Если Не ТекРезультат.Пустой() Тогда
        ТаблицаДанных = ТекРезультат.Выгрузить();
        // Теперь таблицу можно анализировать
    КонецЕсли;
КонецЦикла;

Резюме

Мы рассмотрели несколько подходов к решению проблемы. Если вам нужно быстро посмотреть данные «здесь и сейчас», используйте вычисление выражений в отладчике с методом ПолучитьДанные(). Если вы занимаетесь глубокой разработкой сложных отчетов в ЗУП, лучше всего внедрить вспомогательный отладочный модуль, который будет готовить данные для вывода на клиент через временное хранилище. Помните, что архитектура управляемого приложения требует четкого разделения: сервер готовит данные, клиент их отображает.

← На главную