В процессе разработки на управляемых формах 1С программисты часто сталкиваются с загадочной ошибкой при вызове серверных процедур или функций: «Ошибка преобразования данных XDTO: Запись значения свойства 'cr'... Ошибка отображения типов: Отсутствует отображение для типа 'ДанныеФормыЭлементКоллекции'». Эта проблема особенно коварна тем, что отладчик часто даже не заходит внутрь серверного метода, прерываясь на самом моменте перехода с клиента на сервер. Давайте подробно разберем, почему это происходит и как привести форму в рабочее состояние.
Для начала проанализируем механизм работы управляемого приложения. Когда мы вызываем процедуру с директивой &НаСервере, платформа выполняет так называемую сериализацию контекста. Это означает, что 1С пытается упаковать все данные формы (реквизиты, списки выбора, параметры) в специальный XML-пакет для передачи на сервер. После выполнения серверного кода происходит обратный процесс.
Объект типа ДанныеФормыЭлементКоллекции — это временный тип, представляющий собой строку таблицы или дерева непосредственно в интерфейсе. Этот тип «живет» только на клиенте и в контексте формы. Платформа 1С не умеет сериализовать (превращать в строку данных) этот тип для передачи через XDTO-пакет. Если в каком-либо реквизите формы (даже в том, который вы не передаете в функцию напрямую!) оказывается значение этого типа, вся попытка обращения к серверу завершается аварийно.
Рассмотрим ситуацию: автор темы использует функцию ПолучитьЕдиныйНалог(Объект.Дата, Объект.Организация). При контекстном вызове &НаСервере на сервер передается весь Объект и все прочие реквизиты формы. Если же мы перепишем директиву на &НаСервереБезКонтекста, платформа передаст только те параметры, которые явно указаны в скобках. Это самый быстрый и правильный способ решить проблему, если функции не требуются данные всей формы.
Проанализируем пример кода:
&НаКлиенте
Процедура УстановитьВидимость()
// Передаем только конкретные значения, а не всю форму
ЕдиныйНалог = ПолучитьЕдиныйНалог(Объект.Дата, Объект.Организация);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьЕдиныйНалог(Знач Дата, Знач Организация)
Структура = Новый Структура;
Структура.Вставить("Организация", Организация);
// Используем метод ПолучитьПоследнее вместо СрезПоследних для оптимизации
Данные = РегистрыСведений.УчетнаяПолитикаОрганизаций.ПолучитьПоследнее(Дата, Структура);
Возврат Данные.СхемаНалогообложения.ЕдиныйНалог;
КонецФункции
Если использование &НаСервереБезКонтекста невозможно (например, вам нужно модифицировать Объект напрямую), придется выяснить, какой именно реквизит формы содержит недопустимый тип ДанныеФормыЭлементКоллекции. Рассмотрим основные места, где он может прятаться:
Элементы.Таблица.ТекущиеДанные), форма перестанет передаваться на сервер. Проверьте обработчики ПриИзменении или НачалоВыбора.Ссылку или ИндексСтроки, но не саму строку.ОткрытьФорму в структуру параметров могли передать данные строки другой формы.Проанализируем пример исправления работы со списком выбора:
&НаКлиенте
Процедура ТаблицаПриИзменении(Элемент)
ТекущаяСтрока = Элементы.Таблица.ТекущиеДанные;
// ОШИБКА: Записываем элемент коллекции в список выбора другого поля
// Элементы.ПолеВыбора.СписокВыбора.Добавить(ТекущаяСтрока);
// ПРАВИЛЬНО: Записываем только значимое данное (ссылку или строку)
Элементы.ПолеВыбора.СписокВыбора.Добавить(ТекущаяСтрока.СсылкаНаОбъект);
КонецПроцедуры
Как было замечено в обсуждении, работа через цикл Для каждого строка из УП Цикл для получения одного значения из среза последних является избыточной. Если нам нужно одно конкретное значение, эффективнее использовать метод ПолучитьПоследнее, который возвращает структуру с ресурсами, а не таблицу значений.
Рассмотрим правильный подход к получению данных из регистра:
&НаСервере
Функция ПолучитьЗначениеНалога(Дата, Организация)
Отбор = Новый Структура("Организация", Организация);
Ресурс = РегистрыСведений.УчетнаяПолитикаОрганизаций.ПолучитьПоследнее(Дата, Отбор);
// Проверяем, не пустое ли значение вернул регистр
Если Ресурс.СхемаНалогообложения.Пустая() Тогда
Возврат Ложь;
КонецЕсли;
Возврат Ресурс.СхемаНалогообложения.ЕдиныйНалог;
КонецФункции
В некоторых случаях ошибка возникает из-за незавершенных процессов в интерфейсе (например, когда фокус еще находится на строке, которая в этот момент меняется). Если стандартные методы не помогают, можно попробовать «разнести» выполнение кода во времени, используя ПодключитьОбработчикОжидания.
Выясним, как это работает: вы вызываете клиентскую процедуру, которая не сразу идет на сервер, а дает форме «продышаться» 0.1 секунды, после чего вызывается серверный метод. Это часто помогает обойти внутренние конфликты блокировок типов в платформе.
Если ваша форма огромна (например, форма документа в УПП или ERP) и найти виновника вручную сложно, проанализируем следующий алгоритм действий:
ДанныеФормыЭлементКоллекции.Важный совет: Если вы столкнулись с ошибкой в типовой конфигурации после собственных доработок, первым делом проверьте те реквизиты, которые были добавлены вами или изменены в расширении. Типовой функционал 1С редко содержит такие ошибки «из коробки», обычно это результат записи интерфейсных объектов в переменные контекста формы.