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