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