Создаём собственный ресурс Количество с формулой Сумма(Количество), действительную таблицу обычных настроек с именованными строками по складу и колонками по коду. Итоговые описания ссылаются на обе реальные группы и существующие области. Переставляем, меняем второй enum, удаляем и восстанавливаем каталог; контролируем всю основу и независимую копию без выполнения отчёта.
Где и как запускать
Полный серверный общий модуль УчебныеЗадачи новой пустой конфигурации УчебныеМакетыИтогов85; в1С не запускался.
Подготовка
Нужна НОВАЯ отдельная учебная база, не копия рабочей: точно8.5.1.1343, имя конфигурации УчебныеМакетыИтогов85, совместимость Не использовать. Нет бизнес-объектов, расширений, подписок и фоновых заданий; модули вручную пустые, кроме данного общего модуля.
Общий модуль УчебныеЗадачи: Сервер=Да, Вызов сервера=Да, Клиент=Нет, Глобальный=Нет, Привилегированный=Нет. Вставьте весь основной модуль. Своя внешняя обработка УчебныеМакетыИтогов85 → управляемая Форма: команда/кнопка Выполнить с действием Выполнить; реквизиты не нужны. Полный отдельный модуль формы дан ниже.
Будущая ручная подготовка только вне опыта: завершить прежний собственный сеанс, сохранить конфигурацию, Конфигурация → Обновить конфигурацию базы данных (F7), затем свежий собственный клиент и своя обработка. Здесь F7, BSL, отчёты, запросы и печать не запускались.
Собственная основа содержит один Local-источник, один набор с буквальным запросом A01/3/Учебный, вручную объявленные КодТовара Строка/Количество Число/Склад Строка и четыре именованные области. Значения написаны в объявлении и постоянных надписях, не получены из рабочей базы.
Количество в буквальном запросе равно3. Его собственное описание — Число(1,0), неотрицательное: один общий разряд, ноль дробных, допустимые целые0–9. Это предел учебного исходного поля, не диапазон количества рабочего отчёта и не описание типа агрегата Сумма(Количество).
Процедура ВыполнитьПример() Экспорт
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Привилегированный режим не нужен";
КонецЕсли;
Пусто = Новый Массив;
ДваТипа = Новый Массив;
ДваТипа.Добавить(ТипМакетаОбластиКомпоновкиДанных.Заголовок);
ДваТипа.Добавить(ТипМакетаОбластиКомпоновкиДанных.Подвал);
ОдинЗаголовок = Новый Массив;
ОдинЗаголовок.Добавить(ДваТипа[0]);
ОдинПодвал = Новый Массив;
ОдинПодвал.Добавить(ДваТипа[1]);
Схема = СоздатьСвоюОсновуИтогов();
Каталог = Схема.МакетыПолейИтога;
ПроверитьСвоиИтоговыеМакеты(Схема, Пусто, Пусто, Пусто);
Первый = Каталог.Добавить();
ЗаполнитьСвойИтоговыйМакет(Схема, Первый, "Количество", ДваТипа[0], ДваТипа[0]);
ПроверитьСвоиИтоговыеМакеты(Схема, СтрРазделить("Количество", ","), ОдинЗаголовок, ОдинЗаголовок);
Второй = Каталог.Вставить(0);
ЗаполнитьСвойИтоговыйМакет(Схема, Второй, "КоличествоВыделено85", ДваТипа[1], ДваТипа[1]);
ОбратныеТипы = Новый Массив;
ОбратныеТипы.Добавить(ДваТипа[1]);
ОбратныеТипы.Добавить(ДваТипа[0]);
ПроверитьСвоиИтоговыеМакеты(Схема, СтрРазделить("КоличествоВыделено85,Количество", ","), ОбратныеТипы, ОбратныеТипы);
Каталог.Сдвинуть(Второй, 1);
Имена = СтрРазделить("Количество,КоличествоВыделено85", ",");
ПроверитьСвоиИтоговыеМакеты(Схема, Имена, ДваТипа, ДваТипа);
Первый.ТипМакета2 = ДваТипа[1];
ВременныеТипы2 = Новый Массив;
ВременныеТипы2.Добавить(ДваТипа[1]);
ВременныеТипы2.Добавить(ДваТипа[1]);
ПроверитьСвоиИтоговыеМакеты(Схема, Имена, ДваТипа, ВременныеТипы2);
Первый.ТипМакета2 = ДваТипа[0];
ПроверитьСвоиИтоговыеМакеты(Схема, Имена, ДваТипа, ДваТипа);
Копия = СоздатьСвоюОсновуИтогов();
ВосстановитьСвоиИтоговыеМакеты(Копия);
Каталог.Удалить(Первый);
ПроверитьСвоиИтоговыеМакеты(Схема, СтрРазделить("КоличествоВыделено85", ","), ОдинПодвал, ОдинПодвал);
ПроверитьСвоиИтоговыеМакеты(Копия, Имена, ДваТипа, ДваТипа);
НовыйПервый = Каталог.Вставить(0);
ЗаполнитьСвойИтоговыйМакет(Схема, НовыйПервый, "Количество", ДваТипа[0], ДваТипа[0]);
ПроверитьСвоиИтоговыеМакеты(Схема, Имена, ДваТипа, ДваТипа);
Каталог.Очистить();
ПроверитьСвоиИтоговыеМакеты(Схема, Пусто, Пусто, Пусто);
ПроверитьСвоиИтоговыеМакеты(Копия, Имена, ДваТипа, ДваТипа);
ВосстановитьСвоиИтоговыеМакеты(Схема);
ПроверитьСвоиИтоговыеМакеты(Схема, Имена, ДваТипа, ДваТипа);
ПроверитьСвоиИтоговыеМакеты(Копия, Имена, ДваТипа, ДваТипа);
Сообщить("Ресурс Сумма(Количество), строки по складу, колонки по коду и два итоговых описания восстановлены");
КонецПроцедуры
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Функция СоздатьУчебнуюОбласть(ТекстОбласти)
Область = Новый МакетОбластиКомпоновкиДанных;
СтрокаОбласти = Область.Добавить(Тип("СтрокаТаблицыОбластиКомпоновкиДанных"));
Ячейка = СтрокаОбласти.Ячейки.Добавить();
Поле = Ячейка.Элементы.Добавить(Тип("ПолеОбластиКомпоновкиДанных"));
Поле.Значение = ТекстОбласти;
Возврат Область;
КонецФункции
Процедура ЗаполнитьСвойИменованныйМакет(Описание, Имя, Текст)
Если ТипЗнч(Описание) <> Тип("ОписаниеМакетаСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужно настоящее описание макета именно собственной схемы";
КонецЕсли;
Описание.Имя = Имя;
Описание.Макет = СоздатьУчебнуюОбласть(Текст);
КонецПроцедуры
Процедура ПроверитьСвоюПолнуюОбласть(Описание, Текст)
Если ТипЗнч(Описание.Макет) <> Тип("МакетОбластиКомпоновкиДанных")
Или ТипЗнч(Описание.Параметры) <> Тип("ПараметрыОбластиКомпоновкиДанных") Тогда
ВызватьИсключение "Нужна собственная область СКД, не табличный документ или имя файла";
КонецЕсли;
Если Описание.Параметры.Количество() <> 0 Или Описание.Макет.Количество() <> 1 Тогда
ВызватьИсключение "Собственная постоянная область имеет одну строку и не имеет параметров";
КонецЕсли;
СтрокаОбласти = Описание.Макет.Получить(0);
Если ТипЗнч(СтрокаОбласти) <> Тип("СтрокаТаблицыОбластиКомпоновкиДанных")
Или ТипЗнч(СтрокаОбласти.Ячейки) <> Тип("ЯчейкиТаблицыОбластиКомпоновкиДанных") Тогда
ВызватьИсключение "Нужна реальная собственная строка с коллекцией ячеек";
КонецЕсли;
Если СтрокаОбласти.Ячейки.Количество() <> 1 Тогда
ВызватьИсключение "В собственной строке ровно одна ячейка";
КонецЕсли;
Ячейка = СтрокаОбласти.Ячейки.Получить(0);
Если ТипЗнч(Ячейка) <> Тип("ЯчейкаТаблицыОбластиКомпоновкиДанных")
Или ТипЗнч(Ячейка.Элементы) <> Тип("ЭлементыМакетаОбластиКомпоновкиДанных") Тогда
ВызватьИсключение "Нужна реальная ячейка с коллекцией элементов области";
КонецЕсли;
Если Ячейка.Элементы.Количество() <> 1 Тогда
ВызватьИсключение "В собственной ячейке ровно одно постоянное поле";
КонецЕсли;
Поле = Ячейка.Элементы.Получить(0);
Если ТипЗнч(Поле) <> Тип("ПолеОбластиКомпоновкиДанных")
Или ТипЗнч(Поле.Значение) <> Тип("Строка") Или Поле.Значение <> Текст Тогда
ВызватьИсключение "Не совпало полное текстовое содержимое собственной области";
КонецЕсли;
КонецПроцедуры
Функция СвойТипКоличестваМакета()
Возврат Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(1, 0, ДопустимыйЗнак.Неотрицательный));
КонецФункции
Процедура ПроверитьСвоюРазрядностьМакета(Описание)
Квалификаторы = Описание.КвалификаторыЧисла;
Если ТипЗнч(Квалификаторы) <> Тип("КвалификаторыЧисла") Или Квалификаторы.Разрядность <> 1
Или Квалификаторы.РазрядностьДробнойЧасти <> 0
Или Квалификаторы.ДопустимыйЗнак <> ДопустимыйЗнак.Неотрицательный Тогда
ВызватьИсключение "Своё количество макета имеет один разряд, ноль дробных и неотрицательный знак";
КонецЕсли;
КонецПроцедуры
Функция СоздатьСвоюОсновуМакетовПолей()
Схема = Новый СхемаКомпоновкиДанных;
Источник = Схема.ИсточникиДанных.Добавить();
Источник.Имя = "СвоиДанные85";
Источник.ТипИсточникаДанных = "Local";
Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
Если ТипЗнч(Набор) <> Тип("НаборДанныхЗапросСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужен собственный набор запроса";
КонецЕсли;
Набор.Имя = "УчебныеОстатки85";
Набор.ИсточникДанных = "СвоиДанные85";
Набор.АвтоЗаполнениеДоступныхПолей = Ложь;
Набор.Запрос = "ВЫБРАТЬ ""A01"" КАК КодТовара, 3 КАК Количество, ""Учебный"" КАК Склад";
Имена = СтрРазделить("КодТовара|Количество|Склад", "|");
Для Индекс = 0 По 2 Цикл
Поле = Набор.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
Если ТипЗнч(Поле) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужно простое собственное описание поля, не папка";
КонецЕсли;
Поле.Поле = Имена[Индекс];
Поле.ПутьКДанным = Имена[Индекс];
Если Индекс = 1 Тогда
Поле.ТипЗначения = СвойТипКоличестваМакета();
Иначе
Поле.ТипЗначения = Новый ОписаниеТипов("Строка");
КонецЕсли;
КонецЦикла;
ИменаМакетов = СтрРазделить("КодТовара|Количество|Склад|КоличествоВыделено85", "|");
Тексты = СтрРазделить("Код: A01|Количество: 3|Склад: Учебный|Количество: 3 (выделено)", "|");
Для Индекс = 0 По 3 Цикл
Описание = Схема.Макеты.Добавить();
ЗаполнитьСвойИменованныйМакет(Описание, ИменаМакетов[Индекс], Тексты[Индекс]);
КонецЦикла;
ПроверитьСвоюОсновуМакетовПолей(Схема);
Возврат Схема;
КонецФункции
Процедура ПроверитьСвоюОсновуМакетовПолей(Схема)
Если ТипЗнч(Схема) <> Тип("СхемаКомпоновкиДанных") Или Схема.ИсточникиДанных.Количество() <> 1
Или Схема.НаборыДанных.Количество() <> 1 Или Схема.Макеты.Количество() <> 4 Тогда
ВызватьИсключение "Нужны только собственные источник, набор и четыре согласованные области";
КонецЕсли;
Источник = Схема.ИсточникиДанных.Получить(0);
Если ТипЗнч(Источник) <> Тип("ИсточникДанныхСхемыКомпоновкиДанных")
Или Источник.Имя <> "СвоиДанные85" Или Источник.ТипИсточникаДанных <> "Local" Тогда
ВызватьИсключение "Не совпал собственный источник";
КонецЕсли;
Набор = Схема.НаборыДанных.Получить(0);
Если ТипЗнч(Набор) <> Тип("НаборДанныхЗапросСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужен собственный набор запроса";
КонецЕсли;
Если Набор.Имя <> "УчебныеОстатки85" Или Набор.ИсточникДанных <> "СвоиДанные85"
Или Набор.АвтоЗаполнениеДоступныхПолей Или Набор.Запрос <> "ВЫБРАТЬ ""A01"" КАК КодТовара, 3 КАК Количество, ""Учебный"" КАК Склад"
Или Набор.Поля.Количество() <> 3 Тогда
ВызватьИсключение "Не совпали полный собственный запрос и ручное описание полей";
КонецЕсли;
Имена = СтрРазделить("КодТовара|Количество|Склад", "|");
Типы = СтрРазделить("Строка,Число,Строка", ",");
Для Индекс = 0 По 2 Цикл
Поле = Набор.Поля.Получить(Индекс);
Если ТипЗнч(Поле) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных")
Или Поле.Поле <> Имена[Индекс] Или Поле.ПутьКДанным <> Имена[Индекс]
Или ТипЗнч(Поле.ТипЗначения) <> Тип("ОписаниеТипов") Тогда
ВызватьИсключение "Не совпали полный путь, имя и описание собственного поля";
КонецЕсли;
ПолныеТипы = Поле.ТипЗначения.Типы();
Если ПолныеТипы.Количество() <> 1 Или ПолныеТипы[0] <> Тип(Типы[Индекс]) Тогда
ВызватьИсключение "Не совпал полный набор типов собственного поля";
КонецЕсли;
Если Индекс = 1 Тогда
ПроверитьСвоюРазрядностьМакета(Поле.ТипЗначения);
КонецЕсли;
КонецЦикла;
ИменаМакетов = СтрРазделить("КодТовара|Количество|Склад|КоличествоВыделено85", "|");
Тексты = СтрРазделить("Код: A01|Количество: 3|Склад: Учебный|Количество: 3 (выделено)", "|");
Для Индекс = 0 По 3 Цикл
Описание = Схема.Макеты.Получить(Индекс);
Если ТипЗнч(Описание) <> Тип("ОписаниеМакетаСхемыКомпоновкиДанных")
Или Описание.Имя <> ИменаМакетов[Индекс] Или Схема.Макеты.Найти(ИменаМакетов[Индекс]) <> Описание Тогда
ВызватьИсключение "Не совпали имена и порядок существующих собственных макетов";
КонецЕсли;
ПроверитьСвоюПолнуюОбласть(Описание, Тексты[Индекс]);
КонецЦикла;
КонецПроцедуры
Функция СвоеПолеВXML(Поле)
Если ТипЗнч(Поле) <> Тип("ПолеКомпоновкиДанных") Тогда
ВызватьИсключение "Сериализуется только собственное поле СКД, не объект или записи базы";
КонецЕсли;
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
Попытка
СериализаторXDTO.ЗаписатьXML(Запись, Поле);
Возврат Запись.Закрыть();
Исключение
Запись.Закрыть();
ВызватьИсключение;
КонецПопытки;
КонецФункции
Процедура ЗаполнитьСвоюГруппуТаблицы(Группа, Имя, Путь)
Если ТипЗнч(Группа) <> Тип("ГруппировкаТаблицыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужна собственная группировка строки или колонки таблицы";
КонецЕсли;
Группа.Имя = Имя;
Группа.Использование = Истина;
Поле = Группа.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
Если ТипЗнч(Поле) <> Тип("ПолеГруппировкиКомпоновкиДанных") Тогда
ВызватьИсключение "Нужно собственное явно заданное поле группировки";
КонецЕсли;
Поле.Поле = Новый ПолеКомпоновкиДанных(Путь);
Поле.Использование = Истина;
Поле.ТипГруппировки = ТипГруппировкиКомпоновкиДанных.Элементы;
КонецПроцедуры
Процедура ПроверитьСвоюГруппуТаблицы(Группа, Имя, Путь)
Если ТипЗнч(Группа) <> Тип("ГруппировкаТаблицыКомпоновкиДанных")
Или Группа.Имя <> Имя Или Не Группа.Использование
Или ТипЗнч(Группа.ПоляГруппировки) <> Тип("ПоляГруппировкиКомпоновкиДанных") Тогда
ВызватьИсключение "Не совпало собственное имя и тип группы таблицы";
КонецЕсли;
Если Группа.ПоляГруппировки.Элементы.Количество() <> 1 Тогда
ВызватьИсключение "В своей группе таблицы ровно одно явно заданное поле";
КонецЕсли;
Поле = Группа.ПоляГруппировки.Элементы.Получить(0);
Если ТипЗнч(Поле) <> Тип("ПолеГруппировкиКомпоновкиДанных") Или Не Поле.Использование
Или Поле.ТипГруппировки <> ТипГруппировкиКомпоновкиДанных.Элементы Тогда
ВызватьИсключение "Не совпал тип собственного используемого поля";
КонецЕсли;
Если СвоеПолеВXML(Поле.Поле) <> СвоеПолеВXML(Новый ПолеКомпоновкиДанных(Путь)) Тогда
ВызватьИсключение "Не совпал полный собственный путь строки или колонки";
КонецЕсли;
КонецПроцедуры
Функция СоздатьСвоюОсновуИтогов()
Схема = СоздатьСвоюОсновуМакетовПолей();
Ресурс = Схема.ПоляИтога.Добавить();
Если ТипЗнч(Ресурс) <> Тип("ПолеИтогаСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужен настоящий собственный ресурс итога";
КонецЕсли;
Ресурс.ПутьКДанным = "Количество";
Ресурс.Выражение = "Сумма(Количество)";
Таблица = Схема.НастройкиПоУмолчанию.Структура.Добавить(Тип("ТаблицаКомпоновкиДанных"));
Если ТипЗнч(Таблица) <> Тип("ТаблицаКомпоновкиДанных") Тогда
ВызватьИсключение "Нужна настоящая собственная таблица обычных настроек";
КонецЕсли;
Таблица.Использование = Истина;
Строки = Таблица.Строки.Добавить();
ЗаполнитьСвоюГруппуТаблицы(Строки, "СтрокиПоСкладу85", "Склад");
Колонки = Таблица.Колонки.Добавить();
ЗаполнитьСвоюГруппуТаблицы(Колонки, "КолонкиПоКоду85", "КодТовара");
Выбор = Таблица.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
Если ТипЗнч(Выбор) <> Тип("ВыбранноеПолеКомпоновкиДанных") Тогда
ВызватьИсключение "Нужно явно выбранное собственное поле количества";
КонецЕсли;
Выбор.Поле = Новый ПолеКомпоновкиДанных("Количество");
Выбор.Использование = Истина;
ПроверитьСвоюОсновуИтогов(Схема);
Возврат Схема;
КонецФункции
Процедура ПроверитьСвоюОсновуИтогов(Схема)
ПроверитьСвоюОсновуМакетовПолей(Схема);
Если Схема.ПоляИтога.Количество() <> 1 Или Схема.НастройкиПоУмолчанию.Структура.Количество() <> 1 Тогда
ВызватьИсключение "Нужны единственный свой ресурс и таблица";
КонецЕсли;
Ресурс = Схема.ПоляИтога.Получить(0);
Если ТипЗнч(Ресурс) <> Тип("ПолеИтогаСхемыКомпоновкиДанных")
Или Ресурс.ПутьКДанным <> "Количество" Или Ресурс.Выражение <> "Сумма(Количество)" Тогда
ВызватьИсключение "Не совпали полный собственный путь ресурса и формула";
КонецЕсли;
Таблица = Схема.НастройкиПоУмолчанию.Структура.Получить(0);
Если ТипЗнч(Таблица) <> Тип("ТаблицаКомпоновкиДанных") Или Не Таблица.Использование Тогда
ВызватьИсключение "Нужна используемая собственная таблица обычных настроек";
КонецЕсли;
Если Таблица.Строки.Количество() <> 1 Или Таблица.Колонки.Количество() <> 1 Или Таблица.Выбор.Элементы.Количество() <> 1 Тогда
ВызватьИсключение "Не совпал полный размер строк, колонок и выбора своей таблицы";
КонецЕсли;
ПроверитьСвоюГруппуТаблицы(Таблица.Строки.Получить(0), "СтрокиПоСкладу85", "Склад");
ПроверитьСвоюГруппуТаблицы(Таблица.Колонки.Получить(0), "КолонкиПоКоду85", "КодТовара");
Выбор = Таблица.Выбор.Элементы.Получить(0);
Если ТипЗнч(Выбор) <> Тип("ВыбранноеПолеКомпоновкиДанных") Или Не Выбор.Использование Тогда
ВызватьИсключение "Нужно используемое собственное поле количества в выборе";
КонецЕсли;
Если СвоеПолеВXML(Выбор.Поле) <> СвоеПолеВXML(Новый ПолеКомпоновкиДанных("Количество")) Тогда
ВызватьИсключение "Не совпал полный собственный путь выбранного ресурса";
КонецЕсли;
КонецПроцедуры
Процедура ЗаполнитьСвойИтоговыйМакет(Схема, Описание, ИмяМакета, Тип1, Тип2)
ПроверитьСвоюОсновуИтогов(Схема);
Если ТипЗнч(Описание) <> Тип("МакетПолейИтогаСхемыКомпоновкиДанных")
Или ТипЗнч(Схема.Макеты.Найти(ИмяМакета)) <> Тип("ОписаниеМакетаСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужны настоящее итоговое описание и существующая собственная область";
КонецЕсли;
Если (Тип1 <> ТипМакетаОбластиКомпоновкиДанных.Заголовок И Тип1 <> ТипМакетаОбластиКомпоновкиДанных.Подвал)
Или (Тип2 <> ТипМакетаОбластиКомпоновкиДанных.Заголовок И Тип2 <> ТипМакетаОбластиКомпоновкиДанных.Подвал) Тогда
ВызватьИсключение "В опыте используются только явно согласованные enum заголовка и подвала";
КонецЕсли;
Описание.ИмяГруппировки1 = "СтрокиПоСкладу85";
Описание.ИмяГруппировки2 = "КолонкиПоКоду85";
Описание.Макет = ИмяМакета;
Описание.ТипМакета1 = Тип1;
Описание.ТипМакета2 = Тип2;
Если ТипЗнч(Описание.ПоляГруппировки1) <> Тип("Массив") Или ТипЗнч(Описание.ПоляГруппировки2) <> Тип("Массив")
Или Описание.ПоляГруппировки1.Количество() <> 0 Или Описание.ПоляГруппировки2.Количество() <> 0 Тогда
ВызватьИсключение "Дополнительные массивы выбора полей в этом именованном опыте пусты";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвоиИтоговыеМакеты(Схема, Имена, Типы1, Типы2)
ПроверитьСвоюОсновуИтогов(Схема);
Каталог = Схема.МакетыПолейИтога;
Если ТипЗнч(Каталог) <> Тип("МакетыПолейИтогаСхемыКомпоновкиДанных")
Или Каталог.Количество() <> Имена.Количество() Или Типы1.Количество() <> Имена.Количество()
Или Типы2.Количество() <> Имена.Количество() Тогда
ВызватьИсключение "Не совпал полный размер собственного итогового каталога";
КонецЕсли;
Для Индекс = 0 По Имена.Количество() - 1 Цикл
Описание = Каталог.Получить(Индекс);
Если ТипЗнч(Описание) <> Тип("МакетПолейИтогаСхемыКомпоновкиДанных")
Или Описание.ИмяГруппировки1 <> "СтрокиПоСкладу85" Или Описание.ИмяГруппировки2 <> "КолонкиПоКоду85"
Или Описание.Макет <> Имена[Индекс] Или Описание.ТипМакета1 <> Типы1[Индекс] Или Описание.ТипМакета2 <> Типы2[Индекс]
Или Каталог.Индекс(Описание) <> Индекс Или Каталог[Индекс] <> Описание Тогда
ВызватьИсключение "Не совпали обе группы, ссылка, два enum и порядок итоговых описаний";
КонецЕсли;
Если ТипЗнч(Описание.ПоляГруппировки1) <> Тип("Массив") Или ТипЗнч(Описание.ПоляГруппировки2) <> Тип("Массив")
Или Описание.ПоляГруппировки1.Количество() <> 0 Или Описание.ПоляГруппировки2.Количество() <> 0
Или ТипЗнч(Схема.Макеты.Найти(Описание.Макет)) <> Тип("ОписаниеМакетаСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужны прежние пустые массивы и существующая собственная область";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ВосстановитьСвоиИтоговыеМакеты(Схема)
Пусто = Новый Массив;
ПроверитьСвоиИтоговыеМакеты(Схема, Пусто, Пусто, Пусто);
Первый = Схема.МакетыПолейИтога.Добавить();
ЗаполнитьСвойИтоговыйМакет(Схема, Первый, "Количество", ТипМакетаОбластиКомпоновкиДанных.Заголовок, ТипМакетаОбластиКомпоновкиДанных.Заголовок);
Второй = Схема.МакетыПолейИтога.Добавить();
ЗаполнитьСвойИтоговыйМакет(Схема, Второй, "КоличествоВыделено85", ТипМакетаОбластиКомпоновкиДанных.Подвал, ТипМакетаОбластиКомпоновкиДанных.Подвал);
КонецПроцедурыУчебныеМакетыИтогов85.Форма
Своя внешняя обработка УчебныеМакетыИтогов85 → управляемая Форма → Модуль
Полный отдельный модуль собственной формы с серверным вызовом; здесь не запускался.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
Сообщить("Ресурс количества, группы таблицы, каталог итоговых макетов и восстановление проверены");
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныеЗадачи.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
Явно добавить ресурс в Схема.ПоляИтога: ПутьКДанным="Количество", Выражение="Сумма(Количество)". Нельзя называть макет итоговым для ресурса, которого в схеме нет. Каждый контроль сверяет весь путь и формулу, не только наличие строки в каталоге.
В обычные НастройкиПоУмолчанию.Структура добавить включённую ТаблицаКомпоновкиДанных. Её Строки.Добавить() создаёт именованную СтрокиПоСкладу85 по реальному Склад, Колонки.Добавить() — КолонкиПоКоду85 по реальному КодТовара. В обеих группах явно заданы использование и тип Элементы; в Выбор выбран используемый ресурс Количество.
Проверить полные пути полей через XML/XDTO в памяти и независимо созданные эталоны. Проверить настоящий тип таблицы/групп, размеры, имена, использование, типы enum, выбор, источник, три описания полей и все тексты реальных областей. Отчёт и запрос не выполняются.
МакетыПолейИтога readonly, но собственная коллекция изменяется методами. Добавить возвращает МакетПолейИтогаСхемыКомпоновкиДанных. Его две строки имён групп должны совпадать с созданными группами, Макет — строковое имя существующей области. ТипМакета1/2 — независимые значения специального enum, не строки.
Добавить правило заголовок/заголовок и вставить подвал/подвал по индексу0. Сдвинуть(Второй,1) — объект и относительное смещение — восстанавливает исходный порядок. В первом правиле изменить только ТипМакета2 на Подвал и проверить, что ТипМакета1 остался Заголовок; затем вернуть второй тип.
Два readonly массива ПоляГруппировки1/2 проверяются как Массив с количеством0. В этом именованном опыте дополнительных условий выбора полей нет; типы элементов и алгоритм отбора этим массивом не выдумываются. Реальные поля и группы проверяются независимо.
Независимую схему с источником, ресурсом, таблицей, группами, областями и правилами создать заново. Удалить текущий объект Первый, не число; старое правило не использовать. Копия сохраняет исходный каталог. Восстановить новым Вставить(0), очистить только каталог оригинала, подтвердить0 при сохранённой основе и копии, заново создать оба правила.
Десять прямых проверок оригинального каталога каждый раз сверяют обе группы, два enum, строковую ссылку, порядок, массивы и полное содержимое основы. Финальные оригинал/копия проверяются по одному полному согласованному эталону. Коллекция не имеет Найти, поиск не придумывается.
Как проверить результат
Будущий результат модели: единственный ресурс Количество/Сумма(Количество); включённая таблица с группами СтрокиПоСкладу85/КолонкиПоКоду85 и выбранным Количество. После восстановления каталог содержит Количество с Заголовок/Заголовок, затем КоличествоВыделено85 с Подвал/Подвал. У обоих правила привязаны к обеим существующим группам, дополнительные массивы пусты.
Будущий отрицательный контроль: после заполнения второго правила присвоить Второй.ИмяГруппировки2 = "НетТакойКолонки85", не меняя ожидаемое имя. Полная проверка должна отказать при прежних размерах, двух enum и ссылке на существующий макет. Вернуть код, сохранить/F7 вне опыта и открыть новый собственный сеанс. Здесь контроль не выполнялся.
runtimeVerifiedScenarios=0. Ресурс и его формула объявлены, не вычислены. Постоянные тексты областей не выдаются за агрегаты или готовое оформление таблицы. Нет записей, сети, рабочей конфигурации, компиляции СКД и печати.
Ожидаемый результат
Полный пример не оставляет ресурс, группы или макет неизвестными: проверяет реальную собственную основу и весь цикл восстановления итоговых описаний.
На что обратить внимание
ИмяГруппировки1/2 и Макет — Строка, ТипМакета1/2 — ТипМакетаОбластиКомпоновкиДанных, ПоляГруппировки1/2 — readonly Массив. Не заменяйте enum строкой или массив коллекцией настроек.
Строки/Колонки таблицы и свойства групп здесь принадлежат обычным настройкам; у объектов пользовательских настроек нужные свойства недоступны. Макеты ресурсов группировок отличаются от макетов отдельных полей и от самого каталога областей.
Вставить — абсолютный индекс, Сдвинуть — описание и относительное смещение, Удалить — описание. Нет метода Найти. После удаления/очистки старые правила не используются; схема и независимая копия сохраняют собственных владельцев.
Массивы выбора полей оставлены пустыми намеренно; их неописанные здесь типы элементов и правила отбора не выдаются за доказанный контракт. Изменение второго enum демонстрируется отдельно от первого.
XML-сериализация получает только собственное ПолеКомпоновкиДанных и пишет строку в памяти. Не передаются объекты метаданных, записи или вся схема; собственный писатель закрывается в обоих исходах.
Установленная справка для класса итогового описания содержит подозрительную метку XDTO GroupTemplate и ссылки на соседние каталоги. Они не используются для приведения типа или сериализации итогового правила: проверяется его фактический тип и семь документированных свойств.
Без выполнения компоновщика и процессора не заявляется, что правила визуально применились. Это содержательный опыт редактирования собственной схемы и проверки ссылок, не доказательство готового отчёта.
Число в ОписаниеТипов задаётся вместе со вторым аргументом КвалификаторыЧисла(1,0,Неотрицательный), а не одним именем типа. Полная проверка сначала сверяет единственный тип Число, затем тип квалификаторов, общую разрядность1, дробную0 и знак. Строковые КодТовара/Склад остаются строками без числовых квалификаторов. Не расширяйте данные за0–9 без согласованного изменения описания и его эталона; запрос и агрегат здесь не исполняются.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.