Полностью создаем свой вложенный отчет и данные расшифровки, настраиваем основное действие, читаем выражения реальных параметров и связываем runtime-группировки заголовков с фактически сформированными данными.
Где и как запускать
Полный серверный общий модуль УчебныеПараметрыРасшифровки85 нового собственного стенда интерфейса8.5; отдельный полный модуль формы ниже.
Подготовка
НОВАЯ пустая файловая база платформы8.5.1.1343: Имя=УчебныеПараметрыРасшифровки85, совместимость НеИспользовать, управляемое приложение, РежимСовместимостиИнтерфейса=Версия8_5. Без бизнес-метаданных, расширений и заданий. Не рабочая база. Здесь не запускалось: runtimeVerifiedScenarios=0.
Общий модуль УчебныеПараметрыРасшифровки85: Сервер=Да, Клиент=Нет, Вызов сервера=Нет, Глобальный=Нет, Привилегированный=Нет. Вставьте весь код одного урока, включая все вызываемые функции.
Обработка УчебныеПараметрыРасшифровки85 → управляемая форма Пульт → команда Выполнить с одноименным действием и кнопкой. Полный отдельный модуль формы ниже. F7 и обновление только своего нового стенда перед будущим отдельно разрешенным запуском.
Свой Local-запрос: Север/Книга/3/750, Север/Ручка/1/50, Юг/Книга/2/500. Группировки Магазин → Наименование вложенные, ресурсы Количество и Сумма. Источник имеет3строки,6единиц,1300; недостающей Юг/Ручка нет.
Один настоящий ДанныеРасшифровки передается компоновщику макета третьим аргументом. Для каждого опыта вывода полностью копируется согласованная ПАРА макет+данные расшифровки, затем копия данных передается процессору также третьим аргументом. Внешних наборов здесь нет.
Для нового readonly Группировка нужны runtime-параметры заголовков интерфейса8.5. Параметр скомпилированного описания области еще не гарантирует заполненную родительскую строку. Код читает ее у фактически полученных элементов потока и ищет соответствующие настоящие группировочные элементы данных.
Проверка чисел читает настоящий небольшой табличный документ, а отдельно поля расшифровки должны содержать Север/Юг и Книга/Ручка. Это не проверка внешнего клика: клиентский обработчик расшифровки и ОткрытьЗначение здесь не запускаются.
Редактор создает только временные дубли реальных Поле/Выражение в отдельном полном черновике. Дубли и очищенный каталог не исполняются; прежде повторного вывода восстанавливается весь макет. XML остается строками памяти, файлов и резервных копий нет.
Процедура ВыполнитьПример() Экспорт
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Привилегированный режим не нужен";
КонецЕсли;
Если Метаданные.РежимСовместимостиИнтерфейса <> РежимСовместимостиИнтерфейса.Версия8_5 Тогда
ВызватьИсключение "Для свойств заголовка требуется именно интерфейс Версия8_5";
КонецЕсли;
Схема = Новый СхемаКомпоновкиДанных;
Источник = Схема.ИсточникиДанных.Добавить();
Источник.Имя = "УчебныеПродажи";
Источник.ТипИсточникаДанных = "Local";
Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
Набор.Имя = "СвоиТриСтроки";
Набор.ИсточникДанных = Источник.Имя;
Набор.АвтоЗаполнениеДоступныхПолей = Истина;
Набор.Запрос = "ВЫБРАТЬ
| ""Север"" КАК Магазин,
| ""Книга"" КАК Наименование,
| 3 КАК Количество,
| 750 КАК Сумма
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ ""Север"", ""Ручка"", 1, 50
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ ""Юг"", ""Книга"", 2, 500";
Для Каждого ИмяРесурса Из СтрРазделить("Сумма,Количество", ",") Цикл
Ресурс = Схема.ПоляИтога.Добавить();
Ресурс.ПутьКДанным = ИмяРесурса;
Ресурс.Выражение = "Сумма(" + ИмяРесурса + ")";
КонецЦикла;
Настройки = Схема.НастройкиПоУмолчанию;
Для Каждого ИмяПоля Из СтрРазделить("Магазин,Сумма,Количество", ",") Цикл
Выбор = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
Выбор.Поле = Новый ПолеКомпоновкиДанных(ИмяПоля);
Выбор.Использование = Истина;
КонецЦикла;
ГруппировкаНастроек = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
ГруппировкаНастроек.Имя = "УчебныеМагазины";
ГруппировкаНастроек.Использование = Истина;
ПолеМагазина = ГруппировкаНастроек.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
ПолеМагазина.Поле = Новый ПолеКомпоновкиДанных("Магазин");
ПолеМагазина.ТипГруппировки = ТипГруппировкиКомпоновкиДанных.Элементы;
ПолеМагазина.Использование = Истина;
АвтоВыбор = ГруппировкаНастроек.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
АвтоВыбор.Использование = Истина;
ВыборТовара = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыборТовара.Поле = Новый ПолеКомпоновкиДанных("Наименование");
ВыборТовара.Использование = Истина;
Товары = ГруппировкаНастроек.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
Товары.Имя = "СвоиТоварыВМагазине";
Товары.Использование = Истина;
ПолеТовара = Товары.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
ПолеТовара.Поле = Новый ПолеКомпоновкиДанных("Наименование");
ПолеТовара.ТипГруппировки = ТипГруппировкиКомпоновкиДанных.Элементы;
ПолеТовара.Использование = Истина;
ВыборТоваров = Товары.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
ВыборТоваров.Использование = Истина;
КонтрольныйЗапрос = Новый Запрос;
КонтрольныйЗапрос.Текст = Набор.Запрос;
Источник = КонтрольныйЗапрос.Выполнить().Выгрузить();
Если Источник.Количество() <> 3 Или Источник.Итог("Количество") <> 6 Или Источник.Итог("Сумма") <> 1300 Тогда
ВызватьИсключение "Источник должен сохранить только свои три продажи";
КонецЕсли;
Расшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
Компоновщик = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = Компоновщик.Выполнить(Схема, Настройки, Расшифровки);
Параметр = ПолучитьСвойПараметрРасшифровки(Макет);
НастроитьСвоиДействияРасшифровки(Макет);
ПроверитьСвоиВыраженияРасшифровки(Параметр);
ПроверитьСвойПотокРасшифровки(Макет, Расшифровки);
КонецПроцедуры
Функция ПолучитьСвойПараметрРасшифровки(Макет)
Для Каждого Область Из Макет.Макеты Цикл
Для Каждого Параметр Из Область.Параметры Цикл
Если ТипЗнч(Параметр) = Тип("ПараметрОбластиРасшифровкаКомпоновкиДанных") Тогда
Если Параметр.ВыраженияПолей.Количество() > 0 Тогда
Возврат Параметр;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
ВызватьИсключение "В полном собственном макете не найден настоящий непустой параметр расшифровки";
КонецФункции
Процедура НастроитьСвоиДействияРасшифровки(Макет)
Найдено = 0;
Для Каждого Область Из Макет.Макеты Цикл
Для Каждого Параметр Из Область.Параметры Цикл
Если ТипЗнч(Параметр) = Тип("ПараметрОбластиРасшифровкаКомпоновкиДанных") Тогда
Параметр.ОсновноеДействие = ДействиеОбработкиРасшифровкиКомпоновкиДанных.Расшифровать;
Если Параметр.ОсновноеДействие <> ДействиеОбработкиРасшифровкиКомпоновкиДанных.Расшифровать Тогда
ВызватьИсключение "Не задано основное действие своего параметра";
КонецЕсли;
Найдено = Найдено + 1;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Если Найдено = 0 Тогда
ВызватьИсключение "Нет действительных параметров для настройки действия";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвоиВыраженияРасшифровки(Параметр)
Каталог = Параметр.ВыраженияПолей;
Если Каталог.Количество() = 0 Тогда
ВызватьИсключение "В выбранном собственном параметре нужны реальные выражения";
КонецЕсли;
Для Номер = 0 По Каталог.Количество() - 1 Цикл
Элемент = Каталог.Получить(Номер);
Если ТипЗнч(Элемент) <> Тип("ВыражениеПоляПараметраОбластиРасшифровкаКомпоновкиДанных")
Или Каталог.Индекс(Элемент) <> Номер Тогда
ВызватьИсключение "Индекс должен соответствовать тому же настоящему выражению";
КонецЕсли;
Если ТипЗнч(Элемент.Поле) <> Тип("Строка") Или ТипЗнч(Элемент.Выражение) <> Тип("Строка")
Или Элемент.Поле = "" Или Элемент.Выражение = "" Тогда
ВызватьИсключение "Компоновщик должен создать имена и выражения своего поля";
КонецЕсли;
Найденный = Каталог.Найти(Элемент.Поле);
Если Найденный = Неопределено Или Найденный <> Элемент Тогда
ВызватьИсключение "Найти по действительному имени поля должно вернуть тот же элемент";
КонецЕсли;
Сообщить(Параметр.Имя + ": " + Элемент.Поле + " ← " + Элемент.Выражение);
КонецЦикла;
КонецПроцедуры
Функция СвойОбъектРасшифровкиВСтроку(Объект)
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(Запись, Объект);
Возврат Запись.Закрыть();
КонецФункции
Функция СвойОбъектРасшифровкиИзСтроки(СтрокаXML, ТребуемыйТип)
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаXML);
Попытка
Объект = СериализаторXDTO.ПрочитатьXML(Чтение, ТребуемыйТип);
Исключение
Чтение.Закрыть();
ВызватьИсключение;
КонецПопытки;
Чтение.Закрыть();
Если ТипЗнч(Объект) <> ТребуемыйТип Тогда
ВызватьИсключение "Нужен полный собственный типизированный объект, не кусок ссылок";
КонецЕсли;
Возврат Объект;
КонецФункции
Функция ПрочитатьСвоеЧисло(Ячейка)
Если Ячейка.СодержитЗначение Тогда
Значение = Ячейка.Значение;
Если ТипЗнч(Значение) = Тип("Число") Тогда
Возврат Значение;
КонецЕсли;
Возврат Неопределено;
КонецЕсли;
Текст = СтрЗаменить(СтрЗаменить(СокрЛП(Ячейка.Текст), Символ(160), ""), " ", "");
Если Текст = "" Тогда
Возврат Неопределено;
КонецЕсли;
ЕстьЦифра = Ложь;
Для Позиция = 1 По СтрДлина(Текст) Цикл
Знак = Сред(Текст, Позиция, 1);
Если СтрНайти("0123456789", Знак) > 0 Тогда
ЕстьЦифра = Истина;
ИначеЕсли СтрНайти(",.-", Знак) = 0 Тогда
Возврат Неопределено;
КонецЕсли;
КонецЦикла;
Если Не ЕстьЦифра Тогда
Возврат Неопределено;
КонецЕсли;
Возврат Число(Текст);
КонецФункции
Процедура ПроверитьСвоиЧислаОтчета(Документ)
Если ТипЗнч(Документ) <> Тип("ТабличныйДокумент") Или Документ.ВысотаТаблицы < 1
Или Документ.ШиринаТаблицы < 1 Или Документ.ВысотаТаблицы > 200 Или Документ.ШиринаТаблицы > 100 Тогда
ВызватьИсключение "Нужен небольшой настоящий документ своей задачи";
КонецЕсли;
КнигаСевер = Ложь;
РучкаСевер = Ложь;
КнигаЮг = Ложь;
ОбщийИтог = Ложь;
Для НомерСтроки = 1 По Документ.ВысотаТаблицы Цикл
Для НомерКолонки = 1 По Документ.ШиринаТаблицы Цикл
ЧислоЯчейки = ПрочитатьСвоеЧисло(Документ.Область(НомерСтроки, НомерКолонки));
Если ЧислоЯчейки = 750 Тогда
КнигаСевер = Истина;
ИначеЕсли ЧислоЯчейки = 50 Тогда
РучкаСевер = Истина;
ИначеЕсли ЧислоЯчейки = 500 Тогда
КнигаЮг = Истина;
ИначеЕсли ЧислоЯчейки = 1300 Тогда
ОбщийИтог = Истина;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Если Не КнигаСевер Или Не РучкаСевер Или Не КнигаЮг Или Не ОбщийИтог Тогда
ВызватьИсключение "В настоящем вложенном отчете потеряны свои суммы 750/50/500/1300";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвойПотокРасшифровки(Макет, Расшифровки)
МакетКопии = СвойОбъектРасшифровкиИзСтроки(СвойОбъектРасшифровкиВСтроку(Макет), Тип("МакетКомпоновкиДанных"));
ДанныеКопии = СвойОбъектРасшифровкиИзСтроки(СвойОбъектРасшифровкиВСтроку(Расшифровки), Тип("ДанныеРасшифровкиКомпоновкиДанных"));
Процессор = Новый ПроцессорКомпоновкиДанных;
Процессор.Инициализировать(МакетКопии, , ДанныеКопии);
Документ = Новый ТабличныйДокумент;
Вывод = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
Вывод.УстановитьДокумент(Документ);
Вывод.ОтображатьПроцентВывода = Ложь;
ГруппировкиЗаголовков = Новый Соответствие;
ЗначенияИмен = 0;
Вывод.НачатьВывод();
Попытка
Пока Истина Цикл
Элемент = Процессор.Следующий();
Если Элемент = Неопределено Тогда
Прервать;
КонецЕсли;
Для Каждого Описание Из Элемент.Макеты Цикл
Для Каждого Параметр Из Описание.Параметры Цикл
Если ТипЗнч(Параметр) = Тип("ПараметрОбластиРасшифровкаКомпоновкиДанных") Тогда
Если Параметр.Группировка <> "" Тогда
ГруппировкиЗаголовков.Вставить(Параметр.Группировка, Истина);
КонецЕсли;
ЗначениеПараметра = Элемент.ЗначенияПараметров.Найти(Параметр.Имя);
Если ЗначениеПараметра <> Неопределено Тогда
Если ЗначениеПараметра.Имя <> Параметр.Имя Тогда
ВызватьИсключение "Смешались имена реальных параметров элемента";
КонецЕсли;
ЗначенияИмен = ЗначенияИмен + 1;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Вывод.ВывестиЭлемент(Элемент);
КонецЦикла;
Исключение
Вывод.ЗакончитьВывод();
ВызватьИсключение;
КонецПопытки;
Результат = Вывод.ЗакончитьВывод();
ПроверитьСвоиЧислаОтчета(Результат);
СвязанныеГруппировки = 0;
Север = Ложь;
Юг = Ложь;
Книга = Ложь;
Ручка = Ложь;
Для Каждого Часть Из ДанныеКопии.Элементы Цикл
Если ТипЗнч(Часть) = Тип("ЭлементРасшифровкиКомпоновкиДанныхГруппировка") Тогда
Если ГруппировкиЗаголовков.Получить(Часть.Группировка) <> Неопределено Тогда
СвязанныеГруппировки = СвязанныеГруппировки + 1;
КонецЕсли;
ИначеЕсли ТипЗнч(Часть) = Тип("ЭлементРасшифровкиКомпоновкиДанныхПоля") Тогда
Для Каждого ЗначениеПоля Из Часть.ПолучитьПоля() Цикл
Если ЗначениеПоля.Поле = "Магазин" Тогда
Север = Север Или ЗначениеПоля.Значение = "Север";
Юг = Юг Или ЗначениеПоля.Значение = "Юг";
ИначеЕсли ЗначениеПоля.Поле = "Наименование" Тогда
Книга = Книга Или ЗначениеПоля.Значение = "Книга";
Ручка = Ручка Или ЗначениеПоля.Значение = "Ручка";
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Если ГруппировкиЗаголовков.Количество() = 0 Или СвязанныеГруппировки = 0 Или ЗначенияИмен = 0
Или Не Север Или Не Юг Или Не Книга Или Не Ручка Тогда
ВызватьИсключение "Не получены настоящие связи заголовков интерфейса8.5 и поля своих магазинов/товаров";
КонецЕсли;
Сообщить("Поток, реальные поля и связанные группировки расшифровки проверены; суммы 750/50/500/1300 сохранены.");
КонецПроцедуры
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедурыУчебныеПараметрыРасшифровки85.Пульт
УчебныеПараметрыРасшифровки85 → Обработки → УчебныеПараметрыРасшифровки85 → Формы → Пульт → Модуль
Полный модуль собственной управляемой формы; здесь не выполнялся.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныеПараметрыРасшифровки85.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
Схема/настройки/оба уровня группировок создаются внутри. Родительский ID не сочиняется и не записывается в readonly Группировка.
Параметры находятся в ОписаниеМакетаОбласти.Параметры, не в самом МакетОбласти. Проверяем точный тип параметра до чтения его специализированных свойств.
ОсновноеДействие=Расшифровать задается своим настоящим описаниям, а Имя используется для поиска значения в полученном элементе результата.
Количество/Получить/Индекс и Найти по реальному Поле должны согласоваться на том же объекте выражения. Выражение — строка языка выражений СКД, а не автоматически исполняемый текст BSL.
НачатьВывод → цикл Следующий до Неопределено → ВывестиЭлемент для каждого настоящего элемента → ЗакончитьВывод. Нельзя исчерпать поток и затем снова вызвать массовый Вывести на нем.
Непустые Группировка runtime-параметров заголовков сохраняются в соответствие. После вывода должны существовать группировочные элементы с такими же фактическими идентификаторами и реальные поля магазинов/товаров.
Числа750/50/500/1300 ищутся в настоящих числовых ячейках только своего небольшого документа. Отдельно проверяется исходная арифметика3/6/1300; внешний вид и клик не подтверждены.
Как проверить результат
Источник3строки/6единиц/1300. Фактический документ содержит числовые750/50/500/1300; данные расшифровки содержат Север/Юг и Книга/Ручка.
Непустые runtime-ID Группировка найдены среди реально созданных группировочных элементов. Имя параметра разрешается в настоящих значениях элементов потока, а не в выдуманном словаре.
Каждый Get/Index/Find возвращает то же настоящее выражение выбранного параметра; редакторские дубли в этом уроке не создаются.
Ожидаемый результат
Описания и фактический поток собственной расшифровки связаны по настоящим полям/именам/группировкам; вывод проверен по своим числам. Здесь не запускалось в 1С.
На что обратить внимание
Параметр расшифровки, его выражение, значение параметра результата и элемент данных расшифровки — разные типы. Для них нельзя копировать случайные свойства/конструкторы.
Группировка readonly и предназначена для runtime-заголовков интерфейса8.5. Пустое значение в статическом описании не заменяется угаданным ID; отсутствие реальных связей завершает свой опыт диагностикой.
ОсновноеДействие готовит описание, но не запускает внешний клиентский обработчик. Этот код не обещает автоматическую работу клика без отдельной интеграции формы.
Числовая проверка относится только к своей простой вложенной задаче и не универсальна для чужих отчетов/форматов. Расшифровки проверяются отдельно от табличных ячеек.
Полная пара макет+расшифровки копируется типизированно из своей памяти; идентификаторы расшифровки не конструируются вручную. Дубли/очищенный каталог не исполняются.
1С, UI, сеть, production, печать и файлы здесь не запускались. Сверка со справкой и статические тесты не равны реальному тесту пользовательского опыта.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.