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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Анализ ошибки в логическом условии отбора

Выясним причину, почему условие отбора по прочим складам перестает выбирать данные. Очень часто при составлении отбора в параметрах виртуальной таблицы остатков указывают следующее выражение:


И Организация <> &Организация
И Субконто2 <> &Склад

Посмотрим на логику работы этого условия. Оператор И требует одновременного выполнения обоих критериев. Если позиция находится на другом складе, но той же самой организации, выражение Организация <> &Организация принимает значение Ложь. В результате вся строка отбрасывается, и запрос ничего не возвращает.

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

НЕ (Организация = &Организация И Субконто2 = &Склад)

Согласно правилам логики, это условие эквивалентно следующему выражению с оператором ИЛИ:

(Организация <> &Организация ИЛИ Субконто2 <> &Склад)

Правильная структура пакетного запроса

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

  1. Формирование базовой таблицы номенклатуры: первично выбираем список товаров из документа и помещаем его во временную таблицу ВТ_ПеремещениеТоваров. Свертка по номенклатуре гарантирует исключение дублей.
  2. Получение остатков по документу: отбираем остатки из регистра по списку номенклатуры, строго ограничивая выборку текущими параметрами &Организация и &Склад.
  3. Получение остатков по другим складам и организациям: отбираем остатки для тех же позиций номенклатуры, исключая конкретную пару организации и склада документа.
  4. Итоговое соединение: выполняем ЛЕВОЕ СОЕДИНЕНИЕ, где базовой (левой) таблицей выступает таблица товаров документа ВТ_ПеремещениеТоваров. Это гарантирует, что из результата не выпадут товары, по которым остаток на основном складе равен нулю.

Рассмотрим пример готового пакетного запроса:


ВЫБРАТЬ
	ПеремещениеТоваровТовары.Номенклатура КАК Номенклатура,
	СУММА(ПеремещениеТоваровТовары.Количество) КАК КоличествоДокумента
ПОМЕСТИТЬ ВТ_ТоварыДокумента
ИЗ
	Документ.ПеремещениеТоваров.Товары КАК ПеремещениеТоваровТовары
ГДЕ
	ПеремещениеТоваровТовары.Ссылка = &Ссылка
СГРУППИРОВАТЬ ПО
	ПеремещениеТоваровТовары.Номенклатура
;

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

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВТ_ТоварыДокумента.Номенклатура КАК Номенклатура,
	ВТ_ТоварыДокумента.КоличествоДокумента КАК КоличествоДокумента,
	ЕСТЬNULL(ВТ_ОстаткиОсновногоСклада.ОстатокНаСкладе, 0) КАК ОстатокНаСкладе,
	ВТ_ОстаткиПрочие.Организация КАК ПрочаяОрганизация,
	ВТ_ОстаткиПрочие.Склад КАК ПрочийСклад,
	ЕСТЬNULL(ВТ_ОстаткиПрочие.ОстатокПрочий, 0) КАК ОстатокПрочий
ИЗ
	ВТ_ТоварыДокумента КАК ВТ_ТоварыДокумента
		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ОстаткиОсновногоСклада КАК ВТ_ОстаткиОсновногоСклада
		ПО ВТ_ТоварыДокумента.Номенклатура = ВТ_ОстаткиОсновногоСклада.Номенклатура
		ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ОстаткиПрочие КАК ВТ_ОстаткиПрочие
		ПО ВТ_ТоварыДокумента.Номенклатура = ВТ_ОстаткиПрочие.Номенклатура

Альтернативное решение с использованием Системы Компоновки Данных (СКД)

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

  1. В запросе набора данных СКД получаем общую плоскую таблицу остатков без жесткого разделения на прочие и основные склады. Полями выборки будут Номенклатура, Организация, Склад и КоличествоОстаток.
  2. В настройках структуры отчета добавляем элемент **Таблица**.
  3. В **Строки** таблицы добавляем группировку Номенклатура.
  4. В **Колонки** таблицы добавляем иерархическую группировку Организация, а вложенной группировкой — Склад.
  5. В качестве ресурсов настраиваем выражение СУММА(КоличествоОстаток).

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

← На главную