Как перехватить ввод данных в ячейку списка 1С v7.7 для выбора значения из пользовательского списка?

Программист 1С v7.7
← На главную

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

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

Метод 1: Использование невидимого текстового реквизита и функции-формулы

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

  1. Размещение невидимого текстового реквизита на форме:

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

  2. Привязка функции к невидимому реквизиту:

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

  3. Реализация функции в модуле формы:

    Откройте модуль формы списка справочника и добавьте в него следующую функцию:

    
    Функция ВыделениеКолонки()
        // Проверяем, в какой колонке находится курсор
        Если Форма.ТекущаяКолонка() = "Наименование" Тогда
            // Создаем объект СписокЗначений для формирования списка выбора
            спис = СоздатьОбъект("СписокЗначений");
            спис.ДобавитьЗначение("Значение1", "Описание для Значения1"); // Значение, Описание
            спис.ДобавитьЗначение("Значение2", "Описание для Значения2");
            спис.ДобавитьЗначение("Значение3", "Описание для Значения3");
            
            // Устанавливаем текущую строку для удобства пользователя
            спис.ТекущаяСтрока(1);
            
            Зн = ""; // Переменная для хранения выбранного значения
            
            // Вызываем диалог выбора значения из списка
            // Параметры: Зн (переменная для результата), Заголовок, Подсказка, Ширина, Высота, ТипВыбора (1 - выбор значения)
            Если спис.ВыбратьЗначение(Зн, "Выберите новое наименование", , , , 1) = 1 Тогда
                // Если пользователь что-то выбрал, обновляем реквизит текущего элемента
                Спр = СоздатьОбъект("Справочник.Номенклатура"); // Замените на имя вашего справочника
                Спр.НайтиЭлемент(ТекущийЭлемент()); // Находим текущий элемент по его идентификатору
                
                НовоеНаименование = "";
                // Получаем выбранное значение по его индексу (Зн)
                спис.ПолучитьЗначение(Зн, НовоеНаименование);
                
                // Устанавливаем новое наименование и записываем элемент
                Спр.Наименование = НовоеНаименование;
                Спр.Записать();
            КонецЕсли;
        КонецЕсли;
        Возврат ""; // Функция должна что-то возвращать
    КонецФункции
    

    Разберем основные моменты этой функции:

    • Форма.ТекущаяКолонка(): Этот метод позволяет нам определить имя колонки, в которой в данный момент находится курсор пользователя. Мы используем его для того, чтобы наша логика выбора срабатывала только при входе в нужный нам реквизит (в данном случае, "Наименование").
    • СоздатьОбъект("СписокЗначений"): Мы создаем объект "СписокЗначений". Этот агрегатный тип данных в 1С v7.7 идеально подходит для формирования динамических списков выбора. Он позволяет хранить значения различных типов и управлять ими.
    • спис.ДобавитьЗначение(): Добавляем в список нужные нам значения. В первом параметре идет само значение, во втором — его текстовое представление, которое увидит пользователь.
    • спис.ВыбратьЗначение(Зн, ..., 1): Этот ключевой метод объекта "СписокЗначений" открывает модальное диалоговое окно или выпадающий список (в зависимости от параметров), позволяя пользователю выбрать значение. Параметр 1 в конце означает, что мы хотим получить именно выбранное значение. Если пользователь ничего не выбрал или отменил, метод вернет 0.
    • СоздатьОбъект("Справочник.Номенклатура"): После выбора значения нам необходимо найти текущий элемент справочника, чтобы изменить его реквизит. Для этого мы создаем объект справочника.
    • Спр.НайтиЭлемент(ТекущийЭлемент()): Метод ТекущийЭлемент() возвращает идентификатор текущего элемента в списке. С помощью НайтиЭлемент() мы позиционируемся на нем.
    • спис.ПолучитьЗначение(Зн, НовоеНаименование): После того как пользователь выбрал значение, переменная Зн будет содержать его индекс в списке. Мы используем ПолучитьЗначение(), чтобы получить само значение по этому индексу.
    • Спр.Наименование = НовоеНаименование; Спр.Записать();: Устанавливаем новое значение реквизита и сохраняем изменения.

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

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

Метод 2: Использование свойства "Имеет кнопку выбора" и процедуры ПриНачалеВыбораЗначения()

Этот метод является более стандартным, но имеет ряд ограничений, особенно для системных реквизитов, таких как "Наименование".

  1. Настройка свойств реквизита:

    Откройте свойства нужного реквизита в конфигураторе (например, "Наименование"). Установите флажок "Запретить редактирование" (чтобы пользователь не мог вводить текст напрямую) и флажок "Имеет кнопку выбора". Флажок "Сделать недоступным" при этом не устанавливайте.

  2. Реализация процедуры ПриНачалеВыбораЗначения():

    В модуле формы списка справочника пропишите следующую процедуру:

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

    В этой процедуре мы также используем СписокЗначений и ВыбратьЗначение() для предоставления выбора.

Ограничения и особенности этого метода:

Метод 3: Использование предопределенных процедур формы списка

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

  1. ПриНачалеРедактированияСтроки():

    Эта процедура вызывается при начале интерактивного редактирования *существующей* строки в форме списка. В ней можно регулировать доступность реквизитов или выполнять другие действия.

    
    Процедура ПриНачалеРедактированияСтроки()
        Если Форма.ТекущаяКолонка() = "Наименование" Тогда
            // Здесь можно вызвать список выбора
            // Но проблема в том, что текстовое редактирование уже началось
            // и пользователь может начать вводить текст до вызова списка.
            // Поэтому этот метод менее подходит для полного перехвата ввода.
            спис = СоздатьОбъект("СписокЗначений");
            спис.ДобавитьЗначение("Новое Значение A");
            спис.ДобавитьЗначение("Новое Значение B");
            
            Выбор = "";
            Если спис.ВыбратьЗначение(Выбор, "Выберите значение") = 1 Тогда
                // Если выбрали, можно установить значение
                ТекущийЭлемент.Наименование = Выбор;
            КонецЕсли;
        КонецЕсли;
    КонецПроцедуры
    

    Ограничения: Проблема этого метода в том, что он срабатывает *после* того, как поле ввода уже активизировалось, и пользователь теоретически уже может начать вводить текст. Он не обеспечивает полного перехвата именно *входа* в режим редактирования с немедленным вызовом списка. Также есть сложности с его поведением при вводе новых элементов и при перемещении по колонкам, если реквизит не первый.

  2. ПриРедактированииНовойСтроки():

    Эта процедура вызывается в модуле формы списка справочника при начале интерактивного редактирования *новой* строки. Она полезна для заполнения начальных значений реквизитов нового элемента, но также имеет те же ограничения по перехвату ввода, что и ПриНачалеРедактированияСтроки().

  3. ПриНачалеРедактированияЗначения(ИД, ФСО):

    В некоторых случаях эта процедура может быть более гибкой, чем ПриНачалеРедактированияСтроки(), так как она передает идентификатор элемента формы (ИД), который начал редактироваться, и флаг открытия стандартной формы редактирования (ФСО), который можно сбросить. Однако, по своей сути, она также срабатывает, когда редактирование уже началось.

    
    Процедура ПриНачалеРедактированияЗначения(ИД, ФСО)
        Если ИД = "Наименование" Тогда
            // Здесь также можно вызвать список, но редактирование уже активировано.
            // Важно: установить ФСО = 0, чтобы отменить стандартное действие редактирования
            ФСО = 0; 
            спис = СоздатьОбъект("СписокЗначений");
            спис.ДобавитьЗначение("Опция 1");
            спис.ДобавитьЗначение("Опция 2");
            
            Выбор = "";
            Если спис.ВыбратьЗначение(Выбор, "Выберите значение") = 1 Тогда
                // Устанавливаем выбранное значение
                Форма.УстановитьЗначение(ИД, Выбор);
            КонецЕсли;
        КонецЕсли;
    КонецПроцедуры
    
  4. ПриВыбореСтроки():

    Эта процедура срабатывает при выборе строки списка (двойной щелчок мыши или клавиша Enter). Режим ее обработки включается методом Форма.ОбработкаВыбораСтроки(1). В ней можно определить, по какой колонке произошел щелчок, используя Форма.ТекущаяКолонка(). Однако это не перехватывает *вход* в редактирование, а скорее *выбор* строки, после чего обычно открывается форма элемента.

Общие рекомендации и продвинутые решения

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

← На главную