Как правильно передать объект управляемой формы в общий модуль для редактирования табличной части

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

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

Почему нельзя передать «ЭтотОбъект» напрямую с клиента

Разберем ситуацию: вы находитесь в процедуре &НаКлиенте и пытаетесь вызвать процедуру общего модуля, передав туда Объект или ЭтаФорма. Проблема заключается в механизме сериализации. На клиенте Объект представлен в упрощенном виде, а тип УправляемаяФорма вообще не может быть передан с клиента на сервер напрямую через параметры вызова серверного общего модуля. Протокол обмена данными между тонким клиентом и сервером накладывает строгие ограничения на типы передаваемых данных.

Проанализируем типичную ошибку. Если ваш общий модуль имеет флаг «Вызов сервера» и вы вызываете его так:


&НаКлиенте
Процедура ПриИзмененииРеквизита(Элемент)
    // Ошибка! Напрямую с клиента передавать данные формы в общий модуль нельзя
    ОбщийМодульСервер.ПоредактироватьТЧ(Объект); 
КонецПроцедуры

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

Решение: Использование промежуточной серверной процедуры в модуле формы

Самый стабильный и производительный способ — это вызов процедуры общего модуля через «прослойку» в виде серверной процедуры самой формы. Выясним, как это работает по шагам:

  1. В обработчике события &НаКлиенте вызывается процедура &НаСервере, расположенная в этом же модуле формы.
  2. Внутри серверной процедуры формы контекст Объект уже доступен как тип ДанныеФормыСтруктура.
  3. Мы передаем этот Объект в общий модуль. Поскольку вызов происходит «внутри» сервера, 1С позволяет передать ссылку на данные формы.

Рассмотрим пример правильной реализации:


&НаКлиенте
Процедура ПриИзмененииРеквизита(Элемент)
    // Переходим на сервер формы
    ПриИзмененииРеквизитаНаСервере();
КонецПроцедуры

&НаСервере
Процедура ПриИзмененииРеквизитаНаСервере()
    // Теперь передаем Объект в общий модуль. На сервере это допустимо.
    ОбщийМодульСервер.ПоредактироватьТЧ(Объект);
КонецПроцедуры

В самом общем модуле процедура будет выглядеть следующим образом:


Процедура ПоредактироватьТЧ(ДанныеФормы) Экспорт
    // ДанныеФормы здесь имеют тип ДанныеФормыСтруктура
    Для Каждого СтрокаТЧ Из ДанныеФормы.Товары Цикл
        СтрокаТЧ.Цена = 100; // Пример изменения данных в ТЧ
    КонецЦикла;
КонецПроцедуры

Обратите внимание, что нам не потребовалось выполнять ресурсоемкие операции РеквизитФормыВЗначение и обратно. Мы работаем напрямую с данными формы, что экономит память и процессорное время.

Работа с ДанныеФормыКоллекция vs ТаблицаЗначений

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

  1. Используем РеквизитФормыВЗначение("Объект"), чтобы получить полноценный программный объект (например, ДокументОбъект.РеализацияТоваровУслуг).
  2. Выполняем необходимые действия с объектом в общем модуле.
  3. Используем ЗначениеВРеквизитФормы(ДокОбъект, "Объект"), чтобы вернуть изменения на форму.

Важный нюанс: Если ваша задача — только модификация колонок в ТЧ, как в примере автора темы, то передача Объект.ИмяВашейТЧ (тип ДанныеФормыКоллекция) будет работать намного быстрее. Выясним причину: создание ДокументОбъект — это «тяжелая» операция, загружающая все обработчики модуля объекта, тогда как работа с ДанныеФормыКоллекция — это прямая манипуляция буфером данных формы.

Исправление проблемы с гиперссылками в табличной части

Часто в дополнение к редактированию ТЧ программисты хотят настроить визуальное отображение, например, сделать колонку со ссылками только для чтения, но при этом разрешить переход по гиперссылке. Если вы установили ТолькоПросмотр = Истина и ГиперссылкаЯчейки = Истина, но ссылка не открывается, проанализируем возможные причины:

Рассмотрим пример программного открытия значения, если стандартный механизм блокируется:


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

Подведем итоги

Для эффективной работы с общими модулями в управляемых формах придерживайтесь следующих правил:

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

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

← На главную