Как исправить ошибку создания источника доступных настроек компоновки данных в тонком клиенте 1С?

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

При работе с системой компоновки данных (СКД) в управляемых формах 1С:Предприятия, особенно в тонком клиенте, мы можем столкнуться с ошибкой: "ошибка создания источника доступных настроек компоновки данных". Эта проблема чаще всего проявляется при попытке инициализировать объект КомпоновщикНастроекКомпоновкиДанных схемой компоновки, которая была предварительно помещена во временное хранилище. Давайте подробно разберем, почему возникает эта ошибка и как ее эффективно устранить, а также рассмотрим связанные нюансы и лучшие практики.

Анализ проблемы и контекст возникновения ошибки

Наш сценарий, как правило, выглядит следующим образом: мы разрабатываем произвольную форму, которая содержит реквизит типа КомпоновщикНастроекКомпоновкиДанных. Цель — дать пользователю возможность настраивать отборы и параметры данных для последующего заполнения табличной части документа (удобно через система программной настройки поведения форм через СКД) или формирования отчета. Схема компоновки данных обычно берется из макета документа или отчета и помещается во временное хранилище, чтобы быть доступной в серверных вызовах и для инициализации компоновщика настроек на клиенте.

Типичный код инициализации в обработчике ПриСозданииНаСервере выглядит так:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    МакетСКД = Документы.УстановкаКоэффициентовРасходаМатериалов.ПолучитьМакет("МакетСКД");
    АдресМакета = ПоместитьВоВременноеХранилище(МакетСКД); // Здесь потенциальная проблема
    НастройкиЗаполнения.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресМакета));
    НастройкиЗаполнения.ЗагрузитьНастройки(МакетСКД.НастройкиПоУмолчанию);
    СсылкаНаДокумент = Параметры.СсылкаНаДокумент;
КонецПроцедуры

А затем, при выполнении каких-либо действий (например, по кнопке "Принять отбор") на сервере мы пытаемся получить схему и выполнить компоновку:


&НаСервере
Процедура ПринятьОтборНаСервере()
    МакетСКД = ПолучитьИзВременногоХранилища(АдресМакета);
    Настройки = НастройкиЗаполнения.Настройки;
    // ... дальнейшая работа с компоновщиком и процессором ...
КонецПроцедуры

В толстом клиенте такой подход часто работает без сбоев. Однако в тонком клиенте при возврате с сервера после успешного выполнения серверной процедуры, или даже при попытке инициализации ИсточникаДоступныхНастроекКомпоновкиДанных, мы видим ошибку. Отладка показывает, что серверная процедура может отрабатывать корректно, а сбой происходит именно в момент возврата управления на клиент — для диагностики подобных случаев поможет инструмент для пошаговой отладки кода 1С в режиме предприятия.

Первоначальные догадки часто сводятся к проблемам с передачей данных между клиентом и сервером или некорректной работой с ТаблицейЗначений во временном хранилище. Однако, как выясняется, корень проблемы кроется глубже.

Основное решение: Использование УникальногоИдентификатора для временного хранилища

Ключевая причина возникновения ошибки заключается в том, что объект СхемаКомпоновкиДанных (полученный из макета) помещается во временное хранилище без явного указания УникальногоИдентификатора. В тонком клиенте механизм работы временного хранилища более строг, и без этого идентификатора система может некорректно управлять жизненным циклом объекта, удаляя его из хранилища до того, как он будет повторно использован или делая его недоступным в другом контексте.

Для устранения этой проблемы нам необходимо при помещении схемы компоновки данных во временное хранилище явно передать вторым параметром конструктор Новый УникальныйИдентификатор. Это гарантирует, что адрес во временном хранилище будет уникальным и объект будет корректно храниться и извлекаться.

Рассмотрим, как изменить наш код:

В процедуре ПриСозданииНаСервере мы должны скорректировать строку помещения макета во временное хранилище:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    МакетСКД = Документы.УстановкаКоэффициентовРасходаМатериалов.ПолучитьМакет("МакетСКД");
    // Изменяем эту строку: добавляем Новый УникальныйИдентификатор
    АдресМакета = ПоместитьВоВременноеХранилище(МакетСКД, Новый УникальныйИдентификатор);
    
    НастройкиЗаполнения.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресМакета));
    НастройкиЗаполнения.ЗагрузитьНастройки(МакетСКД.НастройкиПоУмолчанию);
    СсылкаНаДокумент = Параметры.СсылкаНаДокумент;
КонецПроцедуры

Это простое, но критически важное изменение позволяет платформе правильно управлять объектом МакетСКД во временном хранилище, предотвращая его преждевременное удаление или некорректную адресацию. После внесения этого изменения проблема, как правило, исчезает, и наш КомпоновщикНастроекКомпоновкиДанных начинает работать корректно.

Как показывают сообщения форума, именно это изменение оказалось эффективным: "Помогло)!!!!!!!!!!!!!!!!!!!!!!!!!" и "Резюме: УникальныйИдентификатор надо было указать при сохранении макета СКД во временное хранилище."

Рекомендации разработчиков платформы

Разработчики 1С также подтверждают эту практику. В документации и примерах часто встречается рекомендация использовать УникальныйИдентификатор при помещении схемы СКД во временное хранилище для последующей инициализации ИсточникаДоступныхНастроекКомпоновкиДанных в управляемых формах.

Пример официальной рекомендации:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    СКД = РеквизитФормыВЗначение("Объект").ПолучитьМакет("Макет");
    // Передаем УникальныйИдентификатор для стабильной работы
    АдресВоВременномХранилище = ПоместитьВоВременноеХранилище(СКД, Новый УникальныйИдентификатор);
    ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресВоВременномХранилище);
    КомпоновщикНастроек.Инициализировать(ИсточникНастроек);
    КомпоновщикНастроек.ЗагрузитьНастройки(СКД.НастройкиПоУмолчанию);
КонецПроцедуры

Альтернативные подходы и оптимизации

Хотя использование УникальногоИдентификатора решает проблему, иногда мы можем рассмотреть и другие подходы, чтобы упростить код или избежать потенциальных проблем с временным хранилищем.

Получение макета СКД напрямую

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

Например, в процедуре ПринятьОтборНаСервере мы могли бы сделать так:


&НаСервере
Процедура ПринятьОтборНаСервере()
    // Получаем макет СКД непосредственно в этой процедуре
    МакетСКД = Документы.УстановкаКоэффициентовРасходаМатериалов.ПолучитьМакет("МакетСКД");
    Настройки = НастройкиЗаполнения.Настройки;
    Настройки.ПараметрыДанных.Элементы[1].Значение = СсылкаНаДокумент;
    Настройки.ПараметрыДанных.Элементы[0].Значение = СсылкаНаДокумент.Дата;
    КомпоновщикМакетаКомпоновкиДанных = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновкиДанных = КомпоновщикМакетаКомпоновкиДанных.Выполнить(МакетСКД, Настройки,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    // ... дальнейшая работа ...
КонецПроцедуры

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

Связанные проблемы с внешними отчетами и обработками

Иногда подобные ошибки могут возникать в специфических условиях, связанных с внешними отчетами и обработками, особенно когда мы отлаживаем их через "Файл - Открыть" вне стандартного механизма БСП "Дополнительные отчеты и обработки". В таких случаях платформа может некорректно определять контекст отчета, что приводит к проблемам с инициализацией СКД.

Для решения этой проблемы мы можем явно указать, что отчет является внешним, используя обработчики событий формы.

Рассмотрим примеры кода для внешних отчетов:

В модуле отчета мы добавляем процедуры:


Процедура ОпределитьНастройкиФормы(Форма, КлючВарианта, НастройкиОтчета) Экспорт
    НастройкиОтчета.События.ПриСозданииНаСервере = Истина;
КонецПроцедуры

Процедура ПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
    // Определяем, что отчет запущен через Файл-Открыть
    Если Прав(ЭтотОбъект.ИспользуемоеИмяФайла,3) = "erf" Тогда
        Форма.НастройкиОтчета.Внешний = Истина;
    КонецЕсли;
КонецПроцедуры

Процедура ОпределитьНастройкиФормы позволяет нам указать, что у формы отчета есть обработчик ПриСозданииНаСервере. А уже в ПриСозданииНаСервере мы проверяем, является ли текущий файл внешним отчетом (например, по расширению "erf") и, если да, устанавливаем свойство Форма.НастройкиОтчета.Внешний = Истина;. Это помогает платформе правильно интерпретировать контекст выполнения отчета.

Проблемы с функцией СведенияОВнешнейОбработке

Еще одной причиной ошибок, связанных с внешними обработками, может быть некорректная реализация или неполное заполнение функции СведенияОВнешнейОбработке. Эта функция является ключевой для определения свойств и взаимодействия внешней обработки с системой 1С:Предприятия. Если в ней допущены ошибки или отсутствуют необходимые данные, это может привести к сбоям при работе с СКД и другими механизмами платформы. Мы всегда должны убедиться, что функция СведенияОВнешнейОбработке в нашей внешней обработке реализована корректно и возвращает все необходимые метаданные.

Заключение

Ошибка "создания источника доступных настроек компоновки данных" в тонком клиенте 1С:Предприятия является распространенной проблемой, которая чаще всего решается путем правильного использования УникальногоИдентификатора при помещении объекта СхемаКомпоновкиДанных во временное хранилище. Мы рассмотрели основной подход, а также альтернативные методы получения макета СКД и решения сопутствующих проблем, которые могут возникать с внешними отчетами. Следуя этим рекомендациям, мы сможем обеспечить стабильную и корректную работу наших разработок с СКД в управляемых формах.

← На главную