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

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

Процесс программного изменения данных в табличной части (ТЧ) управляемой формы — одна из базовых задач разработчика 1С. Однако часто возникают ситуации, когда код кажется верным, отладчик не выдает ошибок, но данные в документе не обновляются или рассчитываются некорректно. В данной статье мы проанализируем типичные ошибки при заполнении ТЧ из формы выбора и разберем, как сделать код надежным и универсальным.

Разбор основной проблемы: почему не работал расчет суммой

В исходной ситуации разработчик столкнулся с тем, что «расчет процентом» работал, а «расчет суммой» — нет. Проанализируем представленный код и выясним причины. Первая критическая ошибка заключалась в использовании функции Формат() для получения значения. В 1С функция Формат() всегда возвращает строку. Когда вы пытаетесь записать строку в числовой реквизит или использовать ее в дальнейших математических операциях (например, при расчете чистой цены), платформа может либо выдать ошибку, либо (что чаще в управляемых формах) неявно преобразовать ее в 0, что и приводило к отсутствию результата.

Вторая проблема — нарушение структуры циклов. Расчет итоговых полей (ЦенаЧистая, Сумма) был вынесен за пределы цикла Для Каждого. В результате пересчитывалась только последняя строка из массива выделенных строк, а остальные оставались с некорректными данными.

Правильная работа с типами данных и округлением

Для корректных финансовых расчетов вместо форматирования строки необходимо использовать функцию Окр(). Рассмотрим, как должен выглядеть расчет процента:


// Вместо: ПроцентРасчет = Формат(ТекСтрока.ЦенаЧистая * ВыбранноеЗначение.Процент/100, "ЧДЦ=2");
// Используем:
ПроцентРасчет = Окр(ТекСтрока.ЦенаЧистая * (ВыбранноеЗначение.Процент / 100), 2, РежимОкругления.Окр15как20);

Использование третьего параметра РежимОкругления.Окр15как20 гарантирует, что копейки будут округляться по правилам бухгалтерского учета. Также важно помнить, что если данные приходят из структуры ВыбранноеЗначение, которая была сформирована в другой форме, полезно явно приводить их к числу с помощью функции Число(), чтобы избежать ошибок типизации.

Оптимизация кода через универсальное обращение к колонкам

Вместо написания огромных конструкций Если... ИначеЕсли для каждой колонки (Комиссия, Тара, Транспорт), мы можем использовать мощный механизм обращения к свойствам объекта по имени в квадратных скобках. Это позволяет сократить код в несколько раз и избежать опечаток.

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


&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
    
    // Проверяем, что вернулась именно наша структура с данными
    Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура") И ВыбранноеЗначение.Свойство("ВидОперации") Тогда
        
        МассивСтрок = Элементы.Товары.ВыделенныеСтроки;
        
        Для Каждого ИдентификаторСтроки Из МассивСтрок Цикл
            ТекСтрока = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);
            
            Если ТекСтрока = Неопределено Тогда
                Продолжить;
            КонецЕсли;
            
            // Если выбран расчет суммой, просто берем значение из структуры
            Если ВыбранноеЗначение.ВидОперации = "РасчетСуммой" Тогда
                // Используем универсальное обращение к реквизиту ТЧ по имени
                ТекСтрока[ВыбранноеЗначение.ИмяКолонки] = ВыбранноеЗначение.Значение;
                
            // Если выбран расчет процентом, вычисляем долю
            ИначеЕсли ВыбранноеЗначение.ВидОперации = "РасчетПроцентом" Тогда
                ВычисленнаяСумма = ТекСтрока.ЦенаЧистая * (ВыбранноеЗначение.Процент / 100);
                ТекСтрока[ВыбранноеЗначение.ИмяКолонки] = Окр(ВычисленнаяСумма, 2);
            КонецЕсли;
            
            // Вызываем единую процедуру пересчета итогов для строки
            ПересчитатьИтогиСтроки(ТекСтрока);
            
        КонецЦикла;
        
    КонецЕсли;

КонецПроцедуры

Создание единой процедуры пересчета

Одним из стандартов разработки в 1С является вынос логики расчета сумм в отдельную процедуру. Это избавляет от дублирования кода. Если завтра логика расчета «Чистой цены» изменится, вам не придется искать и править ее во всех обработчиках. Создадим процедуру, которую можно вызывать как из ОбработкаВыбора, так и из события ПриИзменении колонок табличной части.


&НаКлиенте
Процедура ПересчитатьИтогиСтроки(СтрокаТЧ)
    
    // 1. Сначала рассчитываем чистую цену (база может зависеть от других колонок)
    СтрокаТЧ.ЦенаЧистая = СтрокаТЧ.Цена 
                        - СтрокаТЧ.ЦенаТары 
                        - СтрокаТЧ.ЦенаТранспорта 
                        - СтрокаТЧ.ЦенаКомиссии;
    
    // 2. Рассчитываем итоговые суммы
    СтрокаТЧ.Сумма = СтрокаТЧ.Цена * СтрокаТЧ.Количество;
    СтрокаТЧ.СуммаЧистая = СтрокаТЧ.ЦенаЧистая * СтрокаТЧ.Количество;
    
    // 3. Расчет цены за штуку, если это необходимо
    Если СтрокаТЧ.КоличествоШт <> 0 Тогда
        СтрокаТЧ.ЦенаШт = СтрокаТЧ.Сумма / СтрокаТЧ.КоличествоШт;
    Иначе
        СтрокаТЧ.ЦенаШт = 0;
    КонецЕсли;
    
КонецПроцедуры

Рекомендации по улучшению взаимодействия с пользователем

При работе с выделенными строками в табличной части важно учитывать несколько нюансов:

  1. Проверка выделения: Перед началом цикла всегда проверяйте, выбрал ли пользователь хотя бы одну строку. Если массив ВыделенныеСтроки пуст, стоит вывести предупреждение или обработать текущую строку (Элементы.Товары.ТекущаяСтрока).
  2. Модифицированность формы: При программном изменении данных на клиенте 1С обычно понимает, что форма изменена. Однако для надежности в конце обработки можно явно установить ЭтаФорма.Модифицированность = Истина;.
  3. Серверный контекст: Если табличная часть содержит тысячи строк и вы планируете обрабатывать их все (а не только выделенные), лучше передать данные на сервер. Работа с коллекцией Объект.Товары на сервере происходит значительно быстрее, чем поиск по идентификатору на клиенте в цикле.

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

← На главную