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

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

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

В этой статье мы подробно разберем, как правильно и оптимально работать со строками табличной части «на лету», рассмотрим разницу между типами форм и изучим типичные ошибки, возникающие при написании кода.

Проблема неоптимального обхода табличной части

Рассмотрим исходный код, который часто пишут новички:


Процедура ТабличноеПоле1КоличествоЦенаПриИзменении(Элемент)
    Для каждого Строка Из ТабличнаяЧасть1 Цикл
        Строка.Сумма = Строка.Цена * Строка.Количество;
    КонецЦикла;
КонецПроцедуры

Выясним причину, почему данный подход считается плохим тоном в программировании 1С. Когда пользователь меняет количество или цену в конкретной строке, платформа генерирует событие изменения. Запуская цикл Для каждого по всей коллекции ТабличнаяЧасть1, мы заставляем систему заново пересчитывать суммы даже для тех строк, которые не редактировались. Если в документе 1000 строк, система выполнит 1000 операций умножения и перезаписи на каждое изменение символа. Правильный подход — изменять данные только в текущей строке, которую в данный момент редактирует пользователь.

Использование свойства «ТекущиеДанные»

Для получения доступа к редактируемой строке формы в реальном времени используется свойство ТекущиеДанные. Оно возвращает объект, содержащий данные именно той строки, на которой сейчас установлен курсор (фокус) пользователя.

Давайте проанализируем, как будет выглядеть оптимальный код для расчета суммы:


ТекущаяСтрока = ЭлементыФормы.ТабличноеПоле1.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено Тогда
    ТекущаяСтрока.Сумма = ТекущаяСтрока.Цена * ТекущаяСтрока.Количество;
КонецЕсли;

В этом случае система отрабатывает мгновенно, так как обращение и расчет происходят ровно для одной строки, независимо от общего объема данных в документе.

Различие между Обычными и Управляемыми формами

Часто разработчики сталкиваются с ошибками вида «Поле объекта не обнаружено», пытаясь использовать код из интернета без оглядки на тип формы, с которой они работают. Разберем это различие подробнее.

  1. Обычные формы (ОФ): Используются в старых конфигурациях (например, УПП 1.3, УТ 10.3). Обращение к элементам формы происходит через коллекцию ЭлементыФормы. ТекущаяСтрока = ЭлементыФормы.ИмяТаблицы.ТекущиеДанные;
  2. Управляемые формы (УФ): Используются во всех современных конфигурациях (ERP, БП 3.0, ЗУП 3, УТ 11). Здесь доступ к элементам осуществляется через коллекцию Элементы. ТекущаяСтрока = Элементы.ИмяТаблицы.ТекущиеДанные;

Попытка вызвать Элементы.ТабличноеПоле1.ТекущиеДанные в обычной форме вызовет критическую ошибку, так как объект Элементы в ОФ не содержит табличных полей формы.

Разбор ошибки «Поле объекта не обнаружено (ТекущиеДанные)» при использовании переменной Элемент

Рассмотрим ситуацию, когда разработчик пытается получить текущую строку напрямую через параметр обработчика события:


Процедура ТабличноеПоле1КоличествоПриИзменении(Элемент)
    // Ошибка!
    ТекущаяСтрока = Элемент.ТекущиеДанные; 
КонецПроцедуры

Почему возникает эта ошибка? В обработчик события изменения конкретной колонки в качестве параметра Элемент передается не само табличное поле (вся таблица), а конкретное поле ввода (активный элемент управления в ячейке, например, числовое поле ввода количества). У этого поля ввода нет свойства ТекущиеДанные. Данное свойство есть только у родительского элемента — таблицы формы. Именно поэтому обращаться нужно напрямую к табличному полю через коллекцию элементов формы.

Важная разница между «ТекущиеДанные» и «ТекущаяСтрока»

Еще одна классическая ошибка программистов 1С — путаница между похожими по названию свойствами:

  1. ТекущиеДанные — возвращает саму строку (коллекцию значений текущей строки). Через нее мы можем читать и записывать реквизиты (ТекущиеДанные.Цена = 100;).
  2. ТекущаяСтрока — возвращает идентификатор строки. В управляемых формах это число (индекс строки/внутренний ID), а в динамических списках — ссылка на объект БД. Если написать Элементы.Товары.ТекущаяСтрока.Цена = 100, система выдаст ошибку, так как вы пытаетесь обратиться к свойству «Цена» у числового идентификатора.

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

Рекомендации по написанию качественного кода (Best Practices)

Для того чтобы ваш код был читаемым, масштабируемым и легко поддерживаемым, придерживайтесь следующих правил:

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

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


&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
    РассчитатьСуммуСтроки();
КонецПроцедуры

&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
    РассчитатьСуммуСтроки();
КонецПроцедуры

&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
    // Обратный расчет цены при изменении суммы пользователем
    СтрокаТЧ = Элементы.Товары.ТекущиеДанные;
    Если СтрокаТЧ <> Неопределено Тогда
        Если СтрокаТЧ.Количество <> 0 Тогда
            СтрокаТЧ.Цена = СтрокаТЧ.Сумма / СтрокаТЧ.Количество;
        Иначе
            СтрокаТЧ.Цена = 0;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура РассчитатьСуммуСтроки()
    СтрокаТЧ = Элементы.Товары.ТекущиеДанные;
    Если СтрокаТЧ <> Неопределено Тогда
        СтрокаТЧ.Сумма = СтрокаТЧ.Цена * СтрокаТЧ.Количество;
    КонецЕсли;
КонецПроцедуры

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

← На главную