Как получить ссылку на документ из строки табличной части (ДанныеФормыЭлементКоллекции) в 1С

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

При доработке типовых конфигураций (например, 1С:ERP, 1С:Комплексная автоматизация или 1С:Управление торговлей) разработчики часто сталкиваются с ситуацией, когда в общий модуль передается исключительно текущая строка табличной части — объект с типом ДанныеФормыЭлементКоллекции. Возникает практическая задача: как внутри универсальной процедуры узнать, к какому именно документу принадлежит эта строка, чтобы выполнить специфический расчет (например, скорректировать расчет расчетной ставки НДС 18/118 или 20/120)?

В этой статье мы подробно проанализируем ограничения платформы 1С:Предприятие 8.3 при работе с коллекциями формы и разберем практические способы решения задачи определения контекста документа.

Почему нельзя получить ссылку напрямую из ДанныеФормыЭлементКоллекции?

Рассмотрим природу объекта ДанныеФормыЭлементКоллекции. В клиент-серверной архитектуре управляемых форм этот тип данных представляет собой лишь проекцию одной строки таблицы или дерева на клиенте либо сервере. У него нет встроенных ссылок на владельца, форму или исходный объект базы данных.

У объекта ДанныеФормыЭлементКоллекции доступны только:

  1. Значения реквизитов (колонок), входящих в состав конкретной строки.
  2. Метод ПолучитьИдентификатор(), возвращающий целочисленный идентификатор строки во временной коллекции формы.

Таких методов, как ЭтотОбъект, Владелец() или Родитель(), у строки нет. Соответственно, получить ссылку на документ или даже имя типа документа непосредственно из переменной типа ДанныеФормыЭлементКоллекции невозможно, если колонка со ссылкой не была добавлена в табличную часть явным образом.

Способ 1. Передача контекста через структуру параметров (СтруктураДействий)

Разберем типовой механизм БСП и 1С:ERP, в котором обработка изменений строк табличной части выполняется через процедуру ОбработкаТабличнойЧастиКлиент.ОбработатьСтрокуТЧ. Посмотрим на типовой вызов при изменении реквизита строки:


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

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


// В модуле ОбработкаТабличнойЧастиКлиентСервер или в расширении формы:
Процедура ДобавитьВСтруктуруДействияПриИзмененииКоличестваУпаковок(СтруктураДействий, Объект) Экспорт
    
    // Передаем признак типа документа или сам тип ссылки
    СтруктураДействий.Вставить("ТипДокумента", ТипЗнч(Объект.Ссылка));
    СтруктураДействий.Вставить("ИмяДокумента", Объект.Ссылка.Метаданные().Имя);
    
    // Формирование остальных параметров пересчета
    СтруктураПересчета = ОбработкаТабличнойЧастиКлиентСервер.ПолучитьСтруктуруПересчетаСуммыНДСВСтрокеТЧ(Объект);
    СтруктураДействий.Вставить("ПересчитатьСуммуНДС", СтруктураПересчета);

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

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


Если СтруктураДействий.Свойство("ИмяДокумента") И СтруктураДействий.ИмяДокумента = "РеализацияТоваровУслуг" Тогда
    // Выполняем специфичный расчет для документа Реализация товаров и услуг
Иначе
    // Стандартный типовой расчет
КонецЕсли;

Способ 2. Определение типа документа по уникальному составу реквизитов строки

Если сигнатуру вызовов менять нельзя или доработка структуры действий затрагивает слишком много модулей, применим проверку уникальных свойств строки. В разных объектах конфигурации (например, Заказ клиента, Реализация товаров и услуг, Приобретение товаров и услуг) состав реквизитов табличных частей различается.

Проверим наличие реквизита, присущего только целевому документу, с помощью метода Свойство() или обращения к реквизиту:


Функция ЭтоСтрокаРеализацииТоваров(ТекущаяСтрока)
    
    // Проверяем наличие уникального реквизита, который есть только в реализации
    // Например, реквизит "КодСтроки" или специализированное поле статуса отгрузки
    РеквизитНайден = Ложь;
    
    Попытка
        ТестовоеЗначение = ТекущаяСтрока.УникальныйРеквизитРеализации;
        РеквизитНайден = Истина;
    Исключение
        РеквизитНайден = Ложь;
    КонецПопытки;
    
    Возврат РеквизитНайден;

КонецФункции

Такой подход позволяет безопасно внедрить проверку внутри универсального модуля без риска вызвать синтаксическую ошибку в других документах базы.

Особенности расчета ставки НДС (18/118, 20/120) в 1С:ERP

Выясним причину, по которой часто возникает потребность в такой доработке. В типовых решениях 1С флаг Цена включает НДС обычно задается в шапке документа или соглашении и распространяется на весь документ целиком. Если флаг снят, модуль пересчета может по умолчанию рассчитывать НДС «сверху» даже для расчетных ставок вида 18/118 или 20/120.

Формула расчета НДС, когда налог выделяется из итоговой суммы (расчетная ставка):


СуммаБезНДС = Окр((Сумма * 100) / (100 + СтавкаЧислом), 2);
СуммаНДС    = Сумма - СуммаБезНДС;

Формула расчета налога «сверху» (прямая ставка):


СуммаНДС    = Окр((Сумма * СтавкаЧислом) / 100, 2);
СуммаСНДС   = Сумма + СуммаНДС;

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

← На главную