ИзмеренияПостроителяОтчета.Индекс

Методы · IndexOf

Получает индекс элемента коллекции.

Синтаксис

Индекс(<Измерение>)
Полное описание, параметры и ограничения

ИзмеренияПостроителяОтчета.Индекс (ReportBuilderDimensions.IndexOf)

ИзмеренияПостроителяОтчета (ReportBuilderDimensions)

Индекс (IndexOf)

Доступен, начиная с версии 8.0.

Синтаксис:
Индекс(<Измерение>)
Параметры:

<Измерение> (обязательный)
Тип: ИзмерениеПостроителяОтчета.
Искомое измерение.
Возвращаемое значение:
Тип: Число.
Индекс указанного элемента коллекции. Если такого элемента нет, возвращается -1.
Описание:

Получает индекс элемента коллекции.

Доступность:

Сервер, толстый клиент, внешнее соединение.

Использование в версии:

Доступен, начиная с версии 8.0.

Методическая информация

Практические примеры

ПостроительОтчета: свой иерархический справочник, порядок группировок и четыре макета измерения

Полный обычный клиентский маршрут читает только свой справочник: сначала Класс→элемент, затем реально переставляет измерения и выводит контрольный кандидат, удаляет Класс и строит полную иерархию. Числа и ссылки проверяются в настоящих ячейках результата до замены отображаемых документов.

Где и как запускать

Полный модуль обычной формы своей обработки; только толстый клиент в обычном приложении Windows8.5.1.1343. Supporting общий модуль — обычный клиент, не сервер.

Подготовка

  1. ВРУЧНУЮ создайте НОВУЮ отдельную файловую базу только платформы8.5.1.1343 в C:\1C85_OwnHierarchyLab\6a7df6aa-5e73-41b5-bda1-8f9c86ee4164\Base. Имя конфигурации=УчебнаяИерархияПостроителя85; основной режим запуска=Обычное приложение. Ровно один собственный пользователь Иерархия85Ученик с полными правами в этом пустом стенде. Не копируйте рабочую базу. Нет расширений, документов, регистров, планов, бизнес-процессов, подписок, заданий и внешних источников. Автор НЕ создавал базу, не запускал1С, не записывал карточки, не менялGUI/файлы/настройки; actualruntime=0, новых backups/archives нет.

  2. В Конфигураторе: Справочники→Добавить→УчебнаяНоменклатура85. Иерархический=Да, вид=ИерархияГруппИЭлементов, не ограничивайте число уровней; подчинения владельцу нет. Код=Строка6, наименование=Строка40; уникальность кода=Да. Нет предопределённых строк и табличных частей. Ровно3 собственных реквизита, использование ДляГруппыИЭлемента: Класс85=Строка8, Количество85 и Сумма85=Число(12,0). История данных отключена, обработчики объекта/менеджера отсутствуют. Ссылка, Родитель, ЭтоГруппа, ПометкаУдаления — реальные стандартные реквизиты, не добавляйте их заново.

  3. После обновления ТОЛЬКО своего стенда вручную создайте группы: код000001 Корень85 с пустым родителем; код000002 Напитки85 и код000003 Расходники85 с родителем Корень85. У всех групп Класс85="", Количество85=0, Сумма85=0. Затем создайте элементы: 000004 Альфа85 внутри Напитки85, Класс85=А85, Количество85=2, Сумма85=200; 000005 Бета85 внутри Напитки85, Б85/3/450; 000006 Гамма85 внутри Расходники85, А85/5/1000. Ровно6 строк, все без пометки удаления и без предопределённости. Никаких придумываемых UUID ссылок: код сам получает реальные ссылки этой выборки.

  4. Обработки→Добавить→УчебныйИерархическийОтчет85. Создайте ровно одну Обычную форму Основная. Её реквизиты: ИсходныйОтчет85 и ИтоговыйОтчет85 типа ТабличныйДокумент, Состояние85 типа Строка неограниченной длины. Значения при открытии не восстанавливать. Разместите два ПолеТабличногоДокумента с данными этих реквизитов и многострочное поле состояния только для просмотра. Не используйте управляемую форму и НЕ помещайте код внутрь другого обработчика.

  5. В своей форме назначьте событию ПриОткрытии точную процедуру ПриОткрытии(). Разместите обычный элемент управления Кнопка с именем Сформировать85 и свяжите его событие Нажатие с Сформировать85(Кнопка). Native Кнопка.Нажатие() имеет0 payload-параметров, но ordinary расширение элемента, расположенного в форме, добавляет первый Элемент — здесь это Кнопка. Это НЕ кнопка командной панели и НЕ managed Команда. Других callbacks и обработчиков расшифровки не нужно. Весь основной код вставьте в модуль этой формы на уровне модуля. Сама кнопка вызывает процедуру; не вызывайте её вручную из ПриОткрытии.

  6. ОбщиеМодули→Добавить→СтендИерархии85. Клиент(обычное приложение)=Да, Сервер=Нет, Клиент(управляемое приложение)=Нет, ВнешнееСоединение=Нет, Глобальный=Нет, Привилегированный=Нет. В модуль вставьте полный supportingModules код. Экспортная ПроверитьСвойСтенд85 вызывается формой перед чтением. Других общих модулей нет. Откройте свою обработку вручную толстым клиентом в обычном приложении, не запускайте урок в тонком/web/managed клиенте.

  7. Строгий guard принимает СтрокаСоединенияИнформационнойБазы() ровно File="C:\1C85_OwnHierarchyLab\6a7df6aa-5e73-41b5-bda1-8f9c86ee4164\Base";. Он не выводит эту строку и не разрешает Srvr/Ref/другую базу. Если собственный запуск даёт иную строку соединения, сначала разберите её в своём тестовом стенде; не отключайте guard и не подставляйте рабочие пути. Пустой стенд назван так по происхождению, но содержит только перечисленные собственные6 строк.

  8. Макет НЕ внешняя картинка и не чужой MXL: код строит в памяти6 областей1×4: Элементы85, Группы85, ПодвалЭлемента85, ПодвалГруппы85, Класс85, Общие85. Колонка1=уникальный текстовый маркер, колонка2=настоящая ссылка или строковый класс, колонка3=числовой параметр Количество, колонка4=числовой параметр Сумма. СодержитЗначение и точные допустимые типы заданы ДО native вывода; после вывода код только читает ячейки, не чинит их ожидаемыми значениями.

#Если ТолстыйКлиентОбычноеПриложение Тогда

Процедура ПриОткрытии()
    СтендИерархии85.ПроверитьСвойСтенд85();
    ПрочитатьСобственныеСтроки85();
    ИсходныйОтчет85 = Новый ТабличныйДокумент;
    ИтоговыйОтчет85 = Новый ТабличныйДокумент;
    ИсходныйОтчет85.ТолькоПросмотр = Истина;
    ИтоговыйОтчет85.ТолькоПросмотр = Истина;
    Состояние85 = "Сформировать85: слева Класс→Номенклатура без групп; справа полная иерархия Номенклатуры. Все числа читаются из своих карточек.";
КонецПроцедуры

Процедура Сформировать85(Кнопка)
    СтендИерархии85.ПроверитьСвойСтенд85();
    Свои = ПрочитатьСобственныеСтроки85();
    Построитель = СоздатьСобственныйПостроитель85(Свои);
    Измерения = Построитель.ИзмеренияСтроки;
    Номенклатура = Измерения.Добавить("Номенклатура", "Номенклатура", ТипИзмеренияПостроителяОтчета.Элементы);
    Класс = Измерения.Вставить("Класс", "Класс", ТипИзмеренияПостроителяОтчета.Элементы, , , 0);
    Если Измерения.Количество() <> 2 Или Измерения.Индекс(Класс) <> 0
        Или Измерения.Индекс(Номенклатура) <> 1 Или Измерения.Получить(0) <> Класс
        Или Измерения.Получить(1) <> Номенклатура Или Измерения.Найти("Класс") <> Класс
        Или Измерения.Найти("Номенклатура") <> Номенклатура Тогда
        ВызватьИсключение "Вставить должен создать свой Класс на позиции0, не перед первым аргументом";
    КонецЕсли;
    УстановитьСобственныеМакеты85(Номенклатура, Класс);
    Построитель.Выполнить();
    ПроверитьСобственныйЗапрос85(Построитель, Свои);
    ПервыйКандидат = Новый ТабличныйДокумент;
    Построитель.Вывести(ПервыйКандидат);
    ПроверитьСобственныйВывод85(ПервыйКандидат, Свои, "КлассПервый");
    СнимокПервого = СнимокСвоегоДокумента85(ПервыйКандидат);
    Измерения.Сдвинуть(Класс, 1);
    Если Измерения.Индекс(Номенклатура) <> 0 Или Измерения.Индекс(Класс) <> 1
        Или Измерения.Получить(0) <> Номенклатура Или Измерения.Получить(1) <> Класс Тогда
        ВызватьИсключение "Сдвиг должен реально поменять порядок собственных группировок";
    КонецЕсли;
    Построитель.Выполнить();
    ПроверитьСобственныйЗапрос85(Построитель, Свои);
    Переставленный = Новый ТабличныйДокумент;
    Построитель.Вывести(Переставленный);
    ПроверитьСобственныйВывод85(Переставленный, Свои, "КлассВторой");
    Если СнимокСвоегоДокумента85(Переставленный) = СнимокПервого Тогда
        ВызватьИсключение "После перестановки нужен реально иной native вывод, не только иной индекс";
    КонецЕсли;
    Измерения.Удалить(Класс);
    Если Измерения.Количество() <> 1 Или Измерения.Индекс(Класс) <> -1
        Или Измерения.Найти("Класс") <> Неопределено Или Измерения.Найти("НетТакогоИзмерения85") <> Неопределено
        Или Измерения.Получить(0) <> Номенклатура Или Измерения.Индекс(Номенклатура) <> 0 Тогда
        ВызватьИсключение "После удаления свой Класс отсутствует, собственная Номенклатура остаётся";
    КонецЕсли;
    Номенклатура.ТипИзмерения = ТипИзмеренияПостроителяОтчета.Иерархия;
    Если Номенклатура.ТипИзмерения <> ТипИзмеренияПостроителяОтчета.Иерархия Тогда
        ВызватьИсключение "Не прочиталось изменение native типа измерения";
    КонецЕсли;
    Построитель.Выполнить();
    ПроверитьСобственныйЗапрос85(Построитель, Свои);
    ВторойКандидат = Новый ТабличныйДокумент;
    Построитель.Вывести(ВторойКандидат);
    ПроверитьСобственныйВывод85(ВторойКандидат, Свои, "Иерархия");
    СвоиПосле = ПрочитатьСобственныеСтроки85();
    Для Каждого Пара Из Свои Цикл
        ФактПосле = СвоиПосле.Получить(Пара.Ключ);
        Если ФактПосле.Ссылка <> Пара.Значение.Ссылка Или ФактПосле.Родитель <> Пара.Значение.Родитель Тогда
            ВызватьИсключение "До передачи результата изменились реальные собственные ссылки или их иерархия";
        КонецЕсли;
    КонецЦикла;
    Если СнимокСвоегоДокумента85(ПервыйКандидат) <> СнимокПервого Тогда
        ВызватьИсключение "Перестройка не должна изменять ранее выведенный самостоятельный документ";
    КонецЕсли;
    ПервыйКандидат.ТолькоПросмотр = Истина;
    ВторойКандидат.ТолькоПросмотр = Истина;
    ИсходныйОтчет85 = ПервыйКандидат;
    ИтоговыйОтчет85 = ВторойКандидат;
    Состояние85 = "Приняты проверенные свои отчёты: элементы3, группы3, количество10, сумма1650. База не записывалась.";
КонецПроцедуры

Функция ПрочитатьСобственныеСтроки85()
    СтендИерархии85.ПроверитьСвойСтенд85();
    Ожидания = Новый Соответствие;
    Ожидания.Вставить("Корень85", Новый ФиксированнаяСтруктура("Код,Наименование,Родитель,ЭтоГруппа,Класс,Количество,Сумма", "000001", "Корень85", "", Истина, "", 0, 0));
    Ожидания.Вставить("Напитки85", Новый ФиксированнаяСтруктура("Код,Наименование,Родитель,ЭтоГруппа,Класс,Количество,Сумма", "000002", "Напитки85", "Корень85", Истина, "", 0, 0));
    Ожидания.Вставить("Расходники85", Новый ФиксированнаяСтруктура("Код,Наименование,Родитель,ЭтоГруппа,Класс,Количество,Сумма", "000003", "Расходники85", "Корень85", Истина, "", 0, 0));
    Ожидания.Вставить("Альфа85", Новый ФиксированнаяСтруктура("Код,Наименование,Родитель,ЭтоГруппа,Класс,Количество,Сумма", "000004", "Альфа85", "Напитки85", Ложь, "А85", 2, 200));
    Ожидания.Вставить("Бета85", Новый ФиксированнаяСтруктура("Код,Наименование,Родитель,ЭтоГруппа,Класс,Количество,Сумма", "000005", "Бета85", "Напитки85", Ложь, "Б85", 3, 450));
    Ожидания.Вставить("Гамма85", Новый ФиксированнаяСтруктура("Код,Наименование,Родитель,ЭтоГруппа,Класс,Количество,Сумма", "000006", "Гамма85", "Расходники85", Ложь, "А85", 5, 1000));
    Свои = Новый Соответствие;
    Выборка = Справочники.УчебнаяНоменклатура85.Выбрать();
    Если ТипЗнч(Выборка) <> Тип("СправочникВыборка.УчебнаяНоменклатура85") Тогда
        ВызватьИсключение "Нужна настоящая выборка только своего справочника";
    КонецЕсли;
    Пока Выборка.Следующий() Цикл
        Ожидается = Ожидания.Получить(Выборка.Наименование);
        Если Ожидается = Неопределено Или Свои.Получить(Выборка.Наименование) <> Неопределено Тогда
            ВызватьИсключение "В своём справочнике лишняя или повторяющаяся строка";
        КонецЕсли;
        Если ТипЗнч(Выборка.Ссылка) <> Тип("СправочникСсылка.УчебнаяНоменклатура85")
            Или Выборка.Ссылка.Пустая() Или Выборка.ПометкаУдаления Или Выборка.Предопределенный
            Или Выборка.Код <> Ожидается.Код Или Выборка.ЭтоГруппа <> Ожидается.ЭтоГруппа
            Или ТипЗнч(Выборка.Класс85) <> Тип("Строка") Или Выборка.Класс85 <> Ожидается.Класс
            Или ТипЗнч(Выборка.Количество85) <> Тип("Число") Или Выборка.Количество85 <> Ожидается.Количество
            Или ТипЗнч(Выборка.Сумма85) <> Тип("Число") Или Выборка.Сумма85 <> Ожидается.Сумма Тогда
            ВызватьИсключение "Фактические данные собственной строки не совпали с ручной учебной подготовкой";
        КонецЕсли;
        Свои.Вставить(Выборка.Наименование, Новый ФиксированнаяСтруктура("Ссылка,Родитель,Наименование,ЭтоГруппа,Класс,Количество,Сумма",
            Выборка.Ссылка, Выборка.Родитель, Выборка.Наименование, Выборка.ЭтоГруппа, Выборка.Класс85, Выборка.Количество85, Выборка.Сумма85));
    КонецЦикла;
    Если Свои.Количество() <> 6 Тогда
        ВызватьИсключение "Нужны ровно6 настоящих собственных ссылок: 3группы и3карточки";
    КонецЕсли;
    Для Каждого Пара Из Ожидания Цикл
        Факт = Свои.Получить(Пара.Ключ);
        Если Факт = Неопределено Тогда
            ВызватьИсключение "Не найдена собственная строка " + Пара.Ключ;
        КонецЕсли;
        Если Пара.Значение.Родитель = "" Тогда
            Родитель = Справочники.УчебнаяНоменклатура85.ПустаяСсылка();
        Иначе
            Родитель = Свои.Получить(Пара.Значение.Родитель).Ссылка;
        КонецЕсли;
        Если Факт.Родитель <> Родитель Тогда
            ВызватьИсключение "Фактический родитель не совпал с собственной подготовленной иерархией";
        КонецЕсли;
    КонецЦикла;
    Возврат Новый ФиксированноеСоответствие(Свои);
КонецФункции

Функция СоздатьСобственныйПостроитель85(Свои)
    Карточки = Новый Массив;
    Для Каждого Пара Из Свои Цикл
        Если Не Пара.Значение.ЭтоГруппа Тогда
            Карточки.Добавить(Пара.Значение.Ссылка);
        КонецЕсли;
    КонецЦикла;
    Если Карточки.Количество() <> 3 Тогда
        ВызватьИсключение "В запрос передаются только3 реально прочитанные свои карточки";
    КонецЕсли;
    Построитель = Новый ПостроительОтчета;
    Построитель.Текст = "ВЫБРАТЬ Н.Ссылка КАК Номенклатура, Н.Класс85 КАК Класс,
|    Н.Количество85 КАК Количество, Н.Сумма85 КАК Сумма
|ИЗ Справочник.УчебнаяНоменклатура85 КАК Н
|ГДЕ Н.Ссылка В (&Карточки85) И НЕ Н.ЭтоГруппа И НЕ Н.ПометкаУдаления
|ИТОГИ СУММА(Количество), СУММА(Сумма) ПО ОБЩИЕ
|{ИТОГИ ПО Номенклатура.*, Класс}";
    Построитель.Параметры.Вставить("Карточки85", Карточки);
    Построитель.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
    Построитель.ЗаполнитьНастройки();
    Построитель.ВыбранныеПоля.Очистить();
    Для Каждого ИмяПоля Из СтрРазделить("Номенклатура,Класс,Количество,Сумма", ",") Цикл
        Построитель.ВыбранныеПоля.Добавить(ИмяПоля, ИмяПоля);
    КонецЦикла;
    Построитель.ИзмеренияСтроки.Очистить();
    Построитель.ИзмеренияКолонки.Очистить();
    Построитель.АвтоДетальныеЗаписи = Ложь;
    Построитель.ВыводитьДетальныеЗаписи = Ложь;
    Построитель.ВыводитьОбщиеИтоги = Истина;
    Построитель.ВыводитьЗаголовокОтчета = Ложь;
    Построитель.ВыводитьШапкуТаблицы = Ложь;
    Построитель.ВыводитьПодвалТаблицы = Ложь;
    Построитель.ВыводитьПодвалОтчета = Ложь;
    Построитель.ОтображатьСостояние = Ложь;
    Построитель.ОбрабатыватьПрерываниеПользователя = Ложь;
    Построитель.РазмещениеИтоговВСтроках = ТипРазмещенияИтогов.ЗаголовокИПодвал;
    Построитель.Макет = СоздатьСобственныйМакет85();
    Построитель.МакетОбщихИтогов = "Общие85";
    Возврат Построитель;
КонецФункции

Функция СоздатьСобственныйМакет85()
    Макет = Новый ТабличныйДокумент;
    Макет.Область(1, 1, 6, 4).ШиринаКолонки = 24;
    Области = СтрРазделить("Элементы85,Группы85,ПодвалЭлемента85,ПодвалГруппы85,Класс85,Общие85", ",");
    Метки = СтрРазделить("ЭЛЕМЕНТ85,ГРУППА85,ПОДВАЛЭЛЕМЕНТА85,ПОДВАЛГРУППЫ85,КЛАСС85,ИТОГ85", ",");
    Для Индекс = 0 По Области.Количество() - 1 Цикл
        Номер = Индекс + 1;
        Макет.Область(Номер, 1, Номер, 4).Имя = Области[Индекс];
        Макет.Область(Номер, 1).Текст = Метки[Индекс];
        Для Колонка = 2 По 4 Цикл
            Ячейка = Макет.Область(Номер, Колонка);
            Ячейка.СодержитЗначение = Истина;
            Если Колонка = 2 Тогда
                Если Индекс < 4 Тогда
                    Ячейка.ТипЗначения = Новый ОписаниеТипов("СправочникСсылка.УчебнаяНоменклатура85");
                    Ячейка.Параметр = "Номенклатура";
                    Ячейка.Значение = Справочники.УчебнаяНоменклатура85.ПустаяСсылка();
                Иначе
                    Ячейка.ТипЗначения = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(8));
                    Ячейка.Значение = "";
                    Если Индекс = 4 Тогда
                        Ячейка.Параметр = "Класс";
                    КонецЕсли;
                КонецЕсли;
            Иначе
                Ячейка.ТипЗначения = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(12, 0));
                Ячейка.Значение = 0;
                Ячейка.Параметр = ?(Колонка = 3, "Количество", "Сумма");
            КонецЕсли;
            Если Не (Индекс = 5 И Колонка = 2) Тогда
                Ячейка.Заполнение = ТипЗаполненияОбластиТабличногоДокумента.Параметр;
            КонецЕсли;
        КонецЦикла;
        Область = Макет.ПолучитьОбласть(Области[Индекс]);
        Если ТипЗнч(Область) <> Тип("ТабличныйДокумент") Или Область.ВысотаТаблицы <> 1
            Или Область.ШиринаТаблицы <> 4 Или Область.Область(1, 1).Текст <> Метки[Индекс] Тогда
            ВызватьИсключение "Не создана собственная именованная область1×4";
        КонецЕсли;
    КонецЦикла;
    Возврат Макет;
КонецФункции

Процедура УстановитьСобственныеМакеты85(Номенклатура, Класс)
    Номенклатура.Макет = "Элементы85";
    Номенклатура.МакетИерархии = "Группы85";
    Номенклатура.МакетПодвала = "ПодвалЭлемента85";
    Номенклатура.МакетПодвалаИерархии = "ПодвалГруппы85";
    Класс.Макет = "Класс85";
    Класс.МакетПодвала = "Класс85";
    Если Номенклатура.Макет <> "Элементы85" Или Номенклатура.МакетИерархии <> "Группы85"
        Или Номенклатура.МакетПодвала <> "ПодвалЭлемента85" Или Номенклатура.МакетПодвалаИерархии <> "ПодвалГруппы85"
        Или Номенклатура.ТипИзмерения <> ТипИзмеренияПостроителяОтчета.Элементы
        Или Класс.Макет <> "Класс85" Или Класс.МакетПодвала <> "Класс85" Тогда
        ВызватьИсключение "Native значения своих макетов и первоначального типа измерения не прочитались обратно";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьСобственныйЗапрос85(Построитель, Свои)
    Результат = Построитель.Результат;
    Если ТипЗнч(Результат) <> Тип("РезультатЗапроса") Тогда
        ВызватьИсключение "Нужен настоящий результат именно этого собственного построителя";
    КонецЕсли;
    Строки = Результат.Выгрузить(ОбходРезультатаЗапроса.Прямой);
    Если ТипЗнч(Строки) <> Тип("ТаблицаЗначений") Или Строки.Количество() <> 3
        Или Строки.Итог("Количество") <> 10 Или Строки.Итог("Сумма") <> 1650 Тогда
        ВызватьИсключение "Прямые собственные данные должны давать ровно3 строки и итог10/1650";
    КонецЕсли;
    Найденные = Новый Соответствие;
    Для Каждого СтрокаДанных Из Строки Цикл
        Факт = СвояСтрокаПоСсылке85(Свои, СтрокаДанных.Номенклатура);
        Если Факт.ЭтоГруппа Или Найденные.Получить(Факт.Ссылка) <> Неопределено
            Или СтрокаДанных.Класс <> Факт.Класс Или ТипЗнч(СтрокаДанных.Количество) <> Тип("Число")
            Или ТипЗнч(СтрокаДанных.Сумма) <> Тип("Число") Или СтрокаДанных.Количество <> Факт.Количество
            Или СтрокаДанных.Сумма <> Факт.Сумма Тогда
            ВызватьИсключение "Реальная строка запроса не совпала со своей настоящей карточкой";
        КонецЕсли;
        Найденные.Вставить(Факт.Ссылка, Истина);
    КонецЦикла;
КонецПроцедуры

Функция СвояСтрокаПоСсылке85(Свои, Ссылка)
    Если ТипЗнч(Ссылка) <> Тип("СправочникСсылка.УчебнаяНоменклатура85") Тогда
        ВызватьИсключение "Ожидалась настоящая ссылка своей metadata, не текст представления";
    КонецЕсли;
    Для Каждого Пара Из Свои Цикл
        Если Пара.Значение.Ссылка = Ссылка Тогда
            Возврат Пара.Значение;
        КонецЕсли;
    КонецЦикла;
    ВызватьИсключение "В результат попала ссылка вне своих6 проверенных строк";
КонецФункции

Функция СвойИтогСтроки85(Свои, Факт)
    Если Не Факт.ЭтоГруппа Тогда
        Возврат Новый ФиксированнаяСтруктура("Количество,Сумма", Факт.Количество, Факт.Сумма);
    КонецЕсли;
    Количество = 0;
    Сумма = 0;
    Для Каждого Пара Из Свои Цикл
        Карточка = Пара.Значение;
        Если Карточка.ЭтоГруппа Тогда
            Продолжить;
        КонецЕсли;
        Родитель = Карточка.Родитель;
        Шаг = 0;
        Пока Не Родитель.Пустая() Цикл
            Шаг = Шаг + 1;
            Если Шаг > 3 Тогда
                ВызватьИсключение "Иерархия собственной подготовки повреждена или зациклена";
            КонецЕсли;
            Если Родитель = Факт.Ссылка Тогда
                Количество = Количество + Карточка.Количество;
                Сумма = Сумма + Карточка.Сумма;
                Прервать;
            КонецЕсли;
            Родитель = СвояСтрокаПоСсылке85(Свои, Родитель).Родитель;
        КонецЦикла;
    КонецЦикла;
    Возврат Новый ФиксированнаяСтруктура("Количество,Сумма", Количество, Сумма);
КонецФункции

Процедура ПроверитьСобственныйВывод85(Документ, Свои, Профиль)
    Если Профиль <> "КлассПервый" И Профиль <> "КлассВторой" И Профиль <> "Иерархия" Тогда
        ВызватьИсключение "Нет такого собственного профиля вывода";
    КонецЕсли;
    Если Документ.ВысотаТаблицы < 1 Или Документ.ВысотаТаблицы > 200 Или Документ.ШиринаТаблицы <> 4 Тогда
        ВызватьИсключение "Native результат не соответствует маленькому собственному макету";
    КонецЕсли;
    Заголовки = Новый Соответствие;
    Подвалы = Новый Соответствие;
    Итогов = 0;
    Классы = Новый Соответствие;
    Для Номер = 1 По Документ.ВысотаТаблицы Цикл
        Метка = Документ.Область(Номер, 1).Текст;
        Если Метка = "" Тогда
            Для Колонка = 1 По 4 Цикл
                ПустаяЯчейка = Документ.Область(Номер, Колонка);
                Если ПустаяЯчейка.Текст <> "" Или ПустаяЯчейка.СодержитЗначение Тогда
                    ВызватьИсключение "Нельзя пропускать неизвестные данные под видом пустой строки оформления";
                КонецЕсли;
            КонецЦикла;
            Продолжить;
        КонецЕсли;
        Если СтрРазделить("ЭЛЕМЕНТ85,ГРУППА85,ПОДВАЛЭЛЕМЕНТА85,ПОДВАЛГРУППЫ85,КЛАСС85,ИТОГ85", ",").Найти(Метка) = Неопределено Тогда
            ВызватьИсключение "В native выводе неизвестная область вместо своего маркера";
        КонецЕсли;
        ЯчейкаКоличества = Документ.Область(Номер, 3);
        ЯчейкаСуммы = Документ.Область(Номер, 4);
        Если Не ЯчейкаКоличества.СодержитЗначение Или Не ЯчейкаСуммы.СодержитЗначение Тогда
            ВызватьИсключение "Native числовые ячейки не содержат значения; не подставляем ожидаемые числа";
        КонецЕсли;
        Количество = ЯчейкаКоличества.Значение;
        Сумма = ЯчейкаСуммы.Значение;
        Если ТипЗнч(Количество) <> Тип("Число") Или ТипЗнч(Сумма) <> Тип("Число") Тогда
            ВызватьИсключение "Вычисленные значения нужно читать как числа, не превращать подпись в число";
        КонецЕсли;
        Если Метка = "ИТОГ85" Тогда
            Если Количество <> 10 Или Сумма <> 1650 Тогда
                ВызватьИсключение "Фактический общий итог native ячеек не равен10/1650";
            КонецЕсли;
            Итогов = Итогов + 1;
            Продолжить;
        КонецЕсли;
        ЯчейкаКлюча = Документ.Область(Номер, 2);
        Если Не ЯчейкаКлюча.СодержитЗначение Тогда
            ВызватьИсключение "Native ключ строки должен быть значением, не угаданной подписью";
        КонецЕсли;
        Если Метка = "КЛАСС85" Тогда
            Класс = ЯчейкаКлюча.Значение;
            Если Профиль = "Иерархия" Или ТипЗнч(Класс) <> Тип("Строка") Или (Класс <> "А85" И Класс <> "Б85") Тогда
                ВызватьИсключение "После удаления измерения его область не должна выводиться";
            КонецЕсли;
            Если Профиль = "КлассПервый" Тогда
                Верно = (Класс = "А85" И Количество = 7 И Сумма = 1200) Или (Класс = "Б85" И Количество = 3 И Сумма = 450);
            Иначе
                Верно = (Класс = "А85" И ((Количество = 2 И Сумма = 200) Или (Количество = 5 И Сумма = 1000)))
                    Или (Класс = "Б85" И Количество = 3 И Сумма = 450);
            КонецЕсли;
            Если Не Верно Тогда
                ВызватьИсключение "Native итог класса не соответствует фактическому уровню собственных группировок";
            КонецЕсли;
            Классы.Вставить(Класс, Истина);
            Продолжить;
        КонецЕсли;
        Факт = СвояСтрокаПоСсылке85(Свои, ЯчейкаКлюча.Значение);
        Группа = Метка = "ГРУППА85" Или Метка = "ПОДВАЛГРУППЫ85";
        Если Группа <> Факт.ЭтоГруппа Или (Группа И Профиль <> "Иерархия") Тогда
            ВызватьИсключение "Native роль строки не совпала с реально подготовленной собственной группой или элементом";
        КонецЕсли;
        Ожидается = СвойИтогСтроки85(Свои, Факт);
        Если Количество <> Ожидается.Количество Или Сумма <> Ожидается.Сумма Тогда
            ВызватьИсключение "Native итог элемента или группы не совпал с суммой своих настоящих потомков";
        КонецЕсли;
        Если Метка = "ЭЛЕМЕНТ85" Или Метка = "ГРУППА85" Тогда
            Набор = Заголовки;
        Иначе
            Набор = Подвалы;
        КонецЕсли;
        Если Набор.Получить(Факт.Ссылка) <> Неопределено Тогда
            ВызватьИсключение "Повторён собственный заголовок или подвал одной и той же ссылки";
        КонецЕсли;
        Набор.Вставить(Факт.Ссылка, Истина);
    КонецЦикла;
    ОжидаетсяСтрок = ?(Профиль = "Иерархия", 6, 3);
    Если Итогов = 0 Или Заголовки.Количество() <> ОжидаетсяСтрок Или Подвалы.Количество() <> ОжидаетсяСтрок
        Или Классы.Количество() <> ?(Профиль = "Иерархия", 0, 2) Тогда
        ВызватьИсключение "Потеряны свои фактические элементы, группы, подвал или общий итог";
    КонецЕсли;
КонецПроцедуры

Функция СнимокСвоегоДокумента85(Документ)
    Если Документ.ВысотаТаблицы > 200 Или Документ.ШиринаТаблицы <> 4 Тогда
        ВызватьИсключение "Снимок разрешён только для маленького собственного вывода";
    КонецЕсли;
    Части = Новый Массив;
    Части.Добавить(Строка(Документ.ВысотаТаблицы));
    Для Номер = 1 По Документ.ВысотаТаблицы Цикл
        Для Колонка = 1 По 4 Цикл
            Ячейка = Документ.Область(Номер, Колонка);
            Части.Добавить(Ячейка.Текст);
            Если Ячейка.СодержитЗначение Тогда
                Части.Добавить(Строка(ТипЗнч(Ячейка.Значение)));
                Части.Добавить(Строка(Ячейка.Значение));
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    Возврат СтрСоединить(Части, Символы.ПС);
КонецФункции

#КонецЕсли
Полный общий модуль допуска собственного стенда

ОбщиеМодули.СтендИерархии85.Модуль

Клиент обычного приложения; КлиентОбычноеПриложение=Да, все остальные контексты=Нет, Глобальный=Нет, Привилегированный=Нет

Процедура ПроверитьСвойСтенд85() Экспорт
    Если СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1C85_OwnHierarchyLab\6a7df6aa-5e73-41b5-bda1-8f9c86ee4164\Base"";"
        Или ИмяПользователя() <> "Иерархия85Ученик" Тогда
        ВызватьИсключение "Нужен только свой отдельный файловый стенд и собственный учебный пользователь";
    КонецЕсли;
    Если Метаданные.Справочники.Количество() <> 1 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.Обработки.Количество() <> 1 Или Метаданные.ОбщиеМодули.Количество() <> 1 Тогда
        ВызватьИсключение "Разрешены только своя обработка и собственный общий модуль стенда";
    КонецЕсли;
    Обработка = Метаданные.Обработки.Найти("УчебныйИерархическийОтчет85");
    Если Обработка = Неопределено Или Метаданные.ОбщиеМодули.Найти("СтендИерархии85") = Неопределено Тогда
        ВызватьИсключение "Нет точно подготовленных собственной обработки и общего модуля";
    КонецЕсли;
    Если Обработка.Формы.Количество() <> 1 Или Обработка.Формы.Найти("Основная") = Неопределено Тогда
        ВызватьИсключение "Нужна ровно своя обычная форма Основная";
    КонецЕсли;
    Описание = Метаданные.Справочники.Найти("УчебнаяНоменклатура85");
    Если Описание = Неопределено Тогда
        ВызватьИсключение "Нет собственного иерархического справочника";
    КонецЕсли;
    Если Не Описание.Иерархический Или Описание.ВидИерархии <> Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов
        Или Описание.Владельцы.Количество() <> 0 Или Описание.Реквизиты.Количество() <> 3
        Или Описание.ТабличныеЧасти.Количество() <> 0 Или Описание.ДлинаКода <> 6
        Или Описание.ДлинаНаименования <> 40 Или Описание.ТипКода <> Метаданные.СвойстваОбъектов.ТипКодаСправочника.Строка Тогда
        ВызватьИсключение "Метаданные справочника не совпали с собственной учебной схемой";
    КонецЕсли;
    Для Каждого ИмяРеквизита Из СтрРазделить("Класс85,Количество85,Сумма85", ",") Цикл
        Реквизит = Описание.Реквизиты.Найти(ИмяРеквизита);
        Если Реквизит = Неопределено Тогда
            ВызватьИсключение "Отсутствует собственный реквизит " + ИмяРеквизита;
        КонецЕсли;
        Если Реквизит.Использование <> Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппыИЭлемента Тогда
            ВызватьИсключение "Все3 собственных реквизита должны существовать у групп и элементов";
        КонецЕсли;
        Типы = Реквизит.Тип.Типы();
        Если Типы.Количество() <> 1 Тогда
            ВызватьИсключение "Реквизит должен иметь ровно один подготовленный тип";
        КонецЕсли;
        Если ИмяРеквизита = "Класс85" Тогда
            Если Типы[0] <> Тип("Строка") Или Реквизит.Тип.КвалификаторыСтроки.Длина <> 8 Тогда
                ВызватьИсключение "Класс85 должен иметь тип Строка8";
            КонецЕсли;
        Иначе
            Если Типы[0] <> Тип("Число") Или Реквизит.Тип.КвалификаторыЧисла.Разрядность <> 12
                Или Реквизит.Тип.КвалификаторыЧисла.РазрядностьДробнойЧасти <> 0 Тогда
                ВызватьИсключение "Числовые реквизиты должны иметь тип Число(12,0)";
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры

Разбор по шагам

  1. Guard сначала сверяет путь, пользователя, состав своей конфигурации, метаданные3 реквизитов, расширения и отсутствие активной транзакции. Затем Выбрать() без отбора получает все6 строк своего каталога. Любая лишняя/дублированная/помеченная строка, неправильное число/класс/родитель означает отказ ДО запроса.

  2. Свои — неизменяемый снимок фактических6 ссылок и значений. Ожидания задают только условия допуска стенда; итоговый отчёт берёт Количество85/Сумма85 из реальных карточек запросом. В параметр Карточки85 передаются только3 фактически прочитанные ссылки элементов, а не строковые идентификаторы.

  3. ЗаполнитьНастройки работает с собственным текстом запроса и расширением {ИТОГИ ПО Номенклатура.*, Класс}. ИТОГИ суммируют оба ресурса; звёздочка разрешает доступные реквизиты ссылки при настройке. Фиксированного порядка native результата здесь не обещаем.

  4. Добавить создаёт Номенклатуру. Вставить("Класс", "Класс", Элементы, , , 0) реально вставляет Класс первым: обязательная Позиция — ШЕСТОЙ слот. Найти обращается к имени измерения, Получить — к индексу0/1, Индекс получает само измерение и проверяет его принадлежность коллекции.

  5. Четыре RW свойства Номенклатуры получают свои существующие имена областей и читаются обратно. Вначале ТипИзмерения=Элементы: группы не выводятся. РазмещениеИтоговВСтроках=ЗаголовокИПодвал включает оба вида областей. Детальные записи отключены: элемент здесь является измерением, а не произвольно добавленной строкой.

  6. Первый native Вывести формирует самостоятельный кандидат Класс→Номенклатура. Проверяем фактические3 прямые строки запроса и3 ссылки элементов в заголовках/подвалах, значения каждой карточки, итоги классов А85=7/1200 и Б85=3/450, реальные числовые общие итоги10/1650.

  7. Сдвинуть(Класс, 1) меняет коллекцию на Номенклатура→Класс. Снова Выполнить/Вывести, readback индексов и другой текстово-типовой снимок результата. У класса теперь сумма отдельной вышестоящей карточки: А85 даёт2/200 или5/1000, Б85=3/450. Контрольный документ остаётся в памяти, не сохраняется в файле/базе.

  8. Удалить принимает настоящий элемент Класс, не его имя и не индекс. После удаления Найти возвращает Неопределено, Индекс старого элемента=-1, Количество=1. Оставшаяся Номенклатура — тот же реальный элемент. Честная отрицательная ветвь отсутствующего имени не считается ошибкой.

  9. ТипИзмерения меняется на Иерархия и читается обратно. Новый native вывод должен реально содержать группы и элементы, каждый со своим заголовком и подвалом. Итог группы вычисляется для проверки из фактических собственных карточек проходом по реальным Родитель-ссылкам с ограничением длины; это не фиктивный числовой getter.

  10. Все3 вывода проходят проверки до присваивания реквизитам формы. Повторное чтение допускает только тот же состав/значения и те же реальные6 ссылок/родителей, а не новые карточки с совпавшими именами. Ранее сформированный первый кандидат также должен сохранить снимок. Если что-то не совпало, показанные ранее два документа не присваиваются заново. Два последних присваивания UI не объявляются атомарной операцией/транзакцией; сбой самой передачи в форму требует отдельного разбора.

Как проверить результат

  1. Начальная проверка допускает ровно6 своих строк: 3 группы и3 карточки. Реквизиты: один строковый и два numeric, все точных типов/квалификаторов. Попробуйте вручную в своём стенде изменить родителя Бета85, количество или добавить седьмую строку: на следующем запуске guard/fixture проверка должна отказать до запроса. Затем вручную восстановите ровно указанную собственную подготовку.

  2. Слева фактические элементы Альфа85=2/200, Бета85=3/450, Гамма85=5/1000 и классы А85=7/1200, Б85=3/450. Группы Корень85/Напитки85/Расходники85 как измерения элементов слева не показываются. Справа тип Иерархия должен вывести все6 реальных ссылок.

  3. Справа обе области группы должны дать Напитки85=5/650, Расходники85=5/1000, Корень85=10/1650. Оба ресурса читаются через Значение настоящих numeric ячеек, а не из текста и не из EXPECTATION_CODE. Порядок строк/номера строк заранее не фиксируются.

  4. После Сдвинуть свой контрольный вывод должен отличаться от первого: суммы классов становятся вложенными под элементом. После Удалить области КЛАСС85 в итоговой иерархии должны отсутствовать. Исходный отдельный документ остаётся прежним.

  5. Индекс удалённого своего Класс=-1, Найти("Класс") и Найти("НетТакогоИзмерения85")=Неопределено. Это проверка реального lifecycle измерения, не обращение к неизвестному объекту.

  6. Измените имя своей области или тип numeric ячейки в КОПИИ учебного кода внутри своего отдельного стенда: построение/валидация должно честно отказать. Не включайте СодержитЗначение и не вставляйте10/1650 после вывода, чтобы скрыть несовпадение.

  7. Автором выполнены только статические source/native проверки. Ожидаемые числа вычислены из явно описанной подготовки; фактическое поведение renderer/отображения на платформе8.5.1.1343 не запускалось. Все runtime контрольные шаги выполняет пользователь только на своём стенде.

Ожидаемый результат

Подготовлен полный самостоятельный учебный маршрут11 API: настоящая перестановка/удаление измерений, четыре разные области измерения и проверяемый иерархический отчёт на своих6 ссылках. Авторство и static/native проверка — не подтверждение runtime.

На что обратить внимание

  1. Это старый ПостроительОтчета, не КомпоновщикМакета/Процессор СКД и не диаграмма. Нельзя переносить его обычную форму в thin/web или вставлять native ordinary сигнатуры в managed форму.

  2. Форма.ПриОткрытии() не имеет Отказ и не позволяет отменить открытие формы; ошибка допуска не выдаётся за закрытие окна. Обработчик прекращает дальнейшее чтение/формирование исключением. У обычной Кнопка.Нажатие() первый Элемент появляется именно из ordinary расширения controls в форме; не копируйте0 payload как готовую сигнатуру обработчика на форме.

  3. Запрос читает данные, не пишет их. Любые manualfixture изменения принадлежат только отдельному стенду; урок не подключается к предоставленным УТ/КА2/УНФ конфигурациям. История данных/предопределённые строки/автоматические обработчики выключены в подготовке.

  4. Вставить имеет6 слотов с обязательным последним Позиция. Сдвинуть принимает ИзмерениеПостроителяОтчета плюс число, Удалить — это же измерение. Не переносите сигнатуры других коллекций с индексом первым.

  5. Заголовок/подвал группы нельзя выдавать за сумму её единственного прямого реквизита0: собственные3 группы имеют0, их native итог должен быть суммой реальных элементов-потомков.

  6. ИТОГИ/Иерархия не означают, что каждая строка всегда в фиксированной позиции. Проверки анализируют собственные маркеры и реальные ссылки/числа, не рисуют таблицу результата сами.

  7. Если native вывод имеет другой shape, отсутствие подвала, пустую/чужую ссылку либо текст вместо Число, код отказывает, а не маскирует ошибку. Не обещаем, что статические тесты доказывают реальную работу renderer.

  8. МакетыУровней и МакетыПодваловУровней НЕ цели урока: их семантика не подтверждена простым чтением readonly массива. Не добавляйте их в PRIMARY только ради покрытия.

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

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.