Часто при формировании отчетов по остаткам, например, по товарам на складе, возникает задача показать не только те позиции, по которым есть движение или остаток, но и абсолютно все товары из справочника. Это позволяет увидеть полную картину, включая товары с нулевыми остатками. Давайте разберем, как правильно составить запрос в 1С:Предприятие 7.7 для решения этой задачи и почему распространенная ошибка с группировкой Все ВошедшиеВЗапрос не приводит к желаемому результату.
Проанализируем ситуацию: разработчик пытается построить отчет по остаткам и хочет, чтобы в него попали все товары. Он использует в тексте запроса конструкцию |Группировка Товар все ВошедшиеВЗапрос;, но отчет выводит только те товары, у которых есть остаток. Выясним причину такого поведения и рассмотрим правильные способы решения.
Ключ к решению задачи лежит в понимании фундаментального различия между двумя параметрами группировки в языке запросов 1С 7.7. Хотя их названия могут показаться похожими, они работают по совершенно разным принципам.
Группировка с параметром "Все"
При использовании ключевого слова Все система формирует итоговые записи отчета, основываясь на полном списке элементов справочника, который указан в качестве измерения группировки. Это именно то, что нужно для нашей задачи.
Рассмотрим по шагам, как это работает на примере |Группировка Товар Все;:
Таким образом, параметр Все гарантирует, что в итоговый отчет попадет каждая запись из указанного справочника.
Группировка с параметром "Все ВошедшиеВЗапрос"
Этот параметр работает иначе. Он оперирует не полным справочником, а только теми уникальными значениями, которые попали в результат выполнения запроса на первом шаге.
Проанализируем его логику:
Вывод: если у товара нулевой остаток, он не попадает в первоначальную выборку из регистра. Следовательно, группировка Все ВошедшиеВЗапрос его просто "не увидит" и, соответственно, не выведет в отчет. Этот параметр предназначен для других, более сложных задач, например, для построения кросс-отчетов, где состав строк или колонок динамически определяется на основе данных самого запроса (например, вывести в колонки месяцы, в которых были продажи).
Теперь, когда мы разобрались в теории, рассмотрим практические способы реализации поставленной задачи.
Это самый эффективный, идеологически верный и производительный метод для платформы 1С 7.7. Он использует встроенные механизмы языка запросов, которые оптимизированы для таких операций.
Текст запроса должен выглядеть следующим образом:
// Устанавливаем период, за который будем получать остатки
|Период С ДатаНач По ДатаКон;
// Определяем переменные запроса
// Товар - это измерение из регистра ОстаткиТМЦ
|Товар = Регистр.ОстаткиТМЦ.Товар;
// Количество - это ресурс регистра
|Количество = Регистр.ОстаткиТМЦ.Количество;
// Объявляем функцию для расчета конечного остатка
|Функция КоличествоКонОст = КонОст(Количество);
// Указываем группировку по товару, используя параметр "Все"
// Это заставит систему перебрать все элементы справочника
|Группировка Товар Все;
При выполнении такого запроса система сначала рассчитает остатки для товаров, которые их имеют, а затем дополнит результат всеми остальными товарами из справочника, проставив им нулевые остатки. Это быстро, лаконично и не требует написания дополнительного кода на встроенном языке.
Этот метод также приведет к желаемому результату, и именно к нему пришел автор в обсуждении на форуме. Суть его заключается в том, чтобы отказаться от попытки решить задачу целиком внутри запроса, а вместо этого организовать цикл по всем элементам справочника и для каждого элемента получать остаток отдельно.
Алгоритм действий:
ВыбратьЭлементы()).Регистры или выполняя короткий запрос только для одного этого товара).Примерный код (иллюстрация логики):
Процедура Сформировать()
Перем Запрос, ТекстЗапроса;
// Создаем объекты
Запрос = СоздатьОбъект("Запрос");
Спр = СоздатьОбъект("Справочник.Номенклатура");
Рег = СоздатьОбъект("Регистры");
Остатки = Рег.ОстаткиТМЦ;
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("Сформировать");
// Начинаем перебор справочника
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
// Пропускаем группы, если нужно
Если Спр.ЭтоГруппа() = 1 Тогда
Продолжить;
КонецЕсли;
// Для каждого элемента получаем остаток
ТекОстаток = Остатки.СводныйОстаток(ДатаОтчета, "Количество", "Товар", Спр.ТекущийЭлемент());
// Выводим строку в отчет
Таб.ВывестиСекцию("Строка");
КонецЦикла;
Таб.Показать("Остатки");
КонецПроцедуры
Недостатки этого способа:
Тем не менее, этот подход можно считать рабочим "костылем" или обходным путем в ситуациях, когда по каким-то причинам составить корректный запрос не удается.
Для задачи вывода в отчете всех элементов справочника с их остатками (включая нулевые) правильным, эффективным и рекомендуемым решением является использование в запросе 1С 7.7 группировки с параметром Все.
Конструкция |Группировка ИмяИзмерения <strong>Все</strong>; — это штатный инструмент платформы, созданный специально для таких целей.
Параметр Все ВошедшиеВЗапрос служит для других задач и работает только с теми данными, которые уже были отобраны запросом, поэтому он не подходит для вывода элементов с нулевыми остатками, если они не участвовали в движениях.