Как в запросе 1С 7.7 вывести все товары, включая те, у которых нулевые остатки?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

Часто при формировании отчетов по остаткам, например, по товарам на складе, возникает задача показать не только те позиции, по которым есть движение или остаток, но и абсолютно все товары из справочника. Это позволяет увидеть полную картину, включая товары с нулевыми остатками. Давайте разберем, как правильно составить запрос в 1С:Предприятие 7.7 для решения этой задачи и почему распространенная ошибка с группировкой Все ВошедшиеВЗапрос не приводит к желаемому результату.

Проанализируем ситуацию: разработчик пытается построить отчет по остаткам и хочет, чтобы в него попали все товары. Он использует в тексте запроса конструкцию |Группировка Товар все ВошедшиеВЗапрос;, но отчет выводит только те товары, у которых есть остаток. Выясним причину такого поведения и рассмотрим правильные способы решения.

Разбираемся в группировках: "Все" против "Все ВошедшиеВЗапрос"

Ключ к решению задачи лежит в понимании фундаментального различия между двумя параметрами группировки в языке запросов 1С 7.7. Хотя их названия могут показаться похожими, они работают по совершенно разным принципам.

Группировка с параметром "Все"

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

Рассмотрим по шагам, как это работает на примере |Группировка Товар Все;:

  1. Выполнение запроса. Сначала система выполняет основную часть запроса к виртуальной таблице регистра остатков. В результате получается временный набор данных, содержащий только те товары, по которым на конечную дату периода есть ненулевой остаток.
  2. Получение полного списка. Затем система обращается к справочнику "Номенклатура" (или тому, что указан в поле "Товар") и получает полный список всех его элементов, независимо от их участия в движениях.
  3. Сопоставление и вывод. На последнем этапе система "соединяет" эти два набора данных. Для товаров, которые присутствовали в результате запроса (шаг 1), подставляются их рассчитанные остатки. Для всех остальных товаров из полного списка справочника (шаг 2), которых не было в результатах запроса, все числовые поля (наши остатки) будут равны нулю.

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

Группировка с параметром "Все ВошедшиеВЗапрос"

Этот параметр работает иначе. Он оперирует не полным справочником, а только теми уникальными значениями, которые попали в результат выполнения запроса на первом шаге.

Проанализируем его логику:

  1. Выполнение запроса. Как и в предыдущем случае, система сначала получает данные из регистров. В нашем случае — это список товаров с ненулевыми остатками.
  2. Формирование списка для группировки. Вот здесь и кроется ключевое отличие. Система берет уникальные значения измерения (в нашем случае, уникальные товары) только из набора данных, полученного на шаге 1. Она не обращается к справочнику целиком.
  3. Вывод. В отчет выводятся только те товары, которые были в этом ограниченном списке.

Вывод: если у товара нулевой остаток, он не попадает в первоначальную выборку из регистра. Следовательно, группировка Все ВошедшиеВЗапрос его просто "не увидит" и, соответственно, не выведет в отчет. Этот параметр предназначен для других, более сложных задач, например, для построения кросс-отчетов, где состав строк или колонок динамически определяется на основе данных самого запроса (например, вывести в колонки месяцы, в которых были продажи).

Решение задачи: два способа

Теперь, когда мы разобрались в теории, рассмотрим практические способы реализации поставленной задачи.

Способ 1. Использование группировки "Все" (правильный и рекомендуемый)

Это самый эффективный, идеологически верный и производительный метод для платформы 1С 7.7. Он использует встроенные механизмы языка запросов, которые оптимизированы для таких операций.

Текст запроса должен выглядеть следующим образом:


// Устанавливаем период, за который будем получать остатки
|Период С ДатаНач По ДатаКон;
// Определяем переменные запроса
// Товар - это измерение из регистра ОстаткиТМЦ
|Товар = Регистр.ОстаткиТМЦ.Товар;
// Количество - это ресурс регистра
|Количество = Регистр.ОстаткиТМЦ.Количество;
// Объявляем функцию для расчета конечного остатка
|Функция КоличествоКонОст = КонОст(Количество);
// Указываем группировку по товару, используя параметр "Все"
// Это заставит систему перебрать все элементы справочника
|Группировка Товар Все;

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

Способ 2. Программный перебор справочника (обходной путь)

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

Алгоритм действий:

  1. Создать объект "Справочник" для номенклатуры.
  2. Организовать цикл для перебора всех элементов справочника (например, с помощью метода ВыбратьЭлементы()).
  3. Внутри цикла для каждого текущего элемента справочника программно получать его остаток на нужную дату (например, с помощью объекта Регистры или выполняя короткий запрос только для одного этого товара).
  4. Выводить полученные данные (товар и его остаток) в табличную часть или отчет.

Примерный код (иллюстрация логики):


Процедура Сформировать()
    Перем Запрос, ТекстЗапроса;
    // Создаем объекты
    Запрос = СоздатьОбъект("Запрос");
    Спр = СоздатьОбъект("Справочник.Номенклатура");
    Рег = СоздатьОбъект("Регистры");
    Остатки = Рег.ОстаткиТМЦ;

    Таб = СоздатьОбъект("Таблица");
    Таб.ИсходнаяТаблица("Сформировать");
    
    // Начинаем перебор справочника
    Спр.ВыбратьЭлементы();
    Пока Спр.ПолучитьЭлемент() = 1 Цикл
        // Пропускаем группы, если нужно
        Если Спр.ЭтоГруппа() = 1 Тогда
            Продолжить;
        КонецЕсли;

        // Для каждого элемента получаем остаток
        ТекОстаток = Остатки.СводныйОстаток(ДатаОтчета, "Количество", "Товар", Спр.ТекущийЭлемент());

        // Выводим строку в отчет
        Таб.ВывестиСекцию("Строка");
    КонецЦикла;
    
    Таб.Показать("Остатки");
КонецПроцедуры

Недостатки этого способа:

Тем не менее, этот подход можно считать рабочим "костылем" или обходным путем в ситуациях, когда по каким-то причинам составить корректный запрос не удается.

Подведем итог

Для задачи вывода в отчете всех элементов справочника с их остатками (включая нулевые) правильным, эффективным и рекомендуемым решением является использование в запросе 1С 7.7 группировки с параметром Все.

Конструкция |Группировка ИмяИзмерения <strong>Все</strong>; — это штатный инструмент платформы, созданный специально для таких целей.

Параметр Все ВошедшиеВЗапрос служит для других задач и работает только с теми данными, которые уже были отобраны запросом, поэтому он не подходит для вывода элементов с нулевыми остатками, если они не участвовали в движениях.

← На главную