СКД: классифицировать продажи пользовательским полем выбора и проверить группы

Учебные задачи

Полностью создаём собственную схему из трёх константных строк и пользовательские поля; проверяем редактирование, доступные поля, реальные детали и сводную прибыль. Всё только в памяти.

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

Полный обычный клиентский общий модуль УчебныеПользовательскиеПоляСКД85 → УчебныеПользовательскиеПоля85. Своя Local-схема и результаты в памяти, без записи/печати/сети; не выполнялся.

Подготовка

  1. НОВАЯ отдельная файловая база 8.5.1.1343, имя конфигурации УчебныеПользовательскиеПоляСКД85, совместимость НеИспользовать, обычное приложение, толстый клиент. Нет документов, справочников, регистров, расширений, подписок, обмена или внешних источников. Запуск в 1С не выполнялся: runtimeVerifiedScenarios=0.

  2. Общий модуль УчебныеПользовательскиеПоля85: неглобальный, Клиент (обычное приложение)=Да, Сервер=Нет, остальные клиентские флаги=Нет, Привилегированный=Нет. Полный основной модуль одного урока вставьте целиком. Не смешивайте оба урока с одинаковыми именами процедур.

  3. Обработка УчебныеПользовательскиеПоля85 → обычная форма Пульт → кнопка Выполнить → действие ВыполнитьНажатие. Отдельный полный модуль Пульта ниже. F7, обновление только своего стенда, запуск Пульта в толстом клиенте. ТаблицаЗначений и схема здесь доступны; напрямую в тонкий клиент их не переносите.

  4. Источник Local — запрос только собственных констант: Книга 750/500, Ручка 50/30, Книга 500/300 (выручка/затраты). Прибыль деталей 250/20/200, всего 470. По товарам Книга 450 и Ручка 20; по категориям Крупная 250 и Обычная 220.

  5. Схема, настройки, поля и таблицы создаются заново в памяти. Готовые метаданные/макеты СКД не нужны. Внешний сервер, SQL, настоящая сеть, запись файла/БД, печать и открытие отчётных окон отсутствуют. Результаты инспектируются в отладчике или проверками кода, не отправляются клиенту как неизвестный объект.

Процедура ВыполнитьПример() Экспорт
    ПроверитьСвойКонтекст();
    Схема = Новый СхемаКомпоновкиДанных;
    Источник = Схема.ИсточникиДанных.Добавить();
    Источник.Имя = "УчебныйИсточник";
    Источник.ТипИсточникаДанных = "Local";
    Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
    Набор.Имя = "УчебныеТовары";
    Набор.ИсточникДанных = Источник.Имя;
    Набор.АвтоЗаполнениеДоступныхПолей = Истина;
    Набор.Запрос = "ВЫБРАТЬ ""Книга"" КАК Наименование, 750 КАК Выручка, 500 КАК Затраты
    |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""Ручка"", 50, 30
    |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""Книга"", 500, 300";
    Настройки = Новый НастройкиКомпоновкиДанных;
    Для Каждого ИмяПоля Из СтрРазделить("Наименование,Выручка,Затраты", ",") Цикл
        Выбранное = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
        Выбранное.Поле = Новый ПолеКомпоновкиДанных(ИмяПоля);
        Выбранное.Использование = Истина;
    КонецЦикла;
    Детали = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
    Детали.Использование = Истина;
    АвтоВыбор = Детали.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
    АвтоВыбор.Использование = Истина;
    Для Каждого ИмяРесурса Из СтрРазделить("Выручка,Затраты", ",") Цикл
        Ресурс = Схема.ПоляИтога.Добавить();
        Ресурс.ПутьКДанным = ИмяРесурса;
        Ресурс.Выражение = "Сумма(" + ИмяРесурса + ")";
    КонецЦикла;
    Пользовательские = Настройки.ПользовательскиеПоля;
    Поля = Пользовательские.Элементы;
    Прибыль = Поля.Добавить(Тип("ПользовательскоеПолеВыражениеКомпоновкиДанных"));
    Прибыль.Заголовок = "Учебная прибыль";
    Прибыль.Использование = Истина;
    Прибыль.УстановитьВыражения("Выручка - Затраты", "Сумма(Выручка)");
    Если Прибыль.ПолучитьВыражениеДетальныхЗаписей() <> "Выручка - Затраты"
        Или Прибыль.ПолучитьВыражениеИтоговыхЗаписей() <> "Сумма(Выручка)" Тогда
        ВызватьИсключение "Первичная пара выражений собственного черновика не сохранилась";
    КонецЕсли;
    Прибыль.УстановитьВыражениеИтоговыхЗаписей("Сумма(Выручка) - Сумма(Затраты)");
    Прибыль.УстановитьПредставлениеВыражений("Черновик прибыли строки", "Черновик общей прибыли");
    Прибыль.УстановитьПредставлениеВыраженияДетальныхЗаписей("Выручка - Затраты");
    Прибыль.УстановитьПредставлениеВыраженияИтоговыхЗаписей("Сумма(Выручка) - Сумма(Затраты)");
    Если Прибыль.ПолучитьПредставлениеВыраженияДетальныхЗаписей() <> "Выручка - Затраты"
        Или Прибыль.ПолучитьПредставлениеВыраженияИтоговыхЗаписей() <> "Сумма(Выручка) - Сумма(Затраты)"
        Или Прибыль.ПолучитьВыражениеДетальныхЗаписей() <> "Выручка - Затраты"
        Или Прибыль.ПолучитьВыражениеИтоговыхЗаписей() <> "Сумма(Выручка) - Сумма(Затраты)" Тогда
        ВызватьИсключение "Представления непривязанного черновика и его реальные выражения проверяются отдельно";
    КонецЕсли;
    ПутьПрибыли = Прибыль.ПутьКДанным;
    Если ТипЗнч(Прибыль) <> Тип("ПользовательскоеПолеВыражениеКомпоновкиДанных") Или ПутьПрибыли = ""
        Или Прибыль.Заголовок <> "Учебная прибыль" Или Не Прибыль.Использование Тогда
        ВызватьИсключение "Нужно своё реальное пользовательское поле с автоматически созданным readonly путём";
    КонецЕсли;
    ИдентификаторПрибыли = Пользовательские.ПолучитьИдентификаторПоОбъекту(Прибыль);
    Если ИдентификаторПрибыли = Неопределено Тогда
        ВызватьИсключение "Свое поле должно принадлежать своим пользовательским полям";
    КонецЕсли;
    Если Пользовательские.ПолучитьОбъектПоИдентификатору(ИдентификаторПрибыли) <> Прибыль Тогда
        ВызватьИсключение "Обратный поиск собственного поля по его идентификатору не совпал";
    КонецЕсли;
    Временное = Поля.Вставить(0, Тип("ПользовательскоеПолеВыражениеКомпоновкиДанных"));
    Временное.Заголовок = "Временный выключенный черновик";
    Временное.Использование = Ложь;
    Если Поля.Индекс(Прибыль) <> 1 Или Поля.Получить(0) <> Временное Тогда
        ВызватьИсключение "Вставка должна сместить своё поле прибыли на индекс 1";
    КонецЕсли;
    Поля.Сдвинуть(Прибыль, -1);
    Если Поля.Индекс(Прибыль) <> 0 Или Прибыль.ПутьКДанным <> ПутьПрибыли Тогда
        ВызватьИсключение "Сдвиг меняет индекс, а не автоматически созданный путь поля";
    КонецЕсли;
    Поля.Удалить(Временное);
    Если Поля.Количество() <> 1 Или Поля.Получить(0) <> Прибыль Тогда
        ВызватьИсключение "Удаляется только собственный временный черновик";
    КонецЕсли;
    ДобавитьСвоюКолонку(Настройки, ПутьПрибыли);
    Категория = Поля.Добавить(Тип("ПользовательскоеПолеВыборКомпоновкиДанных"));
    Категория.Заголовок = "Учебная категория";
    Категория.Использование = Истина;
    ПутьКатегории = Категория.ПутьКДанным;
    Если ТипЗнч(Категория) <> Тип("ПользовательскоеПолеВыборКомпоновкиДанных")
        Или ПутьКатегории = "" Или ПутьКатегории = ПутьПрибыли
        Или Категория.Заголовок <> "Учебная категория" Или Не Категория.Использование Тогда
        ВызватьИсключение "Нужно отдельное своё поле выбора со своим автоматически созданным путём";
    КонецЕсли;
    Варианты = Категория.Варианты;
    ЭлементыВариантов = Варианты.Элементы;
    Крупная = ЭлементыВариантов.Добавить();
    Крупная.Значение = "Крупная";
    Крупная.Представление = "Крупная";
    Крупная.Использование = Истина;
    Условие = Крупная.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    Условие.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Выручка");
    Условие.ВидСравнения = ВидСравненияКомпоновкиДанных.БольшеИлиРавно;
    Условие.ПравоеЗначение = 700;
    Условие.Использование = Истина;
    Обычная = ЭлементыВариантов.Добавить();
    Обычная.Значение = "Обычная";
    Обычная.Представление = "Обычная";
    Обычная.Использование = Истина;
    Условие = Обычная.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    Условие.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Выручка");
    Условие.ВидСравнения = ВидСравненияКомпоновкиДанных.Меньше;
    Условие.ПравоеЗначение = 700;
    Условие.Использование = Истина;
    Если ТипЗнч(Варианты) <> Тип("ВариантыПользовательскогоПоляВыборКомпоновкиДанных")
        Или ТипЗнч(ЭлементыВариантов) <> Тип("КоллекцияВариантовПользовательскогоПоляВыборКомпоновкиДанных")
        Или ТипЗнч(Крупная) <> Тип("ВариантПользовательскогоПоляВыборКомпоновкиДанных")
        Или Крупная.Значение <> "Крупная" Или Крупная.Представление <> "Крупная"
        Или Не Крупная.Использование Или Крупная.Отбор.Элементы.Количество() <> 1 Тогда
        ВызватьИсключение "Нужны настоящие свои варианты с включёнными условиями и значениями";
    КонецЕсли;
    ИдентификаторКрупной = Варианты.ПолучитьИдентификаторПоОбъекту(Крупная);
    Если ИдентификаторКрупной = Неопределено Тогда
        ВызватьИсключение "Свой вариант должен принадлежать своим вариантам поля";
    КонецЕсли;
    Если Варианты.ПолучитьОбъектПоИдентификатору(ИдентификаторКрупной) <> Крупная Тогда
        ВызватьИсключение "Обратный поиск собственного варианта по идентификатору не совпал";
    КонецЕсли;
    ВременныйВариант = ЭлементыВариантов.Вставить(0);
    ВременныйВариант.Использование = Ложь;
    ВременныйВариант.Значение = "Не используется";
    ВременныйВариант.Представление = "Не используется";
    Если ЭлементыВариантов.Индекс(Крупная) <> 1 Или ЭлементыВариантов.Получить(0) <> ВременныйВариант Тогда
        ВызватьИсключение "Вставка собственного варианта должна менять индекс, не идентичность";
    КонецЕсли;
    ЭлементыВариантов.Сдвинуть(Крупная, -1);
    Если ЭлементыВариантов.Индекс(Крупная) <> 0
        Или Варианты.ПолучитьОбъектПоИдентификатору(ИдентификаторКрупной) <> Крупная Тогда
        ВызватьИсключение "Сдвиг варианта не должен подменять сам вариант";
    КонецЕсли;
    ЭлементыВариантов.Удалить(ВременныйВариант);
    Если ЭлементыВариантов.Количество() <> 2 Или ЭлементыВариантов.Получить(1) <> Обычная Тогда
        ВызватьИсключение "Остаются ровно свои два взаимоисключающих условия";
    КонецЕсли;
    ДобавитьСвоюКолонку(Настройки, ПутьКатегории);
    Доступные = Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема);
    Редактор = Новый КомпоновщикНастроекКомпоновкиДанных;
    Редактор.Инициализировать(Доступные);
    Редактор.ЗагрузитьНастройки(Настройки);
    СвязанныеПоля = Редактор.Настройки.ПользовательскиеПоля;
    ПроверитьСвоюДоступность(СвязанныеПоля.ДоступныеПоляЗначений, СвязанныеПоля.ДоступныеПоляОтбора);
    СвязаннаяКатегория = СвязанныеПоля.ПолучитьОбъектПоИдентификатору(Пользовательские.ПолучитьИдентификаторПоОбъекту(Категория));
    Если СвязаннаяКатегория = Неопределено Тогда
        ВызватьИсключение "В загруженных настройках должен сохраниться идентификатор собственного поля выбора";
    КонецЕсли;
    СвязанныеВарианты = СвязаннаяКатегория.Варианты;
    ПроверитьСвоюДоступность(СвязанныеВарианты.ДоступныеПоляЗначений, СвязанныеВарианты.ДоступныеПоляОтбора);
    Рабочие = Редактор.ПолучитьНастройки();
    Результат = СформироватьСвоюТаблицу(Схема, Рабочие);
    ПроверитьСвоиСтроки(Результат, ПутьПрибыли, ПутьКатегории);
    Сводные = Редактор.ПолучитьНастройки();
    Сводные.Выбор.Элементы.Очистить();
    ДобавитьСвоюКолонку(Сводные, ПутьКатегории);
    ДобавитьСвоюКолонку(Сводные, ПутьПрибыли);
    Сводные.Структура.Очистить();
    Группа = Сводные.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
    Группа.Использование = Истина;
    ПолеГруппы = Группа.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
    ПолеГруппы.Поле = Новый ПолеКомпоновкиДанных(ПутьКатегории);
    ПолеГруппы.ТипГруппировки = ТипГруппировкиКомпоновкиДанных.Элементы;
    ПолеГруппы.Использование = Истина;
    АвтоВыбор = Группа.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
    АвтоВыбор.Использование = Истина;
    СводныйРезультат = СформироватьСвоюТаблицу(Схема, Сводные);
    ПроверитьСвоиИтоги(СводныйРезультат, ПутьКатегории, "Учебная категория", ПутьПрибыли, "Крупная", 250, "Обычная", 220);
    КопияДляОчистки = Редактор.ПолучитьНастройки();
    КопияКатегории = КопияДляОчистки.ПользовательскиеПоля.ПолучитьОбъектПоИдентификатору(Пользовательские.ПолучитьИдентификаторПоОбъекту(Категория));
    Если КопияКатегории = Неопределено Тогда
        ВызватьИсключение "В собственной копии должно быть своё поле выбора";
    КонецЕсли;
    КопияКатегории.Варианты.Элементы.Очистить();
    Если КопияКатегории.Варианты.Элементы.Количество() <> 0 Или СвязаннаяКатегория.Варианты.Элементы.Количество() <> 2 Тогда
        ВызватьИсключение "Очищаются варианты только независимой копии, рабочие правила остаются";
    КонецЕсли;
    КопияДляОчистки.ПользовательскиеПоля.Элементы.Очистить();
    Если КопияДляОчистки.ПользовательскиеПоля.Элементы.Количество() <> 0
        Или Редактор.Настройки.ПользовательскиеПоля.Элементы.Количество() <> 2 Тогда
        ВызватьИсключение "Очищается только своя отброшенная копия, а не рабочий вариант редактора";
    КонецЕсли;
    Сообщить("Полностью проверены три детали, два итога и независимость копии. Ни запись, ни печать, ни файл не выполнялись.");
КонецПроцедуры

Процедура ДобавитьСвоюКолонку(Настройки, Путь)
    Колонка = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
    Колонка.Поле = Новый ПолеКомпоновкиДанных(Путь);
    Колонка.Использование = Истина;
КонецПроцедуры

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

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

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

Процедура ПроверитьСвоиСтроки(Таблица, ПутьПрибыли, ПутьКатегории)
    Размер = 4;
    Если ПутьКатегории <> "" Тогда
        Размер = 5;
    КонецЕсли;
    Если Таблица.Количество() <> 3 Или Таблица.Колонки.Количество() <> Размер Тогда
        ВызватьИсключение "Проверяется полный собственный результат, не одна удобная строка";
    КонецЕсли;
    ИмяПрибыли = ИмяСвоейКолонки(Таблица, ПутьПрибыли, "Учебная прибыль");
    ИмяКатегории = "";
    Если ПутьКатегории <> "" Тогда
        ИмяКатегории = ИмяСвоейКолонки(Таблица, ПутьКатегории, "Учебная категория");
    КонецЕсли;
    Найденные = Новый Массив;
    ОбщаяПрибыль = 0;
    Для Каждого СтрокаРезультата Из Таблица Цикл
        Если СтрокаРезультата.Выручка = 750 Тогда
            Наименование = "Книга";
            Затраты = 500;
            Прибыль = 250;
            Категория = "Крупная";
        ИначеЕсли СтрокаРезультата.Выручка = 50 Тогда
            Наименование = "Ручка";
            Затраты = 30;
            Прибыль = 20;
            Категория = "Обычная";
        ИначеЕсли СтрокаРезультата.Выручка = 500 Тогда
            Наименование = "Книга";
            Затраты = 300;
            Прибыль = 200;
            Категория = "Обычная";
        Иначе
            ВызватьИсключение "Неизвестная строка константного учебного источника";
        КонецЕсли;
        Если Найденные.Найти(СтрокаРезультата.Выручка) <> Неопределено
            Или СтрокаРезультата.Наименование <> Наименование Или СтрокаРезультата.Затраты <> Затраты
            Или ТипЗнч(СтрокаРезультата[ИмяПрибыли]) <> Тип("Число") Или СтрокаРезультата[ИмяПрибыли] <> Прибыль Тогда
            ВызватьИсключение "Не совпали все исходные и рассчитанные значения собственной строки";
        КонецЕсли;
        Если ПутьКатегории <> "" Тогда
            Если СтрокаРезультата[ИмяКатегории] <> Категория Тогда
                ВызватьИсключение "Реально рассчитанная категория не совпала с условием Выручка 700";
            КонецЕсли;
        КонецЕсли;
        Найденные.Добавить(СтрокаРезультата.Выручка);
        ОбщаяПрибыль = ОбщаяПрибыль + СтрокаРезультата[ИмяПрибыли];
    КонецЦикла;
    Если Найденные.Количество() <> 3 Или ОбщаяПрибыль <> 470 Тогда
        ВызватьИсключение "Нужны все свои три строки и общий контроль прибыли 470";
    КонецЕсли;
КонецПроцедуры

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

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

УчебныеПользовательскиеПоляСКД85 → Обработки → УчебныеПользовательскиеПоля85 → Формы → Пульт → Модуль

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

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

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

  1. Сначала создаём Local-схему, три исходных колонки и детальную структуру. Для выручки/затрат задаём настоящие Сумма-ресурсы; без них нельзя подменять сводный опыт простой арифметикой одной строки.

  2. Пользовательское поле создаёт Настройки.ПользовательскиеПоля.Элементы.Добавить(Тип(...)), а не выдуманный конструктор. ПутьКДанным создаётся автоматически, readonly и используется для выбора колонки; Заголовок — отдельно редактируемая подпись.

  3. У прибыльного поля детальное выражение Выручка - Затраты, итоговое Сумма(Выручка) - Сумма(Затраты). Сначала намеренно задано неполное итоговое Сумма(Выручка), затем исправлено отдельным setter и проверено до исполнения; неправильное выражение не используется в отчёте.

  4. Текст выражения и пользовательское представление — разные значения. На ещё НЕ привязанных настройках проверяем пару и отдельные setter/getter представлений без изменения формулы. После привязки к источнику доступных настроек установка представления может обновлять выражение; эти гарантии непривязанного черновика туда не переносятся.

  5. Вставка/сдвиг/получение/индекс/удаление показываются на собственном выключенном временном поле. Индекс меняется, автоматически созданный путь прибыли сохраняется. Идентификатор поля получен у собственной коллекции; обратный поиск сверяет тот же объект, а не созданный UUID.

  6. Инициализируем собственный редактор источником доступных настроек нашей схемы, загружаем настройки и ищем реальное поле Выручка в доступных значениях/отборе. Эти readonly-свойства дают коллекции, а не право присваивать им другой источник. Для найденного доступного поля отдельно проверяем идентификатор и обратный поиск.

  7. Выбор создаёт два взаимоисключающих включённых варианта: Выручка>=700 → Крупная, Выручка<700 → Обычная. Каждый вариант имеет настоящее условие Отбор, своё Значение, Представление и Использование. Вставляем/сдвигаем/удаляем только выключенный временный вариант; остаётся ровно два собственных правила.

  8. Каждый полный вывод заново компилирует макет для коллекции значений, инициализирует новый процессор и получает реальную ТаблицаЗначений. Включены проверки всех размеров, исходных значений, типов прибыли и каждого рассчитанного значения. Константные ожидания не вставляются в результат вместо исполнения.

  9. Проверяем три детали и обе сводные группы. Имя колонки прибыли/категории берётся из реальной таблицы: сначала по пути, затем по единственному своему заголовку; отсутствие/неоднозначность — ошибка, не повод подставлять ожидаемое значение.

  10. Очистить вызывается лишь на новой независимой копии после вывода. Проверка подтверждает, что пользовательские поля рабочего редактора остались. В уроке выбора отдельно очищаются варианты только копии; рабочие два варианта сохраняются.

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

  1. Будущий опыт F7 и свой Пульт. Три детали, исходные выручки 750/50/500 и затраты 500/30/300; прибыли 250/20/200, общий контроль 470.

  2. Сводные группы Крупная=250 и Обычная=220; реальные детали имеют категории Крупная/Обычная/Обычная, все две группы проверяются.

  3. Путь пользовательского поля непуст и сохраняется после сдвига; обратный поиск по собственным идентификаторам совпадает. После привязки доступная Выручка найдена в значениях и отборе.

  4. После очистки отброшенной копии рабочий редактор сохраняет два поля и два варианта категории.

  5. Ошибка компиляции, отсутствующая/неоднозначная колонка, неправильный тип, количество строк или сумма означает НЕуспех. Здесь эти результаты ещё не получены: runtimeVerifiedScenarios=0.

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

Будущий результат: полноценные детали и сводная прибыль своего константного отчёта, сохранность рабочей настройки после операций только над своими временными объектами и копиями. Статически подготовлено; 1С не запускалась.

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

  1. У пользовательских полей, вариантов и коллекций нет использованного здесь конструктора Новый: получаем их из собственного дерева настроек. ПутьКДанным, Варианты, Отбор и доступные коллекции readonly, но их собственные вложенные элементы редактируемы.

  2. Представление выражения не является просто синонимом его строки: при связи с источником setter представления может обновлять код выражения. Проверки равенства строк выполнены только ДО привязки.

  3. Индекс элемента, автоматически созданный путь и ИдентификаторКомпоновкиДанных — три разных адреса. Не храните индекс как вечный идентификатор и не создавайте ID случайным UUID.

  4. Эти >=700/<700 условия не пересекаются и покрывают собственные числовые строки. Для Null, другого типа, пересекающихся правил или рабочих данных нужна отдельная подготовка; это не универсальная классификация любой базы.

  5. Поля и варианты очищаются только в отдельной копии. Изменение настоящих настроек чужого отчёта могло бы сломать его; такие объекты не принимаются и не изменяются.

  6. Код выполняет вычисление СКД только при будущей ручной проверке своего стенда. Здесь нет подтверждённого runtime или доказательства визуального интерфейса/производительности.

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

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

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

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

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