Как правильно настроить программный отбор по номерам документов в журнале 1С (обычные формы)

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

При работе в конфигурациях на обычных формах (таких как УТ 10.3, КА 1.1 или УПП 1.3) разработчики часто сталкиваются с необходимостью программно ограничить видимость документов в журнале. Типичная задача — скрыть определенные документы по их номерам или другим реквизитам. Однако при реализации этой задачи возникают две основные проблемы: ошибка «Неверный тип значения» и некорректная работа фильтра при попытке объединить несколько условий. В этой статье мы подробно разберем, как избежать этих ловушек и сделать работу пользователя с журналом максимально комфортной.

Разберем причину ошибки: почему важен порядок строк

Проанализируем типичную ошибку начинающего разработчика. При попытке установить СписокЗначений в качестве отбора система часто выдает ошибку контекста. Это происходит из-за того, что объект Отбор в 1С ведет себя как строгая машина состояний.

По умолчанию у любого поля отбора (например, Номер) свойство ВидСравнения установлено в значение ВидСравнения.Равно. Этот вид сравнения ожидает в поле Значение одиночную строку. Если мы первым делом пишем ЖурналДокументовСписок.Отбор.Номер.Значение = СписокНомеров;, система видит, что в поле, ожидающее строку, пытаются записать объект типа СписокЗначений, и немедленно генерирует ошибку.

Рассмотрим правильный алгоритм установки отбора:

  1. Сначала указываем вид сравнения (например, НеВСписке или ВСписке). Это переключает внутренние механизмы поля отбора на работу с коллекциями.
  2. Затем устанавливаем признак использования в Истина.
  3. И только в последнюю очередь передаем само значение (список).

Посмотрим на пример правильного кода:


// ПРАВИЛЬНАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ
ЖурналДокументовСписок.Отбор.Номер.ВидСравнения = ВидСравнения.НеВСписке;
ЖурналДокументовСписок.Отбор.Номер.Использование = Истина;
ЖурналДокументовСписок.Отбор.Номер.Значение = СписокНенужныхНомеров;

Как объединить несколько списков документов для одного отбора

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

Чтобы решить эту задачу, нам необходимо объединить все «плохие» номера в один единый СписокЗначений перед тем, как передать его в объект отбора. Рассмотрим, как это сделать эффективно.

Вариант 1: Использование метода ЗагрузитьЗначения()

Если ваши функции возвращают массивы, проще всего объединить их и загрузить в список одной командой. Это работает быстрее, чем перебор элементов в цикле.


// Объединяем два массива в один
МассивВсехНомеров = ПолучитьМассивВЗ();
МассивЗП = ПолучитьМассивЗП();

Для Каждого Номер Из МассивЗП Цикл
    МассивВсехНомеров.Добавить(Номер);
КонецЦикла;

// Создаем список значений и загружаем данные
СписокДляОтбора = Новый СписокЗначений;
СписокДляОтбора.ЗагрузитьЗначения(МассивВсехНомеров);

// Устанавливаем отбор
ЖурналДокументовСписок.Отбор.Номер.ВидСравнения = ВидСравнения.НеВСписке;
ЖурналДокументовСписок.Отбор.Номер.Значение = СписокДляОтбора;
ЖурналДокументовСписок.Отбор.Номер.Использование = Истина;

Вариант 2: Объединение через запросы (самый правильный путь)

Вместо того чтобы получать списки по отдельности, а потом мучительно соединять их в коде, лучше всего использовать возможности языка запросов 1С. Мы можем использовать оператор ОБЪЕДИНИТЬ ВСЕ, чтобы получить итоговую таблицу номеров одним обращением к базе данных.


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	РеализацияТоваровУслуг.Номер КАК Номер
|ИЗ
|	Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
|	РеализацияТоваровУслуг.СпецПризнак = &Признак
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
|	ЗаказПокупателя.Номер
|ИЗ
|	Документ.ЗаказПокупателя КАК ЗаказПокупателя
|ГДЕ
|	ЗаказПокупателя.Статус = &Статус";

Запрос.УстановитьПараметр("Признак", Истина);
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыЗаказов.Отменен);

РезультатЗапроса = Запрос.Выполнить();
СписокНомеров = Новый СписокЗначений;
СписокНомеров.ЗагрузитьЗначения(РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Номер"));

// Далее устанавливаем отбор, как в предыдущем примере

Проблема уникальности: почему отбор по номеру — не лучший выбор

Выясним одну важную деталь: номер документа в 1С не является глобально уникальным. В разных годах номера могут повторяться, также они могут дублироваться у документов разных видов, если у них не настроены префиксы. Если вы установите отбор НеВСписке по номеру "000001", система скроет все документы с таким номером, даже те, которые скрывать не планировалось.

Рекомендация: Если ваша конфигурация позволяет, лучше делать отбор по полю Ссылка. Ссылка всегда уникальна. Принцип настройки отбора при этом остается таким же, меняется только поле: ЖурналДокументовСписок.Отбор.Ссылка.

Оптимизация и производительность

Важно понимать, что отборы в обычных формах напрямую влияют на скорость работы интерфейса. Проанализируем ситуацию: если ваш список исключаемых документов содержит тысячи элементов, SQL-сервер будет вынужден выполнять тяжелый запрос с огромным условием NOT IN (...). Это может привести к "зависанию" журнала при открытии или прокрутке.

Профессиональным решением в такой ситуации будет один из следующих вариантов:

Итоги

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

← На главную