Счета: плоский список, дерево и собственный родитель G

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

На настоящих G/A/B/C разберём источник списка, показ иерархии, ограничение участка G и настройки поля без изменения записей.

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

Полный модуль собственной обычной формы УчебныеМенеджерыПланов85 → Обработки → УчебныйСписокСчетов85 → Формы → Список. Общий модуль и Пульт ниже; не выполнялся.

Подготовка

  1. Создайте НОВУЮ отдельную файловую базу 8.5.1.1343: имя конфигурации УчебныеМенеджерыПланов85, совместимость НеИспользовать, обычное приложение, толстый клиент. Не рабочая БП/КА2/УТ и не её копия. Нет разделителей, общих реквизитов, расширений, подписок, РИБ и фоновых прикладных заданий. Здесь база и код не запускались: runtimeVerifiedScenarios=0.

  2. Планы счетов → УчебныеСчета85: длина кода 10, маска пустая, длина наименования 100, контроль уникальности включён. Без видов субконто, признаков учёта и предопределённых счетов. Реквизит УчебныйКлюч85: Строка(10), переменная длина, индексирование Индексировать. Формы и макет подготовьте далее, модули пустые.

  3. Планы видов характеристик → УчебныеСвойства85: иерархия групп и элементов включена, длина кода 10, тип кода Строка, длина наименования 100, тип характеристик только Строка(30). Реквизит УчебныйКлюч85: Строка(10), переменная длина, Индексировать, использование для групп и элементов. Без предопределённых элементов и дополнительных значений.

  4. Для ОБОИХ основных планов заранее вручную создайте только четыре обычные записи: G — код 01, наименование Учебный родитель, ключ G, родитель пустой; A — код 10, наименование Учебный верхний A, ключ A, родитель пустой; B — код 30, наименование Учебный дочерний B, ключ B, родитель G; C — код 20, наименование Учебный верхний C, ключ C, родитель пустой. У плана характеристик G именно группа, A/B/C элементы типа Строка(30). У плана счетов G обычный родительский счёт, не группа справочника. Записи пометкой удаления не отмечены. Эти собственные записи готовит человек; код уроков их не создаёт и не записывает.

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

  6. Обработка УчебныеМенеджеры85 → обычная основная форма Пульт → кнопка Выполнить, действие ВыполнитьНажатие. Полный модуль формы отдельно. Вставляйте один вариант урока, не оба общих модуля одновременно.

  7. Создайте обработку УчебныйСписокСчетов85 с обычной основной формой Список. Реквизит СписокРасчетов типа ПланСчетовСписок.УчебныеСчета85, имя общее для структуры опыта. Поле Виды связано с этим реквизитом. Визуальные колонки Код/Наименование/УчебныйКлюч85 с одноимёнными данными; у Наименование включите ОтображатьИерархию. ТолькоПросмотр=Да, команд записи/создания/удаления нет.

  8. Кнопки Плоский, Дерево, Дети, ТолькоB, Восстановить, Фиксированный, Настраиваемый, АвтоОбновление, Закрыть: назначьте соответствующие действия *Нажатие и ПриОткрытии. В контекстном меню оставьте стандартный диалог настройки списка. Начальный профиль задаётся до открытия, а не вручную в чужом окне.

  9. F7 и обновление только собственного стенда, запуск Пульта в толстом клиенте. Код читает свои четыре записи и меняет только UI нового собственного окна. Нет Записать, удаления, расчёта регистров, проводок, обмена, файлов, сети и печати. Стенд и UI здесь не выполнялись.

Перем Подготовлено;
Перем СвоиЗаписи;

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

Процедура ПриОткрытии()
    Если Подготовлено <> Истина Тогда
        ВызватьИсключение "Открывайте список через собственный Пульт после подготовки";
    КонецЕсли;
    СписокРасчетов.Обновить();
    Сообщить("Проверьте четыре строки по коду: 01/G,10/A,20/C,30/B. B имеет настоящего родителя G.");
КонецПроцедуры

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

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

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

Процедура ПлоскийНажатие(Кнопка)
    ПроверитьСвойОткрытыйСписок();
    УстановитьВид("Плоский");
    Сообщить("Проверьте G,A,C,B по коду. Дочерний B не перемещён в корень базы, изменён только показ.");
КонецПроцедуры

Процедура ДеревоНажатие(Кнопка)
    ПроверитьСвойОткрытыйСписок();
    УстановитьВид("Дерево");
    Сообщить("Корневые записи G,A,C. Раскройте G: внутри единственный B. Порядок кода действует среди соседей.");
КонецПроцедуры

Процедура ДетиНажатие(Кнопка)
    ПроверитьСвойОткрытыйСписок();
    УстановитьВид("Дети");
    Сообщить("Проверьте единственного B внутри G. Смена текущего родителя и иерархического режима интерактивно запрещены.");
КонецПроцедуры

Процедура ТолькоBНажатие(Кнопка)
    ПроверитьСвойОткрытыйСписок();
    УстановитьВид("Плоский");
    СписокРасчетов.Отбор.УчебныйКлюч85.Установить("B", Истина);
    СписокРасчетов.Обновить();
    Сообщить("Проверьте единственную строку 30/Учебный дочерний B/B: отбор источника работает и без ручной настройки.");
КонецПроцедуры

Процедура ВосстановитьНажатие(Кнопка)
    ПроверитьСвойОткрытыйСписок();
    УстановитьВид("Плоский");
КонецПроцедуры

Процедура ЗакрытьНажатие(Кнопка)
    ПроверитьСвойОткрытыйСписок();
    ЭлементыФормы.Виды.АвтоОбновление = Ложь;
    ЭтаФорма.Закрыть();
КонецПроцедуры

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

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

Процедура НастраиваемыйНажатие(Кнопка)
    ПроверитьСвойОткрытыйСписок();
    НастроитьПоле(Истина);
    Сообщить("Откройте стандартный диалог настройки списка: отбор по ключу, порядок кода и настройки автообновления доступны. Запись строк по-прежнему запрещена настройкой ТолькоПросмотр.");
КонецПроцедуры

Процедура ФиксированныйНажатие(Кнопка)
    ПроверитьСвойОткрытыйСписок();
    НастроитьПоле(Ложь);
    ВосстановитьНажатие(Неопределено);
    Сообщить("Фиксированный профиль восстановлен. Программный отбор кнопкой ТолькоB работает независимо от запрета его интерактивного изменения.");
КонецПроцедуры

Процедура АвтоОбновлениеНажатие(Кнопка)
    ПроверитьСвойОткрытыйСписок();
    Поле = ЭлементыФормы.Виды;
    Поле.ИзменятьАвтоОбновление = Ложь;
    Поле.ПериодАвтоОбновления = 10;
    Поле.АвтоОбновление = Не Поле.АвтоОбновление;
    Сообщить(СтрШаблон("АвтоОбновление=%1, период=%2 секунд, интерактивное изменение=%3",
        Поле.АвтоОбновление, Поле.ПериодАвтоОбновления, Поле.ИзменятьАвтоОбновление));
КонецПроцедуры
УчебныеМенеджеры85.Пульт

УчебныеМенеджерыПланов85 → Обработки → УчебныеМенеджеры85 → Формы → Пульт → Модуль

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

Процедура ВыполнитьНажатие(Кнопка)
    УчебныеМенеджеры85.ВыполнитьПример();
КонецПроцедуры
УчебныеМенеджеры85.ОбщийМодуль

УчебныеМенеджерыПланов85 → Общие модули → УчебныеМенеджеры85

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

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

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

Функция ПрочитатьСвойПлан() Экспорт
    ПроверитьСвойКонтекст();
    Менеджер = ПланыСчетов.УчебныеСчета85;
    G = Менеджер.НайтиПоРеквизиту("УчебныйКлюч85", "G");
    Если G.Пустая() Тогда
        ВызватьИсключение "Подготовьте реальную собственную родительскую запись G";
    КонецЕсли;
    Коды = Новый Структура("G,A,B,C", "01", "10", "30", "20");
    Имена = Новый Структура("G,A,B,C", "Учебный родитель", "Учебный верхний A", "Учебный дочерний B", "Учебный верхний C");
    Свои = Новый Структура;
    Ключи = Новый Массив;
    Выборка = Менеджер.Выбрать(,, "Код Возр");
    Пока Выборка.Следующий() Цикл
        Ключ = Выборка.УчебныйКлюч85;
        Код = Неопределено;
        Имя = Неопределено;
        Если Не Коды.Свойство(Ключ, Код) Или Не Имена.Свойство(Ключ, Имя) Или Свои.Свойство(Ключ) Тогда
            ВызватьИсключение "В своём плане лишний или повторный учебный ключ";
        КонецЕсли;
        Родитель = Менеджер.ПустаяСсылка();
        Если Ключ = "B" Тогда
            Родитель = G;
        КонецЕсли;
        Если Выборка.Код <> Код Или Выборка.Наименование <> Имя Или Выборка.Родитель <> Родитель
            Или Выборка.ПометкаУдаления Или Выборка.Предопределенный Или Выборка.ИмяПредопределенныхДанных <> "" Тогда
            ВызватьИсключение "Не совпали свои код, имя, родитель и признаки G/A/B/C";
        КонецЕсли;

        Свои.Вставить(Ключ, Выборка.Ссылка);
        Ключи.Добавить(Ключ);
    КонецЦикла;
    Если СтрСоединить(Ключи, ",") <> "G,A,C,B" Тогда
        ВызватьИсключение "Своя плоская выборка должна содержать ровно G,A,C,B";
    КонецЕсли;
    Свои.Вставить("Пустая", Менеджер.ПустаяСсылка());
    Возврат Свои;
КонецФункции

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

  1. В новом собственном стенде вручную сохранены ровно G/A/B/C; дочерняя B имеет родителя G. Общий модуль перед каждым действием заново читает код, имя, родителя и признаки, не создавая случайных ссылок.

  2. Основной блок — полный модуль обычной формы списка. Визуальное поле Виды связано с настоящим реквизитом СписокРасчетов своего прикладного типа. Полный общий модуль запуска/проверки и Пульт даны отдельно.

  3. Колонки источника списка readonly как свойство, но состав меняется через Найти/Добавить. Визуальные колонки заранее связаны с Код/Наименование/УчебныйКлюч85; ОтображатьИерархию у колонки Наименование рисует линии дерева и пиктограммы, а не меняет родителя записи.

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

  5. Плоский показ: Дерево=Ложь, ИерархическийПросмотр=Ложь, верхний родитель пустой. Источник явно отсортирован Код Возр, ожидаем G,A,C,B. B остаётся дочерней записью в базе.

  6. Дерево: Дерево и ИерархическийПросмотр включены, верхняя граница пустая. Корневые G,A,C, при раскрытии G единственный B. Видимый порядок иерархии не равен глобальной сортировке всех записей по коду.

  7. Дети: Дерево=Ложь и ИерархическийПросмотр=Истина. РодительВерхнегоУровня и ТекущийРодитель получают настоящую G; показывается B. ИзменятьТекущегоРодителя и ИзменятьИерархическийПросмотр выключены, чтобы UI не выводил пользователя из заданного участка.

  8. У плана счетов G — родительский счёт, не группа. ПросмотрГруппИЭлементов/Автонумерация этого расширения отсутствуют и в коде не используются. Сортируем только Код: справка Порядок этого списка разрешает предопределённые Код и Наименование.

  9. НастройкаОтбора/НастройкаПорядка управляют интерактивной доступностью ключа/кода. Их readonly коллекции не заменяются. ТолькоB меняет фактический Отбор источника программно: запрет ручной настройки этому не мешает.

  10. Фиксированный/Настраиваемый переключают доступность настроек, способ редактирования и проверку новой строки. ТолькоПросмотр сохраняется, поэтому записи не редактируются; проверяется настройка, а не выполненный ввод и сообщение о несоответствии фильтру.

  11. АвтоОбновление переключается программно при периоде 10 секунд, не меньше native-минимума 5. ИзменятьАвтоОбновление — разрешение ручной настройки, не запрет программного присваивания. ВосстанавливатьТекущуюСтроку выключен для нового независимого опыта.

  12. Восстановить возвращает четыре плоские строки, пустую верхнюю границу и фиксированный профиль. Закрыть выключает таймер своего поля и закрывает только эту форму. Данные базы, родитель B и остальные окна не меняются.

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

  1. Будущий тест: вставить три полных блока в разные указанные модули, связать поле/колонки и назначить действия, F7, запустить только через свой Пульт.

  2. Плоский: реальные строки 01/G,10/A,20/C,30/B. Сообщение ожидаемого порядка не заменяет осмотр поля.

  3. Дерево: корневые G,A,C; вручную раскрыть G и увидеть B. Если нет пиктограммы, проверить ОтображатьИерархию именно визуальной колонки Наименование.

  4. Дети: только B внутри G, интерактивная смена родителя/режима недоступна. Плоский восстанавливает все четыре строки.

  5. ТолькоB: одна сохранённая B; Настраиваемый/Фиксированный меняют доступность диалога, но запись строк не разрешается. После ручных настроек нажать Восстановить.

  6. АвтоОбновление: фактические флаги и период 10; наблюдение таймера остаётся будущим ручным тестом. Закрыть своё окно, заново проверить исходные четыре записи и родителя B стандартным списком.

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

Будущий опыт показывает четыре собственные записи плоско и деревом, а также одного ребёнка B под G; UI-профиль возвращается, родитель записи не изменяется.

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

  1. Это обычные формы толстого клиента. ДинамическийСписок управляемой формы — другой API; конструктор Новый для прикладного списка не используется.

  2. РодительВерхнегоУровня ограничивает навигацию UI, ТекущийРодитель задаёт текущий участок, а сохранённый Родитель принадлежит записи. Эти три значения нельзя смешивать.

  3. Свойства Дерево и ИерархическийПросмотр решают разные задачи. У дерева Код Возр сортирует соседей, а не переставляет дочернюю B в корень.

  4. Readonly Колонки/Отбор/Порядок источника и НастройкаОтбора/НастройкаПорядка поля не заменяются новыми объектами. Используются методы/элементы существующих коллекций.

  5. ТолькоПросмотр и недоступность ручных настроек не являются правами доступа к базе. Здесь не выполняется ни запись, ни тест фактического редактирования новой строки.

  6. ВосстанавливатьТекущуюСтроку намеренно выключен; урок не доказывает сохранение позиции после повторного открытия. Обновить — перечитывание списка, не сохранение объекта.

  7. Код, UI и таймер не запускались в 1С: runtimeVerifiedScenarios=0. Не переносите опыт в рабочую БП/КА/УТ.

  8. Не обращайтесь к ЭтоГруппа у счёта и не добавляйте этому расширению свойства групп/автонумерации от характеристик. Никаких бухгалтерских проводок этот опыт не создаёт.

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

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

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

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

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