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

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

При разработке интерфейсов в 1С:Предприятие 8.3 программисты часто сталкиваются с задачей групповой обработки строк табличной части. Типичный сценарий: пользователь выделяет несколько строк в документе (например, в накладной или заказе покупателя) и нажимает кнопку, чтобы массово изменить в них ставку НДС, склад или цену. При реализации этой логики начинающие разработчики совершают классическую ошибку, которая приводит к аварийному завершению программы с системным сообщением: «Значение не является значением объектного типа». В этой статье мы подробно разберем, почему возникает данная ошибка, изучим внутренние механизмы платформы 1С для работы с выделенными строками и напишем правильный, оптимизированный код с учетом пересчета зависимых суммовых показателей.

Выясняем причину ошибки «Значение не является значением объектного типа»

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


ВыдСтроки = Элементы.Товары.ВыделенныеСтроки;
Для каждого ДанныеТч из ВыдСтроки Цикл
    ДанныеТч.СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС0");
КонецЦикла;

Давайте разберемся, почему этот код не работает. Свойство ВыделенныеСтроки элемента формы (в данном случае это таблица формы Товары) возвращает не коллекцию самих строк и не объекты данных, а обычный массив идентификаторов выделенных строк. Идентификатор строки — это просто числовое значение (например, 1, 2, 10), которое платформа присваивает каждой строке для связи между элементами интерфейса и данными.

Когда мы пишем цикл Для каждого ДанныеТч из ВыдСтроки, переменная ДанныеТч на каждой итерации принимает значение этого числового идентификатора (тип Число). Попытка обратиться к числу через точку (ДанныеТч.СтавкаНДС) и вызывает ошибку. Число, разумеется, не имеет свойства СтавкаНДС, так как оно не является объектом.

Разбираем правильные способы работы с выделенными строками

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

Способ 1. Использование метода НайтиПоИдентификатору (Рекомендуемый)

Самый надежный и правильный способ работы с данными формы — это обращение к ним через основное свойство формы (обычно это реквизит Объект). Для этого мы используем метод коллекции НайтиПоИдентификатору(). Давайте посмотрим на рабочий пример кода:


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

В этом примере мы сначала получаем массив идентификаторов. Затем на каждой итерации с помощью метода НайтиПоИдентификатору() вытаскиваем конкретную строку из коллекции Объект.Товары. Переменная СтрокаТабличнойЧасти теперь имеет тип ДанныеФормыЭлементКоллекции, который ведет себя как объект, и мы можем без проблем изменять любые его реквизиты.

Способ 2. Использование метода Элементы.ИмяТаблицы.ДанныеСтроки (Для чтения)

Существует еще один метод получения данных строки по ее идентификатору — это обращение к интерфейсному свойству таблицы формы: Элементы.Товары.ДанныеСтроки(ИдентификаторСтроки). Этот метод возвращает данные, отображаемые в данный момент в интерфейсе. Однако у него есть важные особенности:

  1. Этот метод предназначен в основном для **чтения** данных строки (например, чтобы проверить какое-то условие перед обработкой).
  2. Для изменения данных в объекте формы (который впоследствии будет записан в базу данных) настоятельно рекомендуется использовать именно первый способ через Объект.Товары.НайтиПоИдентификатору(). Это гарантирует правильную синхронизацию данных между клиентом и сервером.

Анализируем ошибку совета «ПолучитьОбъект()»

На форумах часто можно встретить совет: *«Вам нужно получить объект методом ПолучитьОбъект(), изменить строки и записать его»*. Давайте проанализируем, почему этот совет вреден и опасен при работе в управляемой форме документа.

Метод ПолучитьОбъект() предназначен для работы с базой данных на сервере. Если вы уже находитесь в открытой форме документа и пользователь внес туда какие-то изменения (но еще не нажал кнопку «Записать»), вызов метода ПолучитьОбъект() на сервере прочитает данные из базы данных **без учета текущих изменений пользователя на форме**. Вы измените строки в копии объекта из базы, запишете ее, а когда пользователь попытается сохранить свою форму, он либо затрет ваши изменения, либо получит ошибку блокировки данных.

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

Важность пересчета сумм при изменении ставки НДС

Просто изменить значение в колонке СтавкаНДС недостаточно для корректного учета. В любой типовой конфигурации (например, в «1С:Бухгалтерия», «Управление торговлей» или «ERP») изменение ставки налога должно влечь за собой автоматический пересчет суммы НДС и общей суммы строки. Если этого не сделать, возникнет серьезная логическая ошибка: в документе будет стоять ставка «НДС 20%», а сумма налога останется нулевой или рассчитанной по старой ставке.

В профессиональной разработке принято использовать серверные процедуры пересчета, заложенные в типовые конфигурации (БСП). Рассмотрим, как реализовать правильный алгоритм с пересчетом показателей, перенеся обработку на сервер для максимального быстродействия:


&НаКлиенте
Процедура ИзменитьСтавкуНДСИПересчитатьСуммы(Команда)
    
    ВыделенныеСтроки = Элементы.Товары.ВыделенныеСтроки;
    Если ВыделенныеСтроки.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    // Передаем массив идентификаторов на сервер для быстрой обработки
    ИзменитьСтавкуНДСНаСервере(ВыделенныеСтроки);
    
КонецПроцедуры

&НаСервере
Процедура ИзменитьСтавкуНДСНаСервере(МассивИдентификаторов)
    
    НоваяСтавкаНДС = Перечисления.СтавкиНДС.НДС20; // Пример установки 20%
    
    Для Каждого ИдентификаторСтроки Из МассивИдентификаторов Цикл
        
        СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);
        Если СтрокаТЧ <> Неопределено Тогда
            
            // Устанавливаем новое значение
            СтрокаТЧ.СтавкаНДС = НоваяСтавкаНДС;
            
            // Ниже приведен пример логики пересчета сумм.
            // В реальных конфигурациях лучше вызывать готовые общие модули.
            // Например, для Бухгалтерии Предприятия 3.0:
            // Обработка Табличной Части на сервере
            
            // Ручной пример пересчета, если конфигурация самописная:
            ТекущиеПараметры = Новый Структура;
            ТекущиеПараметры.Вставить("Цена", СтрокаТЧ.Цена);
            ТекущиеПараметры.Вставить("Количество", СтрокаТЧ.Количество);
            ТекущиеПараметры.Вставить("Сумма", СтрокаТЧ.Сумма);
            ТекущиеПараметры.Вставить("СтавкаНДС", СтрокаТЧ.СтавкаНДС);
            
            // Рассчитываем НДС (пример простой формулы)
            Если СтрокаТЧ.СтавкаНДС = Перечисления.СтавкиНДС.НДС20 Тогда
                СтрокаТЧ.СуммаНДС = Округление(СтрокаТЧ.Сумма * 0.20, 2);
            ИначеЕсли СтрокаТЧ.СтавкаНДС = Перечисления.СтавкиНДС.НДС10 Тогда
                СтрокаТЧ.СуммаНДС = Округление(СтрокаТЧ.Сумма * 0.10, 2);
            Иначе
                СтрокаТЧ.СуммаНДС = 0;
            КонецЕсли;
            
            СтрокаТЧ.Всего = СтрокаТЧ.Сумма + СтрокаТЧ.СуммаНДС;
            
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

&НаСервере
Функция Округление(Значение, Разрядность)
    Возврат Окр(Значение, Разрядность, РежимОкругления.Округление15сотых);
КонецФункции

Альтернатива: Использование типового группового изменения

Если вы работаете в современной типовой конфигурации 1С, перед тем как писать собственный программный код для массового изменения реквизитов строк, обратите внимание на стандартные возможности платформы. В командной панели большинства табличных частей документов (например, в «Реализации товаров и услуг») присутствует стандартная кнопка «Изменить» (или сочетание клавиш для группового изменения строк).

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

← На главную