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

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

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

Разберем причину проблемы: почему запрос не видит типы?

Когда мы создаем объект ТаблицаЗначений программно, по умолчанию колонки не имеют строгого типа. Для платформы 1С и, что более важно, для СУБД (SQL Server, PostgreSQL и др.), такая таблица выглядит как набор неопределенных данных. При попытке поместить эту таблицу во временную таблицу запроса через МенеджерВременныхТаблиц, система пытается угадать типы данных, но это не всегда удается, особенно если в таблице нет строк или если данные в строках имеют составной тип.

Проанализируем ситуацию: автор сообщения пытался добавить колонку просто передав значение валюты в качестве второго параметра метода Добавить. Однако второй параметр метода Колонки.Добавить() ожидает объект ОписаниеТипов, а не саму ссылку на валюту. Рассмотрим, как сделать это правильно.

Шаг 1. Создание и правильная типизация Таблицы Значений

Для того чтобы запрос корректно обработал входящую таблицу, каждую колонку нужно типизировать с помощью объекта ОписаниеТипов. Это гарантирует, что СУБД будет знать точный размер и структуру полей. Рассмотрим пример кода:


// 1. Создаем объект Таблица Значений
ИсходныеДанные = Новый ТаблицаЗначений;

// 2. Формируем описание типов для Даты
// Рекомендуется указывать КвалификаторыДаты, чтобы исключить лишние части (время)
КвалификаторДаты = Новый КвалификаторыДаты(ЧастиДаты.Дата);
ОписаниеТипаДата = Новый ОписаниеТипов("Дата", , КвалификаторДаты);
ИсходныеДанные.Колонки.Добавить("Дата", ОписаниеТипаДата);

// 3. Формируем описание типов для Валюты
// Используем строковое имя метаданных или ссылку
ОписаниеТипаВалюта = Новый ОписаниеТипов("СправочникСсылка.Валюты");
ИсходныеДанные.Колонки.Добавить("Валюта", ОписаниеТипаВалюта);

Важный совет: Если вы хотите сделать код более устойчивым к изменениям в конфигураторе, лучше получать тип напрямую из метаданных. Вместо того чтобы писать строку "СправочникСсылка.Валюты", используйте конструкцию Метаданные.Справочники.Валюты.Тип. Это поможет избежать ошибок, если объект будет переименован.

Шаг 2. Заполнение таблицы данными из формы

После того как структура таблицы определена, её необходимо наполнить данными. Если данные берутся из реквизитов формы обработки, нужно помнить о контексте выполнения. В управляемых формах работа с ТаблицейЗначений возможна только на сервере. В обычных формах (толстый клиент) это можно делать непосредственно в модуле формы.

Рассмотрим, как добавить строку в нашу таблицу, используя данные из реквизитов формы (например, ДатаОтчета и ВыбраннаяВалюта):


// Добавляем новую строку в ТЗ
НоваяСтрока = ИсходныеДанные.Добавить();

// Заполняем данными из реквизитов (на форме или из объекта)
НоваяСтрока.Дата = Объект.ДатаОтчета; 
НоваяСтрока.Валюта = Объект.Валюта; // Здесь 'Валюта' - это ссылка на справочник

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

Шаг 3. Подготовка и выполнение запроса

Теперь, когда наша таблица типизирована и заполнена, мы можем передать её в запрос. В тексте запроса мы обращаемся к ней как к обычному параметру, но с использованием конструкции ВЫБРАТЬ ... ПОМЕСТИТЬ. Проанализируем пример сложного запроса для получения курсов валют на разные даты:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	ИсходныеДанные.Дата КАК Дата,
|	ИсходныеДанные.Валюта КАК Валюта
|ПОМЕСТИТЬ ВТ_ИсходныеДанные
|ИЗ
|	&ИсходныеДанные КАК ИсходныеДанные
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	ВТ_ИсходныеДанные.Дата КАК Дата,
|	ВТ_ИсходныеДанные.Валюта КАК Валюта,
|	МАКСИМУМ(КурсыВалют.Период) КАК Период
|ПОМЕСТИТЬ ВТ_ДатыКурсов
|ИЗ
|	ВТ_ИсходныеДанные КАК ВТ_ИсходныеДанные
|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют
|		ПО ВТ_ИсходныеДанные.Валюта = КурсыВалют.Валюта
|			И ВТ_ИсходныеДанные.Дата >= КурсыВалют.Период
|СГРУППИРОВАТЬ ПО
|	ВТ_ИсходныеДанные.Дата,
|	ВТ_ИсходныеДанные.Валюта
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	ВТ_ДатыКурсов.Дата КАК Дата,
|	ВТ_ДатыКурсов.Валюта КАК Валюта,
|	КурсыВалют.Курс КАК Курс,
|	КурсыВалют.Кратность КАК Кратность
|ИЗ
|	ВТ_ДатыКурсов КАК ВТ_ДатыКурсов
|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют
|		ПО ВТ_ДатыКурсов.Валюта = КурсыВалют.Валюта
|			И ВТ_ДатыКурсов.Период = КурсыВалют.Период";

Запрос.УстановитьПараметр("ИсходныеДанные", ИсходныеДанные);

РезультатЗапроса = Запрос.Выполнить();

Как улучшить работу запроса (Best Practices)

Проанализируем несколько продвинутых техник, которые сделают ваш код более профессиональным и быстрым:

  1. Индексация временных таблиц. Если в вашей таблице &ИсходныеДанные ожидается более 10-20 строк, обязательно добавьте индексацию. В тексте запроса после помещения во временную таблицу напишите: ИНДЕКСИРОВАТЬ ПО Валюта, Дата. Это позволит SQL-серверу мгновенно выполнять соединения.
  2. Использование оператора ВЫРАЗИТЬ. В первом пакете запроса (где мы выбираем данные из параметра) крайне полезно явно указывать типы. Например: ВЫРАЗИТЬ(ИсходныеДанные.Валюта КАК Справочник.Валюты) КАК Валюта. Это предотвращает ошибки с "составными типами" и помогает оптимизатору запросов.
  3. Проверка на пустую таблицу. Перед тем как выполнять запрос, всегда проверяйте, есть ли в таблице строки: Если ИсходныеДанные.Количество() > 0 Тогда.... Передача пустой таблицы в запрос с соединениями может привести к избыточной нагрузке или пустым временным таблицам, которые могут вызвать ошибки в последующих пакетах.
  4. Клиент-серверное взаимодействие. Помните, что Запрос и ТаблицаЗначений — это серверные объекты. Если вы работаете в Управляемом приложении, передавайте необходимые данные с формы (например, массив ссылок или структуру) на сервер, и уже там формируйте таблицу значений и выполняйте запрос.

Типичные ошибки, которых стоит избегать

Рассмотрим, на чем чаще всего "спотыкаются" новички:

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

← На главную