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

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

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

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

Ограничения платформы и особенности событий таблицы формы

Проанализируем базовую проблему: у элемента формы Таблица отсутствуют специализированные события вроде ПередПеремещениемСтроки или ПослеПеремещенияСтроки. При вызове стандартных команд перемещения платформа сама меняет порядок элементов в коллекции и пересчитывает свойство НомерСтроки.

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

Способ 1. Использование связки событий ПриАктивизацииСтроки и ПриИзменении

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

  1. В контексте формы (в реквизите формы или переменной модуля) запоминаем номер строки в момент ее активизации:

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

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

Способ 2. Замена стандартных кнопок перемещения на собственные команды

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

Разберем реализацию по шагам:

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

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

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

Способ 3. Использование идентификаторов строк и метода Элементы.Переместить

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


&НаКлиенте
Процедура ПереместитьКолонкуФормы(ИмяКолонки, ИмяКолонкиПередКоторойВставить)
    КолонкаДляПеремещения = Элементы[ИмяКолонки];
    КолонкаОриентир = Элементы[ИмяКолонкиПередКоторойВставить];
    
    Элементы.Переместить(КолонкаДляПеремещения, Элементы.ТЧ2, КолонкаОриентир);
КонецПроцедуры

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

← На главную