Процесс программного изменения данных в табличной части (ТЧ) управляемой формы — одна из базовых задач разработчика 1С. Однако часто возникают ситуации, когда код кажется верным, отладчик не выдает ошибок, но данные в документе не обновляются или рассчитываются некорректно. В данной статье мы проанализируем типичные ошибки при заполнении ТЧ из формы выбора и разберем, как сделать код надежным и универсальным.
В исходной ситуации разработчик столкнулся с тем, что «расчет процентом» работал, а «расчет суммой» — нет. Проанализируем представленный код и выясним причины. Первая критическая ошибка заключалась в использовании функции Формат() для получения значения. В 1С функция Формат() всегда возвращает строку. Когда вы пытаетесь записать строку в числовой реквизит или использовать ее в дальнейших математических операциях (например, при расчете чистой цены), платформа может либо выдать ошибку, либо (что чаще в управляемых формах) неявно преобразовать ее в 0, что и приводило к отсутствию результата.
Вторая проблема — нарушение структуры циклов. Расчет итоговых полей (ЦенаЧистая, Сумма) был вынесен за пределы цикла Для Каждого. В результате пересчитывалась только последняя строка из массива выделенных строк, а остальные оставались с некорректными данными.
Для корректных финансовых расчетов вместо форматирования строки необходимо использовать функцию Окр(). Рассмотрим, как должен выглядеть расчет процента:
// Вместо: ПроцентРасчет = Формат(ТекСтрока.ЦенаЧистая * ВыбранноеЗначение.Процент/100, "ЧДЦ=2");
// Используем:
ПроцентРасчет = Окр(ТекСтрока.ЦенаЧистая * (ВыбранноеЗначение.Процент / 100), 2, РежимОкругления.Окр15как20);
Использование третьего параметра РежимОкругления.Окр15как20 гарантирует, что копейки будут округляться по правилам бухгалтерского учета. Также важно помнить, что если данные приходят из структуры ВыбранноеЗначение, которая была сформирована в другой форме, полезно явно приводить их к числу с помощью функции Число(), чтобы избежать ошибок типизации.
Вместо написания огромных конструкций Если... ИначеЕсли для каждой колонки (Комиссия, Тара, Транспорт), мы можем использовать мощный механизм обращения к свойствам объекта по имени в квадратных скобках. Это позволяет сократить код в несколько раз и избежать опечаток.
Рассмотрим ситуацию: из формы выбора нам возвращается структура, где указано имя колонки, которую нужно заполнить. Тогда процедура ОбработкаВыбора становится лаконичной и понятной:
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
// Проверяем, что вернулась именно наша структура с данными
Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура") И ВыбранноеЗначение.Свойство("ВидОперации") Тогда
МассивСтрок = Элементы.Товары.ВыделенныеСтроки;
Для Каждого ИдентификаторСтроки Из МассивСтрок Цикл
ТекСтрока = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);
Если ТекСтрока = Неопределено Тогда
Продолжить;
КонецЕсли;
// Если выбран расчет суммой, просто берем значение из структуры
Если ВыбранноеЗначение.ВидОперации = "РасчетСуммой" Тогда
// Используем универсальное обращение к реквизиту ТЧ по имени
ТекСтрока[ВыбранноеЗначение.ИмяКолонки] = ВыбранноеЗначение.Значение;
// Если выбран расчет процентом, вычисляем долю
ИначеЕсли ВыбранноеЗначение.ВидОперации = "РасчетПроцентом" Тогда
ВычисленнаяСумма = ТекСтрока.ЦенаЧистая * (ВыбранноеЗначение.Процент / 100);
ТекСтрока[ВыбранноеЗначение.ИмяКолонки] = Окр(ВычисленнаяСумма, 2);
КонецЕсли;
// Вызываем единую процедуру пересчета итогов для строки
ПересчитатьИтогиСтроки(ТекСтрока);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Одним из стандартов разработки в 1С является вынос логики расчета сумм в отдельную процедуру. Это избавляет от дублирования кода. Если завтра логика расчета «Чистой цены» изменится, вам не придется искать и править ее во всех обработчиках. Создадим процедуру, которую можно вызывать как из ОбработкаВыбора, так и из события ПриИзменении колонок табличной части.
&НаКлиенте
Процедура ПересчитатьИтогиСтроки(СтрокаТЧ)
// 1. Сначала рассчитываем чистую цену (база может зависеть от других колонок)
СтрокаТЧ.ЦенаЧистая = СтрокаТЧ.Цена
- СтрокаТЧ.ЦенаТары
- СтрокаТЧ.ЦенаТранспорта
- СтрокаТЧ.ЦенаКомиссии;
// 2. Рассчитываем итоговые суммы
СтрокаТЧ.Сумма = СтрокаТЧ.Цена * СтрокаТЧ.Количество;
СтрокаТЧ.СуммаЧистая = СтрокаТЧ.ЦенаЧистая * СтрокаТЧ.Количество;
// 3. Расчет цены за штуку, если это необходимо
Если СтрокаТЧ.КоличествоШт <> 0 Тогда
СтрокаТЧ.ЦенаШт = СтрокаТЧ.Сумма / СтрокаТЧ.КоличествоШт;
Иначе
СтрокаТЧ.ЦенаШт = 0;
КонецЕсли;
КонецПроцедуры
При работе с выделенными строками в табличной части важно учитывать несколько нюансов:
ВыделенныеСтроки пуст, стоит вывести предупреждение или обработать текущую строку (Элементы.Товары.ТекущаяСтрока).ЭтаФорма.Модифицированность = Истина;.Объект.Товары на сервере происходит значительно быстрее, чем поиск по идентификатору на клиенте в цикле.Подводя итог, можно сказать, что ключ к исправлению ошибок в подобных задачах — это внимательное отношение к типам данных (число vs строка) и структурирование кода. Вынос расчетов в отдельные процедуры и использование универсального доступа к реквизитам через квадратные скобки делает ваш код профессиональным и легким в поддержке.