Очищает коллекцию.
Синтаксис
Очистить()Полное описание, параметры и ограничения
ПоляНабораДанныхСхемыКомпоновкиДанных.Очистить (DataCompositionSchemaDataSetFields.Clear)
ПоляНабораДанныхСхемыКомпоновкиДанных (DataCompositionSchemaDataSetFields)
Очистить (Clear)
Доступен, начиная с версии 8.1.
Синтаксис:
Очистить()
Описание:
Очищает коллекцию.
Доступность:
Сервер, толстый клиент, внешнее соединение.
Использование в версии:
Доступен, начиная с версии 8.1.
Методическая информация
Практические примеры
Заказы с настоящими вложенными таблицами позиций: поле СКД, пути и независимость
В памяти создаются O1 с A01/3 и B02/5, O2 с C03/9. Каждая ячейка Позиции85 содержит свою ТаблицуЗначений. Объектный набор описывает эти данные, а не подменяет их именем чужого набора или вложенной схемой.
Где и как запускать
Полный серверный общий модуль УчебныеЗадачи новой пустой конфигурации УчебныеВложенныеДанные85; в1С не запускался.
Подготовка
Только НОВАЯ пустая учебная база на платформе8.5.1.1343, не копия КА2/УНФ/УТ/БП и не рабочая база. В корне конфигурации установите Имя=УчебныеВложенныеДанные85. Не создавайте бизнес-метаданные, расширения, подписки и задания. Здесь база не создаётся и опыт не запускается.
Создайте вручную пустой общий модуль УчебныеЗадачи: Сервер=Да, Вызов сервера=Да; клиентские флаги, Глобальный и Привилегированный=Нет. Полный основной код вставляется целиком в этот модуль, не внутрь ещё одной процедуры.
Создайте свою внешнюю обработку УчебныеВложенныеДанные85 с управляемой Формой. Добавьте команду Выполнить, действие Выполнить и кнопку команды. Полный отдельный модуль формы ниже вставьте в её модуль. В нём нет неизвестных объектов и код общих модулей не смешивается с директивами формы.
До будущего отдельно разрешённого теста выполните F7 и обновление только собственной учебной базы вне процедуры. Откройте свежий сеанс без расширений. Весь пример создаёт только собственные объекты памяти; исходники конфигураций читались как доказательство способа описания полей и не изменялись.
Справка разрешает ВложенныйНаборДанныхСхемыКомпоновкиДанных в аргументе Поля.Добавить, но список возвращаемых типов этой страницы его опускает. Реальный модуль КА2 КонструкторФормулСлужебный, процедура ДобавитьГруппуЭлементовВНаборДанных, подтверждает именно создание через Добавить(Тип(...)) и составные дочерние пути. Это статическое подтверждение, не запуск этой конфигурации.
Процедура ВыполнитьПример() Экспорт
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Привилегированный режим не нужен";
КонецЕсли;
Стенд = СоздатьСвойСтендПозиций();
Копия = СоздатьСвойСтендПозиций();
ПроверитьСвойСтендПозиций(Стенд, Истина, "Позиции заказа", 5);
ПроверитьСвойСтендПозиций(Копия, Истина, "Позиции заказа", 5);
Набор = Стенд.Схема.НаборыДанных.Получить(0);
ВложенноеПоле = Набор.Поля.Получить(1);
ВложенноеПоле.Заголовок = "Строки учебного заказа";
ПроверитьСвойСтендПозиций(Стенд, Истина, "Строки учебного заказа", 5);
ПроверитьСвойСтендПозиций(Копия, Истина, "Позиции заказа", 5);
ВложенноеПоле.Заголовок = "Позиции заказа";
ПроверитьСвойСтендПозиций(Стенд, Истина, "Позиции заказа", 5);
Заказы = Стенд.ВнешниеДанные.Заказы85;
ПервыйЗаказ = Заказы.Получить(0);
ВтораяПозиция = ПервыйЗаказ.Позиции85.Получить(1);
ВтораяПозиция.Количество = 8;
ПроверитьСвойСтендПозиций(Стенд, Истина, "Позиции заказа", 8);
ПроверитьСвойСтендПозиций(Копия, Истина, "Позиции заказа", 5);
ВтораяПозиция.Количество = 5;
ПроверитьСвойСтендПозиций(Стенд, Истина, "Позиции заказа", 5);
Набор.Поля.Очистить();
ПроверитьСвойСтендПозиций(Стенд, Ложь, "Позиции заказа", 5);
ПроверитьСвойСтендПозиций(Копия, Истина, "Позиции заказа", 5);
ЗаполнитьСвоиОписанияПолей(Набор);
ПроверитьСвойСтендПозиций(Стенд, Истина, "Позиции заказа", 5);
ПроверитьСвойСтендПозиций(Копия, Истина, "Позиции заказа", 5);
КонецПроцедуры
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Функция СвойТипКоличества()
Возврат Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(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;
КонецЕсли;
Поле = Набор.Поля.Получить(ИндексПоля);
Если ТипЗнч(Поле) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных")
Или Поле.Поле <> Пути[Индекс] Или Поле.ПутьКДанным <> Пути[Индекс] Тогда
ВызватьИсключение "Не совпали все простые исходные поля и полные составные пути";
КонецЕсли;
ПроверитьСвойТип(Поле.ТипЗначения, Типы[Индекс]);
КонецЦикла;
КонецПроцедурыУчебныеВложенныеДанные85.Форма
Своя внешняя обработка УчебныеВложенныеДанные85 → управляемая Форма → Модуль
Полный отдельный модуль собственной формы с серверным вызовом; здесь не запускался.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
Сообщить("Вложенные таблицы позиций, полные пути, независимость и восстановление проверены");
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныеЗадачи.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
СвойТипКоличества возвращает описание Число с явно переданным вторым аргументом КвалификаторыЧисла(10,0,Неотрицательный). Проверка отдельно сравнивает единственный допустимый тип и все три числовых квалификатора. Строковые колонки также имеют явные описания.
Колонка Позиции85 намеренно создаётся без параметра Тип: справка Колонки.Добавить разрешает тогда значения любого типа. Мы не пытаемся включить ТаблицаЗначений в недоказанное ОписаниеТипов и не присваиваем readonly ТипЗначения колонки. Тип каждой фактической ячейки проверяется как ТаблицаЗначений до чтения её строк.
Для каждого заказа создаётся новая таблица позиций внутри цикла, не одна переиспользованная таблица. Проверка сравнивает обе колонки и каждый код/количество: O1 имеет ровно две строки, O2 ровно одну; номер, порядок и тип каждой ячейки проверяются.
Свой объектный набор Заказы85 с ИмяОбъекта=Заказы85 ссылается на настоящий внешний ключ Заказы85. Ключ, набор и имя объекта одинаковы намеренно; это не доказательство сопоставления разных имён. Local — имя вида логического источника, не новая реальная база.
Каталог Набор.Поля плоский: Номер85, описание вложенного поля Позиции85, затем простые Позиции85.Код и Позиции85.Количество. У ВложенногоПоля нет собственного каталога Поля. Поле указывает фактическую колонку с вложенными данными, ПутьКДанным — имя в модели и настройках, Заголовок — понятный пользователю текст; в этом опыте Поле и ПутьКДанным одинаковы.
Семь состояний оригинала: исходное, другой заголовок, возвращённый заголовок, B02=8, восстановленное B02=5, пустой каталог описаний, заново заполненный каталог. После очистки таблицы и их ячейки должны сохраниться. Промежуточный пустой каталог — редакторское состояние, не готовая схема для компоновки.
Пять сверок копии подтверждают исходные заголовки, четыре описания и все вложенные ячейки при изменениях оригинала. Копия создаётся заново со всеми своими таблицами, строками, структурой, источником, набором и полями. Это не неглубокая копия внешней таблицы с общими ссылками на внутренние таблицы.
После Набор.Поля.Очистить старая ссылка ВложенноеПоле больше не используется. Заполнение создаёт новые описания на той же собственной таблице. Процессор компоновки, компоновщик макета и запросы здесь не вызываются.
Как проверить результат
Ожидаемый будущий итог: O1 → A01/3, B02/5; O2 → C03/9. Один источник СвоиЗаказы85, один объектный набор Заказы85, четыре описания в исходном порядке и заголовок Позиции заказа. Проверка не ограничивается количеством элементов.
Будущий отрицательный контроль в собственном разрешённом опыте: после создания стенда заменить вторую вложенную ячейку B02 на X99 без изменения эталона. Полная проверка должна отказать даже при прежних размерах и типах. В другом отдельном опыте заменить вложенную таблицу строкой: отказ должен произойти до чтения её колонок. Здесь эти проверки не запускались.
При B02=8 проверяется сама изменённая ячейка оригинала, сохранение A01/3 и C03/9, неизменность всех ячеек копии и всей схемы. Это подтверждает задуманный тест независимости, но не полученный итог отчёта.
runtimeVerifiedScenarios=0. Успешные статические проверки не подтверждают создание объектов или компоновку в реальной 1С. Нет работы с записями бизнес-базы, запросов, сети, печати или изменения конфигураций.
Ожидаемый результат
Полный учебный стенд с настоящими вложенными значениями, описаниями полей и проверкой глубокой независимости; без исполнения отчёта.
На что обратить внимание
ВложенныйНаборДанныхСхемыКомпоновкиДанных — описание поля с вложенными данными. Это НЕ ВложеннаяСхемаКомпоновкиДанных и НЕ второй самостоятельный набор со своим именем. Текст Позиции85 без вложенных таблиц не заменяет реальные данные.
Свойства вложенного поля доступны на сервере и во внешнем соединении; здесь они не выносятся в тонкий клиент. Не угадывайте конструктор, Имя, ТипЗначения, Поля или АвтоЗаполнениеДоступныхПолей у этого типа: справка объявляет только Заголовок, Поле и ПутьКДанным.
Нет гарантии автозаполнения, разворачивания позиций в выводе, группировки, суммы17 или работы произвольного источника. Для этого нужен отдельный разрешённый опыт с настройками, макетом и процессором. Этот урок проверяет собственную модель и данные.
Колонка Позиции85 принимает любой тип по своему объявлению: ограничение ТаблицаЗначений обеспечивает явная проверка содержимого, а не фиктивная типизация. Проверка не утверждает недоказанный размер массива Типы() для такого описания.
Read-only каталог Набор.Поля не заменяется новым объектом: меняется содержимое каталога через Добавить и Очистить. Очистка описаний не должна выдавать себя за удаление собственных вложенных строк; обе части модели проверяются независимо.
Не копируйте типы, названия бизнес-метаданных или права КА2 в новую базу. Подтверждённый фрагмент использован только как доказательство способа создания описаний и дочерних путей. runtime остаётся0.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.
Объединённый набор СКД: редактор двух запросов и полей с полным восстановлением
Создаём один настоящий набор-объединение, а внутри — собственные буквальные запросы A01/3 и B02/5. Редактируем порядок и состав частей, затем каталог полей первой части. Каждый шаг сверяет полную схему и независимую копию; финал заново восстанавливает обе части и все типизированные поля.
Где и как запускать
Полный серверный общий модуль УчебныеЗадачи новой пустой конфигурации УчебноеОбъединение85; редактор собственной модели, не запуск1С.
Подготовка
НОВАЯ отдельная учебная база, не копия рабочей: точно8.5.1.1343, конфигурация УчебноеОбъединение85, совместимость Не использовать. Нет справочников, документов, регистров, расширений, подписок и заданий. Все модули вручную пустые, кроме данного общего модуля.
Конфигуратор → Общие → Общие модули → УчебныеЗадачи: Сервер=Да, Вызов сервера=Да, Клиент=Нет, Глобальный=Нет, Привилегированный=Нет. Вставить ВЕСЬ основной код. Своя внешняя обработка УчебноеОбъединение85 → управляемая Форма: команда/кнопка Выполнить с действием Выполнить. Полный модуль формы приведён отдельно ниже; реквизиты не нужны.
Будущая ручная подготовка вне опыта: завершить прежний свой сеанс, сохранить, Конфигурация → Обновить конфигурацию базы данных (F7), открыть свежий свой клиент и свою обработку. Здесь ни F7, ни 1С, ни запросы не запускались.
Записи учебной базы не нужны: код сам объявляет один Local-источник СвоиОбъединения85, корневой Объединение85, два запроса и их поля Код Строка/Количество Число. У частей автозаполнение выключено; реальные имена/полные запросы/описания полей задаются явно.
Процедура ВыполнитьПример() Экспорт
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Привилегированный режим в своём редакторе не нужен";
КонецЕсли;
Пусто = Новый Массив;
Имена = СтрРазделить("ПервыйНабор85,ВторойНабор85", ",");
Поля = СтрРазделить("Код,Количество", ",");
Схема = СоздатьСвоюОсновуОбъединения();
Объединение = Схема.НаборыДанных.Получить(0);
Каталог = Объединение.Элементы;
ПроверитьСвоиНаборы(Схема, Пусто, Поля);
Первый = Каталог.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
ЗаполнитьСвойНабор(Схема, Первый, "ПервыйНабор85");
ПроверитьСвоиНаборы(Схема, СтрРазделить("ПервыйНабор85", ","), Поля);
Второй = Каталог.Вставить(0, Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
ЗаполнитьСвойНабор(Схема, Второй, "ВторойНабор85");
ПроверитьСвоиНаборы(Схема, СтрРазделить("ВторойНабор85,ПервыйНабор85", ","), Поля);
Каталог.Сдвинуть(Второй, 1);
ПроверитьСвоиНаборы(Схема, Имена, Поля);
Копия = СоздатьСвоюОсновуОбъединения();
ВосстановитьСвоиНаборы(Копия);
ПроверитьСвоиНаборы(Копия, Имена, Поля);
КаталогПолей = Первый.Поля;
ПолеКоличество = КаталогПолей.Получить(1);
КаталогПолей.Удалить(ПолеКоличество);
ПроверитьСвоиНаборы(Схема, Имена, СтрРазделить("Код", ","));
НовоеПолеКоличество = КаталогПолей.Вставить(0, Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
ЗаполнитьСвоеПоле(КаталогПолей, НовоеПолеКоличество, "Количество");
ПроверитьСвоиНаборы(Схема, Имена, СтрРазделить("Количество,Код", ","));
КаталогПолей.Сдвинуть(НовоеПолеКоличество, 1);
ПроверитьСвоиНаборы(Схема, Имена, Поля);
КаталогПолей.Очистить();
ПроверитьСвоиНаборы(Схема, Имена, Пусто);
ПроверитьСвоиНаборы(Копия, Имена, Поля);
ВосстановитьСвоиПоля(КаталогПолей);
ПроверитьСвоиНаборы(Схема, Имена, Поля);
Каталог.Удалить(Первый);
ПроверитьСвоиНаборы(Схема, СтрРазделить("ВторойНабор85", ","), Поля);
ПроверитьСвоиНаборы(Копия, Имена, Поля);
НовыйПервый = Каталог.Вставить(0, Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
ЗаполнитьСвойНабор(Схема, НовыйПервый, "ПервыйНабор85");
ПроверитьСвоиНаборы(Схема, Имена, Поля);
Каталог.Очистить();
ПроверитьСвоиНаборы(Схема, Пусто, Поля);
ПроверитьСвоиНаборы(Копия, Имена, Поля);
ВосстановитьСвоиНаборы(Схема);
ПроверитьСвоиНаборы(Схема, Имена, Поля);
ПроверитьСвоиНаборы(Копия, Имена, Поля);
Сообщить("Свои части объединения и поля полностью восстановлены; копия не изменилась");
КонецПроцедуры
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Функция ИмяТипаСвоегоПоля(Имя)
Если Имя = "Код" Тогда
Возврат "Строка";
ИначеЕсли Имя = "Количество" Тогда
Возврат "Число";
КонецЕсли;
ВызватьИсключение "В своём объединении используются только Код и Количество";
КонецФункции
Функция СвойЗапросНабора(Имя)
Если Имя = "ПервыйНабор85" Тогда
Возврат "ВЫБРАТЬ ""A01"" КАК Код, 3 КАК Количество";
ИначеЕсли Имя = "ВторойНабор85" Тогда
Возврат "ВЫБРАТЬ ""B02"" КАК Код, 5 КАК Количество";
КонецЕсли;
ВызватьИсключение "В своём объединении только два известных буквальных запроса";
КонецФункции
Процедура ЗаполнитьСвоеПоле(Каталог, Поле, Имя)
Если ТипЗнч(Каталог) <> Тип("ПоляНабораДанныхСхемыКомпоновкиДанных")
Или ТипЗнч(Поле) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных") Или Каталог.Индекс(Поле) < 0 Тогда
ВызватьИсключение "Нужно текущее простое поле именно своего каталога";
КонецЕсли;
ИмяТипа = ИмяТипаСвоегоПоля(Имя);
Поле.Поле = Имя;
Поле.ПутьКДанным = Имя;
Поле.ТипЗначения = Новый ОписаниеТипов(ИмяТипа);
КонецПроцедуры
Процедура ПроверитьСвоиПоля(Каталог, Имена)
Если ТипЗнч(Каталог) <> Тип("ПоляНабораДанныхСхемыКомпоновкиДанных") Или Каталог.Количество() <> Имена.Количество() Тогда
ВызватьИсключение "Не совпал полный состав своего каталога полей";
КонецЕсли;
Для Индекс = 0 По Имена.Количество() - 1 Цикл
Поле = Каталог.Получить(Индекс);
Если ТипЗнч(Поле) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных")
Или Поле.Поле <> Имена[Индекс] Или Поле.ПутьКДанным <> Имена[Индекс]
Или Каталог.Индекс(Поле) <> Индекс Или Каталог[Индекс] <> Поле
Или ТипЗнч(Поле.ТипЗначения) <> Тип("ОписаниеТипов") Тогда
ВызватьИсключение "Не совпали полные имена, пути, порядок и типы полей";
КонецЕсли;
ИмяТипа = ИмяТипаСвоегоПоля(Имена[Индекс]);
ПолныеТипы = Поле.ТипЗначения.Типы();
Если ПолныеТипы.Количество() <> 1 Или ПолныеТипы[0] <> Тип(ИмяТипа) Тогда
ВызватьИсключение "Не совпал полный единственный тип собственного поля";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ВосстановитьСвоиПоля(Каталог)
Пусто = Новый Массив;
ПроверитьСвоиПоля(Каталог, Пусто);
Имена = СтрРазделить("Код,Количество", ",");
Для Каждого Имя Из Имена Цикл
Поле = Каталог.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
ЗаполнитьСвоеПоле(Каталог, Поле, Имя);
КонецЦикла;
ПроверитьСвоиПоля(Каталог, Имена);
КонецПроцедуры
Функция СоздатьСвоюОсновуОбъединения()
Схема = Новый СхемаКомпоновкиДанных;
Источник = Схема.ИсточникиДанных.Добавить();
Источник.Имя = "СвоиОбъединения85";
Источник.ТипИсточникаДанных = "Local";
Объединение = Схема.НаборыДанных.Добавить(Тип("НаборДанныхОбъединениеСхемыКомпоновкиДанных"));
Если ТипЗнч(Объединение) <> Тип("НаборДанныхОбъединениеСхемыКомпоновкиДанных") Тогда
ВызватьИсключение "Нужен настоящий свой набор-объединение, не запрос";
КонецЕсли;
Объединение.Имя = "Объединение85";
ВосстановитьСвоиПоля(Объединение.Поля);
Пусто = Новый Массив;
ПроверитьСвоиНаборы(Схема, Пусто, СтрРазделить("Код,Количество", ","));
Возврат Схема;
КонецФункции
Процедура ЗаполнитьСвойНабор(Схема, Набор, Имя)
Объединение = Схема.НаборыДанных.Получить(0);
Если ТипЗнч(Объединение) <> Тип("НаборДанныхОбъединениеСхемыКомпоновкиДанных")
Или ТипЗнч(Набор) <> Тип("НаборДанныхЗапросСхемыКомпоновкиДанных") Или Объединение.Элементы.Индекс(Набор) < 0 Тогда
ВызватьИсключение "Нужен текущий свой запрос именно внутри своего объединения";
КонецЕсли;
Набор.Имя = Имя;
Набор.ИсточникДанных = "СвоиОбъединения85";
Набор.АвтоЗаполнениеДоступныхПолей = Ложь;
Набор.Запрос = СвойЗапросНабора(Имя);
ВосстановитьСвоиПоля(Набор.Поля);
КонецПроцедуры
Процедура ПроверитьСвоиНаборы(Схема, Имена, ПоляПервого)
Если ТипЗнч(Схема) <> Тип("СхемаКомпоновкиДанных") Или Схема.ИсточникиДанных.Количество() <> 1
Или Схема.НаборыДанных.Количество() <> 1 Тогда
ВызватьИсключение "В корне своей схемы только источник и объединение";
КонецЕсли;
Источник = Схема.ИсточникиДанных.Получить(0);
Если ТипЗнч(Источник) <> Тип("ИсточникДанныхСхемыКомпоновкиДанных")
Или Источник.Имя <> "СвоиОбъединения85" Или Источник.ТипИсточникаДанных <> "Local" Тогда
ВызватьИсключение "Не совпал свой полный источник";
КонецЕсли;
Объединение = Схема.НаборыДанных.Получить(0);
Если ТипЗнч(Объединение) <> Тип("НаборДанныхОбъединениеСхемыКомпоновкиДанных")
Или Объединение.Имя <> "Объединение85" Или Схема.НаборыДанных.Найти("Объединение85") <> Объединение
Или Схема.НаборыДанных.Индекс(Объединение) <> 0 Тогда
ВызватьИсключение "Не совпали тип, имя и поиск собственного объединения";
КонецЕсли;
ВсеПоля = СтрРазделить("Код,Количество", ",");
ПроверитьСвоиПоля(Объединение.Поля, ВсеПоля);
Каталог = Объединение.Элементы;
Если ТипЗнч(Каталог) <> Тип("НаборыДанныхСхемыКомпоновкиДанных") Или Каталог.Количество() <> Имена.Количество() Тогда
ВызватьИсключение "Не совпал весь состав собственных частей объединения";
КонецЕсли;
Для Индекс = 0 По Имена.Количество() - 1 Цикл
Набор = Каталог.Получить(Индекс);
Если ТипЗнч(Набор) <> Тип("НаборДанныхЗапросСхемыКомпоновкиДанных")
Или Набор.Имя <> Имена[Индекс] Или Каталог.Индекс(Набор) <> Индекс
Или Каталог[Индекс] <> Набор Или Каталог.Найти(Имена[Индекс]) <> Набор
Или Набор.ИсточникДанных <> "СвоиОбъединения85" Или Набор.АвтоЗаполнениеДоступныхПолей
Или Набор.Запрос <> СвойЗапросНабора(Имена[Индекс]) Тогда
ВызватьИсключение "Не совпали полные собственные запросы, источник, порядок и поиск частей";
КонецЕсли;
ОжидаемыеПоля = ВсеПоля;
Если Набор.Имя = "ПервыйНабор85" Тогда
ОжидаемыеПоля = ПоляПервого;
КонецЕсли;
ПроверитьСвоиПоля(Набор.Поля, ОжидаемыеПоля);
КонецЦикла;
Если Каталог.Найти("НетТакогоНабора85") <> Неопределено Тогда
ВызватьИсключение "Отсутствующая своя часть не должна находиться";
КонецЕсли;
КонецПроцедуры
Процедура ВосстановитьСвоиНаборы(Схема)
Пусто = Новый Массив;
ПроверитьСвоиНаборы(Схема, Пусто, СтрРазделить("Код,Количество", ","));
Каталог = Схема.НаборыДанных.Получить(0).Элементы;
Первый = Каталог.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
ЗаполнитьСвойНабор(Схема, Первый, "ПервыйНабор85");
Второй = Каталог.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
ЗаполнитьСвойНабор(Схема, Второй, "ВторойНабор85");
КонецПроцедурыУчебноеОбъединение85.Форма
Своя внешняя обработка УчебноеОбъединение85 → управляемая Форма → Модуль
Полный отдельный модуль своей формы с серверным вызовом; здесь не запускался.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
Сообщить("Объединение, два каталога, полное восстановление и независимая копия проверены");
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныеЗадачи.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
Набор-объединение получается через Схема.НаборыДанных.Добавить(Тип(...)), не через Новый и не подменяется запросом. У него Имя, Поля и Элементы. Элементы — собственный каталог составных частей, а не результаты выполнения запроса.
Readonly у Поля и Элементы запрещает замену свойства целиком, но не операции над возвращёнными коллекциями. В справке поля объединения описаны как определения ограничений идентичности. Здесь задаём совместимые Код/Количество в модели и сверяем полные пути/типы; не обещаем поведение SQL ОБЪЕДИНИТЬ ВСЕ.
Добавить первый запрос в конец; Вставить(0,Тип(...)) второй перед ним. Проверить обратный порядок и полный текст каждого своего запроса; Сдвинуть(Второй,1) перемещает именно текущий объект на относительное смещение. Индекс, Получить, [] и Найти подтверждают принадлежность и положение.
В первой части удалить поле Количество как объект. Вставить новый объект поля в0, заполнить весь путь/тип; проверить Количество/Код и переставить его на1. Очистить собственные поля и проверить0, сохраняя обе части, их запросы и полный каталог полей объединения. Затем заново построить поля Код/Количество.
Тринадцать контрольных состояний оригинала сверяют весь корень схемы, имя/тип источника, корневое объединение, его два поля, текущий состав частей, полные запросы/флаги/источник, реальные имена/пути/полные наборы типов полей, порядок и положительный/отрицательный поиск частей. Это не проверки одних размеров.
Независимая копия заново создаёт свой источник, объединение, поля и обе части. Пять сверок копии показывают неизменность после очистки полей, удаления первой части и очистки каталога частей оригинала. Ссылки на дочерние объекты оригинала в копию не переносятся.
Удалить первую часть как объект, не индекс; вставить новый запрос в0 и полностью заполнить. Очистить только Элементы собственного объединения: источник, корневой объект и его поля сохраняются. Проверить пустой состав и заново создать обе части в правильном порядке.
Отсутствующие поля или пустой каталог частей — временно неполные состояния РЕДАКТОРА. Они не выдаются за готовую к выполнению схему. После восстановления финал содержит оба полных запроса с двумя согласованными полями в каждой части; движок СКД не запускается.
Как проверить результат
Будущий итог модели: в корне один источник и Объединение85; Элементы содержат ПервыйНабор85/ВторойНабор85. Во всех трёх каталогах полей полный состав Код Строка/Количество Число; запросы строго равны своим исходным строкам, AutoFields=Ложь. Копия имеет тот же полный состав.
Тексты своих запросов объявляют A01/3 и B02/5. Это исходные литералы, не полученные строки результата и не доказательство объединения, удаления дублей, суммирования или порядка вывода. Ни один запрос или компоновщик здесь не выполнялся.
Будущий отрицательный контроль: после полного заполнения заменить только текст первого запроса на Количество=30, оставив прежние имена/число полей. Полная проверка должна отказать по тексту запроса. Другой контроль: тип поля Количество заменить на Строка — отказ по полному набору типов. Здесь контроля не было.
runtimeVerifiedScenarios=0. Только статическая сверка установленной справки8.5.1.1343 и итогового HTML. Нет рабочих данных, чтения/записи записей, исполнения1С, компоновки, сети или печати.
Ожидаемый результат
Содержательный редактор структуры объединения: две реальные собственные части, полный цикл обоих каталогов и независимое восстановление без выдуманного результата отчёта.
На что обратить внимание
Вставить получает ИНДЕКС, затем объект типа Тип. Не передавать готовый экземпляр, строку имени типа или перепутанные аргументы. Добавить набора при неподходящем типе может вернуть Неопределено; помощник проверяет реальный возвращённый тип до чтения свойств.
Индекс и Удалить принимают действительный объект своего каталога, Сдвинуть — объект и относительное смещение. После удаления/очистки прежние ссылки на поля и части не используются; восстановление создаёт новые объекты.
Найти применяется к конкретному каталогу частей. Не предполагается недокументированный рекурсивный поиск по всем объединениям; поля проверяются по индексу и полным именам без выдуманного метода Найти.
Перестановка описаний не доказывает сортировку строк будущего результата. Имена полей отображают псевдонимы собственных запросов; несовместимость типов/путей и временное отсутствие описаний не скрываются.
Это не конструктор готового визуального отчёта и не пример запуска SQL UNION ALL. Выбор полей, ресурсы, группировки, настройки, компиляция и вывод — отдельные уроки и отдельная runtime-проверка.
В КА2 отчёт АнализДоходовРасходов действительно имеет DataSetUnion:83 определения field и11 item, первые части Выручка/Себестоимость — DataSetQuery на ИсточникДанных1. Здесь повторяется структура собственного малого объединения, рабочий отчёт не вызывается и его выгрузка не изменяется.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.