В процессе разработки на платформе 1С:Предприятие 8.3 (Управляемые формы) часто возникает необходимость вынести логику обработки данных в общий модуль. Одной из типичных задач является обход и редактирование колонок табличной части (ТЧ) при изменении какого-либо реквизита. Однако начинающие разработчики часто сталкиваются с ошибками типа «Нельзя изменять поле, содержащее объект данных формы» или «Отсутствует отображение для типа 'УправляемаяФорма'». Рассмотрим подробно, почему возникают эти ошибки и как правильно организовать взаимодействие между формой и общим модулем.
Разберем ситуацию: вы находитесь в процедуре &НаКлиенте и пытаетесь вызвать процедуру общего модуля, передав туда Объект или ЭтаФорма. Проблема заключается в механизме сериализации. На клиенте Объект представлен в упрощенном виде, а тип УправляемаяФорма вообще не может быть передан с клиента на сервер напрямую через параметры вызова серверного общего модуля. Протокол обмена данными между тонким клиентом и сервером накладывает строгие ограничения на типы передаваемых данных.
Проанализируем типичную ошибку. Если ваш общий модуль имеет флаг «Вызов сервера» и вы вызываете его так:
&НаКлиенте
Процедура ПриИзмененииРеквизита(Элемент)
// Ошибка! Напрямую с клиента передавать данные формы в общий модуль нельзя
ОбщийМодульСервер.ПоредактироватьТЧ(Объект);
КонецПроцедуры
Система выдаст исключение, так как контекст формы не может быть корректно упакован для передачи во «внешний» по отношению к форме серверный вызов. Чтобы решить эту задачу, нам необходимо использовать правильную цепочку вызовов.
Самый стабильный и производительный способ — это вызов процедуры общего модуля через «прослойку» в виде серверной процедуры самой формы. Выясним, как это работает по шагам:
&НаКлиенте вызывается процедура &НаСервере, расположенная в этом же модуле формы.Объект уже доступен как тип ДанныеФормыСтруктура.Объект в общий модуль. Поскольку вызов происходит «внутри» сервера, 1С позволяет передать ссылку на данные формы.Рассмотрим пример правильной реализации:
&НаКлиенте
Процедура ПриИзмененииРеквизита(Элемент)
// Переходим на сервер формы
ПриИзмененииРеквизитаНаСервере();
КонецПроцедуры
&НаСервере
Процедура ПриИзмененииРеквизитаНаСервере()
// Теперь передаем Объект в общий модуль. На сервере это допустимо.
ОбщийМодульСервер.ПоредактироватьТЧ(Объект);
КонецПроцедуры
В самом общем модуле процедура будет выглядеть следующим образом:
Процедура ПоредактироватьТЧ(ДанныеФормы) Экспорт
// ДанныеФормы здесь имеют тип ДанныеФормыСтруктура
Для Каждого СтрокаТЧ Из ДанныеФормы.Товары Цикл
СтрокаТЧ.Цена = 100; // Пример изменения данных в ТЧ
КонецЦикла;
КонецПроцедуры
Обратите внимание, что нам не потребовалось выполнять ресурсоемкие операции РеквизитФормыВЗначение и обратно. Мы работаем напрямую с данными формы, что экономит память и процессорное время.
Посмотрим на ситуацию глубже. Иногда требуется не просто изменить значения в строках, а выполнить сложные действия, доступные только для прикладных объектов (например, вызвать метод Заполнить() или РассчитатьНДС(), описанный в модуле объекта документа). В этом случае схема меняется:
РеквизитФормыВЗначение("Объект"), чтобы получить полноценный программный объект (например, ДокументОбъект.РеализацияТоваровУслуг).ЗначениеВРеквизитФормы(ДокОбъект, "Объект"), чтобы вернуть изменения на форму.Важный нюанс: Если ваша задача — только модификация колонок в ТЧ, как в примере автора темы, то передача Объект.ИмяВашейТЧ (тип ДанныеФормыКоллекция) будет работать намного быстрее. Выясним причину: создание ДокументОбъект — это «тяжелая» операция, загружающая все обработчики модуля объекта, тогда как работа с ДанныеФормыКоллекция — это прямая манипуляция буфером данных формы.
Часто в дополнение к редактированию ТЧ программисты хотят настроить визуальное отображение, например, сделать колонку со ссылками только для чтения, но при этом разрешить переход по гиперссылке. Если вы установили ТолькоПросмотр = Истина и ГиперссылкаЯчейки = Истина, но ссылка не открывается, проанализируем возможные причины:
СправочникСсылка), а не строка или число. Платформа умеет автоматически открывать только ссылочные типы.Отображение = ПолеВвода, убедитесь, что включена КнопкаОткрытия.ТолькоПросмотр для всей колонки иногда блокирует стандартную обработку расшифровки. Если гиперссылка не срабатывает, рекомендуем использовать клиентское событие таблицы Выбор.Рассмотрим пример программного открытия значения, если стандартный механизм блокируется:
&НаКлиенте
Процедура ТЧВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
Если Поле.Имя = "ТЧКолонкаСоСсылками1" Тогда
СтандартнаяОбработка = Ложь; // Отключаем штатное поведение
ЗначениеЯчейки = Элементы.ТЧ.ТекущиеДанные[Поле.Имя];
Если ЗначениеЗаполнено(ЗначениеЯчейки) Тогда
ПоказатьЗначение(, ЗначениеЯчейки);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Для эффективной работы с общими модулями в управляемых формах придерживайтесь следующих правил:
Объект.ИмяТЧ, а не весь Объект. Это снизит объем данных, передаваемых между вызовами.ДанныеФормыСтруктура или ДанныеФормыКоллекция. Они ведут себя почти как обычные структуры и таблицы, но имеют свои ограничения (например, их нельзя копировать простым присваиванием).Выбор и метод ПоказатьЗначение().Следуя этим рекомендациям, вы сможете создавать быстрые и отказоустойчивые интерфейсы, сохраняя при этом чистоту кода и вынося бизнес-логику в специализированные общие модули.