Как программно изменить значение в выбранной ячейке таблицы формы и продолжить её редактирование в 1С?

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

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

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

Причина 1: Изменение локальной переменной вместо реквизита строки

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


ТекСтрока = Элементы.ЭлементыДерева.ТекущиеДанные;
ТекСтолбец = Элементы.ЭлементыДерева.ТекущийЭлемент;

ИмяЯчейки = ТекСтолбец.Имя;
// Попытка вырезать имя реквизита из имени элемента
ИмяЯчейки = СокрЛП(СтрЗаменить(ИмяЯчейки, "ЭлементыДерева", ""));

ТекЗначение = ТекСтрока[ИмяЯчейки];

Если ПустаяСтрока(ТекЗначение) Тогда
    ТекЗначение = пТекСтрока;              
Иначе
    ТекЗначение = СокрЛП(ТекЗначение) + " " + пТекСтрока;            
КонецЕсли;

Выясним причину, по которой код отрабатывает без ошибок, но данные в интерфейсе остаются прежними. При чтении ТекЗначение = ТекСтрока[ИмяЯчейки]; значение примитивного типа (в данном случае строка) копируется в локальную переменную ТекЗначение. Последующая конкатенация изменяет лишь эту переменную в памяти. В саму коллекцию данных строки таблицы новое значение так и не было записано.

Для исправления достаточно после формирования итогового текста явно присвоить результат обратно в реквизит строки текущих данных:

ТекСтрока[ИмяЯчейки] = ТекЗначение;

Шаг 1: Надежное определение имени реквизита колонки

Обратите внимание на способ определения имени реквизита: конструкция СтрЗаменить(ИмяЯчейки, "ЭлементыДерева", "") крайне ненадежна. Имя элемента формы может быть названо произвольно и не обязано повторять имя реквизита данных строки.

Рассмотрим более надежный подход: использовать свойство элемента формы ПутьКДанным. Для колонок таблицы оно содержит путь формата "ИмяТаблицы.ИмяРеквизита". Получим имя поля через разделение строки:


&НаКлиенте
Процедура ВставитьТекстВЯчейку()

    ТекСтрока = Элементы.ЭлементыДерева.ТекущиеДанные;
    ТекСтолбец = Элементы.ЭлементыДерева.ТекущийЭлемент;

    Если ТекСтрока = Неопределено Или ТекСтолбец = Неопределено Тогда
        ПоказатьОповещениеПользователя("Внимание", , "Не выбрана строка или ячейка таблицы!");
        Возврат;
    КонецЕсли;

    // Проверяем, что элемент действительно привязан к данным строки
    МассивПути = СтрРазделить(ТекСтолбец.ПутьКДанным, ".");
    Если МассивПути.Количество() < 2 Тогда
        Возврат;
    КонецЕсли;
    
    ИмяКолонки = МассивПути[1];
    
    пТекСтрока = "НеобходимоВставить";
    ТекЗначение = ТекСтрока[ИмяКолонки];
    
    Если ПустаяСтрока(ТекЗначение) Тогда
        ТекЗначение = пТекСтрока;
    Иначе
        ТекЗначение = СокрЛП(ТекЗначение) + " " + пТекСтрока;
    КонецЕсли;
    
    // Записываем обновленные данные в строку таблицы
    ТекСтрока[ИмяКолонки] = ТекЗначение;
    
    // Взводим флаг модифицированности формы при необходимости
    Модифицированность = Истина;

КонецПроцедуры

Шаг 2: Возврат в режим редактирования ячейки

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

Посмотрим на пример его вызова:


// Принудительно переводим текущую строку в режим редактирования
Элементы.ЭлементыДерева.ИзменитьСтроку();

Метод ИзменитьСтроку() платформы 1С аналогичен нажатию клавиши F2 или кнопке «Изменить» на стандартной командной панели: строка снова открывается для ввода данных.

Особенность метода ИзменитьСтроку() и управление курсором

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

  1. Для снятия выделения и перевода каретки в конец текста у элемента формы ПолеВвода используется метод УстановитьГраницыВыделения(Начало, Конец).
  2. Передавая одинаковое число (равное длине итоговой строки) в оба параметра, мы устанавливаем курсор без выделения текста:
    
    ДлинаТекста = СтрДлина(ТекСтрока[ИмяКолонки]);
    ТекСтолбец.УстановитьГраницыВыделения(ДлинаТекста, ДлинаТекста);
    
  3. Важное ограничение платформы: метод установки границ выделения работает только тогда, когда элемент ввода уже активен. Если выполнить его в той же процедуре сразу после ИзменитьСтроку(), платформа может сбросить фокус в стандартное состояние. Наиболее стабильный результат дает перенос снятия выделения в событие таблицы ПриНачалеРедактированияСтроки либо вызов через обработчик ожидания с задержкой 0 секунд.

Альтернативное решение: использование кнопок внутри самого поля ячейки

Чтобы исключить потерю фокуса и завершение редактирования строки при клике на форму, функционал подстановки текста можно вынести непосредственно в саму ячейку:

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

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

← На главную