Приступая к разработке на платформе 1С, особенно новичкам, часто приходится сталкиваться с задачами, требующими выборки данных из информационной базы с использованием запросов. В этом руководстве мы подробно разберем, как осуществить выборку из журнала документов во внешней обработке, передавая параметры с формы и корректно отображая полученные результаты. Мы рассмотрим типовые ошибки и эффективные решения, которые помогут вам уверенно работать с запросами в 1С.
Представим ситуацию: нам необходимо создать внешнюю обработку, которая будет выбирать документы из журнала под названием "Складские документы", фильтруя их по определенному контрагенту и складу. Эти параметры (Контрагент и Склад) должны задаваться пользователем непосредственно на форме внешней обработки.
Прежде всего, создадим новую внешнюю обработку. В ее форме нам потребуются два реквизита: Контрагент и Склад. Эти реквизиты должны иметь соответствующие типы данных – ссылки на справочники Контрагенты и Склады (или аналогичные, в зависимости от конфигурации).
Добавим на форму кнопку "Показать", при нажатии на которую будет выполняться наш запрос. Вот как может выглядеть начальный код обработчика события нажатия кнопки:
&НаКлиенте
Процедура Показать(Команда)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СкладскиеДокументы.Дата КАК Дата,
| СкладскиеДокументы.Контрагент КАК Контрагент,
| СкладскиеДокументы.Склад КАК Склад,
| СкладскиеДокументы.Заказ КАК Заказ
|ПОМЕСТИТЬ ВыборДокументов
|ИЗ
| ЖурналДокументов.СкладскиеДокументы КАК СкладскиеДокументы
|ГДЕ
| СкладскиеДокументы.Контрагент = &Контрагент
|И СкладскиеДокументы.Склад = &Склад";
// Здесь была ошибка в исходном коде
// Запрос.УстановитьПараметр("Контрагент",Контрагент);
// Запрос.УстановитьПараметр("Склад",Склад);
// ... далее код вывода результатов
Результат = Запрос.Выполнить;
Сообщить(Результат); // Это тоже некорректно для вывода данных
КонецПроцедуры
На данном этапе новички часто сталкиваются с проблемой: как правильно передать значения реквизитов формы в параметры запроса? Если просто написать Запрос.УстановитьПараметр("Контрагент", Контрагент);, платформа выдаст ошибку, поскольку в контексте обработчика команды Контрагент (как имя переменной) не определен.
Разберем причину ошибки и найдем верное решение. В управляемых формах 1С для доступа к реквизитам, расположенным на форме, из клиентского или серверного кода используется специальный объект Объект. Этот объект является представлением данных формы и содержит все ее реквизиты. Таким образом, чтобы передать значение реквизита Контрагент с формы в параметр запроса, нам необходимо обратиться к нему как Объект.Контрагент.
Применим это правило к нашему запросу:
&НаКлиенте
Процедура Показать(Команда)
// Передаем команду на сервер для выполнения запроса
ВыполнитьЗапросНаСервере();
КонецПроцедуры
&НаСервере
Процедура ВыполнитьЗапросНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СкладскиеДокументы.Дата КАК Дата,
| СкладскиеДокументы.Контрагент КАК Контрагент,
| СкладскиеДокументы.Склад КАК Склад,
| СкладскиеДокументы.Заказ КАК Заказ
|ПОМЕСТИТЬ ВыборДокументов
|ИЗ
| ЖурналДокументов.СкладскиеДокументы КАК СкладскиеДокументы
|ГДЕ
| СкладскиеДокументы.Контрагент = &Контрагент
|И СкладскиеДокументы.Склад = &Склад";
// **********************************************
// Верное решение для установки параметров запроса:
Запрос.УстановитьПараметр("Контрагент", Объект.Контрагент);
Запрос.УстановитьПараметр("Склад", Объект.Склад);
// **********************************************
РезультатЗапроса = Запрос.Выполнить();
// ... далее код вывода результатов
КонецПроцедуры
Важно: убедитесь, что типы значений реквизитов формы Контрагент и Склад соответствуют типам данных, ожидаемым в запросе для полей журнала документов. Если вы выбрали реквизиты формы как ссылки на соответствующие справочники, то проблем возникнуть не должно.
После того как запрос успешно выполнен, перед нами встает новая задача: как правильно отобразить полученные данные. Простая команда Сообщить(РезультатЗапроса) не даст нам желаемого результата – она выведет лишь объект РезультатЗапроса, а не содержимое выборки. Для просмотра фактических данных нам нужно либо обойти выборку построчно, либо выгрузить ее в табличную часть формы.
Этот метод подходит, если нам нужно обработать каждую строку результата запроса по отдельности, выполнить какие-либо вычисления или вывести данные в виде текстовых сообщений. Для этого используем метод Выбрать() объекта РезультатЗапроса и цикл Пока ... Цикл:
&НаСервере
Процедура ВыполнитьЗапросНаСервере()
// ... (код запроса и установки параметров) ...
РезультатЗапроса = Запрос.Выполнить();
// Получаем выборку из результата запроса
Выборка = РезультатЗапроса.Выбрать();
Сообщить("--- Результаты выборки: ---");
Пока Выборка.Следующий() Цикл
// Обрабатываем каждую строку
Сообщить(Строка(Выборка.Дата) + " | Контрагент: " + Выборка.Контрагент + " | Склад: " + Выборка.Склад + " | Заказ: " + Выборка.Заказ);
КонецЦикла;
Сообщить("-------------------------");
КонецПроцедуры
В этом примере мы получаем объект Выборка, а затем в цикле, используя метод Следующий(), переходим к каждой записи и выводим ее поля. Это полезно для отладки или простых текстовых отчетов.
Наиболее удобный и распространенный способ отображения результатов запроса во внешней обработке – это вывод их в табличную часть формы. Для этого нам нужно предварительно добавить на форму реквизит с типом ТаблицаЗначений и добавить его как табличную часть. Назовем его, например, ТабЧастьРезультатов.
Далее, мы используем метод Выгрузить() объекта РезультатЗапроса, чтобы получить ТаблицуЗначений, и затем загружаем ее в нашу табличную часть формы:
&НаСервере
Процедура ВыполнитьЗапросНаСервере()
// ... (код запроса и установки параметров) ...
РезультатЗапроса = Запрос.Выполнить();
// Выгружаем результат запроса в ТаблицуЗначений
ТаблицаРезультатов = РезультатЗапроса.Выгрузить();
// Очищаем существующую табличную часть формы
Объект.ТабЧастьРезультатов.Очистить();
// Загружаем данные в табличную часть формы
Объект.ТабЧастьРезультатов.Загрузить(ТаблицаРезультатов);
КонецПроцедуры
Важный нюанс: при использовании метода Загрузить() для табличной части, очень желательно, чтобы имена колонок в результате запроса (Дата, Контрагент, Склад, Заказ) совпадали с именами колонок табличной части Объект.ТабЧастьРезультатов. Если имена колонок не совпадают, данные могут быть загружены некорректно или вообще не отобразиться. В таком случае вам придется вручную переносить данные из ТаблицыЗначений в табличную часть формы, создавая новые строки и присваивая значения полям.
В нашем исходном запросе мы использовали конструкцию ПОМЕСТИТЬ ВыборДокументов, что означает создание временной таблицы. Временные таблицы очень полезны для разбиения сложных запросов на несколько более простых шагов, что улучшает читаемость и иногда производительность. Однако есть свои особенности при их использовании.
Если запрос содержит одну или несколько временных таблиц, а затем основной запрос, который использует эти временные таблицы, мы работаем с пакетными запросами. Для выполнения пакета запросов используются методы:
Запрос.ВыполнитьПакет(): Возвращает массив объектов РезультатЗапроса, по одному для каждого запроса в пакете. При этом результаты временных таблиц не детализируются, вы получаете только результат последнего запроса.Запрос.ВыполнитьПакетСПромежуточнымиДанными(): Этот метод также возвращает массив объектов РезультатЗапроса, но позволяет получить доступ к содержимому временных таблиц.Если вы хотите просмотреть содержимое временной таблицы во время отладки или использовать его для дальнейшей обработки, то ВыполнитьПакетСПромежуточнымиДанными() будет предпочтительнее. Каждый элемент массива будет соответствовать порядку запросов в пакете.
Пример использования ВыполнитьПакетСПромежуточнымиДанными() для получения данных из временной таблицы:
&НаСервере
Процедура ВыполнитьЗапросНаСервереСВременнымиТаблицами()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СкладскиеДокументы.Дата КАК Дата,
| СкладскиеДокументы.Контрагент КАК Контрагент,
| СкладскиеДокументы.Склад КАК Склад,
| СкладскиеДокументы.Заказ КАК Заказ
|ПОМЕСТИТЬ ВТ_ВыбранныеДокументы
|ИЗ
| ЖурналДокументов.СкладскиеДокументы КАК СкладскиеДокументы
|ГДЕ
| СкладскиеДокументы.Контрагент = &Контрагент
|И СкладскиеДокументы.Склад = &Склад;
|
|ВЫБРАТЬ
| ВТ_ВыбранныеДокументы.Дата,
| ВТ_ВыбранныеДокументы.Контрагент,
| ВТ_ВыбранныеДокументы.Склад,
| ВТ_ВыбранныеДокументы.Заказ
|ИЗ
| ВТ_ВыбранныеДокументы КАК ВТ_ВыбранныеДокументы
|ГДЕ
| ВТ_ВыбранныеДокументы.Дата >= &НачалоПериода"; // Допустим, добавили дополнительное условие
Запрос.УстановитьПараметр("Контрагент", Объект.Контрагент);
Запрос.УстановитьПараметр("Склад", Объект.Склад);
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ТекущаяДата())); // Пример параметра
МассивРезультатов = Запрос.ВыполнитьПакетСПромежуточнымиДанными();
// Результат первого запроса (временная таблица ВТ_ВыбранныеДокументы)
РезультатВременнойТаблицы = МассивРезультатов[0];
Сообщить("Количество записей во временной таблице: " + РезультатВременнойТаблицы.Количество());
// Если нужно выгрузить и просмотреть:
// ТаблицаВТ = РезультатВременнойТаблицы.Выгрузить();
// Сообщить(ТаблицаВТ.Количество());
// Результат второго (основного) запроса
РезультатОсновногоЗапроса = МассивРезультатов[1];
Объект.ТабЧастьРезультатов.Очистить();
Объект.ТабЧастьРезультатов.Загрузить(РезультатОсновногоЗапроса.Выгрузить());
КонецПроцедуры
Если же временная таблица нужна только для структурирования запроса и ее содержимое не требуется отдельно, вы можете не использовать `ПОМЕСТИТЬ` или выполнять `Запрос.Выполнить()`, если это единственный запрос в тексте.
&НаСервере).Запрос.МенеджерВременныхТаблиц.Таблицы[0].ПолучитьДанные().Выгрузить(), чтобы получить данные первой временной таблицы в виде таблицы значений без выполнения всего пакета запросов, что удобно при поэтапной отладке.Попытка ... Исключение ... КонецПопытки. Это позволит перехватывать ошибки, возникающие при выполнении запросов (например, из-за неверных параметров или отсутствия прав), и выводить пользователю более понятное сообщение, а не стандартное системное.ОбработкаОтображенияОшибки и объект ОбработкаОшибок для более гибкой настройки вывода сообщений и сбора отчетов об ошибках.ГДЕ может существенно ускорить выборку данных. Если запрос работает медленно, проанализируйте его в консоли запросов.Надеемся, что это подробное руководство помогло вам разобраться в тонкостях работы с запросами во внешних обработках 1С. Практикуйтесь, экспериментируйте с кодом, и вы быстро освоите эти мощные инструменты платформы.