Всем привет.
Конфигурация БП 3.0

Есть немного нетривиальная (для меня) задача.

Из ТЗ сделать дерево значений.

ТЗ (собирается запросом из РС) в следующем виде:

Организация | Пользователь | Раздел | Дата

Необходимо получить следующее:

Организация1
   Пользователь1
        Раздел1 Дата
   Пользователь2
        Раздел1 Дата
        Раздел2 Дата
Организация2
   Пользователь1
        Раздел2 Дата
   Пользователь2
        Раздел1 Дата
        Раздел2 Дата

Надеюсь понятно.

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

Как вообще делать эту самую иерархию?

Сейчас код следующий:

```1c
    &НаСервере
    Процедура ЗаполнитьДеревоНаСервере()

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | ДатыЗапретаИзменения.Объект КАК Организация,
    | ДатыЗапретаИзменения.Пользователь КАК Пользователь,
    | ДатыЗапретаИзменения.Раздел КАК РазделДатыЗапрета,
    | ДатыЗапретаИзменения.ДатаЗапрета КАК ДатаЗапрета
    |ИЗ
    | РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения";

    ТЗ = Запрос.Выполнить().Выгрузить();

    Дерево = ВыгрузитьТаблицуЗначенийВДеревоЗначений(ТЗ, "Организация", "Пользователь");

    ЗначениеВРеквизитФормы(Дерево, "ДеревоЗначенийДатыЗапрета");

    КонецПроцедуры

    Функция ВыгрузитьТаблицуЗначенийВДеревоЗначений(Таблица, КлючСтроки = "КлючСтроки", КлючСвязи = "КлючСвязи") Экспорт

    Дерево = Новый ДеревоЗначений;

    ОписаниеОрганизации = Новый ОписаниеТипов("СправочникСсылка.Организации");
    ОписаниеПользователя = Новый ОписаниеТипов("СправочникСсылка.Пользователи");
    ОписаниеРаздела = Новый ОписаниеТипов("ПланВидовХарактеристикСсылка.РазделыДатЗапретаИзменения");
    ОписаниеДаты = Новый ОписаниеТипов("Дата");

    Дерево.Колонки.Добавить("Организация", ОписаниеОрганизации);
    Дерево.Колонки.Добавить("Пользователь", ОписаниеПользователя);
    Дерево.Колонки.Добавить("РазделДатыЗапрета", ОписаниеРаздела);
    Дерево.Колонки.Добавить("ДатаЗапрета", ОписаниеДаты);

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

    КонецФункции
```
---
```1c
    &НаСервере
    Процедура ЗаполнитьДеревоНаСервере()

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | ДатыЗапретаИзменения.Объект КАК Организация,
    | ДатыЗапретаИзменения.Пользователь КАК Пользователь,
    | ДатыЗапретаИзменения.Раздел КАК РазделДатыЗапрета,
    | ДатыЗапретаИзменения.ДатаЗапрета КАК ДатаЗапрета
    |ИЗ
    | РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения";

    ТЗ = Запрос.Выполнить().Выгрузить();

    ТЗ_Организации = ТЗ.Скопировать(, "Организация");
    ТЗ_Организации.Свернуть("Организация");

    Дерево = Новый ДеревоЗначений;

    ОписаниеОрганизации = Новый ОписаниеТипов("СправочникСсылка.Организации");
    ОписаниеПользователя = Новый ОписаниеТипов("СправочникСсылка.Пользователи");
    ОписаниеРаздела = Новый ОписаниеТипов("ПланВидовХарактеристикСсылка.РазделыДатЗапретаИзменения");
    ОписаниеДаты = Новый ОписаниеТипов("Дата");

    Дерево.Колонки.Добавить("Организация", ОписаниеОрганизации);
    Дерево.Колонки.Добавить("Пользователь", ОписаниеПользователя);
    Дерево.Колонки.Добавить("РазделДатыЗапрета", ОписаниеРаздела);
    Дерево.Колонки.Добавить("ДатаЗапрета", ОписаниеДаты);

    СтрокиДерева = Дерево.Строки;

    Для Каждого СтрОрг Из ТЗ_Организации Цикл
    УзелОрганизация = Дерево.Строки.Добавить();
    УзелОрганизация.Организация = СтрОрг.Организация;

    СтрокиОрганизации = ТЗ.Скопировать(Новый Структура("Организация", СтрОрг.Организация));
    ТЗ_Пользователи = СтрокиОрганизации.Скопировать(, "Пользователь");
    ТЗ_Пользователи.Свернуть("Пользователь");
    Для Каждого СтрП Из ТЗ_Пользователи Цикл
    УзелПользователь = УзелОрганизация.Строки.Добавить();
    УзелПользователь.Организация = СтрОрг.Организация;
    УзелПользователь.Пользователь = СтрП.Пользователь;
    СтрокиПользователя = СтрокиОрганизации.Скопировать(Новый Структура("Пользователь", СтрП.Пользователь));
    Для Каждого Стр Из СтрокиПользователя Цикл
    НоваяСтрока = УзелПользователь.Строки.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, Стр);
    КонецЦикла;
    КонецЦикла;
    КонецЦикла;

    ЗначениеВРеквизитФормы(Дерево, "ДеревоЗначенийДатыЗапрета");

    КонецПроцедуры
```
---
```1c
    &НаСервере
    Процедура ЗаполнитьДеревоНаСервере()

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | ДатыЗапретаИзменения.Объект КАК Организация,
    | ДатыЗапретаИзменения.Пользователь КАК Пользователь,
    | ДатыЗапретаИзменения.Раздел КАК РазделДатыЗапрета,
    | ДатыЗапретаИзменения.ДатаЗапрета КАК ДатаЗапрета
    |ИЗ
    | РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения";

    ТЗ = Запрос.Выполнить().Выгрузить();

    ТЗ_Организации = ТЗ.Скопировать(, "Организация");
    ТЗ_Организации.Свернуть("Организация");

    Дерево = Новый ДеревоЗначений;

    ОписаниеОрганизации = Новый ОписаниеТипов("СправочникСсылка.Организации");
    ОписаниеПользователя = Новый ОписаниеТипов("СправочникСсылка.Пользователи");
    ОписаниеРаздела = Новый ОписаниеТипов("ПланВидовХарактеристикСсылка.РазделыДатЗапретаИзменения");
    ОписаниеДаты = Новый ОписаниеТипов("Дата");

    Дерево.Колонки.Добавить("Организация", ОписаниеОрганизации);
    Дерево.Колонки.Добавить("Пользователь", ОписаниеПользователя);
    Дерево.Колонки.Добавить("РазделДатыЗапрета", ОписаниеРаздела);
    Дерево.Колонки.Добавить("ДатаЗапрета", ОписаниеДаты);

    СтрокиДерева = Дерево.Строки;

    Для Каждого СтрОрг Из ТЗ_Организации Цикл
    УзелОрганизация = Дерево.Строки.Добавить();
    УзелОрганизация.Организация = СтрОрг.Организация;

    СтрокиОрганизации = ТЗ.Скопировать(Новый Структура("Организация", СтрОрг.Организация));
    ТЗ_Пользователи = СтрокиОрганизации.Скопировать(, "Пользователь");
    ТЗ_Пользователи.Свернуть("Пользователь");
    Для Каждого СтрП Из ТЗ_Пользователи Цикл
    УзелПользователь = УзелОрганизация.Строки.Добавить();
    УзелПользователь.Организация = СтрОрг.Организация;
    УзелПользователь.Пользователь = СтрП.Пользователь;
    СтрокиПользователя = СтрокиОрганизации.Скопировать(Новый Структура("Пользователь", СтрП.Пользователь));
    Для Каждого Стр Из СтрокиПользователя Цикл
    НоваяСтрока = УзелПользователь.Строки.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, Стр);
    КонецЦикла;
    КонецЦикла;
    КонецЦикла;

    ЗначениеВРеквизитФормы(Дерево, "ДеревоЗначенийДатыЗапрета");

    КонецПроцедуры
```
---
да, спасибо большое
---
Не хочу создавать новую тему, может тут подскажите с еще одним моментом.

Дерево у меня выведено, спасибо Вам.

Как мне написать при изменении таблицы (ну даже не изменении, а, допустим, запись нового элемента) - была собственно запись в РС?

В событии после редактирования можно работать только в "клиенте", там собственно особо не развернешься. На "сервер" передать Элемент.ТекущиеДанные не могу. Как вообще такие вещи реализуются?

Может выгрузить данные в массив и его уже передать на сервер? Или как лучше?
---
Вот в таком виде, с точки зрения пользователя, было бы удобно иметь кнопку "Сохранить" или "Записать" изменения, вместо динамического сохранения в РС. Пользователям не очень комфортно, когда интерактивное изменение в поле ввода сразу же ведёт к изменению в ИБ. Для реализации в дереве необходима еще одна служебная колонка: флаг, указывающий, что в данной строке были сделаны изменения. По нажатию кнопки "Записать изменения", делаем контекстный серверный вызов, обходим дерево, проверяем флаг: если включен – записываем в РС.
Измененные строки можно даже подкрасить через условное оформления для наглядности, чтобы было видно, что изменено.
---
Сделал как Вы и посоветовали - все круто, спасибо большое)
---
а есть возможность при выводе дерева значений (при раскрытии списка) - "родителя" не выводить.

Ну т.е. как сейчас:

-Организация1
    - Организация1 Пользователь1
        - Организация1 Пользователь1 Раздел 1
     - Организация1 Пользователь2
        - Организация1 Пользователь2 Раздел 1
-Организация2
    - Организация2 Пользователь1
        - Организация1 Пользователь1 Раздел 1
     - Организация2 Пользователь2
        - Организация1 Пользователь2 Раздел 1

Хотелось бы видеть

-Организация1
    - Пользователь1
        - Раздел 1
     - Пользователь2
        - Раздел 1

Чет не могу найти как убирается
---
Никак не убирается. Делать одну колонку и самостоятельно заполнять её на разных уровнях разными значениями.
---
Понял, спасибо.
---
Может быть как вариант решения?

```1c
    Процедура СформироватьДеревоЗначений()
    // Запрос для получения данных из регистра сведений
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | РегистрыСведений.НазваниеРегистра.Организация КАК Организация,
    | РегистрыСведений.НазваниеРегистра.Пользователь КАК Пользователь,
    | РегистрыСведений.НазваниеРегистра.Раздел КАК Раздел,
    | РегистрыСведений.НазваниеРегистра.Дата КАК Дата
    |ИЗ
    | РегистрыСведений.НазваниеРегистра КАК РегистрыСведений.НазваниеРегистра";

    ТаблицаЗначений = Запрос.Выполнить().Выгрузить();

    // Создание дерева значений
    Дерево = Новый ДеревоЗначений;
    Дерево.Колонки.Добавить("Наименование");
    Дерево.Колонки.Добавить("Дата");

    // Заполнение дерева значений на основе таблицы значений
    Для Каждого СтрокаОрганизация Из ТаблицаЗначений.Сгруппировать("Организация") Цикл
    УзелОрганизация = Дерево.Строки.Добавить();
    УзелОрганизация.Наименование = СтрокаОрганизация.Организация;

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

    ТаблицаРазделы = ТаблицаПользователи.НайтиСтроки(Новый Структура("Пользователь", СтрокаПользователь.Пользователь));
    Для Каждого СтрокаРаздел Из ТаблицаРазделы Цикл
    УзелРаздел = УзелПользователь.Строки.Добавить();
    УзелРаздел.Наименование = СтрокаРаздел.Раздел;
    УзелРаздел.Дата = СтрокаРаздел.Дата;
    КонецЦикла;
    КонецЦикла;
    КонецЦикла;

    // Вывод результата для проверки
    ВывестиДеревоЗначенийВДеревоФормы(Дерево);
    КонецПроцедуры

    // Вспомогательная процедура для вывода дерева значений на форму (только для проверки)
    Процедура ВывестиДеревоЗначенийВДеревоФормы(Дерево)
    Форма = ПолучитьФорму("ОбщаяФорма.ТестоваяФорма");
    Форма.ЭлементыФормы.Дерево.ЗагрузитьДеревоЗначений(Дерево);
    Форма.Открыть();
    КонецПроцедуры
```
---
Метода сгруппировать нету, свернуть возможно?
---
Добавить в запрос секцию ИТОГИ ПО,
проверить в консоли запросов результат
и выгрузить ПоГруппировкам в уже готовое дерево.
---
как у вас всех легко и быстро получается) пойду анализировать что надо сделать было
---
уже ответил)
---
Неплохая попытка для нейронки)