Решаем проблемы с работой консоли запросов на управляемых формах в 1С 8.3 и исправляем ошибку ОбработкаПолученияФормы

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

Каждый разработчик 1С в своей ежедневной практике сталкивается с необходимостью написания, отладки и анализа запросов к базе данных. В эпоху обычного приложения этот вопрос решался стандартными инструментами, но переход на управляемые формы (УФ) и регулярные обновления Библиотеки стандартных подсистем (БСП) привнесли свои сложности. Часто бывает так: мы скачиваем очередную обработку, запускаем её, но результат выполнения запроса либо не отображается, либо программа аварийно завершает работу с загадочной системной ошибкой. В рамках этой статьи мы детально разберем, как выбрать надежную консоль запросов для управляемого приложения 1С 8.3, и выясним истинную причину возникновения аппаратных сбоев при вызове конструктора запросов в толстом клиенте управляемого приложения.

Выбираем качественную консоль запросов для управляемых форм

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

  1. Стандартная консоль запросов из состава БСП (или с диска ИТС). Это самое простое и надежное решение. Она лишена множества продвинутых функций (таких как подсветка синтаксиса или автоподстановка), но гарантированно открывается в любой современной конфигурации (будь то ERP, Комплексная автоматизация или Бухгалтерия предприятия). Главный плюс этой консоли в том, что она написана с соблюдением стандартов разработки фирмы 1С и не вызывает конфликтов ядра платформы при обновлении метаданных.
  2. Консоль запросов Евгения Люлюка (управляемая консоль отчетов). Чрезвычайно мощный и гибкий инструмент. Она обладает широким функционалом, предоставляет удобные интерфейсные решения для сопоставления таблиц и работы со сложными связями. Именно с её использованием часто возникают специфические нюансы в толстом клиенте, которые мы научимся обходить.
  3. Специализированные асинхронные консоли (например, проект Консоль 9000). Это современные решения с открытым исходным кодом, ориентированные на платформы версии 8.3.12 и выше. Они полностью построены на асинхронных вызовах без использования модальных окон, что позволяет работать в базах с жестким запретом на использование модальности. Кроме того, такие консоли умеют «перехватывать» временные таблицы и пакетные запросы прямо из отладчика вместе с установленными параметрами.
  4. Инструменты разработчика (ИР) в виде расширения. Традиционно этот комплекс утилит работал только в обычном приложении. Однако в настоящее время его можно использовать и в управляемом приложении толстого клиента, подключив в виде расширения конфигурации. Это открывает доступ к глубокому анализу запросов, генерации кода СУБД и просмотру реальных планов выполнения SQL.

Если в процессе выполнения вашего запроса консоль показывает, что результат есть (например, в строке состояния отображается число строк), но сама таблица на форме остается пустой, первым делом проанализируйте текст запроса. Довольно распространенной ошибкой является наличие инструкции ПОМЕСТИТЬ в самом последнем запросе пакета. Помните, что если пакетный запрос заканчивается помещением данных во временную таблицу, СУБД возвращает пустой результирующий набор для этой секции. Чтобы увидеть результат, обязательно добавьте в конец пакета выборку из этой временной таблицы с помощью инструкции ВЫБРАТЬ * ИЗ ИмяВременнойТаблицы.

Анализируем причину ошибки ОбработкаПолученияФормы при открытии конструктора

Теперь давайте перейдем к разбору сложной технической проблемы, с которой массово сталкиваются разработчики после обновления типовых конфигураций (Бухгалтерия предприятия КОРП, ERP Управление предприятием, ЗУП и др.) до свежих релизов БСП. При попытке интерактивно открыть ветку метаданных (например, справочники или документы) или вызвать встроенный конструктор запроса в некоторых внешних консолях система падает со следующей ошибкой:

При подписке ПереопределитьПолучаемуюФормуПрисоединенногоФайлаЗарплатаКадрыБазовая на событие ОбработкаПолученияФормы произошла ошибка. Обработчик события не найден.

Выясним причину этого сбоя. Данная ошибка воспроизводится при одновременном выполнении следующих пяти условий:

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

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

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

Раньше в БСП использовался клиентский вызов, который перенаправлял выполнение на сервер через модуль с установленным признаком «Вызов сервера»:


// Устаревший обработчик, который вызывался корректно из толстого клиента
Процедура ПереопределитьПолучаемуюФормуПрисоединенногоФайла(Источник,
                                                      ВидФормы,
                                                      Параметры,
                                                      ВыбраннаяФорма,
                                                      ДополнительнаяИнформация,
                                                      СтандартнаяОбработка) Экспорт
    
    РаботаСФайламиСлужебныйВызовСервера.ОпределитьФормуПрисоединенногоФайла(
        Источник,
        ВидФормы,
        Параметры,
        ВыбраннаяФорма,
        ДополнительнаяИнформация,
        СтандартнаяОбработка);
        
КонецПроцедуры

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


// Новый обработчик в модуле "РаботаСФайлами" (только сервер)
Процедура ОпределитьФормуПрисоединенногоФайла(Источник, ВидФормы, Параметры,
                ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка) Экспорт
    
    ЭтоФормаВерсии = Ложь;
    Если Источник <> Неопределено Тогда
        ЭтоФормаВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("РодительскаяВерсия", Метаданные.НайтиПоТипу(ТипЗнч(Источник)));
    КонецЕсли;
    
    // ... дальнейшая логика определения формы
КонецПроцедуры

Поскольку общий модуль РаботаСФайлами доступен только на сервере, толстый клиент управляемого приложения при обходе подписок на события во внешних обработках аварийно прерывает выполнение потока.

Пошаговые варианты обхода и решения проблемы

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

Способ 1. Изменение настроек внешней консоли запросов (без изменения конфигурации)

Многие современные консоли (например, консоль Евгения Люлюка) предоставляют возможность гибкой настройки вызова конструктора метаданных. Посмотрим на алгоритм действий:

  1. Откройте внешнюю обработку консоли в вашей пользовательской базе.
  2. Перейдите в раздел настроек или параметров консоли.
  3. Найдите и снимите флаг «Использовать конструктор запросов толстого клиента» (или аналогичный параметр, отвечающий за форсированный вызов толстого клиента).
  4. Сохраните настройки. Теперь консоль будет использовать стандартный конструктор запросов тонкого клиента, работающий через асинхронные вызовы API, что исключит ложное срабатывание серверных подписок на клиенте.

Способ 2. Запуск сеанса в тонком клиенте

Если перед вами не стоит задача визуального проектирования схем компоновки данных (СКД), требующих исключительно толстого клиента, запускайте отладку и работу с базой через Тонкий клиент. В тонком клиенте конструктор запросов функционирует на совершенно иных системных механизмах, транслируя вызовы на сервер корректно, что полностью предотвращает появление ошибки инициализации форм.

Способ 3. Модификация конфигурации (для баз, находящихся на поддержке с возможностью изменения)

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

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

Способ 4. Переход на асинхронные методы в коде внешней обработки

Если вы сами программируете или дорабатываете консоль запросов, замените модальный вызов конструктора на асинхронный. Разберем пример кода. Вместо устаревшего модального вызова:


// Этот вызов приводит к ошибке в толстом клиенте УФ на новых БСП
КонструкторЗапроса = Новый КонструкторЗапроса;
Если КонструкторЗапроса.ОткрытьМодально() Тогда
    ТекстЗапроса = КонструкторЗапроса.Текст;
КонецЕсли;

Нам следует использовать асинхронный метод Показать() с передачей описания оповещения:


// Безопасный асинхронный вызов конструктора запросов
&НаКлиенте
Процедура ОткрытьКонструкторЗапроса()
    
    Конструктор = Новый КонструкторЗапроса;
    Конструктор.Текст = Объект.ТекстЗапроса;
    
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеЗакрытияКонструктора", ЭтотОбъект);
    Конструктор.Показать(ОписаниеОповещения);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияКонструктора(РезультатВыбора, ДополнительныеПараметры) Экспорт
    
    // РезультатВыбора возвращает Истина, если пользователь нажал "ОК" в конструкторе
    Если РезультатВыбора Тогда
        // Здесь мы получаем измененный текст запроса и обновляем поле на форме
        Объект.ТекстЗапроса = РезультатВыбора.Текст;
    КонецЕсли;
    
КонецПроцедуры

Такой подход полностью соответствует современным стандартам разработки фирмы 1С и исключает проблемы совместимости при любых обновлениях платформы или конфигурации.

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

Мало кто знает, но все базовые диалоги и конструкторы (такие как конструктор запросов на управляемых формах, журнал регистрации или активные пользователи) хранятся внутри исполняемых файлов платформы в виде обычных внешних обработок формата .epf. Платформа обращается к ним по внутреннему ресурсному пути v8res://.

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

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


// Копируем встроенную обработку платформы на жесткий диск
ПутьКИсточнику = "v8res://mngbase/QueryWizard.epf";
ПутьКПолучателю = "C:\Temp\QueryWizard.epf";

Попытка
    КопироватьФайл(ПутьКИсточнику, ПутьКПолучателю);
    Сообщить("Файл успешно скопирован в: " + ПутьКПолучателю);
Исключение
    Сообщить("Не удалось скопировать файл. Ошибка: " + ОписаниеОшибки());
КонецПопытки;

После выполнения данного кода вы сможете открыть полученный файл QueryWizard.epf в Конфигураторе, детально изучить алгоритмы построения дерева запроса, перетаскивания таблиц (drag-and-drop) и динамического формирования текста запроса на управляемых формах.

← На главную