Как убрать помеченные на удаление или отфильтрованные элементы из истории выбора поля в 1С Управляемых Формах?

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

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

Прежде всего, проанализируем природу данной особенности платформы 1С. История выбора в полях ввода управляемых форм — это механизм, разработанный для повышения удобства пользователя. Он автоматически запоминает последние и часто выбираемые значения, предоставляя быстрый доступ к ним без необходимости каждый раз открывать полную форму выбора. Однако, критически важно понимать, что механизм истории выбора работает независимо от текущих отборов, установленных для поля ввода или динамического списка, из которого производится выбор. Это означает, что если вы настроили параметр отбора, чтобы отбирались только «действующие» сотрудники (не помеченные на удаление), то основной список выбора будет корректно показывать только их. Но история выбора, которая хранится отдельно, продолжит отображать и тех сотрудников, которые были выбраны ранее, но теперь помечены на удаление или не соответствуют новому отбору.

Когда вы вводите первые буквы значения, система выполняет поиск по текущему динамическому списку с учетом всех отборов. Если искомого элемента там нет (потому что он помечен на удаление или не соответствует отбору), вы получаете сообщение «ин нет в списке». При этом список истории выбора, отображаемый под полем, формируется из сохраненных ранее значений, а не из текущего отфильтрованного списка, поэтому он может содержать «неактуальные» элементы.

Платформа 1С сохраняет историю выбора в системном хранилище настроек пользователя (объект ХранилищеСистемныхНастроек) под ключом «ИсторияВыбора». Эти настройки являются индивидуальными для каждого пользователя. Рассмотрим подробнее возможные пути решения этой «странной» особенности.

Решение 1: Отключение истории данных для поля ввода

Один из наиболее прямолинейных и часто используемых способов избежать появления «неактуальных» элементов в истории выбора — это полное отключение механизма истории для конкретного поля ввода. Этот подход особенно оправдан, когда использование истории противоречит прикладной логике, или когда данные, выбираемые в поле, часто меняют свой статус (например, помечаются на удаление, теряют актуальность).

  1. Настройка свойства в конфигураторе:

    Для поля ввода на управляемой форме вы можете установить свойство ИсторияВыбораПриВводе в значение «Не использовать». Это можно сделать в палитре свойств элемента формы. После такого изменения платформа перестанет записывать и отображать историю выбора для этого конкретного поля.

    Когда это решение особенно полезно:

    • Если в модуле менеджера объекта переопределен обработчик ОбработкаПолученияДанныхВыбора, так как история выбора не учитывает условия, заданные в этом обработчике.
    • Если выбранные значения имеют ограниченный срок актуальности, и сохранение их в истории может ввести пользователя в заблуждение.
  2. Полное скрытие выпадающей истории (дополнительная мера):

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

    • Установите свойство КнопкаВыпадающегоСписка в «Нет».
    • Установите свойство КнопкаВыбора в «Да» с ОтображениеКнопкиВыбора в «В поле ввода».

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

Несмотря на свою эффективность, у этого подхода есть один недостаток: пользователи могут жаловаться на отключение истории, так как они привыкли к удобству быстрого выбора ранее используемых значений, особенно для "долгоиграющих" фильтров, например, для подразделений, которые не часто меняются.

Решение 2: Программная очистка истории выбора пользователя

Если полное отключение истории нежелательно, но необходимо избавиться от "запомненных" неактуальных значений, можно прибегнуть к программной очистке истории выбора. Этот метод позволяет удалить сохраненные данные из хранилища системных настроек.

  1. Очистка истории для всех пользователей:

    Для полной очистки истории выбора для всех пользователей, например, после большого обновления или изменения бизнес-логики, можно использовать следующий программный код. Этот код проходит по всем пользователям системы и удаляет их индивидуальные настройки истории выбора.

    
    &НаСервере
    Процедура УдалитьИсториюВыбораДляВсехПользователей()
        ВыборкаПользователей = Справочники.Пользователи.Выбрать();
        Пока ВыборкаПользователей.Следующий() Цикл
            // Удаляем историю выбора для каждого пользователя
            ХранилищеСистемныхНастроек.Удалить("ИсторияВыбора", , ВыборкаПользователей.Наименование);
            Сообщить("История выбора очищена для пользователя: " + ВыборкаПользователей.Наименование);
        КонецЦикла;
        Сообщить("Очистка истории выбора завершена.");
    КонецПроцедуры
    

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

  2. Очистка истории для конкретного пользователя:

    Если проблема возникает только у одного или нескольких пользователей, вы можете очистить историю выборочно. Для этого нужно получить имя пользователя и передать его третьим параметром в метод Удалить.

    
    &НаСервере
    Процедура УдалитьИсториюВыбораДляКонкретногоПользователя(ИмяПользователя)
        // ИмяПользователя - это строка, например, "Администратор" или "Иванов Иван"
        ХранилищеСистемныхНастроек.Удалить("ИсторияВыбора", , ИмяПользователя);
        Сообщить("История выбора очищена для пользователя: " + ИмяПользователя);
    КонецПроцедуры
    

    Этот подход более точечный и менее инвазивный. Для получения текущего пользователя можно использовать Пользователи.ТекущийПользователь().Наименование (если это справочник Пользователи) или ИмяПользователя() (глобальный контекст).

  3. Использование внешних обработок:

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

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

Решение 3: Проверка значения после выбора

Третий подход заключается в том, чтобы позволить пользователю выбирать любое значение (даже из истории), но проверять его актуальность сразу после выбора. Если выбранное значение не удовлетворяет условиям (например, помечено на удаление), мы программно очищаем поле или предупреждаем пользователя.

  1. Реализация обработчика события ПриИзменении:

    Для поля выбора на форме добавьте обработчик события ПриИзменении. В этом обработчике мы будем анализировать выбранный объект.

    
    &НаКлиенте
    Процедура ПолеВыбораСотрудникаПриИзменении(Элемент)
        ЗначениеПоля = Элементы.ПолеВыбораСотрудника.Значение;
    
        // Если значение не заполнено, ничего не делаем
        Если ЗначениеПоля = Неопределено ИЛИ ЗначениеПоля = Справочники.Сотрудники.ПустаяСсылка() Тогда
            Возврат;
        КонецЕсли;
    
        // Получаем объект, чтобы проверить его свойства
        // Это клиентский код, поэтому используем вызов на сервер
        Если ЗначениеПоля.Метаданные().ТипЗначения.СодержитТип(Тип("СправочникСсылка.Сотрудники")) Тогда
            ОбъектСотрудник = ПолучитьСотрудникаНаСервере(ЗначениеПоля);
            Если ОбъектСотрудник <> Неопределено Тогда
                Если ОбъектСотрудник.ПометкаУдаления Тогда
                    ПоказатьПредупреждение(, "Выбранный сотрудник помечен на удаление. Пожалуйста, выберите другого сотрудника.", , ОбщегоНазначенияКлиентСервер.СтандартнаяКартинкаПредупреждение);
                    Элементы.ПолеВыбораСотрудника.Значение = Справочники.Сотрудники.ПустаяСсылка();
                // Здесь можно добавить другие проверки, например, на актуальность даты
                // Если НЕ ОбъектСотрудник.ДействующийНаДату(ТекущаяДата()) Тогда
                //    ПоказатьПредупреждение(, "Выбранный сотрудник не является действующим.", , ОбщегоНазначенияКлиентСервер.СтандартнаяКартинкаПредупреждение);
                //    Элементы.ПолеВыбораСотрудника.Значение = Справочники.Сотрудники.ПустаяСсылка();
                // КонецЕсли;
                КонецЕсли;
            КонецЕсли;
        КонецЕсли;
    КонецПроцедуры
    
    &НаСервере
    Функция ПолучитьСотрудникаНаСервере(СсылкаСотрудника)
        Если СсылкаСотрудника.Пустая() Тогда
            Возврат Неопределено;
        КонецЕсли;
        Попытка
            Возврат СсылкаСотрудника.ПолучитьОбъект();
        Исключение
            // Объект мог быть физически удален, или прав нет
            Возврат Неопределено;
        КонецПопытки;
    КонецФункции
    

    В этом примере мы проверяем свойство ПометкаУдаления. Если объект помечен на удаление, мы выводим предупреждение и очищаем поле ввода, устанавливая в него пустую ссылку. Этот подход позволяет сохранить удобство истории выбора, при этом гарантируя, что в поле всегда будет актуальное и корректное значение.

  2. Дополнительные проверки:

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

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

Взаимосвязь с отборами и контекстом выбора

Важно еще раз подчеркнуть, что настроенные отборы на динамических списках (например, через параметры отбора для поля формы или через модуль менеджера объекта) контролируют только то, какие элементы отображаются в основном списке выбора, который открывается по кнопке выбора или при наборе текста, если элемента нет в истории. Эти отборы не влияют на содержимое списка истории выбора, который формируется и хранится отдельно.

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

Каждый из предложенных методов имеет свои преимущества и недостатки. Выбор конкретного решения должен основываться на балансе между удобством пользователя, требованиями к актуальности данных и объемом необходимой разработки.

← На главную