Как правильно сравнить значение валюты в выборке запроса 1С и вывести результат в макет

Программист 1С v8.3 (Обычные формы) Управленческий учет
← На главную

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

Анализ основной ошибки: Ссылка vs Строка

Проанализируем фрагмент кода, который вызвал затруднение: Если Область.Параметры.ВалютаДокумента = "дол" Тогда. В системе 1С поле ВалютаДокумента обычно имеет тип СправочникСсылка.Валюты. Это не текст, а уникальный идентификатор записи в базе данных. С другой стороны, значение "дол" — это обычная строка (тип Строка).

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

Решение 1: Правильное сравнение в коде на языке 1С

Если нам необходимо выполнить проверку непосредственно в цикле обхода выборки, мы должны сначала получить ссылку на нужную нам валюту. Рассмотрим несколько способов сделать это правильно:

  1. Поиск по коду или наименованию: Самый простой, но не самый надежный способ. Мы ищем объект в справочнике перед началом цикла.
    
    // Перед циклом находим нужную валюту
    ВалютаДоллар = Справочники.Валюты.НайтиПоКоду("840"); // Код USD по классификатору
    
    Пока Выборка.Следующий() Цикл
        Если Выборка.ВалютаДокумента = ВалютаДоллар Тогда
            // Выполняем расчет
            СуммаС = Выборка.СуммаДокумента * 80; // Пример курса
        Иначе
            СуммаС = Выборка.СуммаДокумента;
        КонецЕсли;
    КонецЦикла;
    
  2. Использование предопределенных элементов: Если в вашей конфигурации валюты созданы как предопределенные элементы, вы можете обращаться к ним напрямую через точку: Справочники.Валюты.Доллар.

Решение 2: Перенос логики в запрос (Конструкция ВЫБОР)

Выполнять условия внутри цикла — не самая лучшая практика с точки зрения производительности. Проанализируем, как можно вычислить нужное значение прямо в тексте запроса. Это позволит системе выдать уже готовый результат, а коду на языке 1С останется только вывести его в макет.

Рассмотрим пример использования конструкции ВЫБОР в запросе:


ТекстЗапроса = 
"ВЫБРАТЬ
|    ППВ.Ссылка,
|    ППВ.СуммаДокумента,
|    ППВ.ВалютаДокумента,
|    ВЫБОР
|        КОГДА ППВ.ВалютаДокумента = &ВалютаДоллар
|            ТОГДА ППВ.СуммаДокумента * &КурсДоллара
|        ИНАЧЕ ППВ.СуммаДокумента
|    КОНЕЦ КАК СуммаВРублях
|ИЗ
|    Документ.ПлатежноеПоручениеВходящее КАК ППВ";

Запрос.УстановитьПараметр("ВалютаДоллар", Справочники.Валюты.НайтиПоКоду("840"));
Запрос.УстановитьПараметр("КурсДоллара", 80);

Такой подход делает ваш код чище, а отчет — быстрее, так как основные вычисления перекладываются на СУБД.

Решение 3: Динамическое получение курса из регистра сведений

Проанализируем еще одну критическую ошибку в исходном коде — "хардкод" курса (например, * 24). Курсы валют меняются ежедневно, и прописывать их в коде нельзя. В типовых конфигурациях 1С для хранения этой информации предназначен регистр сведений КурсыВалют.

Выясним, как получить актуальный курс на дату документа внутри запроса. Для этого используется левое соединение с виртуальной таблицей СрезПоследних:


"ВЫБРАТЬ
|    ППВ.Ссылка,
|    ППВ.Дата КАК ДатаДокумента,
|    ППВ.СуммаДокумента,
|    ЕСТЬNULL(КурсыВалютСрезПоследних.Курс, 1) КАК КурсВалюты,
|    ППВ.СуммаДокумента * ЕСТЬNULL(КурсыВалютСрезПоследних.Курс, 1) КАК СуммаВВалютеУчета
|ИЗ
|    Документ.ПлатежноеПоручениеВходящее КАК ППВ
|    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних(&Период, ) КАК КурсыВалютСрезПоследних
|        ПО ППВ.ВалютаДокумента = КурсыВалютСрезПоследних.Валюта";

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

Оптимизация работы с табличными частями (Проблема N+1)

Посмотрим на строку: НДС = Выборка.Ссылка.РасшифровкаПлатежа[0].СуммаНДС;. Это классическая ошибка "обращения через точку к коллекции".

Почему так делать нельзя:

  1. Производительность: При каждой итерации цикла 1С делает отдельный неявный запрос к базе данных, чтобы получить табличную часть документа. Если документов 1000 — вы сделаете 1000 лишних запросов.
  2. Надежность: Если табличная часть РасшифровкаПлатежа окажется пустой, обращение к индексу [0] вызовет фатальную ошибку и аварийное завершение программы.

Рассмотрим, как правильно получить сумму НДС. Нам нужно просуммировать данные табличной части в самом запросе:


"ВЫБРАТЬ
|    ППВ.Ссылка,
|    СУММА(ППВ.РасшифровкаПлатежа.СуммаНДС) КАК ОбщаяСуммаНДС
|ИЗ
|    Документ.ПлатежноеПоручениеВходящее КАК ППВ
|СГРУППИРОВАТЬ ПО
|    ППВ.Ссылка";

Вывод данных в макет: завершающий этап

Когда мы получили все данные в запросе, нам остается только правильно заполнить параметры области макета. Рассмотрим правильную последовательность действий:


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

Пока Выборка.Следующий() Цикл
    // Сначала заполняем параметры области из выборки запроса
    Область.Параметры.Заполнить(Выборка);
    
    // Если нужно добавить вычисляемые в коде значения
    Область.Параметры.СуммаС = Выборка.СуммаДокумента + Выборка.ОбщаяСуммаНДС;
    
    // И только ПОСЛЕ заполнения всех параметров выводим область
    ТабДок.Вывести(Область);
КонецЦикла;

Подведем итоги: Для корректного сравнения валюты используйте ссылки (объекты), а не строки. Старайтесь переносить расчеты и работу с курсами в запрос — это сделает ваш код профессиональным и устойчивым к изменениям данных.

← На главную