Читайте дальше...
Базовый запрос к виртуальной таблице остатков регистра накопления
// Получение остатков товаров на текущий момент
Процедура ПолучитьОстаткиТоваров()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| ОстаткиТоваров.Номенклатура,
| ОстаткиТоваров.Склад,
| ОстаткиТоваров.Количество Остаток,
| ОстаткиТоваров.Сумма
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Количество > 0";
Результат = Запрос.Выполнить().Выгрузить();
Для Каждого Строка Из Результат Цикл
Сообщить("Товар: " + Строка.Номенклатура +
", Склад: " + Строка.Склад +
", Остаток: " + Строка.Остаток);
КонецЦикла;
КонецПроцедуры
Остатки на конкретную дату
// Получение остатков на определенную дату с условиями отбора
Процедура ПолучитьОстаткиНаДату(ДатаОстатков)
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| ОстаткиТоваров.Номенклатура,
| ОстаткиТоваров.Склад,
| ОстаткиТоваров.Количество КАК Остаток,
| ОстаткиТоваров.Сумма КАК Сумма
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОстатков) КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Количество > 0";
Запрос.УстановитьПараметр("ДатаОстатков", ДатаОстатков);
Результат = Запрос.Выполнить().Выгрузить();
Сообщить("Остатки на " + Формат(ДатаОстатков, "ДФ=yyyy-MM-dd") + ":");
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Номенклатура + ": " + Строка.Остаток + " шт.");
КонецЦикла;
КонецПроцедуры
Остатки с отбором по измерениям
// Получение остатков с фильтрацией по конкретным значениям измерений
Процедура ПолучитьОстаткиПоСкладуИТовару()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| ОстаткиТоваров.Номенклатура,
| ОстаткиТоваров.Количество КАК Остаток,
| ОстаткиТоваров.Сумма КАК Сумма
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(,, Склад = &Склад) КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Номенклатура = &Номенклатура";
// Устанавливаем параметры отбора
Запрос.УстановитьПараметр("Склад", Справочники.Склады.НайтиПоНаименованию("Основной склад"));
Запрос.УстановитьПараметр("Номенклатура", Справочники.Номенклатура.НайтиПоНаименованию("Ноутбук"));
Результат = Запрос.Выполнить().Выгрузить();
Если Результат.Количество() > 0 Тогда
Строка = Результат[0];
Сообщить("Остаток ноутбуков на основном складе: " + Строка.Остаток + " шт.");
Иначе
Сообщить("Товар отсутствует на складе");
КонецЕсли;
КонецПроцедуры
Остатки по нескольким измерениям с группировкой
// Получение остатков с группировкой по измерениям
Процедура ПолучитьОстаткиСГруппировкой()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| ОстаткиТоваров.Склад,
| СУММА(ОстаткиТоваров.Количество) КАК ВсегоТоваров,
| СУММА(ОстаткиТоваров.Сумма) КАК ОбщаяСумма
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(,,) КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Количество > 0
|СГРУППИРОВАТЬ ПО
| ОстаткиТоваров.Склад";
Результат = Запрос.Выполнить().Выгрузить();
Сообщико("Сводка остатков по складам:");
Для Каждого Строка Из Результат Цикл
Сообщить("Склад: " + Строка.Склад +
", количество товаров: " + Строка.ВсегоТоваров +
", сумма: " + Строка.ОбщаяСумма);
КонецЦикла;
КонецПроцедуры
Остатки с использованием периода (срез последних)
// Получение остатков на конец каждого месяца
Процедура ПолучитьОстаткиНаКонцыМесяцев()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Номенклатура.Ссылка КАК Товар,
| Номенклатура.Наименование,
| Периоды.Период,
| Остатки.КонечныйОстаток КАК Остаток,
| Остатки.КонечныйОстатокСумма КАК Сумма
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ (
| ВЫБРАТЬ РАЗЛИЧНЫЕ
| КОНЕЦПЕРИОДА(&ДатаНачала, МЕСЯЦ) КАК Период
| ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки
| ГДЕ
| КОНЕЦПЕРИОДА(&ДатаНачала, МЕСЯЦ) МЕЖДУ &ДатаНачала И &ДатаОкончания
| ) КАК Периоды
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(Периоды.Период,)
| КАК Остатки
| ПО Номенклатура.Ссылка = Остатки.Номенклатура";
Запрос.УстановитьПараметр("ДатаНачала", НачалоГода(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Результат = Запрос.Выполнить().Выгрузить();
// Выводим результат
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Наименование + " на " + Строка.Период + ": " +
Строка.Остаток + " шт. на сумму " + Строка.Сумма);
КонецЦикла;
КонецПроцедуры
Объединение остатков с оборотами
// Получение начальных остатков, оборотов и конечных остатков
Функция ПолучитьОстаткиСОборОтами(ДатаНачала, ДатаОкончания)
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Движения.Номенклатура,
| СУММА(Движения.Количество) КАК ОборотПриход,
| СУММА(Движения.Сумма) КАК ОборотСумма
|ПОМЕСТИТЬ ВТ_Обороты
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНачала, &ДатаОкончания, ,) КАК Движения
|ГДЕ
| Движения.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
|СГРУППИРОВАТЬ ПО
| Движения.Номенклатура";
Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончания", ДатаОкончания);
Результат = Запрос.Выполнить().Выгрузить();
// Получаем начальные остатки
ЗапросОстатки = Новый Запрос;
ЗапросОстатки.Текст = "
|ВЫБРАТЬ
| Остатки.Номенклатура,
| Остатки.Количество КАК НачальныйОстаток,
| Остатки.Сумма КАК НачальнаяСумма
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаНачала) КАК Остатки";
ЗапросОстатки.УстановитьПараметр("ДатаНачала", ДатаНачала);
НачальныеОстатки = ЗапросОстатки.Выполнить().Выгрузить();
// Формируем итоговую таблицу
ИтоговаяТаблица = Новый ТаблицаЗначений;
ИтоговаяТаблица.Колонки.Добавить("Номенклатура");
ИтоговаяТаблица.Колонки.Добавить("НачальныйОстаток");
ИтоговаяТаблица.Колонки.Добавить("ОборотПриход");
ИтоговаяТаблица.Колонки.Добавить("ОборотСумма");
ИтоговаяТаблица.Колонки.Добавить("КонечныйОстаток");
// Объединяем данные
Для Каждого НачОст Из НачальныеОстатки Цикл
НоваяСтрока = ИтоговаяТаблица.Добавить();
НоваяСтрока.Номенклатура = НачОст.Номенклатура;
НоваяСтрока.НачальныйОстаток = НачОст.НачальныйОстаток;
// Ищем обороты
Найденная = Результат.Найти(НачОст.Номенклатура, "Номенклатура");
Если Найденная <> Неопределено Тогда
НоваяСтрока.ОборотПриход = Найденная.ОборотПриход;
НоваяСтрока.ОборотСумма = Найденная.ОборотСумма;
КонецЕсли;
НоваяСтрока.КонечныйОстаток = НоваяСтрока.НачальныйОстаток +
?(ЗначениеЗаполнено(НоваяСтрока.ОборотПриход),
НоваяСтрока.ОборотПриход, 0);
КонецЦикла;
Возврат ИтоговаяТаблица;
КонецФункции
// Пример использования
Процедура АнализДвиженияТоваров()
ДатаНач = НачалоМесяца(ТекущаяДата());
ДатаКон = ТекущаяДата();
Результат = ПолучитьОстаткиСОборОтами(ДатаНач, ДатаКон);
Сообщить("Анализ движения товаров за период:");
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Номенклатура +
": нач=" + Строка.НачальныйОстаток +
", приход=" + Строка.ОборотПриход +
", кон=" + Строка.КонечныйОстаток);
КонецЦикла;
КонецПроцедуры
Остатки с произвольным условием отбора
// Получение остатков с динамическими условиями отбора
Процедура ПолучитьОстаткиСУсловием(ТоварыПоКоторымНужныОстатки)
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| ОстаткиТоваров.Номенклатура,
| ОстаткиТоваров.Склад,
| ОстаткиТоваров.Количество КАК Остаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(,,) КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Номенклатура В (&СписокТоваров)
| И ОстаткиТоваров.Количество > 0";
// Передаем массив товаров как параметр
Запрос.УстановитьПараметр("СписокТоваров", ТоварыПоКоторымНужныОстатки);
Результат = Запрос.Выполнить().Выгрузить();
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Номенклатура + " на складе " +
Строка.Склад + ": " + Строка.Остаток);
КонецЦикла;
КонецПроцедуры
Остатки с использованием временных таблиц
// Работа с остатками через временные таблицы для сложных расчетов
Процедура ОстаткиЧерезВременныеТаблицы()
МенеджерВТ = Новый МенеджерВременныхТаблиц;
// Шаг 1: создаем временную таблицу с нужными товарами
Запрос1 = Новый Запрос;
Запрос1.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос1.Текст = "
|ВЫБРАТЬ
| Номенклатура.Ссылка КАК Товар,
| Номенклатура.Наименование
|ПОМЕСТИТЬ ВТ_НужныеТовары
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ
| И Номенклатура.Цена > 10000";
Запрос1.Выполнить();
// Шаг 2: получаем остатки для этих товаров
Запрос2 = Новый Запрос;
Запрос2.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос2.Текст = "
|ВЫБРАТЬ
| ВТ_НужныеТовары.Товар,
| ВТ_НужныеТовары.Наименование,
| СУММА(Остатки.Количество) КАК ОбщийОстаток,
| СУММА(Остатки.Сумма) КАК ОбщаяСумма
|ИЗ
| ВТ_НужныеТовары КАК ВТ_НужныеТовары
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОтчета,) КАК Остатки
| ПО ВТ_НужныеТовары.Товар = Остатки.Номенклатура
|СГРУППИРОВАТЬ ПО
| ВТ_НужныеТовары.Товар,
| ВТ_НужныеТовары.Наименование
|ИМЕЮЩИЕ
| СУММА(Остатки.Количество) > 0";
Запрос2.УстановитьПараметр("ДатаОтчета", ТекущаяДата());
Результат = Запрос2.Выполнить().Выгрузить();
Сообщить("Дорогие товары с ненулевыми остатками:");
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Наименование + ": остаток " +
Строка.ОбщийОстаток + " шт. на сумму " + Строка.ОбщаяСумма);
КонецЦикла;
КонецПроцедуры
Остатки регистра бухгалтерии
// Получение остатков по регистру бухгалтерии
Процедура ПолучитьОстаткиБухгалтерии()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Остатки.Счет КАК Счет,
| Остатки.Субконто1 КАК Субконто,
| Остатки.СуммаНачальныйОстаток КАК НачальныйОстаток,
| Остатки.СуммаКонечныйОстаток КАК КонечныйОстаток
|ИЗ
| РегистрБухгалтерии.Хозрасчет.Остатки(&ДатаНачала, &ДатаОкончания) КАК Остатки
|ГДЕ
| Остатки.Счет.Вид = ЗНАЧЕНИЕ(ВидСчета.Активный)
| И Остатки.СуммаКонечныйОстаток <> 0
|СГРУППИРОВАТЬ ПО
| Остатки.Счет,
| Остатки.Субконто1";
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Результат = Запрос.Выполнить().Выгрузить();
Сообщико("Остатки по активным счетам:");
Для Каждого Строка Из Результат Цикл
Сообщить("Счет: " + Строка.Счет +
", субконто: " + Строка.Субконто +
", начальный остаток: " + Строка.НачальныйОстаток +
", конечный остаток: " + Строка.КонечныйОстаток);
КонецЦикла;
КонецПроцедуры
Остатки регистра сведений (срез последних)
// Получение актуальных значений из регистра сведений (срез последних)
Процедура ПолучитьАктуальныеКурсыВалют()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Валюты.Ссылка КАК Валюта,
| Валюты.Наименование,
| Курсы.Курс,
| Курсы.Кратность,
| Курсы.Период
|ИЗ
| Справочник.Валюты КАК Валюты
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних(&ДатаОтчета) КАК Курсы
| ПО Валюты.Ссылка = Курсы.Валюта";
Запрос.УстановитьПараметр("ДатаОтчета", ТекущаяДата());
Результат = Запрос.Выполнить().Выгрузить();
Сообщить("Актуальные курсы валют на " + Формат(ТекущаяДата(), "ДФ=yyyy-MM-dd") + ":");
Для Каждого Строка Из Результат Цикл
Если ЗначениеЗаполнено(Строка.Курс) Тогда
Сообщить(Строка.Наименование + ": " + Строка.Курс +
" (кратность " + Строка.Кратность + ")");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Срез последних на определенную дату
Процедура ПолучитьКурсыНаПрошлуюДату()
ПрошлаяДата = ТекущаяДата() - 7;
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Курсы.Валюта,
| Курсы.Курс,
| Курсы.Кратность,
| Курсы.Период
|ИЗ
| РегистрСведений.КурсыВалют.СрезПоследних(&ДатаСреза) КАК Курсы";
Запрос.УстановитьПараметр("ДатаСреза", ПрошлаяДата);
Результат = Запрос.Выполнить().Выгрузить();
Сообщить("Курсы валют на " + Формат(ПрошлаяДата, "ДФ=yyyy-MM-dd") + ":");
Для Каждого Строка Из Результат Цикл
Сообщить(Строка.Валюта + ": " + Строка.Курс);
КонецЦикла;
КонецПроцедуры
Остатки с подзапросом для расчета средневзвешенной цены
// Расчет средневзвешенной цены товара на основе остатков
Процедура РассчитатьСредневзвешеннуюЦену()
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Остатки.Номенклатура,
| СУММА(Остатки.Количество) КАК ВсегоКоличество,
| СУММА(Остатки.Сумма) КАК ОбщаяСумма,
| ВЫРАЗИТЬ(СУММА(Остатки.Сумма) / СУММА(Остатки.Количество) КАК ЧИСЛО(15, 2)) КАК СредняяЦена
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОстатков,,) КАК Остатки
|ГДЕ
| Остатки.Количество > 0
|СГРУППИРОВАТЬ ПО
| Остатки.Номенклатура";
Запрос.УстановитьПараметр("ДатаОстатков", ТекущаяДата());
Результат = Запрос.Выполнить().Выгрузить();
Сообщико("Средневзвешенные цены:");
Для Каждого Строка Из Результат Цикл
Если Строка.ВсегоКоличество > 0 Тогда
Сообщить(Строка.Номенклатура +
": кол-во=" + Строка.ВсегоКоличество +
", сумма=" + Строка.ОбщаяСумма +
", ср.цена=" + Строка.СредняяЦена);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Остатки с использованием периода (срез первых)
// Получение начальных остатков на начало периода (срез первых)
Процедура ПолучитьНачальныеОстатки()
ДатаНачалаПериода = НачалоМесяца(ТекущаяДата());
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Номенклатура.Ссылка КАК Товар,
| Номенклатура.Наименование,
| Остатки.Количество КАК НачальныйОстаток,
| Остатки.Сумма КАК НачальнаяСумма
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаНачала) КАК Остатки
| ПО Номенклатура.Ссылка = Остатки.Номенклатура
|ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ
| И Остатки.Количество > 0";
Запрос.УстановитьПараметр("ДатаНачала", ДатаНачалаПериода);
Результат = Запрос.Выполнить().Выгрузить();
Сообщить("Начальные остатки на " + Формат(ДатаНачалаПериода, "ДФ=yyyy-MM-dd") + ":");
Для Каждого Строка Из Результат Цикл
Если ЗначениеЗаполнено(Строка.НачальныйОстаток) Тогда
Сообщить(Строка.Наименование + ": " + Строка.НачальныйОстаток +
" шт. на сумму " + Строка.НачальнаяСумма);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Примечания
// Важные особенности работы с виртуальными таблицами остатков:
// 1. Виртуальная таблица Остатки рассчитывается на указанную дату
// 2. Синтаксис: РегистрНакопления.ИмяРегистра.Остатки(<Дата>, <ОтборПоИзмерениям>)
// 3. Параметр <ОтборПоИзмерениям> позволяет установить отборы (например, Товар = &Товар)
// 4. Для регистров бухгалтерии используется синтаксис с периодом: Остатки(<ДатаНач>, <ДатаКон>)
// 5. СрезПоследних и СрезПервых доступны для регистров сведений
// 6. Виртуальные таблицы остатков оптимальны по производительности
// 7. Для получения остатков на несколько дат используйте соединение с таблицей периодов
// 8. Виртуальная таблица Остатки не поддерживает группировку по измерениям (нужно группировать в запросе)
// 9. При работе с большими данными рекомендуется использовать условия в параметрах отбора, а не в WHERE
// 10. Для регистров накопления остатки рассчитываются как итог по движениям с учетом активных границ итогов
// 11. Использование виртуальной таблицы Остатки без параметров возвращает остатки на текущий момент
// 12. При массовых расчетах остатков на разные даты эффективнее использовать одну виртуальную таблицу с параметрами








