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