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