Как скрыть конкретную сумму или документ из отчета в 1С (не через СКД)

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

При разработке нетиповых отчетов в 1С, которые строятся на прямых запросах к регистрам (без использования Системы компоновки данных), часто возникает задача исключить конкретную операцию или сумму из итогового результата. Например, когда необходимо убрать из отчета конкретное поступление на расчетный счет. Разберем по шагам, почему простые фильтры в запросе могут не работать и какими способами можно гарантированно скрыть ненужные данные.

Метод 1. Фильтрация на уровне запроса (секции ГДЕ и ИМЕЮЩИЕ)

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


ИсклСумма = Новый Массив; 
ИсклСумма.Добавить(10537829.89); 

ТекстЗапроса = "ВЫБРАТЬ
               | ХозрасчетныйОбороты.КорСчет,
               | СУММА(ХозрасчетныйОбороты.СуммаОборотДт) КАК СуммаОборотДт,
               | СУММА(ХозрасчетныйОбороты.СуммаОборотКт) КАК СуммаОборотКт,
               | ХозрасчетныйОбороты.Субконто1 КАК Контрагент
               |ИЗ
               | РегистрБухгалтерии.Хозрасчетный.Обороты(&НачПериода, &КонПериода, , , , , , ) КАК ХозрасчетныйОбороты
               |ГДЕ
               | НЕ ХозрасчетныйОбороты.СуммаОборотДт В (&ИсклСумма)
               |СГРУППИРОВАТЬ ПО
               | ХозрасчетныйОбороты.КорСчет,
               | ХозрасчетныйОбороты.Субконто1";

Проанализируем ситуацию: почему такой фильтр может не сработать? Виртуальная таблица Обороты возвращает уже сгруппированные данные. Если за один период было два разных документа с одинаковой суммой, они «схлопнутся», и условие ГДЕ может отработать некорректно по отношению к итоговой сумме группы.

Если данные в запросе агрегируются (используется СУММА), то фильтр нужно накладывать не в секции ГДЕ, а в секции ИМЕЮЩИЕ. Это позволит проверить уже рассчитанный результат суммы. Посмотрим на пример изменения запроса:


|ИМЕЮЩИЕ
| НЕ СУММА(ХозрасчетныйОбороты.СуммаОборотДт) В (&ИсклСумма)

Важно помнить, что прямое сравнение дробных чисел в запросах — это «тонкий» момент. Из-за особенностей хранения чисел с плавающей точкой в SQL-базах, число 10.00 может храниться как 10.000000001. Чтобы избежать проблем с точностью, рекомендуется использовать округление или проверку нахождения в очень узком диапазоне.

Метод 2. Исключение по конкретному регистратору (Самый надежный способ)

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

Вместо того чтобы искать сумму, добавим в исключения конкретный документ (Регистратор). Для этого выполним следующие действия:

  1. Добавим поле Регистратор в выборку запроса (если отчет детальный).
  2. Передадим в параметры запроса массив ссылок на документы, которые нужно скрыть.
  3. Добавим условие в секцию ГДЕ.

Рассмотрим пример реализации:


Запрос.Текст = "ВЫБРАТЬ
               | ХозрасчетныйОбороты.Регистратор,
               | ХозрасчетныйОбороты.СуммаОборотДт КАК Сумма
               |ИЗ
               | РегистрБухгалтерии.Хозрасчетный.Обороты(&НачПериода, &КонПериода, Регистратор, , , , , ) КАК ХозрасчетныйОбороты
               |ГДЕ
               | НЕ ХозрасчетныйОбороты.Регистратор В (&ИсклДокументы)";

Запрос.УстановитьПараметр("ИсклДокументы", МассивНужныхДокументов);

Этот метод гарантирует, что мы уберем именно ту операцию, которую планировали, даже если ее сумма в будущем будет отредактирована бухгалтером.

Метод 3. Фильтрация на этапе вывода (обход выборки)

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

Рассмотрим подробнее, как это реализовать в коде обработки:


Выборка = Запрос.Выполнить().Выбрать();

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

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

Метод 4. Использование консоли запросов и отладчика

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

  1. Использование отладчика: установите точку останова на строке Запрос.Выполнить(). Проверьте содержимое параметра ИсклСумма. Убедитесь, что тип данных в массиве совпадает с типом данных в базе (Число, а не Строка).
  2. Консоль запросов: скопируйте текст запроса в консоль, подставьте параметры вручную. Если в консоли строка исчезает, а в отчете нет — значит, проблема в коде вывода (обработки результата).
  3. Проверка итогов: если вы используете ИТОГИ ПО ОБЩИЕ, помните, что фильтрация строк в ГДЕ влияет на итоги, а фильтрация в ИМЕЮЩИЕ — только на отображение групп. Если вы просто скрыли строку при выводе в ТабличныйДокумент, общая сумма итогов в подвале отчета сама не уменьшится — ее придется пересчитывать вручную.

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

← На главную