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