Как в управляемой форме 1С получить и изменить новую строку табличной части сразу после копирования?

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

В разработке на платформе 1С часто возникает задача модифицировать данные в новой строке табличной части сразу после ее создания — для этого подойдёт расширение для настройки обработчиков заполнения объектов. Если строка добавляется стандартной кнопкой "Добавить", обычно используется событие ПриНачалеРедактирования. Однако при копировании существующей строки (через F9 или контекстное меню) это событие может не сработать, особенно в старых версиях платформы или при использовании режимов совместимости. Подобное программное изменение форм требует понимания тонкостей работы событий и жизненного цикла элементов.

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

Анализ стандартных событий и их ограничений

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

ПриНачалеРедактирования(НоваяСтрока, Копирование)

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

ПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, Параметр)

Это событие срабатывает до того, как платформа фактически создаст и добавит новую строку в коллекцию данных табличной части. Его главное преимущество — параметр Копирование, который безошибочно сообщает нам о намерении пользователя скопировать строку. Однако есть и ключевой недостаток: на момент выполнения этого обработчика самой новой строки как объекта данных еще не существует. Мы не можем получить к ней доступ и изменить ее поля. Но именно это событие станет отправной точкой для надежных обходных путей.

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

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

Разберем по шагам:

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

Посмотрим на пример кода:

Предположим, у нас есть табличная часть Товары на форме, и при копировании строки мы хотим очистить поля "Количество" и "Сумма".


&НаКлиенте
Процедура ТоварыПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, ПараметрКопирования)
    // Проверяем, что это именно операция копирования
    Если Копирование Тогда
        // 1. Отменяем стандартное действие платформы
        Отказ = Истина;
        
        // 2. Получаем исходную строку для копирования
        ИсходнаяСтрока = Элементы.Товары.ТекущиеДанные;
        Если ИсходнаяСтрока = Неопределено Тогда
            // На всякий случай, если текущая строка по какой-то причине не определена
            Возврат;
        КонецЕсли;
        
        // 3. Добавляем новую строку программно
        НоваяСтрока = Объект.Товары.Добавить();
        
        // 4. Копируем данные из исходной строки в новую
        ЗаполнитьЗначенияСвойств(НоваяСтрока, ИсходнаяСтрока);
        
        // 5. Вносим необходимые изменения в новую строку
        НоваяСтрока.Количество = 0;
        НоваяСтрока.Сумма = 0;
        
        // Можно также активизировать новую строку для удобства пользователя
        Элементы.Товары.ТекущаяСтрока = НоваяСтрока.ПолучитьИдентификатор();
    КонецЕсли;
КонецПроцедуры

Преимущества этого метода:

Решение 2: Асинхронная обработка с помощью обработчика ожидания

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

Разберем по шагам:

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

Посмотрим на пример кода:


&НаКлиенте
Процедура ТоварыПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, ПараметрКопирования)
    Если Копирование Тогда
        ПодключитьОбработчикОжидания("ОбработатьСкопированнуюСтроку", 0, Истина);
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьСкопированнуюСтроку()
    КоличествоСтрок = Объект.Товары.Количество();
    Если КоличествоСтрок = 0 Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем последнюю строку
    СкопированнаяСтрока = Объект.Товары[КоличествоСтрок - 1];
    
    // Вносим изменения
    СкопированнаяСтрока.Количество = 0;
    СкопированнаяСтрока.Сумма = 0;
КонецПроцедуры

Возможные причины некорректной работы событий

Напоследок выясним, почему вообще может возникать проблема с несрабатыванием ПриНачалеРедактирования. Чтобы детально изучить поведение элементов "вживую", можно использовать редактор форм в режиме предприятия (поможет инструментарий разработчика для отладки управляемых форм), который позволяет менять свойства объектов на лету. Основные причины проблем:

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

← На главную