При разработке в среде «1С:Предприятие» одной из самых частых задач является обработка событий в табличных частях документов или справочников. Например, автоматический расчет суммы при изменении цены или количества. Однако начинающие разработчики часто совершают классическую ошибку: при изменении значения в одной ячейке они запускают цикл по всей табличной части. Это приводит к значительному замедлению работы интерфейса, особенно если в документе содержатся десятки или сотни строк.
В этой статье мы подробно разберем, как правильно и оптимально работать со строками табличной части «на лету», рассмотрим разницу между типами форм и изучим типичные ошибки, возникающие при написании кода.
Рассмотрим исходный код, который часто пишут новички:
Процедура ТабличноеПоле1КоличествоЦенаПриИзменении(Элемент)
Для каждого Строка Из ТабличнаяЧасть1 Цикл
Строка.Сумма = Строка.Цена * Строка.Количество;
КонецЦикла;
КонецПроцедуры
Выясним причину, почему данный подход считается плохим тоном в программировании 1С. Когда пользователь меняет количество или цену в конкретной строке, платформа генерирует событие изменения. Запуская цикл Для каждого по всей коллекции ТабличнаяЧасть1, мы заставляем систему заново пересчитывать суммы даже для тех строк, которые не редактировались. Если в документе 1000 строк, система выполнит 1000 операций умножения и перезаписи на каждое изменение символа. Правильный подход — изменять данные только в текущей строке, которую в данный момент редактирует пользователь.
Для получения доступа к редактируемой строке формы в реальном времени используется свойство ТекущиеДанные. Оно возвращает объект, содержащий данные именно той строки, на которой сейчас установлен курсор (фокус) пользователя.
Давайте проанализируем, как будет выглядеть оптимальный код для расчета суммы:
ТекущаяСтрока = ЭлементыФормы.ТабличноеПоле1.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено Тогда
ТекущаяСтрока.Сумма = ТекущаяСтрока.Цена * ТекущаяСтрока.Количество;
КонецЕсли;
В этом случае система отрабатывает мгновенно, так как обращение и расчет происходят ровно для одной строки, независимо от общего объема данных в документе.
Часто разработчики сталкиваются с ошибками вида «Поле объекта не обнаружено», пытаясь использовать код из интернета без оглядки на тип формы, с которой они работают. Разберем это различие подробнее.
ЭлементыФормы.
ТекущаяСтрока = ЭлементыФормы.ИмяТаблицы.ТекущиеДанные;
Элементы.
ТекущаяСтрока = Элементы.ИмяТаблицы.ТекущиеДанные;
Попытка вызвать Элементы.ТабличноеПоле1.ТекущиеДанные в обычной форме вызовет критическую ошибку, так как объект Элементы в ОФ не содержит табличных полей формы.
Рассмотрим ситуацию, когда разработчик пытается получить текущую строку напрямую через параметр обработчика события:
Процедура ТабличноеПоле1КоличествоПриИзменении(Элемент)
// Ошибка!
ТекущаяСтрока = Элемент.ТекущиеДанные;
КонецПроцедуры
Почему возникает эта ошибка? В обработчик события изменения конкретной колонки в качестве параметра Элемент передается не само табличное поле (вся таблица), а конкретное поле ввода (активный элемент управления в ячейке, например, числовое поле ввода количества). У этого поля ввода нет свойства ТекущиеДанные. Данное свойство есть только у родительского элемента — таблицы формы. Именно поэтому обращаться нужно напрямую к табличному полю через коллекцию элементов формы.
Еще одна классическая ошибка программистов 1С — путаница между похожими по названию свойствами:
ТекущиеДанные — возвращает саму строку (коллекцию значений текущей строки). Через нее мы можем читать и записывать реквизиты (ТекущиеДанные.Цена = 100;).ТекущаяСтрока — возвращает идентификатор строки. В управляемых формах это число (индекс строки/внутренний ID), а в динамических списках — ссылка на объект БД. Если написать Элементы.Товары.ТекущаяСтрока.Цена = 100, система выдаст ошибку, так как вы пытаетесь обратиться к свойству «Цена» у числового идентификатора.Свойство ТекущаяСтрока используется в основном для позиционирования и активизации нужной строки программным путем, но не для прямого изменения ее реквизитов на клиенте.
Для того чтобы ваш код был читаемым, масштабируемым и легко поддерживаемым, придерживайтесь следующих правил:
ТекущиеДанные вернет значение Неопределено, что приведет к аварийному завершению работы программы при попытке чтения свойств.Рассмотрим правильный пример организации кода для управляемых форм с обработкой обратного расчета и защитой от ошибок:
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
РассчитатьСуммуСтроки();
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
РассчитатьСуммуСтроки();
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
// Обратный расчет цены при изменении суммы пользователем
СтрокаТЧ = Элементы.Товары.ТекущиеДанные;
Если СтрокаТЧ <> Неопределено Тогда
Если СтрокаТЧ.Количество <> 0 Тогда
СтрокаТЧ.Цена = СтрокаТЧ.Сумма / СтрокаТЧ.Количество;
Иначе
СтрокаТЧ.Цена = 0;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура РассчитатьСуммуСтроки()
СтрокаТЧ = Элементы.Товары.ТекущиеДанные;
Если СтрокаТЧ <> Неопределено Тогда
СтрокаТЧ.Сумма = СтрокаТЧ.Цена * СтрокаТЧ.Количество;
КонецЕсли;
КонецПроцедуры
Используя данный шаблон, вы обеспечите быструю и стабильную работу интерфейса программы, исключите появление непредвиденных ошибок у пользователей и напишете профессиональный код, соответствующий стандартам разработки фирмы «1С». Для упрощения этой задачи можно использовать готовые шаблоны текста для соблюдения стандартов 1С.