ВложенныеНаборыДанныхМакетаКомпоновкиДанных.Вставить

Методы · Insert

Добавляет элемент в заданную позицию.

Синтаксис

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

ВложенныеНаборыДанныхМакетаКомпоновкиДанных.Вставить (DataCompositionTemplateNestedDataSets.Insert)

ВложенныеНаборыДанныхМакетаКомпоновкиДанных (DataCompositionTemplateNestedDataSets)

Вставить (Insert)

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

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

<Индекс> (обязательный)
Тип: Число.
Расположение элемента в коллекции.
Возвращаемое значение:
Тип: ВложенныйНаборДанныхМакетаКомпоновкиДанных.

Описание:

Добавляет элемент в заданную позицию.

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

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

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

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

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

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

Редактор вложенных наборов: добавить, вставить, сдвинуть, удалить и восстановить

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

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

Полный серверный общий модуль УчебныеВложенныеМакеты85 собственной новой базы; отдельный полный модуль управляемой формы ниже.

Подготовка

  1. Только НОВАЯ пустая учебная база 8.5.1.1343: корневое Имя=УчебныеВложенныеМакеты85, совместимость НеИспользовать, управляемое приложение. Не копия рабочей КА2/УНФ/УТ/БП. Без бизнес-метаданных, расширений, подписок, заданий и внешних действий. Здесь база не создаётся и пример не выполняется: runtimeVerifiedScenarios=0.

  2. Создайте общий модуль УчебныеВложенныеМакеты85: Сервер=Да, Клиент=Нет, Вызов сервера=Нет, Глобальный=Нет, Привилегированный=Нет. Вставьте целиком основной код ОДНОГО урока. Он включает создание всех данных, защиту стенда и проверку результата; неизвестных входных объектов нет.

  3. В своей новой конфигурации создайте обработку УчебныйРазборПозиций85 → управляемая форма Пульт → команда Выполнить с действием Выполнить и кнопкой. Отдельный полный модуль формы ниже. Выполните F7 и обновление только собственной учебной базы перед будущим отдельно разрешённым тестом.

  4. Стенд создаёт в памяти таблицу Заказы85: O1 содержит свою таблицу A01/3 и B02/5, O2 — другую таблицу C03/9. Никаких документов заказов создавать не нужно. Колонка Позиции85 без ограничения типа; её фактические значения и все вложенные примитивные колонки полностью проверяются.

  5. В исходной схеме четыре описания в одном каталоге: Номер85, вложенное поле Позиции85, Позиции85.Код, Позиции85.Количество. У поля исходной схемы нет собственного каталога Поля. Настройки выбирают только номер заказа и два вложенных значения, структура — детальные записи без таблиц и диаграмм.

  6. Макет компилируется генератором для коллекции значений. Настоящие внешние данные передаются ВТОРЫМ аргументом Процессор.Инициализировать, не третьим аргументом расшифровки. Таблицы и макеты не возвращаются в тонкий клиент; весь опыт остаётся серверным.

  7. В редакторском уроке XDTO переносит весь собственный макет в строку памяти и читает её обратно. Файлы, архивы и резервные копии не создаются. Неполный черновой каталог с именами отсутствующих внешних полей НИКОГДА не подаётся в процессор; исполняются только исходный и полностью восстановленный макеты.

  8. Для будущего разрешённого теста поставьте серверные точки останова в ПроверитьСвоиВложенныеОпределения и ПроверитьСвойВыводПозиций. Статические проверки не подтверждают реальную компиляцию макета, его XDTO round-trip или фактическое разворачивание вложенных строк на платформе.

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

Функция СвойТипКоличества()
    Возврат Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 0, ДопустимыйЗнак.Неотрицательный));
КонецФункции

Процедура ПроверитьСвойТип(Описание, ИмяТипа)
    Если ТипЗнч(Описание) <> Тип("ОписаниеТипов") Тогда
        ВызватьИсключение "Нужно собственное описание типа";
    КонецЕсли;
    ПолныеТипы = Описание.Типы();
    Если ПолныеТипы.Количество() <> 1 Или ПолныеТипы[0] <> Тип(ИмяТипа) Тогда
        ВызватьИсключение "Не совпал полный набор допустимых примитивных типов";
    КонецЕсли;
    Если ИмяТипа = "Число" Тогда
        Квалификаторы = Описание.КвалификаторыЧисла;
        Если ТипЗнч(Квалификаторы) <> Тип("КвалификаторыЧисла") Или Квалификаторы.Разрядность <> 10
            Или Квалификаторы.РазрядностьДробнойЧасти <> 0
            Или Квалификаторы.ДопустимыйЗнак <> ДопустимыйЗнак.Неотрицательный Тогда
            ВызватьИсключение "Количество должно быть неотрицательным целым числом до десяти разрядов";
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

Функция СоздатьСвойСтендПозиций()
    Заказы = Новый ТаблицаЗначений;
    Заказы.Колонки.Добавить("Номер85", Новый ОписаниеТипов("Строка"));
    Заказы.Колонки.Добавить("Позиции85");
    Для ИндексЗаказа = 0 По 1 Цикл
        Позиции = Новый ТаблицаЗначений;
        Позиции.Колонки.Добавить("Код", Новый ОписаниеТипов("Строка"));
        Позиции.Колонки.Добавить("Количество", СвойТипКоличества());
        СтрокаПозиции = Позиции.Добавить();
        Если ИндексЗаказа = 0 Тогда
            СтрокаПозиции.Код = "A01";
            СтрокаПозиции.Количество = 3;
            СтрокаПозиции = Позиции.Добавить();
            СтрокаПозиции.Код = "B02";
            СтрокаПозиции.Количество = 5;
        Иначе
            СтрокаПозиции.Код = "C03";
            СтрокаПозиции.Количество = 9;
        КонецЕсли;
        СтрокаЗаказа = Заказы.Добавить();
        Если ИндексЗаказа = 0 Тогда
            СтрокаЗаказа.Номер85 = "O1";
        Иначе
            СтрокаЗаказа.Номер85 = "O2";
        КонецЕсли;
        СтрокаЗаказа.Позиции85 = Позиции;
    КонецЦикла;
    Схема = Новый СхемаКомпоновкиДанных;
    Источник = Схема.ИсточникиДанных.Добавить();
    Источник.Имя = "СвоиЗаказы85";
    Источник.ТипИсточникаДанных = "Local";
    Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхОбъектСхемыКомпоновкиДанных"));
    Если ТипЗнч(Набор) <> Тип("НаборДанныхОбъектСхемыКомпоновкиДанных") Тогда
        ВызватьИсключение "Нужен собственный объектный набор";
    КонецЕсли;
    Набор.Имя = "Заказы85";
    Набор.ИмяОбъекта = "Заказы85";
    Набор.ИсточникДанных = "СвоиЗаказы85";
    ЗаполнитьСвоиОписанияПолей(Набор);
    ВнешниеДанные = Новый Структура;
    ВнешниеДанные.Вставить("Заказы85", Заказы);
    Стенд = Новый Структура;
    Стенд.Вставить("Схема", Схема);
    Стенд.Вставить("ВнешниеДанные", ВнешниеДанные);
    Возврат Стенд;
КонецФункции

Процедура ПроверитьСвойСтендПозиций(Стенд, ЕстьПоля, Заголовок, КоличествоB02)
    Если ТипЗнч(Стенд) <> Тип("Структура") Или Стенд.Количество() <> 2 Тогда
        ВызватьИсключение "Нужна собственная структура схемы и внешних данных";
    КонецЕсли;
    Схема = Неопределено;
    ВнешниеДанные = Неопределено;
    Если Не Стенд.Свойство("Схема", Схема) Или Не Стенд.Свойство("ВнешниеДанные", ВнешниеДанные) Тогда
        ВызватьИсключение "Не совпали оба ключа собственного стенда";
    КонецЕсли;
    Если ТипЗнч(Схема) <> Тип("СхемаКомпоновкиДанных") Или Схема.ИсточникиДанных.Количество() <> 1
        Или Схема.НаборыДанных.Количество() <> 1 Тогда
        ВызватьИсключение "Нужен единственный собственный источник и объектный набор";
    КонецЕсли;
    Если ТипЗнч(ВнешниеДанные) <> Тип("Структура") Или ВнешниеДанные.Количество() <> 1 Тогда
        ВызватьИсключение "Нужен единственный собственный внешний объект";
    КонецЕсли;
    Заказы = Неопределено;
    Если Не ВнешниеДанные.Свойство("Заказы85", Заказы) Тогда
        ВызватьИсключение "Не найдена настоящая собственная таблица заказов";
    КонецЕсли;
    Если ТипЗнч(Заказы) <> Тип("ТаблицаЗначений") Или Заказы.Количество() <> 2 Или Заказы.Колонки.Количество() <> 2 Тогда
        ВызватьИсключение "Нужно ровно два заказа и две колонки";
    КонецЕсли;
    Колонка = Заказы.Колонки.Получить(0);
    Если ТипЗнч(Колонка) <> Тип("КолонкаТаблицыЗначений") Или Колонка.Имя <> "Номер85" Тогда
        ВызватьИсключение "Не совпала первая колонка заказа";
    КонецЕсли;
    ПроверитьСвойТип(Колонка.ТипЗначения, "Строка");
    Колонка = Заказы.Колонки.Получить(1);
    Если ТипЗнч(Колонка) <> Тип("КолонкаТаблицыЗначений") Или Колонка.Имя <> "Позиции85"
        Или ТипЗнч(Колонка.ТипЗначения) <> Тип("ОписаниеТипов") Тогда
        ВызватьИсключение "Не совпала собственная колонка вложенных значений";
    КонецЕсли;
    Для ИндексЗаказа = 0 По 1 Цикл
        СтрокаЗаказа = Заказы.Получить(ИндексЗаказа);
        Если ТипЗнч(СтрокаЗаказа) <> Тип("СтрокаТаблицыЗначений") Или ТипЗнч(СтрокаЗаказа.Номер85) <> Тип("Строка") Тогда
            ВызватьИсключение "Не совпал тип строки заказа или номера";
        КонецЕсли;
        Если ИндексЗаказа = 0 Тогда
            Номер = "O1";
            ЧислоПозиций = 2;
        Иначе
            Номер = "O2";
            ЧислоПозиций = 1;
        КонецЕсли;
        Если СтрокаЗаказа.Номер85 <> Номер Тогда
            ВызватьИсключение "Не совпал полный номер заказа";
        КонецЕсли;
        Позиции = СтрокаЗаказа.Позиции85;
        Если ТипЗнч(Позиции) <> Тип("ТаблицаЗначений") Или Позиции.Количество() <> ЧислоПозиций
            Или Позиции.Колонки.Количество() <> 2 Тогда
            ВызватьИсключение "Ячейка должна содержать настоящую собственную таблицу позиций";
        КонецЕсли;
        Имена = СтрРазделить("Код,Количество", ",");
        Типы = СтрРазделить("Строка,Число", ",");
        Для Индекс = 0 По 1 Цикл
            Колонка = Позиции.Колонки.Получить(Индекс);
            Если ТипЗнч(Колонка) <> Тип("КолонкаТаблицыЗначений") Или Колонка.Имя <> Имена[Индекс] Тогда
                ВызватьИсключение "Не совпали порядок и имена обеих вложенных колонок";
            КонецЕсли;
            ПроверитьСвойТип(Колонка.ТипЗначения, Типы[Индекс]);
        КонецЦикла;
        Для Индекс = 0 По ЧислоПозиций - 1 Цикл
            СтрокаПозиции = Позиции.Получить(Индекс);
            Если ИндексЗаказа = 1 Тогда
                Код = "C03";
                Количество = 9;
            ИначеЕсли Индекс = 0 Тогда
                Код = "A01";
                Количество = 3;
            Иначе
                Код = "B02";
                Количество = КоличествоB02;
            КонецЕсли;
            Если ТипЗнч(СтрокаПозиции) <> Тип("СтрокаТаблицыЗначений")
                Или ТипЗнч(СтрокаПозиции.Код) <> Тип("Строка") Или СтрокаПозиции.Код <> Код
                Или ТипЗнч(СтрокаПозиции.Количество) <> Тип("Число") Или СтрокаПозиции.Количество <> Количество Тогда
                ВызватьИсключение "Не совпали все вложенные ячейки, коды, количества и их типы";
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    Источник = Схема.ИсточникиДанных.Получить(0);
    Если ТипЗнч(Источник) <> Тип("ИсточникДанныхСхемыКомпоновкиДанных")
        Или Источник.Имя <> "СвоиЗаказы85" Или Источник.ТипИсточникаДанных <> "Local" Тогда
        ВызватьИсключение "Не совпал собственный логический источник";
    КонецЕсли;
    Набор = Схема.НаборыДанных.Получить(0);
    Если ТипЗнч(Набор) <> Тип("НаборДанныхОбъектСхемыКомпоновкиДанных") Или Набор.Имя <> "Заказы85"
        Или Набор.ИмяОбъекта <> "Заказы85" Или Набор.ИсточникДанных <> "СвоиЗаказы85"
        Или Схема.НаборыДанных.Найти("Заказы85") <> Набор
        Или ТипЗнч(Набор.Поля) <> Тип("ПоляНабораДанныхСхемыКомпоновкиДанных") Тогда
        ВызватьИсключение "Не совпала связь своего набора с реальным внешним объектом";
    КонецЕсли;
    ЧислоПолей = 0;
    Если ЕстьПоля Тогда
        ЧислоПолей = 4;
    КонецЕсли;
    Если Набор.Поля.Количество() <> ЧислоПолей Тогда
        ВызватьИсключение "Не совпал полный размер своего каталога описаний";
    КонецЕсли;
    Если Не ЕстьПоля Тогда
        Возврат;
    КонецЕсли;
    ВложенноеПоле = Набор.Поля.Получить(1);
    Если ТипЗнч(ВложенноеПоле) <> Тип("ВложенныйНаборДанныхСхемыКомпоновкиДанных")
        Или ТипЗнч(ВложенноеПоле.Поле) <> Тип("Строка") Или ВложенноеПоле.Поле <> "Позиции85"
        Или ТипЗнч(ВложенноеПоле.ПутьКДанным) <> Тип("Строка") Или ВложенноеПоле.ПутьКДанным <> "Позиции85"
        Или ТипЗнч(ВложенноеПоле.Заголовок) <> Тип("Строка") Или ВложенноеПоле.Заголовок <> Заголовок Тогда
        ВызватьИсключение "Не совпали тип, реальное исходное поле, полный путь и заголовок вложенных данных";
    КонецЕсли;
    Пути = СтрРазделить("Номер85,Позиции85.Код,Позиции85.Количество", ",");
    Типы = СтрРазделить("Строка,Строка,Число", ",");
    Для Индекс = 0 По 2 Цикл
        ИндексПоля = Индекс;
        Если Индекс > 0 Тогда
            ИндексПоля = Индекс + 1;
        КонецЕсли;
        Поле = Набор.Поля.Получить(ИндексПоля);
        Если ТипЗнч(Поле) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных")
            Или Поле.Поле <> Пути[Индекс] Или Поле.ПутьКДанным <> Пути[Индекс] Тогда
            ВызватьИсключение "Не совпали все простые исходные поля и полные составные пути";
        КонецЕсли;
        ПроверитьСвойТип(Поле.ТипЗначения, Типы[Индекс]);
    КонецЦикла;
КонецПроцедуры

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

Функция НайтиСвоюКолонкуПоЗначениям(Таблица, Вариант)
    Если Вариант <> "Заказ" И Вариант <> "Код" И Вариант <> "Количество" Тогда
        ВызватьИсключение "У своей узкой модели только три непересекающихся области значений";
    КонецЕсли;
    Найденная = Неопределено;
    Для Каждого Колонка Из Таблица.Колонки Цикл
        Подходит = Истина;
        Для Каждого СтрокаРезультата Из Таблица Цикл
            Значение = СтрокаРезультата[Колонка.Имя];
            Если Вариант = "Заказ" Тогда
                Подходит = Подходит И ТипЗнч(Значение) = Тип("Строка") И (Значение = "O1" Или Значение = "O2");
            ИначеЕсли Вариант = "Код" Тогда
                Подходит = Подходит И ТипЗнч(Значение) = Тип("Строка") И (Значение = "A01" Или Значение = "B02" Или Значение = "C03");
            Иначе
                Подходит = Подходит И ТипЗнч(Значение) = Тип("Число") И (Значение = 3 Или Значение = 5 Или Значение = 9);
            КонецЕсли;
        КонецЦикла;
        Если Подходит Тогда
            Если Найденная <> Неопределено Тогда
                ВызватьИсключение "Роль колонки не должна определяться неоднозначно";
            КонецЕсли;
            Найденная = Колонка;
        КонецЕсли;
    КонецЦикла;
    Если Найденная = Неопределено Тогда
        ВызватьИсключение "В настоящем выводе не найдена колонка своей роли " + Вариант;
    КонецЕсли;
    Возврат Найденная;
КонецФункции

Процедура ПроверитьСвойВыводПозиций(Макет, ВнешниеДанные)
    Процессор = Новый ПроцессорКомпоновкиДанных;
    Процессор.Инициализировать(Макет, ВнешниеДанные);
    Вывод = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
    Приемник = Новый ТаблицаЗначений;
    Вывод.ОтображатьПроцентВывода = Ложь;
    Вывод.УстановитьОбъект(Приемник);
    Результат = Вывод.Вывести(Процессор, Ложь);
    Если ТипЗнч(Результат) <> Тип("ТаблицаЗначений") Или Результат.Количество() <> 3 Или Результат.Колонки.Количество() <> 3 Тогда
        ВызватьИсключение "Настоящий детальный вывод должен дать три позиции и три колонки";
    КонецЕсли;
    КолонкаЗаказа = НайтиСвоюКолонкуПоЗначениям(Результат, "Заказ");
    КолонкаКода = НайтиСвоюКолонкуПоЗначениям(Результат, "Код");
    КолонкаКоличества = НайтиСвоюКолонкуПоЗначениям(Результат, "Количество");
    Если КолонкаЗаказа = КолонкаКода Или КолонкаЗаказа = КолонкаКоличества Или КолонкаКода = КолонкаКоличества Тогда
        ВызватьИсключение "Три разные роли должны иметь три разные настоящие колонки";
    КонецЕсли;
    ЕстьA01 = Ложь;
    ЕстьB02 = Ложь;
    ЕстьC03 = Ложь;
    Итог = 0;
    Для Каждого СтрокаРезультата Из Результат Цикл
        Заказ = СтрокаРезультата[КолонкаЗаказа.Имя];
        Код = СтрокаРезультата[КолонкаКода.Имя];
        Количество = СтрокаРезультата[КолонкаКоличества.Имя];
        Если Код = "A01" Тогда
            Если ЕстьA01 Или Заказ <> "O1" Или Количество <> 3 Тогда
                ВызватьИсключение "Нужна ровно одна позиция O1/A01/3";
            КонецЕсли;
            ЕстьA01 = Истина;
        ИначеЕсли Код = "B02" Тогда
            Если ЕстьB02 Или Заказ <> "O1" Или Количество <> 5 Тогда
                ВызватьИсключение "Нужна ровно одна позиция O1/B02/5";
            КонецЕсли;
            ЕстьB02 = Истина;
        ИначеЕсли Код = "C03" Тогда
            Если ЕстьC03 Или Заказ <> "O2" Или Количество <> 9 Тогда
                ВызватьИсключение "Нужна ровно одна позиция O2/C03/9";
            КонецЕсли;
            ЕстьC03 = Истина;
        Иначе
            ВызватьИсключение "Лишняя позиция в настоящем выводе";
        КонецЕсли;
        Итог = Итог + Количество;
        Сообщить(Заказ + "/" + Код + "/" + Строка(Количество));
    КонецЦикла;
    Если Не ЕстьA01 Или Не ЕстьB02 Или Не ЕстьC03 Или Итог <> 17 Или Результат.Итог(КолонкаКоличества.Имя) <> 17 Тогда
        ВызватьИсключение "Все три собственные позиции и итог количества 17 должны сохраниться";
    КонецЕсли;
    Сообщить("Реальные три позиции связаны со своими заказами, количество=17.");
КонецПроцедуры

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

Функция СвойМакетВСтроку(Макет)
    Запись = Новый ЗаписьXML;
    Запись.УстановитьСтроку();
    СериализаторXDTO.ЗаписатьXML(Запись, Макет);
    Возврат Запись.Закрыть();
КонецФункции

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

Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры
УчебныйРазборПозиций85.Пульт

УчебныеВложенныеМакеты85 → Обработки → УчебныйРазборПозиций85 → Формы → Пульт → Модуль

Полный модуль собственной управляемой формы Пульт; не выполнялся.

&НаКлиенте
Процедура Выполнить(Команда)
    ВыполнитьНаСервере();
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
    УчебныеВложенныеМакеты85.ВыполнитьПример();
КонецПроцедуры

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

  1. СоздатьСвойСтендПозиций формирует два отдельных вложенных объекта ТаблицаЗначений, явные типы Код/Количество и числовые квалификаторы 10/0/Неотрицательный. ПроверитьСвойСтендПозиций сверяет каждую исходную ячейку, тип, имя и путь, а не только размер таблиц.

  2. Компоновщик строит настоящий макет по своей схеме и трём выбранным путям. НаборДанныхОбъектМакетаКомпоновкиДанных — уже описание исполнения, не исходный набор схемы; его ВложенныеНаборыДанных содержит настоящие ВложенныйНаборДанныхМакетаКомпоновкиДанных.

  3. Каталог.Получить(0) даёт элемент; Каталог.Найти("Позиции85") обязан вернуть тот же элемент. Отсутствующее имя проверяется на Неопределено. Имя означает исходное поле со вложенной таблицей; фактические ПутьКДанным и Отбор печатаются из макета и не подменяются выдуманными значениями.

  4. Поля у скомпилированного вложения — readonly-ссылка на настоящий каталог описаний. Код читает элементы, их имена/пути и сверяет поиск по фактическому имени. Нельзя писать Вложенный.Поля=Новый... или переносить это свойство на вложенное поле исходной схемы.

  5. Вывод.Вывести создаёт настоящий результат компоновки в ТаблицаЗначений. Проверка требует три строки и три колонки. Имя колонки составного пути может задаваться генератором: вместо догадки о точках/подчёркиваниях проверка просматривает все фактические колонки по всем строкам.

  6. Только для данного малого стенда роли колонок однозначны: O1/O2, A01/B02/C03 и числа 3/5/9 не пересекаются. Затем проверяются три точные пары заказ/позиция/количество, отсутствие повторов и лишних строк, независимая сумма и ТаблицаЗначений.Итог по фактическому имени колонки. Одна сумма 17 не обнаружила бы перепривязку позиции к чужому заказу.

  7. ТекстМакета — собственная строка полного макета. СвойМакетИзСтроки читает её как МакетКомпоновкиДанных, закрывая ЧтениеXML и при исключении. Черновик содержит независимый каталог; исходное вложение остаётся в оригинальном Макет.

  8. Добавить() создаёт Первый в конце, Вставить(0) — Второй перед настоящим скопированным вложением. Два черновика получают собственные допустимые имена/пути, пустой отбор и два описания полей. Они намеренно не имеют реальных внешних данных и ссылок в теле макета.

  9. Проверяются порядок Второй/Скопированное/Первый, Индекс(Первый)=2. Сдвинуть(Первый,-2) даёт Первый/Второй/Скопированное; Удалить(Второй) оставляет Первый/Скопированное. Затем Очистить убирает только элементы каталога черновика; старые ссылки после очистки больше не используются.

  10. Полностью новый Восстановленный читается из сохранённой исходной строки, а не конструируется по старым ссылкам. Сверяем имя/путь/отбор/число полей, затем настоящий процессор заново проверяет три пары и итог 17 у восстановленного и исходного полного макета. Исходные таблицы также повторно сверяются.

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

  1. Будущий ожидаемый вывод: O1/A01/3, O1/B02/5, O2/C03/9 в любом порядке; ровно три настоящие строки, три колонки и количество 17. Флаги ЕстьA01/ЕстьB02/ЕстьC03 запрещают повторные позиции даже при сохранённом общем размере.

  2. Отрицательный ручной контроль в отдельно разрешённом опыте: передать в проверку полученный реальный результат с C03, перепривязанным к O1. Сумма может остаться 17, но точная проверка O2/C03/9 должна отказать. Здесь этот контроль не выполнялся.

  3. Если компоновка вернула таблицу с вложенными объектами вместо ожидаемых трёх плоских детальных строк, урок должен остановиться на проверке. Не создавайте сами три строки эталона вместо настоящего вывода и не объявляйте такой обход успешной работой СКД.

  4. После Добавить/Вставить должно быть три элемента, после Сдвинуть правильный нулевой индекс Первого, после Удалить два элемента и отсутствующее ВтороеЧерновое85, после Очистить ноль только в Черновик. Каждый этап имеет отдельный отказ с понятной причиной.

  5. Исходный макет сохраняет тот же элемент Вложенный. Полностью восстановленный имеет один настоящий вложенный набор. Два повторных полных вывода и исходный вывод должны каждый дать O1/A01/3, O1/B02/5, O2/C03/9 и итог 17.

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

Ожидается настоящий вывод O1/A01/3, O1/B02/5, O2/C03/9; ровно три позиции, итог количества 17. Здесь в 1С не запускалось.

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

  1. Это подробный учебный проект ожидаемого опыта, не результат запуска в 1С: runtimeVerifiedScenarios=0. Нужна будущая проверка в собственной пустой базе; не исправляйте рабочие конфигурации ради примера.

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

  3. Не путайте вложенный набор макета с объединением наборов, вложенной схемой или группировкой настроек. В корневой native-странице вложенного элемента XDTO-имя названо DataSetUnion; из этой неоднозначной строки не выводится XML-тип. Здесь сериализуется весь настоящий МакетКомпоновкиДанных.

  4. Назначение ролей колонок по непересекающимся буквальным значениям применимо только к этому маленькому стенду. Это не универсальный способ разбора производственных отчётов: повторяющиеся значения и дополнительные колонки требуют отдельного явно согласованного контракта.

  5. Добавить() и Вставить(Индекс) вложенного каталога не принимают параметр Тип. Сдвинуть и Удалить получают собственный элемент этой же коллекции. Поля можно редактировать через его каталог, но readonly-свойство Поля нельзя заменять; неполные черновики не являются готовыми отчётами.

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

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

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

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

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