В процессе сопровождения систем на платформе 1С:Предприятие 8 (особенно на базе обычных форм) часто возникает задача ограничить выбор элементов справочника для пользователей. Типичный пример: номенклатура или контрагент больше не используются, удалять их из базы нельзя, так как они фигурируют в исторических документах, но при этом необходимо сделать так, чтобы менеджеры не могли выбрать их при ручном вводе в новых документах.
В управляемом приложении эта задача легко решается через модуль менеджера и обработчик ОбработкаПолученияДанныхВыбора. Однако в обычных формах (толстый клиент) этот механизм при вводе по строке не работает. В этой статье мы подробно разберем, как решить эту проблему в обычных формах, проанализируем все достоинства и недостатки предложенных на форуме вариантов и реализуем оптимальные программные решения.
Прежде чем перейти к реализации рабочих алгоритмов, проанализируем стандартные подходы, которые часто первыми приходят на ум разработчикам, и выясним, почему они могут не подойти.
Архивный = Истина). Однако у этого способа есть критический недостаток. В 1С нет отдельного права на «Автоподбор» или «Выбор». Запрещая чтение элемента, мы делаем его полностью невидимым для пользователя. Как результат — во всех старых проведенных документах вместо названия товара пользователи увидят надпись <Объект не найден>, а отчеты за прошлые периоды перестанут собираться корректно.ОбработкаПолученияДанныхВыбора: Данное событие действительно присутствует в модуле менеджера справочника начиная с платформы 8.2.14. Однако оно ориентировано на управляемый режим. Если ваше решение работает в толстом клиенте на обычных формах, платформа проигнорирует этот обработчик при интерактивном вводе текста в поле ввода, используя старые внутренние механизмы автоподбора.Теперь рассмотрим рабочие и безопасные альтернативы, которые позволят решить задачу без разрушения исторических данных.
Это самый гибкий и профессиональный программный способ. Он идеально подходит, если вам нужно ограничить выбор только в нескольких ключевых документах (например, в «Заказе покупателя» и «Реализации товаров и услуг»), оставив при этом старые документы работоспособными.
Суть метода заключается в ручном перехвате процесса ввода текста пользователем. Мы самостоятельно выполняем запрос к базе данных, отсекаем ненужные элементы и предлагаем пользователю отфильтрованный список.
Разберем по шагам реализацию этого механизма для поля ввода Номенклатура в табличной части документа.
Шаг 1. Создаем обработчик события АвтоПодборТекста для элемента управления (поля ввода):
Процедура ТоварыНоменклатураАвтоПодборТекста(Элемент, Текст, ТекстАвтоПодбора, СтандартнаяОбработка)
// Отключаем стандартный поиск платформы
СтандартнаяОбработка = Ложь;
// Нам нужно найти первый подходящий элемент, который не является архивным
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Наименование ПОДОБНО &СтрокаПоиска
| И НЕ Номенклатура.Архивный // Исключаем архивные элементы
| И НЕ Номенклатура.ПометкаУдаления";
Запрос.УстановитьПараметр("СтрокаПоиска", Текст + "%");
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
// Подставляем найденное значение в качестве подсказки
ТекстАвтоПодбора = Сред(Выборка.Наименование, СтрДлина(Текст) + 1);
КонецЕсли;
КонецПроцедуры
Шаг 2. Создаем обработчик события ОкончаниеВводаТекста. Этот обработчик срабатывает, когда пользователь завершает ввод (нажимает Enter или переходит в другое поле). Здесь мы должны вернуть конкретное найденное значение или список значений для выбора:
Процедура ТоварыНоменклатураОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Ищем все подходящие неархивные элементы
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Наименование ПОДОБНО &СтрокаПоиска
| И НЕ Номенклатура.Архивный
| И НЕ Номенклатура.ПометкаУдаления";
Запрос.УстановитьПараметр("СтрокаПоиска", Текст + "%");
СписокВыбора = Новый СписокЗначений;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СписокВыбора.Добавить(Выборка.Ссылка, Выборка.Наименование);
КонецЦикла;
Если СписокВыбора.Количество() = 0 Тогда
// Ничего не найдено
Значение = Неопределено;
ИначеЕсли СписокВыбора.Количество() = 1 Тогда
// Найдено точное совпадение
Значение = СписокВыбора[0].Значение;
Иначе
// Найдено несколько элементов, предлагаем пользователю выбрать из списка
Значение = СписокВыбора;
КонецЕсли;
КонецПроцедуры
Этот подход гарантирует, что при интерактивном наборе текста в новых строках архивные товары никогда не появятся в подсказках и результатах поиска, но в старых документах ссылки на них будут отображаться корректно.
Если логика автоподбора кажется вам избыточной или требует слишком много кода для поддержки, можно пойти по пути упрощения интерфейса. Мы можем запретить пользователю вводить наименование номенклатуры вручную с клавиатуры, заставив его всегда выбирать элементы через специализированную форму выбора.
Проанализируем шаги реализации этого сценария:
РедактированиеТекста в значение Ложь. Теперь пользователь физически не может начать набирать буквы в ячейке.НачалоВыбора для этого поля ввода, где программно открываем форму выбора с жестко заданным отбором:
Процедура ТоварыНоменклатураНачалоВыбора(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Получаем форму выбора справочника номенклатуры
ФормаВыбора = Справочники.Номенклатура.ПолучитьФормуВыбора("ФормаВыбора", Элемент, "ВыборНоменклатуры");
// Устанавливаем жесткий отбор по неактуальным позициям
ФормаВыбора.Отбор.Архивный.Использование = Истина;
ФормаВыбора.Отбор.Архивный.Значение = Ложь;
// Если нужно запретить пользователю отключать этот отбор интерактивно в форме выбора:
ФормаВыбора.ЭлементыФормы.СправочникСписок.НастройкаОтбора.Архивный.Доступность = Ложь;
ФормаВыбора.Открыть();
КонецПроцедуры
Этот метод исключает любые ошибки ручного ввода и гарантирует, что пользователь выберет только разрешенный элемент из структуры справочника.
Рассмотрим ситуацию, когда конфигурация находится на жесткой поддержке поставщика, вносить изменения в код форм документов крайне нежелательно или запрещено, а избавиться от старых позиций в поиске нужно немедленно.
В этом случае можно использовать особенность стандартного механизма автоподбора 1С. По умолчанию платформа ищет элементы по началу наименования (слева направо). Если мы переименуем неиспользуемые позиции, добавив в начало специальный префикс, они автоматически пропадут из стандартного поиска.
Выполним следующие шаги:
_Архив_, _Не использовать_ или символы zzz_). Было: «Стол офисный», стало: «zzz_Стол офисный».Преимущества лайфхака: Абсолютная безопасность для исторических документов. Ссылки в базе данных сохраняются, проводки не нарушаются. В старых документах просто изменится представление номенклатуры (появится префикс), что часто является даже плюсом, так как визуально информирует бухгалтера о том, что документ содержит архивную позицию.
Выбор конкретного решения зависит от архитектуры вашей базы данных и требований к удобству работы пользователей: