Как в 1С:УТ 10.3 получить ставку НДС из регистра сведений и вывести её в макет отчета

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

При доработке типовых конфигураций на обычных формах, таких как Управление торговлей 10.3, часто возникает необходимость расширить стандартные отчеты или печатные формы данными из нетиповых (кастомных) регистров. Типичный пример — получение актуальной ставки НДС для контрагента из регистра сведений и выполнение математических расчетов на ее основе. В рамках данной статьи мы подробно разберем, как правильно составить запрос к регистру, обработать его результат и избежать распространенных ошибок при преобразовании типов данных.

Постановка задачи и архитектура решения

Предположим, у нас есть регистр сведений КредитныеЛимиты, где в разрезе контрагентов хранится ресурс НДС (тип ПеречислениеСсылка.СтавкиНДС). Нам нужно вывести это значение в макет отчета и рассчитать «Лимит без НДС». Основная сложность для начинающих разработчиков заключается в том, что в базе данных ставка хранится как ссылка на объект перечисления, а для формул в макете требуется числовое значение.

Рассмотрим процесс реализации по шагам, начиная с создания функции получения данных.

Шаг 1. Создание функции запроса к регистру сведений

Для получения актуальных данных на определенную дату в 1С используется виртуальная таблица СрезПоследних. Проанализируем правильную структуру функции, которая будет возвращать ставку НДС:


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

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

Шаг 2. Преобразование перечисления в числовое значение

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


Функция ПолучитьЧисловуюСтавкуНДС(СтавкаНДС)
    Если СтавкаНДС = Перечисления.СтавкиНДС.НДС20 
       Или СтавкаНДС = Перечисления.СтавкиНДС.НДС20_120 Тогда
        Возврат 20;
    ИначеЕсли СтавкаНДС = Перечисления.СтавкиНДС.НДС18 
           Или СтавкаНДС = Перечисления.СтавкиНДС.НДС18_118 Тогда
        Возврат 18;
    ИначеЕсли СтавкаНДС = Перечисления.СтавкиНДС.НДС10 
           Или СтавкаНДС = Перечисления.СтавкиНДС.НДС10_110 Тогда
        Возврат 10;
    Иначе
        Возврат 0;
    КонецЕсли;
КонецФункции

Использование такой функции позволяет избежать ошибки «Преобразование значения к типу Число не может быть выполнено», которая возникает при попытке использовать ссылку в арифметических операциях.

Шаг 3. Вывод данных в макет и расчет показателей

Теперь объединим все части в основном коде формирования отчета. Предположим, мы обходим список контрагентов в цикле и выводим секцию макета. Выясним, как правильно передать параметры в область макета:


// В цикле по строкам отчета
КонтрагентОбъект = СтрокаДанных.Контрагент;
Лимит = ОпределитьЛимит(КонтрагентОбъект); // Получаем сумму лимита (число)

// 1. Получаем ссылку на НДС
СсылкаНДС = ОпределитьНДС(КонтрагентОбъект, ДатаОтчета);

// 2. Получаем числовое значение для расчетов
ЧислоНДС = ПолучитьЧисловуюСтавкуНДС(СсылкаНДС);

// 3. Выполняем расчет "Лимит без НДС"
// Правильная формула для НДС "в том числе": Сумма / (1 + Ставка/100)
Если ЧислоНДС > 0 Тогда
    ЛимитБезНДС = Лимит / (1 + ЧислоНДС / 100);
Иначе
    ЛимитБезНДС = Лимит;
КонецЕсли;

// 4. Заполнение параметров секции
Секция = Макет.ПолучитьОбласть("Строка");
Секция.Параметры.Контрагент = КонтрагентОбъект;
Секция.Параметры.Лимит = Лимит;
Секция.Параметры.СтавкаНДС = СсылкаНДС; // В макет выведется строковое представление, например "20%"
Секция.Параметры.ЛимитБезНДС = ЛимитБезНДС;

ТабДок.Вывести(Секция);

Оптимизация производительности: "Запрос в цикле"

Рассмотрим важный нюанс. В примере выше функция ОпределитьНДС вызывается внутри цикла. Если в отчете 1000 контрагентов, программа сделает 1000 запросов к базе данных, что значительно замедлит работу. Проанализируем, как сделать это правильно («по-программистски»):

  1. Сначала соберем всех контрагентов, которые попадут в отчет, в Массив.
  2. Выполним один запрос к срезу последних, передав этот массив в параметр ГДЕ Контрагент В (&МассивКонтрагентов).
  3. Выгрузим результат запроса в Соответствие, где ключом будет Контрагент, а значением — СтавкаНДС.
  4. В цикле вывода макета будем просто брать данные из Соответствия по ключу: Ставка = СоответствиеНДС.Получить(ТекущийКонтрагент).

Это позволит сократить время формирования отчета в десятки раз.

Обработка пустых значений

Часто в старых записях или у новых контрагентов данные в регистре могут отсутствовать. Чтобы отчет не «падал» с ошибками, всегда проверяйте значения. В запросе можно использовать функцию ЕСТЬNULL, а в коде 1С — проверку ЗначениеЗаполнено().

Например, в тексте запроса можно сразу возвращать пустую ссылку вместо NULL:

ЕСТЬNULL(КредитныеЛимитыСрезПоследних.НДС, ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.ПустаяСсылка))

Такой подход гарантирует стабильную работу системы даже при неполном заполнении справочников и регистров.

← На главную