Как программно перейти на следующую колонку в табличном поле после удаления текущей в 1С?

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

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

Почему сбрасывается активная колонка и теряется фокус

Проанализируем типичные ошибки, которые приводят к потере текущей ячейки при попытке удалить колонку:

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

Пошаговый алгоритм удаления колонки с переходом на соседнюю

Разберем по шагам правильный механизм управления колонками табличного поля:

  1. Проверка наличия активной колонки: Убеждаемся, что в свойстве ТекущаяКолонка выбрана конкретная колонка.
  2. Фиксация индекса: До удаления определяем индекс текущей колонки в коллекции Колонки табличного поля.
  3. Удаление из источника данных: Находим имя поля через свойство Данные и удаляем колонку из таблицы значений.
  4. Удаление элемента отображения: Удаляем колонку непосредственно из коллекции колонок табличного поля без вызова метода СоздатьКолонки().
  5. Корректировка индекса и назначение активной колонки: Если удалялась последняя колонка в списке, уменьшаем целевой индекс на единицу, чтобы избежать ошибки выхода за границы массива, после чего назначаем новую текущую колонку.
  6. Возврат фокуса ввода: Делаем табличное поле текущим элементом формы.

Пример программного кода для обработчика кнопки

Посмотрим на пример законченной процедуры, реализующей описанную логику:


Процедура УдалитьКолонкуНажатие(Элемент)
    
    // 1. Проверяем, выбрана ли колонка
    Если ЭлементыФормы.ТабПоле.ТекущаяКолонка = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    КолонкаДляУдаления = ЭлементыФормы.ТабПоле.ТекущаяКолонка;
    
    // 2. Запоминаем текущий индекс колонки
    Индекс = ЭлементыФормы.ТабПоле.Колонки.Индекс(КолонкаДляУдаления);
    
    // 3. Получаем имя реквизита в таблице значений и удаляем его из источника
    ИмяДанных = КолонкаДляУдаления.Данные;
    Если ЗначениеЗаполнено(ИмяДанных) И ТЗ.Колонки.Найти(ИмяДанных) <> Неопределено Тогда
        ТЗ.Колонки.Удалить(ИмяДанных);
    КонецЕсли;
    
    // 4. Удаляем колонку из интерфейсного элемента
    ЭлементыФормы.ТабПоле.Колонки.Удалить(КолонкаДляУдаления);
    
    // 5. Проверяем, остались ли колонки в табличном поле
    КоличествоКолонок = ЭлементыФормы.ТабПоле.Колонки.Количество();
    Если КоличествоКолонок > 0 Тогда
        // Если удалили крайнюю правую колонку, смещаем индекс на новую последнюю
        Если Индекс >= КоличествоКолонок Тогда
            Индекс = КоличествоКолонок - 1;
        КонецЕсли;
        
        // Позиционируемся на соседнюю колонку
        ЭлементыФормы.ТабПоле.ТекущаяКолонка = ЭлементыФормы.ТабПоле.Колонки[Индекс];
    КонецЕсли;
    
    // 6. Возвращаем фокус в табличное поле
    ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.ТабПоле;
    
КонецПроцедуры

Особенности работы со строками таблицы

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

Посмотрим на пример удаления текущей строки:


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

Альтернативный вариант: скрытие колонок вместо удаления

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

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


Процедура СкрытьКолонкуНажатие(Элемент)
    
    Если ЭлементыФормы.ТабПоле.ТекущаяКолонка = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ТекущаяКол = ЭлементыФормы.ТабПоле.ТекущаяКолонка;
    Индекс = ЭлементыФормы.ТабПоле.Колонки.Индекс(ТекущаяКол);
    
    // Скрываем колонку
    ТекущаяКол.Видимость = Ложь;
    
    // Ищем следующую видимую колонку
    НайденаКолонка = Ложь;
    Для К = Индекс По ЭлементыФормы.ТабПоле.Колонки.Количество() - 1 Цикл
        Если ЭлементыФормы.ТабПоле.Колонки[К].Видимость Тогда
            ЭлементыФормы.ТабПоле.ТекущаяКолонка = ЭлементыФормы.ТабПоле.Колонки[К];
            НайденаКолонка = Истина;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    // Если справа видимых колонок не нашлось, ищем слева
    Если Не НайденаКолонка Тогда
        Для К = Индекс - 1 По 0 Цикл
            Если ЭлементыФормы.ТабПоле.Колонки[К].Видимость Тогда
                ЭлементыФормы.ТабПоле.ТекущаяКолонка = ЭлементыФормы.ТабПоле.Колонки[К];
                Прервать;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
    ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.ТабПоле;
    
КонецПроцедуры

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

← На главную