Тип: СправочникСсылка.<Имя справочника>. Содержит ссылку на элемент справочника. Это значение может быть записано в базу данных для полей соответствующего типа.
Полное описание, параметры и ограничения
СправочникВыборка.<Имя справочника>.Ссылка (CatalogSelection.<Catalog name>.Ref)
СправочникВыборка.<Имя справочника> (CatalogSelection.<Catalog name>)
Ссылка (Ref)
Доступен, начиная с версии 8.0.
Использование:
Только чтение.
Описание:
Тип: СправочникСсылка.<Имя справочника>.
Содержит ссылку на элемент справочника. Это значение может быть записано в базу данных для полей соответствующего типа.
Доступность:
Сервер, толстый клиент, внешнее соединение, мобильное приложение (сервер), мобильный автономный сервер.
Использование в версии:
Доступен, начиная с версии 8.0.
Методическая информация
Практические примеры
Прочитать товары группы: выборка, поля текущей строки и объект
Показываем G01 → A01 Книга и A02 Ручка, отдельно выбираем BOOK-A по индексированному артикулу и две корневые группы. Объект текущей строки читается без изменений.
Где и как запускать
Учебная база: создайте серверный общий модуль УчебныеЗадачи (флаг Сервер). Код без директив вставьте в тело процедуры ВыполнитьПример() Экспорт. Вызовите её из серверного обработчика команды учебной обработки. Не запускайте в рабочей базе.
Подготовка
Создайте НОВУЮ пустую файловую базу на точной платформе 8.5.1.1343. Имя конфигурации УчебныеВыборкиКаталога85, совместимость НеИспользовать. Это не копия рабочих УТ/КА/УНФ/БП; исходные конфигурации и рабочие базы не трогайте. Здесь код не запускался: runtimeVerifiedScenarios=0.
Создайте единственный справочник УчебныеТовары: иерархия групп и элементов, владельцы не назначены, предопределенных данных нет, код Строка длиной 10, автонумерация выключена, контроль уникальности включён, наименование длиной 100. Других объектов хранения данных не добавляйте.
Добавьте единственный реквизит Артикул: Строка длиной 20, использование для групп и элементов, Индексировать. Индекс обязателен для отбора Выбрать по этому реквизиту. Табличных частей нет. Модули справочника/менеджера, подписки, регламентные задания, разделители и расширения должны быть пустыми/отсутствовать.
Создайте два неглобальных общих модуля: УчебныйКаталог85 и УчебныеПримерыКаталога85, Сервер=Да, клиентские флаги=Нет, Вызов сервера=Да, привилегированный режим=Нет. В первый вставьте полный общий модуль подготовки ниже; во второй — полный основной код только одного выбранного урока. Не склеивайте разные процедуры ВыполнитьПример.
Создайте собственную обработку УчебныйПульт85, управляемую форму Пульт, команду Выполнить и кнопку этой команды. В модуль формы вставьте полный отдельный модуль запуска ниже и назначьте действие команды Выполнить. Обновите конфигурацию базы, проверьте F7; до запуска вручную сверяйте настройки справочника.
Данные создаёт сам урок: G01 Основной и G02 Архив в корне; A01 Книга/BOOK-A и A02 Ручка/PEN-A в Основной; B01 Книга/BOOK-B в Архив. Все пять записей существуют лишь внутри собственной транзакции. При успехе и ошибке выполняется откат; фиксации нет.
Будущий ручной запуск вызывает настоящую запись пяти собственных строк в учебной базе до отката. Откат не отменяет внешние действия неизвестных обработчиков, поэтому рабочая конфигурация или её копия здесь недопустима. Запускайте одним пользователем, вне чужой транзакции; существующие данные код не удаляет.
Процедура ВыполнитьПример() Экспорт
УчебныйКаталог85.ПроверитьСвойСтенд();
НачатьТранзакцию();
Попытка
Данные = УчебныйКаталог85.ПодготовитьСвоиТовары();
Менеджер = Справочники.УчебныеТовары;
Выборка = Менеджер.Выбрать(Данные.G01, , , "Код Возр");
Если ТипЗнч(Выборка) <> Тип("СправочникВыборка.УчебныеТовары") Тогда
ВызватьИсключение "Ожидалась выборка своего справочника";
КонецЕсли;
Коды = Новый Массив;
Пока Выборка.Следующий() Цикл
Если Выборка.Родитель <> Данные.G01 Или Выборка.ЭтоГруппа Или Выборка.ПометкаУдаления
Или Выборка.Предопределенный Или Выборка.ИмяПредопределенныхДанных <> ""
Или Выборка.Владелец <> Неопределено Или ТипЗнч(Выборка.ВерсияДанных) <> Тип("Строка") Тогда
ВызватьИсключение "Строка выборки не соответствует собственному учебному набору";
КонецЕсли;
Если Не Данные.Свойство(Выборка.Код, ОжидаемаяСсылка) Или ОжидаемаяСсылка <> Выборка.Ссылка Тогда
ВызватьИсключение "Код и ссылка своей строки расходятся";
КонецЕсли;
Объект = Выборка.ПолучитьОбъект();
Если Объект = Неопределено Тогда
ВызватьИсключение "Объект текущей строки отсутствует";
КонецЕсли;
Если Объект.Ссылка <> Выборка.Ссылка Или Объект.Наименование <> Выборка.Наименование
Или Объект.ВерсияДанных <> Выборка.ВерсияДанных Тогда
ВызватьИсключение "Прочитанный объект не соответствует текущей строке выборки";
КонецЕсли;
Сообщить(Выборка.Код + ": " + Выборка.Наименование + "; артикул " + Объект.Артикул);
Коды.Добавить(Выборка.Код);
КонецЦикла;
Если Коды.Количество() <> 2 Или СтрСоединить(Коды, ",") <> "A01,A02" Тогда
ВызватьИсключение "Ожидались только два непосредственных потомка G01";
КонецЕсли;
Отбор = Новый Структура("Артикул", "BOOK-A");
Отобранные = Менеджер.Выбрать(, , Отбор, "Код Возр");
Если Не Отобранные.Следующий() Тогда
ВызватьИсключение "Книга BOOK-A не найдена";
КонецЕсли;
Если Отобранные.Ссылка <> Данные.A01 Или Отобранные.Следующий() Тогда
ВызватьИсключение "Ожидалась единственная книга BOOK-A";
КонецЕсли;
Корень = Менеджер.Выбрать(Данные.Пустая, , , "Код Возр");
Группы = Новый Массив;
Пока Корень.Следующий() Цикл
Если Не Корень.ЭтоГруппа Тогда
ВызватьИсключение "В своём корне подготовлены только группы";
КонецЕсли;
Группы.Добавить(Корень.Код);
КонецЦикла;
Если СтрСоединить(Группы, ",") <> "G01,G02" Тогда
ВызватьИсключение "Пустая ссылка должна ограничить выборку корнем";
КонецЕсли;
ОтменитьТранзакцию();
Исключение
Если ТранзакцияАктивна() Тогда
ОтменитьТранзакцию();
КонецЕсли;
ВызватьИсключение;
КонецПопытки;
УчебныйКаталог85.ПроверитьОткат(Данные);
Сообщить("Собственные пять строк отменены; учебный справочник снова пуст");
КонецПроцедурыУчебныйКаталог85
УчебныеВыборкиКаталога85 → Общие → Общие модули → УчебныйКаталог85
Полный серверный общий модуль: защита стенда, подготовка пяти записей и проверка отката. Не выполнялся.
Процедура ПроверитьСвойСтенд() Экспорт
Если Метаданные.Справочники.Количество() <> 1 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Каталог = Метаданные.Справочники[0];
Если Каталог.Имя <> "УчебныеТовары" Или Не Каталог.Иерархический
Или Каталог.Реквизиты.Количество() <> 1 Или Каталог.Реквизиты.Найти("Артикул") = Неопределено Тогда
ВызватьИсключение "Нужен собственный иерархический справочник с единственным реквизитом Артикул";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Функция ПодготовитьСвоиТовары() Экспорт
Если Не ТранзакцияАктивна() Тогда
ВызватьИсключение "Подготовка допустима только внутри собственной отменяемой транзакции";
КонецЕсли;
ПроверкаПустоты = Справочники.УчебныеТовары.Выбрать();
Если ПроверкаПустоты.Следующий() Тогда
ВызватьИсключение "Учебный справочник должен быть пуст; чужие записи не изменяются";
КонецЕсли;
Пустая = Справочники.УчебныеТовары.ПустаяСсылка();
Данные = Новый Структура;
Данные.Вставить("G01", СоздатьСвоюСтроку("G01", "Основной", "GROUP-A", Пустая, Истина));
Данные.Вставить("G02", СоздатьСвоюСтроку("G02", "Архив", "GROUP-B", Пустая, Истина));
Данные.Вставить("A01", СоздатьСвоюСтроку("A01", "Книга", "BOOK-A", Данные.G01, Ложь));
Данные.Вставить("A02", СоздатьСвоюСтроку("A02", "Ручка", "PEN-A", Данные.G01, Ложь));
Данные.Вставить("B01", СоздатьСвоюСтроку("B01", "Книга", "BOOK-B", Данные.G02, Ложь));
Данные.Вставить("Пустая", Пустая);
Возврат Данные;
КонецФункции
Функция СоздатьСвоюСтроку(Код, Наименование, Артикул, Родитель, Группа)
Если Группа Тогда
Объект = Справочники.УчебныеТовары.СоздатьГруппу();
Иначе
Объект = Справочники.УчебныеТовары.СоздатьЭлемент();
КонецЕсли;
Ссылка = Справочники.УчебныеТовары.ПолучитьСсылку(Новый УникальныйИдентификатор);
Объект.УстановитьСсылкуНового(Ссылка);
Объект.Код = Код;
Объект.Наименование = Наименование;
Объект.Артикул = Артикул;
Объект.Родитель = Родитель;
Объект.Записать();
Прочитанный = Ссылка.ПолучитьОбъект();
Если Прочитанный = Неопределено Тогда
ВызватьИсключение "Собственная учебная запись не прочитана";
КонецЕсли;
Если Прочитанный.Код <> Код Или Прочитанный.Наименование <> Наименование
Или Прочитанный.Артикул <> Артикул Или Прочитанный.Родитель <> Родитель
Или Прочитанный.ЭтоГруппа <> Группа Тогда
ВызватьИсключение "Прочитанная учебная строка отличается от подготовленной";
КонецЕсли;
Возврат Ссылка;
КонецФункции
Процедура ПроверитьОткат(Данные) Экспорт
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Собственная транзакция не завершена";
КонецЕсли;
Для Каждого Имя Из СтрРазделить("G01,G02,A01,A02,B01", ",") Цикл
Если Данные[Имя].ПолучитьОбъект() <> Неопределено Тогда
ВызватьИсключение "Собственная запись осталась после отката: " + Имя;
КонецЕсли;
КонецЦикла;
ПроверкаПустоты = Справочники.УчебныеТовары.Выбрать();
Если ПроверкаПустоты.Следующий() Тогда
ВызватьИсключение "После отката справочник не пуст";
КонецЕсли;
КонецПроцедурыУчебныйПульт85.Пульт
УчебныеВыборкиКаталога85 → Обработки → УчебныйПульт85 → Формы → Пульт → Модуль
Полный модуль управляемой формы только собственной обработки. Не выполнялся.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныеПримерыКаталога85.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
Выбрать(G01) ограничивает непосредственным родителем, а не всем деревом. Четвёртый параметр Код Возр задаёт проверяемый порядок A01,A02; второй параметр владельца пропущен, поскольку справочник неподчинённый.
После получения выборки обязательно Следующий: только успешное позиционирование разрешает читать текущую строку. Выборка читает базу порциями, это не готовый массив всех записей.
Код, Наименование и Ссылка сверяются с собственным набором. Родитель равен G01; ЭтоГруппа, ПометкаУдаления и Предопределенный ложны; ИмяПредопределенныхДанных пустое. Свойства выборки доступны только для чтения.
Владелец равен Неопределено именно у неподчинённого справочника. Это не пустая ссылка владельца и не пример выбора подчинённых объектов.
ВерсияДанных — служебная строка, не версия платформы и не бизнес-номер. На своём неизменяемом наборе сравниваем её с только что прочитанным объектом; конкретное содержимое не фиксируем.
ПолучитьОбъект возвращает объект текущей записи либо Неопределено, поэтому сначала проверяем отсутствие. Читаем из него собственный Артикул, но не меняем и не записываем объект.
Отбор содержит только один ключ Артикул. Индексирование задано в подготовке; два поля отбора через эту структуру добавлять нельзя — для сложного условия нужен запрос.
Выбрать(ПустаяСсылка) выбирает корень, тогда как пропущенный родитель не ограничивает уровень. По окончании и при исключении пять собственных записей откатываются.
Как проверить результат
Ожидаются строки A01: Книга; артикул BOOK-A и A02: Ручка; артикул PEN-A. Контрольные проверки подтверждают A01,A02, единственную BOOK-A и корень G01,G02.
После сообщения об откате список снова пуст. Убедитесь в этом в своём учебном списке; код дополнительно проверяет отсутствие всех пяти собственных ссылок.
Для проверки ошибки в копии урока поменяйте ожидаемую строку A01,A02 на A02,A01, не порядок метода. Должно быть исключение с откатом, а не успешное сообщение.
Ожидаемый результат
Прочитаны две строки группы, одна строка индексированного отбора и две группы корня; все пять подготовленных записей отменены. runtimeVerifiedScenarios=0.
На что обратить внимание
Не присваивайте свойства выборки: они readonly. Изменения записывают через объект и только в отдельной разрешённой задаче; этот урок этого не делает.
Нельзя читать поля после Следующий=Ложь. В большой или многопользовательской базе конкурентные изменения требуют отдельной модели согласованности.
Сравнение ВерсияДанных здесь проверяет свой неизменяемый набор, а не заменяет механизм блокировок.
Индекс и ограниченная длина артикула обязательны; произвольный неиндексированный реквизит для Выбрать недопустим.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.
Обойти дерево товаров и выбрать только существующие ссылки
Проверяем, что каждая группа прочитана перед своими товарами и уровни равны 0/1. Затем массив содержит две действительные ссылки, строку и собственную ссылку без записи.
Где и как запускать
Учебная база: создайте серверный общий модуль УчебныеЗадачи (флаг Сервер). Код без директив вставьте в тело процедуры ВыполнитьПример() Экспорт. Вызовите её из серверного обработчика команды учебной обработки. Не запускайте в рабочей базе.
Подготовка
Создайте НОВУЮ пустую файловую базу на точной платформе 8.5.1.1343. Имя конфигурации УчебныеВыборкиКаталога85, совместимость НеИспользовать. Это не копия рабочих УТ/КА/УНФ/БП; исходные конфигурации и рабочие базы не трогайте. Здесь код не запускался: runtimeVerifiedScenarios=0.
Создайте единственный справочник УчебныеТовары: иерархия групп и элементов, владельцы не назначены, предопределенных данных нет, код Строка длиной 10, автонумерация выключена, контроль уникальности включён, наименование длиной 100. Других объектов хранения данных не добавляйте.
Добавьте единственный реквизит Артикул: Строка длиной 20, использование для групп и элементов, Индексировать. Индекс обязателен для отбора Выбрать по этому реквизиту. Табличных частей нет. Модули справочника/менеджера, подписки, регламентные задания, разделители и расширения должны быть пустыми/отсутствовать.
Создайте два неглобальных общих модуля: УчебныйКаталог85 и УчебныеПримерыКаталога85, Сервер=Да, клиентские флаги=Нет, Вызов сервера=Да, привилегированный режим=Нет. В первый вставьте полный общий модуль подготовки ниже; во второй — полный основной код только одного выбранного урока. Не склеивайте разные процедуры ВыполнитьПример.
Создайте собственную обработку УчебныйПульт85, управляемую форму Пульт, команду Выполнить и кнопку этой команды. В модуль формы вставьте полный отдельный модуль запуска ниже и назначьте действие команды Выполнить. Обновите конфигурацию базы, проверьте F7; до запуска вручную сверяйте настройки справочника.
Данные создаёт сам урок: G01 Основной и G02 Архив в корне; A01 Книга/BOOK-A и A02 Ручка/PEN-A в Основной; B01 Книга/BOOK-B в Архив. Все пять записей существуют лишь внутри собственной транзакции. При успехе и ошибке выполняется откат; фиксации нет.
Будущий ручной запуск вызывает настоящую запись пяти собственных строк в учебной базе до отката. Откат не отменяет внешние действия неизвестных обработчиков, поэтому рабочая конфигурация или её копия здесь недопустима. Запускайте одним пользователем, вне чужой транзакции; существующие данные код не удаляет.
Процедура ВыполнитьПример() Экспорт
УчебныйКаталог85.ПроверитьСвойСтенд();
НачатьТранзакцию();
Попытка
Данные = УчебныйКаталог85.ПодготовитьСвоиТовары();
Менеджер = Справочники.УчебныеТовары;
Посещённые = Новый Соответствие;
Выборка = Менеджер.ВыбратьИерархически(, , , "Код Возр");
Пока Выборка.Следующий() Цикл
Если Не Данные.Свойство(Выборка.Код, ОжидаемаяСсылка) Или Выборка.Ссылка <> ОжидаемаяСсылка
Или Посещённые.Получить(Выборка.Ссылка) <> Неопределено Тогда
ВызватьИсключение "Чужая или повторная строка в собственном дереве";
КонецЕсли;
Если Выборка.Родитель.Пустая() Тогда
ОжидаемыйУровень = 0;
Иначе
ОжидаемыйУровень = 1;
Если Посещённые.Получить(Выборка.Родитель) <> Истина Тогда
ВызватьИсключение "Потомок прочитан раньше своей группы";
КонецЕсли;
КонецЕсли;
Если Выборка.УровеньВВыборке() <> ОжидаемыйУровень Тогда
ВызватьИсключение "Неверный уровень своего двухуровневого дерева";
КонецЕсли;
Сообщить(Выборка.Код + ": уровень " + Строка(Выборка.УровеньВВыборке()));
Посещённые.Вставить(Выборка.Ссылка, Истина);
КонецЦикла;
Если Посещённые.Количество() <> 5 Тогда
ВызватьИсключение "Собственное дерево должно содержать пять записей";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(Данные.A01);
Источники.Добавить("BOOK-A — это строка, а не ссылка");
Источники.Добавить(Данные.A02);
Несуществующая = Менеджер.ПолучитьСсылку(Новый УникальныйИдентификатор);
Если Несуществующая.ПолучитьОбъект() <> Неопределено Тогда
ВызватьИсключение "Для проверки нужна собственная ссылка без записи";
КонецЕсли;
Источники.Добавить(Несуществующая);
ПоСсылкам = Менеджер.ВыбратьПоСсылкам(Источники);
Найденные = Новый Соответствие;
Пока ПоСсылкам.Следующий() Цикл
Если ПоСсылкам.Ссылка <> Данные.A01 И ПоСсылкам.Ссылка <> Данные.A02 Тогда
ВызватьИсключение "В выборке по ссылкам оказался посторонний объект";
КонецЕсли;
Найденные.Вставить(ПоСсылкам.Ссылка, Истина);
КонецЦикла;
Если Найденные.Количество() <> 2 Или Найденные.Получить(Данные.A01) <> Истина
Или Найденные.Получить(Данные.A02) <> Истина Тогда
ВызватьИсключение "Ожидались ровно две существующие собственные ссылки";
КонецЕсли;
ОтменитьТранзакцию();
Исключение
Если ТранзакцияАктивна() Тогда
ОтменитьТранзакцию();
КонецЕсли;
ВызватьИсключение;
КонецПопытки;
УчебныйКаталог85.ПроверитьОткат(Данные);
Сообщить("Собственные пять строк отменены; учебный справочник снова пуст");
КонецПроцедурыУчебныйКаталог85
УчебныеВыборкиКаталога85 → Общие → Общие модули → УчебныйКаталог85
Полный серверный общий модуль: защита стенда, подготовка пяти записей и проверка отката. Не выполнялся.
Процедура ПроверитьСвойСтенд() Экспорт
Если Метаданные.Справочники.Количество() <> 1 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Каталог = Метаданные.Справочники[0];
Если Каталог.Имя <> "УчебныеТовары" Или Не Каталог.Иерархический
Или Каталог.Реквизиты.Количество() <> 1 Или Каталог.Реквизиты.Найти("Артикул") = Неопределено Тогда
ВызватьИсключение "Нужен собственный иерархический справочник с единственным реквизитом Артикул";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Функция ПодготовитьСвоиТовары() Экспорт
Если Не ТранзакцияАктивна() Тогда
ВызватьИсключение "Подготовка допустима только внутри собственной отменяемой транзакции";
КонецЕсли;
ПроверкаПустоты = Справочники.УчебныеТовары.Выбрать();
Если ПроверкаПустоты.Следующий() Тогда
ВызватьИсключение "Учебный справочник должен быть пуст; чужие записи не изменяются";
КонецЕсли;
Пустая = Справочники.УчебныеТовары.ПустаяСсылка();
Данные = Новый Структура;
Данные.Вставить("G01", СоздатьСвоюСтроку("G01", "Основной", "GROUP-A", Пустая, Истина));
Данные.Вставить("G02", СоздатьСвоюСтроку("G02", "Архив", "GROUP-B", Пустая, Истина));
Данные.Вставить("A01", СоздатьСвоюСтроку("A01", "Книга", "BOOK-A", Данные.G01, Ложь));
Данные.Вставить("A02", СоздатьСвоюСтроку("A02", "Ручка", "PEN-A", Данные.G01, Ложь));
Данные.Вставить("B01", СоздатьСвоюСтроку("B01", "Книга", "BOOK-B", Данные.G02, Ложь));
Данные.Вставить("Пустая", Пустая);
Возврат Данные;
КонецФункции
Функция СоздатьСвоюСтроку(Код, Наименование, Артикул, Родитель, Группа)
Если Группа Тогда
Объект = Справочники.УчебныеТовары.СоздатьГруппу();
Иначе
Объект = Справочники.УчебныеТовары.СоздатьЭлемент();
КонецЕсли;
Ссылка = Справочники.УчебныеТовары.ПолучитьСсылку(Новый УникальныйИдентификатор);
Объект.УстановитьСсылкуНового(Ссылка);
Объект.Код = Код;
Объект.Наименование = Наименование;
Объект.Артикул = Артикул;
Объект.Родитель = Родитель;
Объект.Записать();
Прочитанный = Ссылка.ПолучитьОбъект();
Если Прочитанный = Неопределено Тогда
ВызватьИсключение "Собственная учебная запись не прочитана";
КонецЕсли;
Если Прочитанный.Код <> Код Или Прочитанный.Наименование <> Наименование
Или Прочитанный.Артикул <> Артикул Или Прочитанный.Родитель <> Родитель
Или Прочитанный.ЭтоГруппа <> Группа Тогда
ВызватьИсключение "Прочитанная учебная строка отличается от подготовленной";
КонецЕсли;
Возврат Ссылка;
КонецФункции
Процедура ПроверитьОткат(Данные) Экспорт
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Собственная транзакция не завершена";
КонецЕсли;
Для Каждого Имя Из СтрРазделить("G01,G02,A01,A02,B01", ",") Цикл
Если Данные[Имя].ПолучитьОбъект() <> Неопределено Тогда
ВызватьИсключение "Собственная запись осталась после отката: " + Имя;
КонецЕсли;
КонецЦикла;
ПроверкаПустоты = Справочники.УчебныеТовары.Выбрать();
Если ПроверкаПустоты.Следующий() Тогда
ВызватьИсключение "После отката справочник не пуст";
КонецЕсли;
КонецПроцедурыУчебныйПульт85.Пульт
УчебныеВыборкиКаталога85 → Обработки → УчебныйПульт85 → Формы → Пульт → Модуль
Полный модуль управляемой формы только собственной обработки. Не выполнялся.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныеПримерыКаталога85.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
ВыбратьИерархически обходит потомков каждой группы перед переходом к следующей ветви. На своём наборе проверяем предшествование родителя, а не приписываем общий плоский порядок всему справочнику.
УровеньВВыборке имеет смысл только для иерархической выборки. Без отбора родителя свои группы дают 0, их товары 1. Если начать с поддерева, уровень относителен выбранному корню.
Соответствие посещённых ссылок обнаруживает повтор и потомка раньше родителя; количество пять подтверждает охват всего подготовленного дерева.
ВыбратьПоСсылкам принимает Массив; у него нет колонок, поэтому второй аргумент не задаём. Для ТаблицыЗначений или РезультатаЗапроса можно задать имя/индекс колонки, по умолчанию используется первая.
Неподходящая строка и ссылка на несуществующий объект игнорируются самим методом. Ссылку без записи получаем новым UUID и отдельно подтверждаем отсутствие через ПолучитьОбъект.
Результат проверяется как набор A01 и A02 через Соответствие. Порядок результата и поведение повторных ссылок контракт здесь не обещает; дубликаты во входе специально не добавлены.
Метод ВыбратьПоСсылкам доступен с 8.3.26, поэтому точная 8.5.1.1343 и отключённая совместимость существенны. Завершаем откатом собственного набора.
Как проверить результат
Ожидается пять сообщений уровней: G01/G02 имеют 0, A01/A02/B01 имеют 1; каждый товар после своей группы. Не требуйте глобального порядка A01,A02,B01,G01,G02.
В наборе по ссылкам только A01/A02; BOOK-A как строка и новый UUID без записи отсутствуют. После отката все пять учебных записей отсутствуют.
Для проверки контроля уровня в копии урока поменяйте ожидаемый уровень товара на 2: должно быть исключение и откат. Не меняйте реальное дерево ради прохождения проверки.
Ожидаемый результат
Подготовлены обход дерева с проверкой родителей/уровней и выбор существующих ссылок из смешанного массива. runtimeVerifiedScenarios=0.
На что обратить внимание
УровеньВВыборке не следует использовать для плоской Выбрать. Уровень поддерева не всегда совпадает с абсолютным уровнем элемента.
Игнорирование ошибочных значений — поведение API, не полноценная валидация входа интеграции. При импорте ошибки входных данных нужно сообщать отдельно.
Соответствие в этом уроке проверяет набор результатов, но не доказывает, что метод удаляет дубликаты в любом источнике.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.