СвязьПараметраВыбораКомпоновкиДанных.ИзменениеЗначения

Свойства · ValueChange

Тип: РежимИзмененияСвязанногоЗначения. Указывает, каким образом изменять связаное значение.

Полное описание, параметры и ограничения

СвязьПараметраВыбораКомпоновкиДанных.ИзменениеЗначения (DataCompositionChoiceParameterLink.ValueChange)

СвязьПараметраВыбораКомпоновкиДанных (DataCompositionChoiceParameterLink)

ИзменениеЗначения (ValueChange)

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

Использование:
Только чтение.
Описание:
Тип: РежимИзмененияСвязанногоЗначения.
Указывает, каким образом изменять связаное значение.
Доступность:

Тонкий клиент, веб-клиент, толстый клиент.

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

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

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

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

Локальный учебный preview: свои связи выбора и подбор750 → 950 → 50 → 1000

Собственные native коллекции выбора СКД используются явно написанным локальным потребителем. Это НЕ изменение стандартной формы выбора/metadata/связей компоновщика: документированного setter такого применения в уроке нет. Полный builder, настоящие native фабрики и только собственные типизированные товары в памяти.

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

Полный непривилегированный common moduleУчебныйПредпросмотр85, клиент обычного приложения. Только thick ordinary8.5.1.1343; own память/частнаяВТ, не server/thin/web.

Подготовка

  1. Создайте вручную отдельную новую пустую файловуюИБ8.5.1.1343. Не используйте рабочуюИБ, копию УНФ/КА/УТ/БП, серверную production базу или чужую форму выбора. Здесь выполнено только авторство/static checks; созданиеИБ, обновление конфигурации и запуск не выполнялись.

  2. Конфигуратор → Конфигурация → Открыть конфигурацию. Имя корня=УчебныйЛокальныйПодбор85, Основной режим запуска=Обычное приложение, Режим совместимости=Не использовать. Учебный запуск именно толстым клиентом в обычном приложении.

  3. Оставьте пустыми справочники, документы, перечисления, планы, регистры, отчеты, обработки, константы, параметры сеанса, подписки, задания, общие реквизиты и хранилища настроек. Никаких расширений, BSP, чужих библиотек или автоматических обработчиков. Код проверяет пустые business metadata и три источника расширений, но новаяИБ/отсутствие чужого кода требуют ручной подготовки.

  4. Общие → Общие модули → Добавить УчебныйПредпросмотр85. Клиент(обычное приложение)=Да; Клиент(управляемое приложение)=Нет; Сервер=Нет; Внешнее соединение=Нет; Глобальный=Нет; Привилегированный=Нет; Вызов сервера=Нет; Повторное использование возвращаемых значений=Не использовать. Вставьте весь основной блок кода целиком на уровне модуля. Директивы#Если/#КонецЕсли уже включены.

  5. Общие → Общие формы → Добавить УчебныйЛокальныйВыбор85. Тип формы=Обычная, это единственная общая форма. В ее модуль вставьте весь вспомогательный блок «Полный модуль своей обычной формы». Никаких &НаКлиенте/&НаСервере и управляемых форм здесь нет.

  6. В реквизиты формы добавьте Результат85 типаТабличныйДокумент. Поместите на форму Поле табличного документа, имяПолеРезультата85, Данные=Результат85. Оставьте только просмотр результата, без команд печати/файлового сохранения.

  7. Добавьте обычную кнопкуВыполнить85 с Действие=Выполнить85. АргументКнопка предоставляет платформа; не создавайте фиктивный объект кнопки и не вызывайте обработчик напрямую.

  8. Корень конфигурации → Модуль обычного приложения. Он должен быть пустым. Вставьте весь блок «Полный модуль обычного приложения». СобытиеПриНачалеРаботыСистемы открывает только подготовленную собственную общую форму; вычисления запускаются явной кнопкой.

  9. Создайте только своего учебного пользователя/учебную роль с доступом к запуску и этой форме. Не включайте обработчики авторизации, фоновые задания, сервисы или связи с внешними системами. Это не образец production прав.

  10. Проверьте синтаксис всех трех полных модулей и вручную обновите конфигурацию только своей новойИБ. Запустите ее толстым клиентом8.5.1.1343 в обычном приложении. Никаких внешних объектов или исходных файлов готовить не нужно.

  11. НажмитеВыполнить85. Код создает реальныйUUID и типизированнуюТаблицаЗначений сBOOK(PAPER,3,250,750), PAD(PAPER,2,100,200), PEN(OFFICE,1,50,50). Эти единственные данные находятся в памяти, передаются в свою частную временную таблицу и проверяются по всем полям.

  12. Полный builder создает собственнуюСхемаКомпоновкиДанных: источникLocal, один объектный наборСвоиТовары с шестью типизированными полями и три параметраКатегорияВыбора/ЦенаМин/ТоварВыбора. ИмяОбъекта совпадает с реальным ключом структурыДанныеОбъектов; неизвестного внешнего источника/запроса к metadata нет.

  13. Компоновщик получает источник по собственной схеме. Берем реальные Компоновщик.Настройки, доступные толстому клиенту по справке свойства Настройки. Настройки должны фактически иметь ДоступныеПараметры и ТоварВыбора; при отсутствии программа останавливается с OWN-PREVIEW-NO-AVAILABLE/NO-PARAMETER. Источник, схема и компоновщик удерживаются в собственном контексте до конца процесса. Не заменяйте отсутствие выдуманным параметром.

  14. Настоящие коллекции получаем только методамиGetChoice* настоящего доступного параметра. Перед добавлением обе должны иметьКоличество()=0. При непустой исходной коллекции стоп: мы не удаляем неизвестные автоматически добавленные элементы.

  15. У собственного элементаПараметрВыбора задаемЦенаМин=200. ЧерезДобавить/Вставить создаем две настоящие связи сПолеКомпоновкиДанных; проверяемИндекс/Получить, сдвигаем именно свой объектЦена на одну позицию и проверяем фактический новый порядок. Далее работает собственный явно заданный потребитель, не стандартная форма выбора.

  16. Предпросмотр строит параметризованный Запрос только к ВТСвоиТовары своего МенеджерВременныхТаблиц. Native имена/поля/значение200 определяют включение условий. После каждого этапа проверяются точные коды, UUID, числовые поля и суммы: BOOK750 → PAPER950 после удаления связи цены → OFFICE50 после изменения категории собственного memory компоновщика native setter УстановитьЗначениеПараметра → все1000 после очистки только подтвержденной собственной коллекции.

  17. ИзменениеЗначения readonly: код читает настоящий режимКатегория.ИзменениеЗначения и принимает толькоОчищать/НеИзменять. Он применяется явно нашей функцией к собственной переменной выбора; не заявляется автоматическое поведение платформы. Даже сохраненныйBOOK не подтверждается допустимым приOFFICE, чей набор содержит толькоPEN.

  18. Отдельные6 отрицательных случаев создают6 свежих собственных контекстов: неверный тип коллекции, чужое поле, дубликат связи, строка200 вместо числа, сумма749 и угаданныйdefault политики. Принимается только соответствующий собственный маркер, неожиданная ошибка передается дальше. Исходные успешные контекст/товары не исправляются слепым rollback.

  19. Ожидаемый при ручном запуске результат: протокол750/950/50/1000, фактическая политика и6 отказов, затем таблица трех своих товаров. СтараяРезультат85 заменяется только после полного завершения. Это не гарантия атомарности действий формы и не доказательство фактического запуска1С здесь.

  20. Закройте собственную форму/сеанс: данные, схемы, кандидаты и вывод находятся в памяти. Свой менеджерВТ закрывается на успехе и при ошибке; не объявляется rollbackИБ или гарантированное сохранение первичного исключения при ошибке самого закрытия. Файлы, сеть, сохраненные пользовательские настройки, metadata, стандартная форма выбора и рабочиеИБ не изменяются. Native setter меняет только настройки собственного компоновщика в памяти.

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

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

Функция СоздатьТовары(СвойUUID)
    Товары = Новый ТаблицаЗначений;
    Товары.Колонки.Добавить("UUID", Новый ОписаниеТипов("УникальныйИдентификатор"));
    Товары.Колонки.Добавить("Код", Новый ОписаниеТипов("Строка"));
    Товары.Колонки.Добавить("Категория", Новый ОписаниеТипов("Строка"));
    ЧисловойТип = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(9, 2, ДопустимыйЗнак.Неотрицательный));
    Для Каждого Имя Из СтрРазделить("Количество,Цена,Сумма", ",") Цикл
        Товары.Колонки.Добавить(Имя, ЧисловойТип);
    КонецЦикла;
    Книга = Товары.Добавить();
    Книга.UUID = СвойUUID;
    Книга.Код = "BOOK";
    Книга.Категория = "PAPER";
    Книга.Количество = 3;
    Книга.Цена = 250;
    Книга.Сумма = 750;
    Блокнот = Товары.Добавить();
    Блокнот.UUID = СвойUUID;
    Блокнот.Код = "PAD";
    Блокнот.Категория = "PAPER";
    Блокнот.Количество = 2;
    Блокнот.Цена = 100;
    Блокнот.Сумма = 200;
    Ручка = Товары.Добавить();
    Ручка.UUID = СвойUUID;
    Ручка.Код = "PEN";
    Ручка.Категория = "OFFICE";
    Ручка.Количество = 1;
    Ручка.Цена = 50;
    Ручка.Сумма = 50;
    Возврат Товары;
КонецФункции

Процедура ПроверитьТовары(Товары, СвойUUID)
    Если ТипЗнч(СвойUUID) <> Тип("УникальныйИдентификатор") Или ТипЗнч(Товары) <> Тип("ТаблицаЗначений") Тогда
        ВызватьИсключение "OWN-PREVIEW-DATA-TYPE";
    КонецЕсли;
    Если Товары.Колонки.Количество() <> 6 Или Товары.Количество() <> 3 Тогда
        ВызватьИсключение "OWN-PREVIEW-FIXTURE";
    КонецЕсли;
    Ожидания = СоздатьТовары(СвойUUID);
    Для Индекс = 0 По 5 Цикл
        Колонка = Товары.Колонки.Получить(Индекс);
        ОжидаемаяКолонка = Ожидания.Колонки.Получить(Индекс);
        Если Колонка.Имя <> ОжидаемаяКолонка.Имя
            Или Колонка.ТипЗначения <> ОжидаемаяКолонка.ТипЗначения Тогда
            ВызватьИсключение "OWN-PREVIEW-FIXTURE";
        КонецЕсли;
    КонецЦикла;
    Для Индекс = 0 По 2 Цикл
        Факт = Товары.Получить(Индекс);
        Ожидание = Ожидания.Получить(Индекс);
        Если Факт.UUID <> СвойUUID Или Факт.Код <> Ожидание.Код Или Факт.Категория <> Ожидание.Категория
            Или Факт.Количество <> Ожидание.Количество Или Факт.Цена <> Ожидание.Цена
            Или Факт.Сумма <> Ожидание.Сумма Или Факт.Количество * Факт.Цена <> Факт.Сумма Тогда
            ВызватьИсключение "OWN-PREVIEW-FIXTURE";
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Функция СоздатьКонтекст(СвойUUID)
    Товары = СоздатьТовары(СвойUUID);
    ПроверитьТовары(Товары, СвойUUID);
    Схема = Новый СхемаКомпоновкиДанных;
    ИсточникСхемы = Схема.ИсточникиДанных.Добавить();
    ИсточникСхемы.Имя = "СвойЛокальныйИсточник";
    ИсточникСхемы.ТипИсточникаДанных = "Local";
    Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхОбъектСхемыКомпоновкиДанных"));
    Если ТипЗнч(Набор) <> Тип("НаборДанныхОбъектСхемыКомпоновкиДанных") Тогда
        ВызватьИсключение "OWN-PREVIEW-SCHEMA";
    КонецЕсли;
    Набор.Имя = "СвоиТовары";
    Набор.ИсточникДанных = ИсточникСхемы.Имя;
    Набор.ИмяОбъекта = "СвоиТовары";
    Для Каждого Колонка Из Товары.Колонки Цикл
        Поле = Набор.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
        Поле.Поле = Колонка.Имя;
        Поле.ПутьКДанным = Колонка.Имя;
        Поле.ТипЗначения = Колонка.ТипЗначения;
    КонецЦикла;
    Для Каждого Имя Из СтрРазделить("КатегорияВыбора,ЦенаМин,ТоварВыбора", ",") Цикл
        Параметр = Схема.Параметры.Добавить();
        Параметр.Имя = Имя;
        Параметр.ВключатьВДоступныеПоля = Истина;
        Параметр.Использование = ИспользованиеПараметраКомпоновкиДанных.Всегда;
        Если Имя = "ЦенаМин" Тогда
            Параметр.ТипЗначения = Товары.Колонки.Найти("Цена").ТипЗначения;
            Параметр.Значение = 0;
        Иначе
            Параметр.ТипЗначения = Новый ОписаниеТипов("Строка");
            Если Имя = "КатегорияВыбора" Тогда
                Параметр.Значение = "PAPER";
            Иначе
                Параметр.Значение = "BOOK";
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    ДанныеОбъектов = Новый Структура("СвоиТовары", Товары);
    Если Не ДанныеОбъектов.Свойство(Набор.ИмяОбъекта, ФактическиеТовары) Или ФактическиеТовары <> Товары
        Или Набор.Поля.Количество() <> Товары.Колонки.Количество() Тогда
        ВызватьИсключение "OWN-PREVIEW-SOURCE";
    КонецЕсли;
    ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема);
    Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
    Компоновщик.Инициализировать(ИсточникНастроек);
    СвоиНастройки = Компоновщик.Настройки;
    Если ТипЗнч(СвоиНастройки) <> Тип("НастройкиКомпоновкиДанных") Тогда
        ВызватьИсключение "OWN-PREVIEW-SETTINGS";
    КонецЕсли;
    Доступные = СвоиНастройки.ПараметрыДанных.ДоступныеПараметры;
    Если ТипЗнч(Доступные) <> Тип("ДоступныеПараметрыКомпоновкиДанных") Тогда
        ВызватьИсключение "OWN-PREVIEW-NO-AVAILABLE: свой native компоновщик не связал доступные параметры; остановитесь";
    КонецЕсли;
    ОписаниеВыбора = Доступные.НайтиПараметр(Новый ПараметрКомпоновкиДанных("ТоварВыбора"));
    Если ТипЗнч(ОписаниеВыбора) <> Тип("ДоступныйПараметрКомпоновкиДанных") Тогда
        ВызватьИсключение "OWN-PREVIEW-NO-PARAMETER";
    КонецЕсли;
    Связи = ОписаниеВыбора.ПолучитьСвязиПараметровВыбора();
    ПараметрыВыбора = ОписаниеВыбора.ПолучитьПараметрыВыбора();
    Если ТипЗнч(Связи) <> Тип("СвязиПараметровВыбораКомпоновкиДанных")
        Или ТипЗнч(ПараметрыВыбора) <> Тип("ПараметрыВыбораКомпоновкиДанных") Тогда
        ВызватьИсключение "OWN-PREVIEW-COLLECTIONS";
    КонецЕсли;
    Если Связи.Количество() <> 0 Или ПараметрыВыбора.Количество() <> 0 Тогда
        ВызватьИсключение "OWN-PREVIEW-NOT-EMPTY: чужие или автоматически заполненные коллекции не очищаем";
    КонецЕсли;
    МинимальнаяЦена = ПараметрыВыбора.Добавить();
    Если ТипЗнч(МинимальнаяЦена) <> Тип("ПараметрВыбораКомпоновкиДанных") Тогда
        ВызватьИсключение "OWN-PREVIEW-CHOICE-TYPE";
    КонецЕсли;
    МинимальнаяЦена.Имя = "ЦенаМин";
    МинимальнаяЦена.Значение = 200;
    Если ПараметрыВыбора.Количество() <> 1 Или ПараметрыВыбора.Получить(0).Имя <> "ЦенаМин"
        Или ПараметрыВыбора.Получить(0).Значение <> 200 Тогда
        ВызватьИсключение "OWN-PREVIEW-CHOICE-READBACK";
    КонецЕсли;
    СвоиНастройки.ПараметрыДанных.УстановитьЗначениеПараметра("КатегорияВыбора", "PAPER");
    СвоиНастройки.ПараметрыДанных.УстановитьЗначениеПараметра("ЦенаМин", МинимальнаяЦена.Значение);
    Категория = Связи.Добавить();
    Если ТипЗнч(Категория) <> Тип("СвязьПараметраВыбораКомпоновкиДанных") Тогда
        ВызватьИсключение "OWN-PREVIEW-LINK-TYPE";
    КонецЕсли;
    Категория.Имя = "Категория";
    Категория.Поле = Новый ПолеКомпоновкиДанных("ПараметрыДанных.КатегорияВыбора");
    Цена = Связи.Вставить(0);
    Цена.Имя = "Цена";
    Цена.Поле = Новый ПолеКомпоновкиДанных("ПараметрыДанных.ЦенаМин");
    Если Связи.Количество() <> 2 Или Связи.Индекс(Цена) <> 0 Или Связи.Индекс(Категория) <> 1
        Или Связи.Получить(0).Имя <> "Цена" Или Связи.Получить(1).Имя <> "Категория" Тогда
        ВызватьИсключение "OWN-PREVIEW-LINK-ORDER";
    КонецЕсли;
    Связи.Сдвинуть(Цена, 1);
    Если Связи.Индекс(Цена) <> 1 Или Связи.Индекс(Категория) <> 0
        Или Связи.Получить(0).Имя <> "Категория" Или Связи.Получить(1).Имя <> "Цена" Тогда
        ВызватьИсключение "OWN-PREVIEW-LINK-MOVE";
    КонецЕсли;
    Политика = Категория.ИзменениеЗначения;
    Если ТипЗнч(Политика) <> Тип("РежимИзмененияСвязанногоЗначения") Тогда
        ВызватьИсключение "OWN-PREVIEW-POLICY";
    КонецЕсли;
    Если Политика <> РежимИзмененияСвязанногоЗначения.Очищать
        И Политика <> РежимИзмененияСвязанногоЗначения.НеИзменять Тогда
        ВызватьИсключение "OWN-PREVIEW-POLICY";
    КонецЕсли;
    Возврат Новый Структура("UUID,Схема,Источник,Компоновщик,ДанныеОбъектов,Настройки,Связи,ПараметрыВыбора,Категория,Цена,Политика",
        СвойUUID, Схема, ИсточникНастроек, Компоновщик, ДанныеОбъектов, СвоиНастройки, Связи, ПараметрыВыбора, Категория, Цена, Политика);
КонецФункции

Функция ПолучитьУсловия(Контекст)
    Если ТипЗнч(Контекст.Схема) <> Тип("СхемаКомпоновкиДанных")
        Или ТипЗнч(Контекст.Источник) <> Тип("ИсточникДоступныхНастроекКомпоновкиДанных")
        Или ТипЗнч(Контекст.Компоновщик) <> Тип("КомпоновщикНастроекКомпоновкиДанных") Тогда
        ВызватьИсключение "OWN-PREVIEW-OWNER";
    КонецЕсли;
    Если ТипЗнч(Контекст.Связи) <> Тип("СвязиПараметровВыбораКомпоновкиДанных") Тогда
        ВызватьИсключение "OWN-PREVIEW-LINKS-TYPE";
    КонецЕсли;
    Если Контекст.ПараметрыВыбора.Количество() <> 1 Тогда
        ВызватьИсключение "OWN-PREVIEW-CHOICE-COUNT";
    КонецЕсли;
    МинимальнаяЦена = Контекст.ПараметрыВыбора.Получить(0);
    Если ТипЗнч(МинимальнаяЦена) <> Тип("ПараметрВыбораКомпоновкиДанных")
        Или МинимальнаяЦена.Имя <> "ЦенаМин" Или ТипЗнч(МинимальнаяЦена.Значение) <> Тип("Число")
        Или МинимальнаяЦена.Значение <> 200 Тогда
        ВызватьИсключение "OWN-PREVIEW-CHOICE-VALUE";
    КонецЕсли;
    ПараметрКатегории = Контекст.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("КатегорияВыбора"));
    ПараметрЦены = Контекст.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("ЦенаМин"));
    Если ТипЗнч(ПараметрКатегории) <> Тип("ЗначениеПараметраНастроекКомпоновкиДанных")
        Или ТипЗнч(ПараметрЦены) <> Тип("ЗначениеПараметраНастроекКомпоновкиДанных") Тогда
        ВызватьИсключение "OWN-PREVIEW-PARAMETER-VALUE";
    КонецЕсли;
    Если ТипЗнч(ПараметрКатегории.Значение) <> Тип("Строка")
        Или (ПараметрКатегории.Значение <> "PAPER" И ПараметрКатегории.Значение <> "OFFICE")
        Или ПараметрЦены.Значение <> МинимальнаяЦена.Значение Тогда
        ВызватьИсключение "OWN-PREVIEW-PARAMETER-VALUE";
    КонецЕсли;
    ИспользоватьКатегорию = Ложь;
    ИспользоватьЦену = Ложь;
    Для Каждого Связь Из Контекст.Связи Цикл
        Если ТипЗнч(Связь) <> Тип("СвязьПараметраВыбораКомпоновкиДанных")
            Или ТипЗнч(Связь.Поле) <> Тип("ПолеКомпоновкиДанных") Тогда
            ВызватьИсключение "OWN-PREVIEW-LINK-TYPE";
        КонецЕсли;
        Если Связь.Имя = "Категория" Тогда
            Если ИспользоватьКатегорию Тогда
                ВызватьИсключение "OWN-PREVIEW-LINK-DUPLICATE";
            КонецЕсли;
            Если Строка(Связь.Поле) <> "ПараметрыДанных.КатегорияВыбора" Тогда
                ВызватьИсключение "OWN-PREVIEW-LINK-FIELD";
            КонецЕсли;
            ИспользоватьКатегорию = Истина;
        ИначеЕсли Связь.Имя = "Цена" Тогда
            Если ИспользоватьЦену Тогда
                ВызватьИсключение "OWN-PREVIEW-LINK-DUPLICATE";
            КонецЕсли;
            Если Строка(Связь.Поле) <> "ПараметрыДанных.ЦенаМин" Тогда
                ВызватьИсключение "OWN-PREVIEW-LINK-FIELD";
            КонецЕсли;
            ИспользоватьЦену = Истина;
        Иначе
            ВызватьИсключение "OWN-PREVIEW-LINK-NAME";
        КонецЕсли;
    КонецЦикла;
    Возврат Новый Структура("Категория,ЦенаМин,ИспользоватьКатегорию,ИспользоватьЦену",
        ПараметрКатегории.Значение, МинимальнаяЦена.Значение, ИспользоватьКатегорию, ИспользоватьЦену);
КонецФункции

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

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

Функция ПрименитьСвоюПолитику(Политика, СвойВыбранныйКод)
    Если ТипЗнч(Политика) <> Тип("РежимИзмененияСвязанногоЗначения") Или ТипЗнч(СвойВыбранныйКод) <> Тип("Строка") Тогда
        ВызватьИсключение "OWN-PREVIEW-POLICY";
    КонецЕсли;
    Если Политика = РежимИзмененияСвязанногоЗначения.Очищать Тогда
        Возврат "";
    ИначеЕсли Политика = РежимИзмененияСвязанногоЗначения.НеИзменять Тогда
        Возврат СвойВыбранныйКод;
    Иначе
        ВызватьИсключение "OWN-PREVIEW-POLICY";
    КонецЕсли;
КонецФункции

Функция ПроверитьОтказы(СвойUUID)
    Для Номер = 1 По 6 Цикл
        Контекст = СоздатьКонтекст(СвойUUID);
        Если Номер = 1 Тогда
            Контекст.Связи = Новый Массив;
            Маркер = "OWN-PREVIEW-LINKS-TYPE";
        ИначеЕсли Номер = 2 Тогда
            Контекст.Категория.Поле = Новый ПолеКомпоновкиДанных("НесуществующееПоле");
            Маркер = "OWN-PREVIEW-LINK-FIELD";
        ИначеЕсли Номер = 3 Тогда
            Контекст.Цена.Имя = "Категория";
            Маркер = "OWN-PREVIEW-LINK-DUPLICATE";
        ИначеЕсли Номер = 4 Тогда
            Контекст.ПараметрыВыбора.Получить(0).Значение = "200";
            Маркер = "OWN-PREVIEW-CHOICE-VALUE";
        ИначеЕсли Номер = 5 Тогда
            Контекст.ДанныеОбъектов.СвоиТовары.Получить(0).Сумма = 749;
            Маркер = "OWN-PREVIEW-FIXTURE";
        Иначе
            Маркер = "OWN-PREVIEW-POLICY";
        КонецЕсли;
        Отказ = Ложь;
        Попытка
            Если Номер = 6 Тогда
                Выбор = ПрименитьСвоюПолитику("угаданный default", "BOOK");
                Если Выбор <> "BOOK" Тогда
                    ВызватьИсключение "Нельзя принять неподдержанную политику";
                КонецЕсли;
            Иначе
                Предпросмотр(Контекст);
            КонецЕсли;
        Исключение
            Если СтрНайти(ОписаниеОшибки(), Маркер) = 0 Тогда
                ВызватьИсключение;
            КонецЕсли;
            Отказ = Истина;
        КонецПопытки;
        Если Не Отказ Тогда
            ВызватьИсключение "Не получен ожидаемый отказ " + Маркер;
        КонецЕсли;
    КонецЦикла;
    Возврат "Проверены6 отказов на6 отдельных локальных кандидатах";
КонецФункции

Функция ВыполнитьПредпросмотр() Экспорт
    ПроверитьСвоюСхему();
    СвойUUID = Новый УникальныйИдентификатор;
    Контекст = СоздатьКонтекст(СвойUUID);
    ТолькоКнига = Предпросмотр(Контекст);
    ПроверитьПредпросмотр(ТолькоКнига, СвойUUID, "BOOK", 750);
    Если Контекст.Связи.Количество() <> 2 Или Контекст.Связи.Индекс(Контекст.Цена) <> 1 Тогда
        ВызватьИсключение "Удаляем только свой подтвержденный элемент цены";
    КонецЕсли;
    Контекст.Связи.Удалить(Контекст.Цена);
    Если Контекст.Связи.Количество() <> 1 Или Контекст.Связи.Получить(0).Имя <> "Категория"
        Или Контекст.Связи.Индекс(Контекст.Категория) <> 0 Тогда
        ВызватьИсключение "OWN-PREVIEW-DELETE";
    КонецЕсли;
    Бумага = Предпросмотр(Контекст);
    ПроверитьПредпросмотр(Бумага, СвойUUID, "BOOK,PAD", 950);
    СвойВыбор = ПрименитьСвоюПолитику(Контекст.Политика, "BOOK");
    Если Контекст.Политика = РежимИзмененияСвязанногоЗначения.Очищать Тогда
        Если СвойВыбор <> "" Тогда
            ВызватьИсключение "OWN-PREVIEW-POLICY-READBACK";
        КонецЕсли;
        ПояснениеПолитики = "Native Очищать: очищена только собственная переменная выбора";
    Иначе
        Если СвойВыбор <> "BOOK" Тогда
            ВызватьИсключение "OWN-PREVIEW-POLICY-READBACK";
        КонецЕсли;
        ПояснениеПолитики = "Native НеИзменять: BOOK сохранен в своей переменной, но проверяется новым набором";
    КонецЕсли;
    Контекст.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("КатегорияВыбора", "OFFICE");
    Офис = Предпросмотр(Контекст);
    ПроверитьПредпросмотр(Офис, СвойUUID, "PEN", 50);
    Если СвойВыбор <> "" И Офис.Найти(СвойВыбор, "Код") <> Неопределено Тогда
        ВызватьИсключение "Старый BOOK не должен считаться допустимым при OFFICE";
    КонецЕсли;
    Если Контекст.Связи.Количество() <> 1 Или Контекст.Связи.Получить(0).Имя <> "Категория" Тогда
        ВызватьИсключение "Очищаем только собственный подтвержденный локальный кандидат";
    КонецЕсли;
    Контекст.Связи.Очистить();
    Если Контекст.Связи.Количество() <> 0 Тогда
        ВызватьИсключение "OWN-PREVIEW-CLEAR";
    КонецЕсли;
    ВсеТовары = Предпросмотр(Контекст);
    ПроверитьПредпросмотр(ВсеТовары, СвойUUID, "BOOK,PAD,PEN", 1000);
    ПроверитьТовары(Контекст.ДанныеОбъектов.СвоиТовары, СвойUUID);
    Отказы = ПроверитьОтказы(СвойUUID);
    Документ = Новый ТабличныйДокумент;
    Документ.Область(1, 1).Текст = "СВОЙ ЛОКАЛЬНЫЙ PREVIEW, НЕ стандартная форма выбораСКД";
    Документ.Область(2, 1).Текст = "BOOK750 → PAPER950 → OFFICE50 → все1000";
    Документ.Область(3, 1).Текст = ПояснениеПолитики;
    Документ.Область(4, 1).Текст = Отказы;
    Документ.Область(5, 1).Текст = "UUID: " + Строка(СвойUUID);
    Номер = 6;
    Для Каждого Товар Из ВсеТовары Цикл
        Документ.Область(Номер, 1).Текст = Товар.Код;
        Документ.Область(Номер, 2).Текст = Товар.Категория;
        Для Каждого Поле Из СтрРазделить("Количество,Цена,Сумма", ",") Цикл
            Если Поле = "Количество" Тогда
                Колонка = 3;
            ИначеЕсли Поле = "Цена" Тогда
                Колонка = 4;
            Иначе
                Колонка = 5;
            КонецЕсли;
            Ячейка = Документ.Область(Номер, Колонка);
            Ячейка.СодержитЗначение = Истина;
            Ячейка.Значение = Товар[Поле];
        КонецЦикла;
        Номер = Номер + 1;
    КонецЦикла;
    Документ.Область(1, 1, 8, 1).ШиринаКолонки = 100;
    Документ.Область(1, 2, 8, 5).ШиринаКолонки = 18;
    Документ.Область(1, 1, 8, 5).Защита = Истина;
    Документ.ТолькоПросмотр = Истина;
    Возврат Документ;
КонецФункции
#КонецЕсли
Полный модуль своей обычной формы

Общие → Общие формы → УчебныйЛокальныйВыбор85 → Модуль

Thick ordinary client; настоящая кнопкаВыполнить85, не вызов обработчика вручную.

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

Корень конфигурации → Модуль обычного приложения

Thick ordinary startup event.

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

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

  1. Создаем и полностью проверяем своиBOOK/PAD/PEN с реальнымUUID. Builder схемы использует ровно те же типы колонок и известное имя объектаСвоиТовары.

  2. Собственная схема → источник настроек → компоновщик → его реальные Настройки → фактические доступные параметры → настоящий ТоварВыбора → GetChoice*. Проверяем каждый nullable результат; ничего не конструируем вместо недоступной коллекции.

  3. ЦенаМин=200 — настоящийПараметрВыбора. Две реальные связи имеют известныеИмя иПолеКомпоновкиДанных, реальные индексы и проверенный порядок послеСдвинуть. ПолитикуИзменениеЗначения только читаем.

  4. Наш потребитель проверяет whitelist имени/пути поля и отсутствие дубликатов, затем получает категорию из реальных настроек собственного нового компоновщика и цену из собственного параметра. Только эти данные становятся параметрами собственного запроса к частной ВТ.

  5. Проверяем BOOK750; удаляем только свой элемент Цена и проверяем BOOK/PAD950; меняем категорию своего компоновщика native setter на OFFICE и проверяем PEN50; очищаем только свой подтвержденный кандидат и проверяем все1000.

  6. Фактический native режимОчищать/НеИзменять применяем только к своей переменной выбора. СохраненныйBOOK не становится допустимым дляOFFICE. Это демонстрация собственного обработчика политики, а не автоматический эффект СКД.

  7. Каждый из6 отказов получает свой свежий полный контекст. Проверяем конкретную ошибку до запроса; нет подавления неожиданной ошибки и нет восстановления чужого состояния.

  8. Только после всех проверок полный модуль обычной формы получает итоговыйТабличныйДокумент. Настройки и коллекции не сериализуются, стандартная форма выбора не открывается, источникиИБ не читаются.

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

  1. При ручном запуске ожидаются четыре подтвержденных состава:BOOK=750; BOOK/PAD=950; PEN=50; BOOK/PAD/PEN=1000. В каждой строкеUUID именно своего набора, количества/цены/суммы остаются числами.

  2. В отладчике новаяЦена послеВставить(0) имеет индекс0, послеСдвинуть(Цена,1) индекс1, Категория индекс0; послеУдалить остается толькоКатегория, послеОчистить элементов0.

  3. Протокол политики отражает реальный native режим, не угаданный default. ПриНеИзменять прежнийBOOK остается в своей переменной, но не принимается в наборOFFICE.

  4. Все6 ожидаемых отказов подтверждаются своими маркерами. При OWN-PREVIEW-NO-AVAILABLE не продолжайте: фактические доступные параметры компоновщика не подтвердились; нельзя считать это успешным уроком.

  5. Запуск, пиксельный вид формы и source-bound доступные поля компоновщика не проверялись здесь. Пройдите весь ручной протокол на своей новойИБ; статические проверки подтверждают только код/контракты.

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

Ожидаемый при ручном запуске результат: локальный ownpreview с проверенными составами750/950/50/1000, реальной readonly политикой и6 отрицательными проверками; запуск1С не проверялся.

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

  1. Связи/параметры создаются native методамиGetChoice*/Добавить/Вставить. У них нет придуманного конструктора; Поле имеет настоящий типПолеКомпоновкиДанных, а не строку или неизвестное поле.

  2. ИзменениеЗначения только для чтения и доступно на клиенте. Весь процесс thick ordinary; не переносите его в серверный общий модуль или тонкую форму. Компоновщик новый собственный, без чужих пользовательских/фиксированных настроек. Его реальные Настройки читаются без сериализации/копирования.

  3. ДоступныеПараметры могут быть Неопределено у настроек без источника. Обязательный fail-stop не заменяет runtime доказательство успешной инициализации; неизвестный объект не подставляется.

  4. Полученные GetChoice коллекции являются локальными кандидатами для нашего потребителя. Не обещаем, что их изменение сохраняет связи в исходной схеме/компоновщике или настраивает стандартную форму выбора. Только значение категории меняется документированным УстановитьЗначениеПараметра у нашего нового memory компоновщика.

  5. МетодСвязи.Найти исключен: rawFind3984 заявляетПараметрВыбора вместоСвязьПараметраВыбора. Сериализация связей исключена: typepage ошибочно ссылается наAppearanceTemplateArea. Эти противоречия не обходятся выдуманными контрактами.

  6. Сдвинуть/Удалить принимают настоящий элемент, не произвольный индекс. Индексы проверяются до и после операции; очистка допустима только своего кандидата с точным ожидаемым составом.

  7. ПараметрЦенаМин здесь — собственный протокол preview, не имя специальной системной команды. Условия запроса создаются фиксированным кодом; имена/поля из коллекции проверяются whitelist, не конкатенируются в SQL/BSL.

  8. Построитель схемы описывает объектный набор с реальным именем и типами, но native процессор компоновки не запускается. Результат рассчитывает наш полностью показанный запрос к собственной таблице; это не native output СКД.

  9. Нет файлов, сети, служб, OS-команд, настроек хранилищ, печати, записейmetadata/ИБ, восстановления рабочей конфигурации или резервных копий. Чтение native контрактов/static tests не равны runtime проверке.

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

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

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

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

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