Эта обработка - это синтез идей из публикации "Открытие консоли запросов при отладке из кода (Обычное приложение)" и статьи "Хитрости отладки".
Саму задачу можно сформулировать следующим образом: нужна возможность из отладчика (Конфигуратора) открыть Консоль запросов в "1С:Предприятии" так, чтобы в этой Консоли запросов текст и параметры были заполнены текстом и параметрами интересующего нас запроса.
Для решения этой задачи будем использовать самую обычную Консоль запросов (не-генномодифицированную, без двойного дна).
Описание решения (для любопытных; нелюбопытные могут пропустить этот раздел).
Анализ кода обработки КонсольЗапросов.epf показал, что разработчики не предоставили нам никаких средств для внешнего управления ею: нет ни экспортных процедур, ни даже каких-либо реквизитов обработки, с помощью которых мы могли бы заставить Консоль запросов заполнить текст запроса и параметры так, как нам нужно. Ну что ж, значит будем работать через реквизиты формы. На мой взгляд, для этой цели лучше всего подходит дерево значений ДеревоЗапросов. Если добавить в него строку и заполнить значения в колонках "ТекстЗапроса", "ПараметрыЗапроса" и "СпособВыгрузки", а потом сделать строку активной, то текст запроса и параметры будут заполнены так как нам надо. Но есть одно но! По какой-то причине эти колонки дерева создаются в обработчике ПриОткрытии (хотя при этом колонка "Запрос" добавлена через редактор форм). Ну и ладно - значит будем получать форму обработки, открывать её (чтобы создались колонки дерева значений), а уже после этого будем добавлять свою строку в ДеревоЗапросов.
Ещё одну интересную идею я подсмотрел в комментариях к публикации про открытие консоли запросов. Идея состоит в том, что иногда имеет смысл открывать Консоль запросов в модальном режиме. Ну например, занимаемся мы отладкой кода, хотим посмотреть какой-нибудь запрос, текст которого генерируется программно и имеет кучу параметров. Тут было бы очень здорово оперативно открыть Консоль запросов в модальном режиме в "1С:Предприятии", выполнить этот запрос, "покрутить" параметры, посмотреть из-за каких условий не попадают нужные данные в результат запроса (или наоборот попадают лишние), закрыть Консоль запросов и продолжить отладку. Но тут есть маленькая трудность - при модальном открытии окна Консоли запросов мы не сможем добавить строку в ДеревоЗапросов описанным выше способом, потому что как только мы вызовем ОткрытьМодально(), выполнение нашего кода будет приостановлено до тех пор, пока мы не закроем модальное окно. Посмотрим ещё раз на код обработчика ПриОткрытии. Помимо всего прочего там есть вызов процедуры вЗагрузитьЗапросыИзФайла(), которая пытается прочитать запрос из файла, имя которого получает процедура вВосстановитьИмяФайла() из сохранённого в базе значения. А это значит, что если мы перед открытием модального окна подготовим дерево значений, которое по структуре будет совпадать с деревом ДеревоЗапросов, и сохраним его во временный файл, а потом имя этого файла с помощью вызова СохранитьЗначение("КонсольЗапросов_ИмяФайла", ИмяВременногоФайла) сохраним в базе, то Консоль запросов загрузит нужный нам текст запроса с параметрами из этого временного файла.
И наконец, последнее - это параметры запроса типа ТаблицаЗначений. Штатным образом в Консоли запросов нельзя задать таблицу значений в качестве значения параметра. Но в реальных запросах таблицы значений в качестве параметров пусть не часто, но всё-таки попадаются (например, Запрос.Текст = "ВЫБРАТЬ * ИЗ &ТЗ КАК ТЗ"). Решая данную задачу, я узнал, что означает загадочный флажок "В" в форме параметров запроса в Консоли запросов (до этого мне как-то особо не было до него дела). Оказывается, если установить этот флажок (на самом деле называется он "ЭтоВыражение"), то Консоль запросов в качестве значения параметра будет использовать результат вычисления выражения, заданного в "Значение параметра" (т.е. она возьмёт текст из "Значение параметра" и применит к нему функцию Вычислить(), а полученный результат будет использовать как значение параметра запроса). Вот так сервис! Ну что ж - тогда провернём ещё раз нашу махинацию с временными файлами. Все параметры запроса, которые имеют тип ТаблицаЗначений, с помощью обычного ЗначениеВФайл() будем сохранять во временные файлы, а в качестве значений таких параметров в Консоли запросов будем указывать "ЗначениеИзФайла(ИмяВременногоФайла)" и устанавливать это волшебный флажок "В".
Код модуля обработки
////////////////////////////////////////////////// // Автор: q_i // Лицензия: GPLv3 ////////////////////////////////////////////////// // Пример использования обработки для отладки запроса: // В режиме отладки вызываем диалог "Вычислить выражение..." (Shift+F9) и пишем выражение вида // ВнешниеОбработки.Создать("(КаталогЭтойОбработки)\ОткрывашкаКонсолиЗапросов.epf").ОткрытьКонсольЗапросов(Запрос, "(КаталогКонсолиЗапросов)\КонсольЗапросов.epf", Истина) // // Функция открывает консоль запросов для отладки запроса. // Функция ОткрытьКонсольЗапросов(Запрос, ФайлКонсолиЗапросов = "", Модально = Истина) Экспорт Результат = Новый Структура("Успех, Сообщение", Ложь, "Неизвестная ошибка"); ИмяФайлаКонсолиЗапросов = ФайлКонсолиЗапросов; Если ПустаяСтрока(ИмяФайлаКонсолиЗапросов) Тогда // по умолчанию считаем, что консоль запросов лежит в том же каталоге, что и эта обработка Файл = Новый Файл(ЭтотОбъект.ИспользуемоеИмяФайла); ИмяФайлаКонсолиЗапросов = Файл.Путь + "КонсольЗапросов.epf"; КонецЕсли; Попытка КонсольЗапросов = ВнешниеОбработки.Создать(ИмяФайлаКонсолиЗапросов); Исключение Результат.Успех = Ложь; Результат.Сообщение = "Не удалось создать обработку Консоль запросов: " + ОписаниеОшибки(); Возврат Результат; КонецПопытки; КомментарииКЗапросу = ""; // скопируем параметры запроса в новую таблицу значений ФормаПараметров = КонсольЗапросов.ПолучитьФорму("ФормаПараметров"); ТаблицаПараметров = ФормаПараметров.Параметры.СкопироватьКолонки(); Для Каждого ТекПараметр Из Запрос.Параметры Цикл ТекИмя = ТекПараметр.Ключ; ТекЗнач = ТекПараметр.Значение; НоваяСтрока = ТаблицаПараметров.Добавить(); НоваяСтрока.ИмяПараметра = ТекИмя; Если ТипЗнч(ТекЗнач) = Тип("Массив") Тогда // массивы преобразуем в списки значений СЗ = Новый СписокЗначений; СЗ.ЗагрузитьЗначения(ТекЗнач); ТекЗнач = СЗ; ИначеЕсли ТипЗнч(ТекЗнач) = Тип("ТаблицаЗначений") Тогда // таблицы значений сохраняем во временные файлы ИмяВремФайла = ПолучитьИмяВременногоФайла(".vt"); ЗначениеВФайл(ИмяВремФайла, ТекЗнач); ТекЗнач = "ЗначениеИзФайла(""" + ИмяВремФайла + """)"; НоваяСтрока.ЭтоВыражение = Истина; КомментарииКЗапросу = КомментарииКЗапросу + ?(ПустаяСтрока(КомментарииКЗапросу), "", Символы.ПС) + "// ВНИМАНИЕ! Параметр """ + ТекИмя + """ имеет тип ТаблицаЗначений, поэтому сохранён в файл """ + ИмяВремФайла + """!"; КонецЕсли; НоваяСтрока.ЗначениеПараметра = ТекЗнач; КонецЦикла; Форма = КонсольЗапросов.ПолучитьФорму("Форма"); Если Модально Тогда ДеревоЗапросов = Форма.ДеревоЗапросов.Скопировать(); ДеревоЗапросов.Строки.Очистить(); // {{ повторяем действия из обработчика ПриОткрытии ДеревоЗапросов.Колонки.Добавить("ТекстЗапроса"); ДеревоЗапросов.Колонки.Добавить("ПараметрыЗапроса"); ДеревоЗапросов.Колонки.Добавить("СпособВыгрузки"); // повторяем действия из обработчика ПриОткрытии }} Иначе // открываем форму чтобы отработал обработчик ПриОткрытии Форма.Открыть(); ДеревоЗапросов = Форма.ДеревоЗапросов; КонецЕсли; Если ДеревоЗапросов.Строки.Количество() > 0 И ДеревоЗапросов.Строки[0].Запрос = "Запросы" Тогда СтрокаРодитель = ДеревоЗапросов.Строки[0]; Иначе СтрокаРодитель = ДеревоЗапросов; КонецЕсли; ИмяЗапроса = "Отладка " + ТекущаяДата(); ТекстЗапроса = Запрос.Текст; СтрокаЗапроса = СтрокаРодитель.Строки.Добавить(); СтрокаЗапроса.Запрос = ИмяЗапроса; СтрокаЗапроса.ТекстЗапроса = ?(ПустаяСтрока(КомментарииКЗапросу), ТекстЗапроса, КомментарииКЗапросу + Символы.ПС + Символы.ПС + ТекстЗапроса); СтрокаЗапроса.ПараметрыЗапроса = ТаблицаПараметров; СтрокаЗапроса.СпособВыгрузки = 1; // список Если Модально Тогда // сохраняем сформированное ДеревоЗапросов во временный файл ИмяВремФайла = ПолучитьИмяВременногоФайла(".sel"); ЗначениеВФайл(ИмяВремФайла, ДеревоЗапросов); Файл = Новый Файл(ИмяВремФайла); ИМЯЗНАЧ_ИМЯФАЙЛА = "КонсольЗапросов_ИмяФайла"; ИМЯЗНАЧ_ИМЯПУТИ = "КонсольЗапросов_ИмяПути"; ПредИмяФайла = ВосстановитьЗначение(ИМЯЗНАЧ_ИМЯФАЙЛА); ПредИмяПути = ВосстановитьЗначение(ИМЯЗНАЧ_ИМЯПУТИ); БылиОшибки = Ложь; Попытка СохранитьЗначение(ИМЯЗНАЧ_ИМЯФАЙЛА, ИмяВремФайла); СохранитьЗначение(ИМЯЗНАЧ_ИМЯПУТИ, Файл.Путь); // в обработчике ПриОткрытии консоль загрузит запросы из нашего файла Форма.ОткрытьМодально(); Исключение Результат.Успех = Ложь; Результат.Сообщение = "Ошибка при модальном открытии формы Консоли запросов: " + ОписаниеОшибки(); БылиОшибки = Истина; КонецПопытки; СохранитьЗначение(ИМЯЗНАЧ_ИМЯФАЙЛА, ПредИмяФайла); СохранитьЗначение(ИМЯЗНАЧ_ИМЯПУТИ, ПредИмяПути); Если БылиОшибки Тогда Возврат Результат; КонецЕсли; Иначе Форма.ЭлементыФормы.ДеревоЗапросов.ТекущаяСтрока = СтрокаЗапроса; КонецЕсли; Результат.Успех = Истина; Результат.Сообщение = "Консоль запросов открыта. Имя текущего запроса = " + ИмяЗапроса; Возврат Результат; КонецФункции
Использование обработки
Обработка состоит всего из одной экспортной функции ОткрытьКонсольЗапросов(Запрос, ФайлКонсолиЗапросов = "", Модально = Истина).
Параметры этой функции:
- Запрос - это объект Запрос, который нужно открыть в Консоли запросов.
- ФайлКонсолиЗапросов - это полное имя файла Консоли запросов. Параметр необязательный. Если не указан, то обработка считает, что консоль запросов имеет имя "КонсольЗапросов.epf" и находится в том же каталоге, что и сама обработка.
- Модально - указывает нужно ли открывать Консоль запросов в модальном режиме (Истина) или нет. Параметр также необязательный. По умолчанию - Истина (т.е. Консоль запросов открывается в модальном режиме).
Теперь о том, как использовать эту обработку.
В режиме отладки вызываем диалог "Вычислить выражение..." (Shift+F9), пишем выражение вида
- ВнешниеОбработки.Создать("КаталогЭтойОбработки\ОткрывашкаКонсолиЗапросов.epf").ОткрытьКонсольЗапросов(Запрос, "КаталогКонсолиЗапросов\КонсольЗапросов.epf", Истина)
и нажимаем кнопку "Рассчитать". Если последний параметр Истина (или не задан), то Консоль запросов откроется в модальном режиме, и мы можем сразу перейти в "1С:Предприятие" и работать с открывшимся запросом. Если последний параметр Ложь, то Консоль запросов откроется в "1С:Предприятие" ПОСЛЕ того, как мы нажмём F5 ("Продолжить отладку").
В этом примере:
- КаталогЭтойОбработки\ОткрывашкаКонсолиЗапросов.epf - это полное имя файла этой обработки.
Ещё примеры запуска:
- ВнешниеОбработки.Создать("КаталогЭтойОбработки\ОткрывашкаКонсолиЗапросов.epf").ОткрытьКонсольЗапросов(Запрос) - откроет Консоль запросов, которая имеет имя "КонсольЗапросов.epf" и находится в каталоге "КаталогЭтойОбработки\".
- ВнешниеОбработки.Создать("КаталогЭтойОбработки\ОткрывашкаКонсолиЗапросов.epf").ОткрытьКонсольЗапросов(Запрос,, Ложь) - то же самое, но Консоль запросов откроется в немодальном режиме.
Собственно и всё. Пожелания и замечания по делу приветствуются!