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

Программист 1С v8.3 (Управляемые формы) Бухгалтерский учет
← На главную

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

Автор столкнулся с такой проблемой при написании запроса к виртуальной таблице РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты. Его запрос выглядел следующим образом:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    Регистр.Регистратор КАК Регистратор,
    Регистр.Счет КАК Счет
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(, , Регистратор, , НЕ Счет В (&Счета), , ЖурналОпераций = &Журнал) КАК Регистр

Несмотря на использование оператора НЕ Счет В (&Счета), фильтрация не работала. Чтобы решить эту задачу, мы должны рассмотреть несколько ключевых моментов.

Причина 1: Неверный тип данных элементов в массиве параметра

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

Если в массив &Счета передаются строковые коды счетов, их наименования или какие-либо другие типы данных, отличные от ссылки на элемент плана счетов, платформа 1С не сможет корректно сравнить эти значения. Оператор В (или НЕ В) в запросах 1С работает на основе сравнения ссылок для ссылочных типов. Строковое сравнение будет производиться только если поле в регистре имеет строковый тип, что не относится к счету бухгалтерского учета.

Что нужно сделать:

  1. Убедитесь, что массив, который вы формируете для параметра &Счета, содержит ссылки на элементы плана счетов (например, ПланыСчетов.Хозрасчетный.НайтиПоКоду("60.01") или ссылки, полученные из других запросов/объектов).
  2. Не передавайте в массив коды или наименования счетов напрямую, если они не были предварительно преобразованы в ссылки.

Пример формирования массива счетов для параметра:


// Пример формирования массива счетов на стороне 1С-кода
МассивСчетовДляИсключения = Новый Массив();

// Добавляем ссылки на конкретные счета
МассивСчетовДляИсключения.Добавить(ПланыСчетов.Хозрасчетный.НайтиПоКоду("60.01"));
МассивСчетовДляИсключения.Добавить(ПланыСчетов.Хозрасчетный.НайтиПоКоду("76"));

// ...можно получить счета из таблицы значений или другой коллекции
// Например, если у вас есть таблица значений с колонкой "СчетСсылка"
// Для Каждого СтрокаТЗ Из МояТаблицаСчетов Цикл
//     МассивСчетовДляИсключения.Добавить(СтрокаТЗ.СчетСсылка);
// КонецЦикла;

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |    Регистр.Регистратор КАК Регистратор,
    |    Регистр.Счет КАК Счет
    |ИЗ
    |    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , НЕ Счет В (&Счета), , ) КАК Регистр";

// Устанавливаем параметры запроса
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("Счета", МассивСчетовДляИсключения);

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл
    Сообщить("Регистратор: " + Выборка.Регистратор + ", Счет: " + Выборка.Счет);
КонецЦикла;

Причина 2: Иерархическая структура Плана счетов и оператор "В ИЕРАРХИИ"

План счетов в 1С имеет иерархическую структуру. Это означает, что счета могут иметь субсчета (подчиненные счета). Например, счет 60 "Расчеты с поставщиками и подрядчиками" может иметь субсчета 60.01 "Расчеты с поставщиками" и 60.02 "Расчеты по авансам выданным".

Оператор В (и соответственно НЕ В) в запросе проверяет только прямое вхождение элемента в переданный список. Он не учитывает иерархию. То есть, если вы добавите в массив &Счета только ссылку на счет 60, оператор НЕ Счет В (&Счета) исключит только сам счет 60, но не его субсчета 60.01 и 60.02. Если проводки были сделаны по субсчетам, они все равно попадут в выборку.

Для корректного исключения счетов вместе с их субсчетами (и всей иерархией), необходимо использовать оператор В ИЕРАРХИИ.

Применение оператора В ИЕРАРХИИ вместо В позволяет запросу учитывать всю ветку иерархии, исключая как сам указанный счет (или группу счетов), так и все его дочерние элементы.

Пример изменения запроса:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    Регистр.Регистратор КАК Регистратор,
    Регистр.Счет КАК Счет
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(, , Регистратор, , НЕ Счет В ИЕРАРХИИ (&Счета), , ЖурналОпераций = &Журнал) КАК Регистр

Обратите внимание на НЕ Счет В ИЕРАРХИИ (&Счета). Теперь, если в массиве &Счета будет счет 60, из выборки будут исключены все проводки как по счету 60, так и по всем его субсчетам (60.01, 60.02 и т.д.).

Этот оператор критически важен при работе с иерархическими справочниками и планами счетов, когда требуется комплексная фильтрация.

Причина 3: Особенности размещения условия в виртуальной таблице ОстаткиИОбороты

В вашем первоначальном запросе условие НЕ Счет В (&Счета) правильно размещено в параметрах виртуальной таблицы РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты. Это является стандартным и наиболее эффективным способом фильтрации данных на уровне формирования виртуальной таблицы, что позволяет СУБД выполнить фильтрацию до того, как данные будут переданы в 1С, значительно улучшая производительность.

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

Параметры виртуальной таблицы ОстаткиИОбороты:

  1. <НачалоПериода>
  2. <КонецПериода>
  3. <ВидДвижения> (Например, 'Итоги', 'Приход', 'Расход' или пусто, если не требуется)
  4. <Регистратор> (Если нужна фильтрация по конкретному регистратору)
  5. <УсловиеСчет> (Это наш случай: НЕ Счет В ИЕРАРХИИ (&Счета))
  6. <УсловиеСубконто> (Если нужна фильтрация по субконто)
  7. <УсловиеОрганизация> (Если нужна фильтрация по организации)
  8. <УсловиеВалюта> (Если нужна фильтрация по валюте)
  9. <УсловиеСчетКорреспондирующий> (Если нужна фильтрация по корреспондирующему счету)
  10. <УсловиеСубконтоКорреспондирующее> (Если нужна фильтрация по субконто корреспондирующего счета)
  11. <УсловиеВидСубконто>
  12. <УсловиеВидСубконтоКорреспондирующее>
  13. <Балансовый> (Ложь/Истина, влияет на вид остатков)
  14. <РазрешенныеСубконто>

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

Дополнительные рекомендации и диагностика

Проверка содержимого параметра в отладчике

Если вы все еще сталкиваетесь с проблемами, критически важно проверить содержимое массива &Счета непосредственно перед выполнением запроса в режиме отладчика. Это позволит вам убедиться, что:

  1. Массив МассивСчетовДляИсключения содержит именно те счета, которые вы ожидаете.
  2. Тип каждого элемента в массиве является ПланСчетов.Хозрасчетный.Ссылка.

Для этого установите точку останова перед строкой Результат = Запрос.Выполнить(); и посмотрите значения переменных МассивСчетовДляИсключения и Запрос.Параметры.Счета.

Обработка пустого массива счетов

Что произойдет, если массив &Счета окажется пустым? В большинстве случаев, если массив пуст, условие НЕ Счет В (&Счета) не будет оказывать никакого влияния на выборку, то есть фактически не будет никакой фильтрации по счетам. Это может быть как желаемым, так и нежелаемым поведением, в зависимости от логики вашей задачи.

Если вам нужно, чтобы при пустом массиве условие НЕ Счет В (&Счета) всегда применялось (например, чтобы ничего не выбрать или выбрать все), вам может потребоваться динамически изменять текст запроса:

  1. Если массив пуст и нужно выбрать все, просто исключите это условие из текста запроса.
  2. Если массив пуст и не нужно выбирать ничего, можно добавить условие, которое гарантированно не вернет строк (например, 1 = 0).
  3. Если массив пуст, но вам нужно исключить "все несуществующие" счета (что обычно не имеет смысла, но как пример), то можно передать в параметр ссылку на несуществующий элемент Плана счетов.

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

Пример динамического формирования текста запроса:


// Предположим, что МассивСчетовДляИсключения уже сформирован
Если МассивСчетовДляИсключения.Количество() > 0 Тогда
    УсловиеПоСчетам = "НЕ Счет В ИЕРАРХИИ (&Счета)";
Иначе
    // Если массив пуст, условие не применяется, выбираем все счета
    УсловиеПоСчетам = ""; 
КонецЕсли;

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |    Регистр.Регистратор КАК Регистратор,
    |    Регистр.Счет КАК Счет
    |ИЗ
    |    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , " + УсловиеПоСчетам + ", , ) КАК Регистр";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДата()));

Если МассивСчетовДляИсключения.Количество() > 0 Тогда
    Запрос.УстановитьПараметр("Счета", МассивСчетовДляИсключения);
КонецЕсли;

Результат = Запрос.Выполнить();
// ... дальнейшая обработка

Итоговый алгоритм решения проблемы

Чтобы окончательно решить проблему с исключением счетов в запросе 1С, рекомендуем придерживаться следующего алгоритма:

  1. Проверьте тип данных: Убедитесь, что массив, который вы передаете в параметр &Счета, состоит из элементов типа ПланСчетов.Хозрасчетный.Ссылка. Используйте отладчик для проверки.
  2. Используйте В ИЕРАРХИИ: Если ваши счета имеют иерархическую структуру и вы хотите исключить не только родительские счета, но и все их субсчета, измените условие на НЕ Счет В ИЕРАРХИИ (&Счета).
  3. Проверьте остальные параметры: Убедитесь, что другие параметры виртуальной таблицы ОстаткиИОбороты (период, вид движения и т.д.) установлены корректно и не влияют на результат выборки счетов.
  4. Обработайте пустой массив: Если массив &Счета может быть пустым, рассмотрите возможность динамического изменения текста запроса, чтобы условие фильтрации по счетам применялось только при наличии счетов в массиве.

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

← На главную