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

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

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

Проблема 1: Как надежно определить активную таблицу?

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

Рассмотрим более надежный способ. Вместо того чтобы пытаться «поймать» момент перехода в обработчиках событий, мы проанализируем состояние формы непосредственно в момент выполнения команды (нажатия кнопки переноса). Для этого используем свойство ЭтаФорма.ТекущийЭлемент.

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


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

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

Проблема 2: Ошибка «Недопустимое значение параметра» при удалении строк

Многие начинающие разработчики путают Индекс строки и Идентификатор строки. Это приводит к ошибке Недопустимое значение параметра (параметр номер '1') при попытке удалить строку после её переноса в другую таблицу. Выясним причину этого поведения.

В управляемых формах 1С 8.3 таблицы (тип ДанныеФормыКоллекция) работают со строками следующим образом:

  1. Индекс — это порядковый номер строки в массиве (от 0 до N). Индексы динамичны: если вы удаляете первую строку (индекс 0), бывшая вторая строка автоматически получает индекс 0.
  2. Идентификатор (RowID) — это уникальное число, присваиваемое строке при создании. Оно остается неизменным, пока строка существует в коллекции, независимо от сортировок или удаления соседних записей.

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


&НаСервере
Процедура ПеренестиСтрокуНаСервере(ИсточникИмя, ПриемникИмя, ИдентификаторСтроки)
    
    Источник = ЭтаФорма[ИсточникИмя];
    Приемник = ЭтаФорма[ПриемникИмя];
    
    // Получаем объект строки по идентификатору
    СтрокаИсточник = Источник.НайтиПоИдентификатору(ИдентификаторСтроки);
    
    Если СтрокаИсточник <> Неопределено Тогда
        
        // Добавляем новую строку в приемник
        НоваяСтрока = Приемник.Добавить();
        
        // Копируем данные всех совпадающих реквизитов
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточник);
        
        // Удаляем строку из источника, передавая сам ОБЪЕКТ строки
        Источник.Удалить(СтрокаИсточник);
        
    КонецЕсли;
    
КонецПроцедуры

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

Альтернативные способы взаимодействия: Drag-and-Drop и Выбор

Если задача состоит в том, чтобы сделать интерфейс максимально удобным, рассмотрим вариант использования перетаскивания (Drag-and-Drop) или двойного клика. Это избавляет от необходимости отслеживать «активную» таблицу, так как источник и приемник определяются самим действием пользователя.

Реализация через событие «Выбор» (двойной клик):

Для таблицы ТЗ1 создадим обработчик события Выбор. По умолчанию двойной клик открывает ячейку для редактирования, но мы можем перехватить это действие.


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

Реализация через Drag-and-Drop:

Этот метод считается наиболее современным. Выполним следующие шаги:

  1. В свойствах элемента формы «Таблица» (для обеих ТЗ) установим флаг РазрешитьНачалоПеретаскивания в значение Истина.
  2. Для таблицы-приемника создадим событие ПроверкаПеретаскивания, где укажем: ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Перемещение.
  3. В событии Перетаскивание таблицы-приемника пропишем логику добавления данных и удаления их из ПараметрыПеретаскивания.Значение.

Использование горячих клавиш

Для повышения скорости работы можно назначить кнопкам переноса сочетания клавиш. Например, Ctrl + Right для переноса из левой таблицы в правую и Ctrl + Left — наоборот. В этом случае пользователю не нужно задумываться об активности таблиц — кнопки будут жестко привязаны к направлению движения данных. Для этого в свойствах команд переноса найдите поле Сочетание клавиш и укажите нужную комбинацию.

Подведем итог: для надежной работы с двумя таблицами на форме следует отказаться от отслеживания фокуса через события активации в пользу прямой проверки ТекущийЭлемент или использования специализированных интерфейсных механизмов, таких как Drag-and-Drop. При удалении строк всегда используйте объект строки или его идентификатор, предварительно полученный через НайтиПоИдентификатору, чтобы избежать ошибок индексации.

← На главную