Как получить данные из таблицы на форме в модуле объекта 1С?

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

Часто перед разработчиками 1С встает задача: как из модуля объекта, например, бизнес-процесса или документа, обратиться к данным, которые пользователь ввел в таблицу на его форме? На первый взгляд, это кажется логичным, но прямой доступ невозможен, и попытка его реализовать говорит о фундаментальном непонимании клиент-серверной архитектуры платформы 1С. Давайте разберемся, почему так происходит и какие существуют правильные, архитектурно верные способы решения этой задачи.

Почему нельзя напрямую получить данные формы из модуля объекта?

Ключевая причина кроется в строгом разделении контекстов выполнения кода в режиме управляемых форм (тонкий или веб-клиент). Проанализируем, где "живет" и выполняется каждый из интересующих нас модулей.

Форма и ее модуль — это то, что видит и с чем взаимодействует пользователь. Код модуля формы может выполняться в двух местах:

  1. На клиенте (директива &НаКлиенте): здесь обрабатываются действия пользователя (нажатия кнопок, ввод текста), выполняются проверки, не требующие данных из базы, и управляется внешний вид формы.
  2. На сервере (директива &НаСервере): сюда передается управление с клиента, когда нужно выполнить бизнес-логику, обратиться к базе данных или вызвать методы объекта.

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

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

Итак, вместо того чтобы "тянуть" данные из формы, нам нужно организовать их правильную "передачу" с клиента на сервер в тот момент, когда они необходимы для выполнения логики. Рассмотрим несколько стандартных и эффективных способов.

Решение 1: Хранение данных в реквизитах объекта (основной способ)

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

Как это работает?

  1. В конфигураторе вы создаете у объекта (например, Бизнес-процесс.МойБизнесПроцесс) табличную часть с нужными колонками (например, Товары с колонками Номенклатура, Количество, Цена).
  2. На форме вы размещаете элемент "Таблица" и в его свойстве ПутьКДанным указываете путь к этой табличной части: Объект.Товары.

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

Посмотрим на пример:

В модуле объекта вы можете просто обратиться к табличной части через ЭтотОбъект.


// В модуле объекта Бизнес-процесса
Процедура ПередЗаписью(Отказ)
    
    ОбщаяСумма = 0;
    // Просто обращаемся к табличной части, данные в ней уже есть
    Для Каждого СтрокаТаблицы Из ЭтотОбъект.Товары Цикл
        ОбщаяСумма = ОбщаяСумма + СтрокаТаблицы.Количество * СтрокаТаблицы.Цена;
    КонецЦикла;
    
    Если ОбщаяСумма > 100000 Тогда
        // какая-то логика
    КонецЕсли;
    
КонецПроцедуры

Когда использовать: Этот метод следует выбирать в 90% случаев, когда данные в таблице должны быть сохранены вместе с объектом и являются его логической частью.

Решение 2: Передача данных через параметры процедур

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

Разберем по шагам:

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

Таким образом, мы явно и контролируемо передали данные с клиентского контекста (формы) в серверный (модуль объекта) для обработки.

Решение 3: Передача через структуру `ДополнительныеСвойства` при записи

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

Как это работает:

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

Этот метод очень удобен, так как не требует создания экспортных процедур в объекте и четко привязан к стандартному механизму записи.

В заключение, помните: правильный подход к разработке на 1С заключается не в поиске обходных путей для нарушения архитектуры, а в использовании штатных механизмов платформы. Вместо вопроса "Как мне получить данные из формы?" всегда задавайте себе вопрос: "Как мне правильно передать данные из формы в нужный серверный контекст для обработки?". Выбор конкретного способа — хранение в реквизитах, передача параметром или через ДополнительныеСвойства — зависит от вашей бизнес-задачи.

← На главную