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

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

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

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

Анализ проблемы: контекст управляемой формы и типизация данных

Проанализируем типовую ситуацию. В модуле формы документа объявлена экспортная серверная процедура:


&НаСервере
Процедура ПриПолученииДанныхСтрокиСостава(СтрокаСостава) Экспорт
    // Обработка реквизитов строки
    СтрокаСостава.Сумма = СтрокаСостава.Количество * СтрокаСостава.Цена;
КонецПроцедуры

Если попытаться вызвать этот метод из клиентского контекста общей команды, передав найденную строку напрямую:


// В модуле команды (Клиент)
СтрокиСостава = ЭтаФорма.Объект.Состав.НайтиСтроки(Новый Структура("ИдентификаторСтроки", ИдентификаторСтроки));
ЭтаФорма.ПриПолученииДанныхСтрокиСостава(СтрокиСостава[0]);

Мы столкнемся со следующими ограничениями платформы 1С:

  1. На клиенте элемент табличной части имеет тип ДанныеФормыЭлементКоллекции. Этот тип не сериализуется напрямую для передачи в неконтекстные серверные процедуры общих модулей или команд.
  2. Саму переменную ЭтаФорма (объект типа УправляемаяФорма) невозможно передать параметром в серверную процедуру другого модуля.
  3. Если серверный метод модифицирует переданный параметр по значению или работает с временной копией данных, эти изменения не попадут обратно в визуальные элементы формы пользователя.

Способ 1. Преобразование строки табличной части в структуру

Рассмотрим основной способ обхода ограничений типизации. Для передачи значений реквизитов строки между клиентом и сервером используем универсальную коллекцию Структура.

Разберем по шагам алгоритм решения:

  1. На клиенте создаем структуру и копируем в нее свойства текущей строки табличной части с помощью метода ЗаполнитьЗначенияСвойств.
  2. Передаем структуру в серверную процедуру.
  3. После выполнения расчета на сервере возвращаем структуру обратно на клиент и перезаполняем исходную строку формы.

Посмотрим на пример клиентского кода в модуле команды:


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

На стороне формы документа экспортная функция принимает структуру и возвращает результат:


&НаСервере
Функция РассчитатьДанныеСтрокиНаСервере(ДанныеСтроки) Экспорт
    
    // Выполняем требуемые алгоритмы
    ДанныеСтроки.Сумма = ДанныеСтроки.Количество * ДанныеСтроки.Цена;
    
    Возврат ДанныеСтроки;
КонецФункции

Способ 2. Решение через механизм расширений конфигурации

Если бизнес-логика документа требует модификации данных без изменения типовой конфигурации, наиболее правильным архитектурным решением является использование механизма расширений (доступен в платформе 8.3).

Разберем по шагам процесс реализации:

  1. Добавляем форму типового документа в расширение конфигурации.
  2. В расширении перехватываем обработчики событий или определяем собственную команду формы с помощью аннотаций &Вместо, &После или &Перед.
  3. Вызываем серверную логику непосредственно в контексте расширяемой формы, где доступны все реквизиты объекта (ЭтаФорма.Объект) без необходимости ручной упаковки данных в структуры.

&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    // Подключение дополнительной логики к форме
КонецПроцедуры

Почему изменения не отображаются на клиенте и как это исправить

Выясним причину, по которой после серверных вызовов данные на экране пользователя могут оставаться прежними:

  1. Работа с непривязанным экземпляром: если в коде команды выполнялось получение формы через ПолучитьФорму или ОткрытьФорму с некорректным ключом уникальности, изменения могли примениться к копии формы в памяти, а не к активному окну пользователя.
  2. Использование серверных методов без контекста: при вызове процедур &НаСервереБезКонтекста данные формы не передаются на сервер автоматически. Если в таком методе происходило считывание объекта из базы по ссылке, изменения оставались в базе данных, но не в открытой форме.
  3. Ошибочный вызов метода обновления: метод Форма.ОбновитьОтображениеДанных() обновляет только вычисляемые визуальные элементы, но не считывает несохраненные данные из памяти. Если данные были изменены на сервере в обход контекста формы, для их перечитывания из базы требуется вызов Прочитать() объекта.

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

← На главную