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

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

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

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

Выясняем причину: почему платформа сбрасывает редактирование?

В управляемом интерфейсе «1С:Предприятия 8» за отображение элементов отвечает декларативная модель. Когда мы изменяем визуальные свойства элементов формы на клиенте (такие как Заголовок, Видимость, Доступность или положение колонки), платформа инициирует принудительную перерисовку (re-render) всего родительского элемента управления. В нашем случае этим элементом является таблица формы.

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

Анализ обходного пути («костыля») с обработчиком ожидания

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

Рассмотрим, как выглядит этот код:


&НаКлиенте
Процедура ТабличнаяЧасть1Реквизит1ПриИзменении(Элемент)
    
    // Меняем заголовок колонки, что приводит к сбросу редактирования
    Элементы.ТабличнаяЧасть1Реквизит2.Заголовок = "Новый заголовок";
    
    // Подключаем однократный обработчик ожидания с минимальной задержкой
    ПодключитьОбработчикОжидания("СменитьЗаголовокИВернутьРедактирование", 0.1, Истина);
    
КонецПроцедуры

&НаКлиенте
Процедура СменитьЗаголовокИВернутьРедактирование()
    
    // Программно возвращаем пользователя в режим редактирования строки
    Элементы.ТабличнаяЧасть1.ИзменитьСтроку();
    
КонецПроцедуры

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

Минусы использования метода ИзменитьСтроку():

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

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

Правильное решение 1: Использование панели детального редактирования

Этот подход является стандартом проектирования интерфейсов в типовых конфигурациях фирмы «1С» (например, в «1С:Бухгалтерии» при редактировании аналитики счетов). Вместо того чтобы пытаться уместить сложную динамическую логику в ячейках таблицы, мы разделяем представление данных и их ввод.

Как это реализовать по шагам:

  1. Колонки в самой табличной части называются нейтрально (например, «Субконто 1», «Субконто 2») и делаются недоступными для прямого редактирования в таблице (или оставляются как есть, но без динамической смены заголовков).
  2. Под табличной частью (или справа от нее) создается группа элементов «Панель подробностей» (обычная группа управляемой формы).
  3. В эту группу перетаскиваются реквизиты текущей строки табличной части в виде обычных полей ввода формы. Чтобы связать их с текущей строкой, в пути к данным указывается Элементы.ТабличнаяЧасть1.ТекущиеДанные.Субконто1.
  4. В обработчике события таблицы ПриАктивизацииСтроки (а также при изменении счета) мы программно меняем свойства Заголовок у полей ввода на этой панели.

Посмотрим на пример кода управления заголовками на панели подробностей:


&НаКлиенте
Процедура ТабличнаяЧасть1ПриАктивизацииСтроки(Элемент)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем реальные имена субконто для текущего счета (например, через кэшированный серверный вызов)
    СтруктураИменСубконто = ПолучитьИменаСубконто(ТекущиеДанные.СчетУчета);
    
    // Меняем заголовки полей ввода на панели под таблицей
    Элементы.ПолеВводаСубконто1.Заголовок = СтруктураИменСубконто.Субконто1;
    Элементы.ПолеВводаСубконто2.Заголовок = СтруктураИменСубконто.Субконто2;
    
КонецПроцедуры

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

Правильное решение 2: Динамическая текстовая подсказка

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

Рассмотрим два варианта реализации:

  1. Декорация над таблицей: Разместите над табличной частью или под ней текстовую декорацию (надпись) с именем, например, ДекорацияИнформацияСубконто. В событии ПриАктивизацииСтроки или ПриИзменении счета обновляйте текст этой декорации: Элементы.ДекорацияИнформацияСубконто.Заголовок = "Редактируется субконто: " + ИмяСубконто;. Это не вызывает перерисовку таблицы.
  2. Динамическая подсказка для поля ячейки: Вы можете программно изменять свойства Подсказка или СверхбыстраяПодсказка для элемента поля ввода в колонке таблицы. При наведении курсора или при активизации ячейки пользователь будет видеть всплывающую подсказку с актуальным названием аналитики, при этом режим редактирования сбиваться не будет.

Правильное решение 3: Изменение заголовков в контексте всей формы

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

Рекомендуемый сценарий:

  1. Вынесите реквизит «Счет учета» из табличной части в шапку документа.
  2. При изменении счета в шапке документа выполняйте переименование колонок табличной части. Поскольку в этот момент пользователь не редактирует строки таблицы, перерисовка пройдет абсолютно бесшовно и незаметно для него.
  3. Дополнительно обновляйте заголовки колонок при открытии формы в событии ПриСозданииНаСервере на основе уже сохраненного в документе счета.

Пример изменения заголовков при изменении реквизита шапки:


&НаКлиенте
Процедура ШапкаСчетУчетаПриИзменении(Элемент)
    
    // Вызываем серверный метод для определения видов субконто
    СтруктураСубконто = ПолучитьВидыСубконтоНаСервере(Объект.СчетУчета);
    
    // Меняем заголовки колонок. Строки не редактируются, сброса фокуса нет
    Элементы.ТабличнаяЧасть1Субконто1.Заголовок = СтруктураСубконто.Субконто1;
    Элементы.ТабличнаяЧасть1Субконто2.Заголовок = СтруктураСубконто.Субконто2;
    
КонецПроцедуры

Правильное решение 4: Использование предопределенных колонок

Если вариантов заголовков колонок относительно немного (например, у вас всего 3-4 возможных типа субконто), отличным решением будет создание отдельных колонок в конфигураторе под каждый тип аналитики с уже заданными статическими заголовками.

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

Резюме

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

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

← На главную