Преобразовать дерево значений в таблицу значений 1с

Обновлено: 07.07.2024

В данном случае получится такое Дерево (значения числовых колонок взяты в скобки):

Нужен рекурсивный алгоритм, который построит такое дерево при заданных n, k, r.

Отбираешь строки по первому столбцу, по которому строится дерево, выгружаешь это в ТЗ, добавляешь в дерево узел, для этой ТЗ делаешь рекурсивно
как то так А на хрена рекурсия. Можно конечно и рекурсией и не сложно.
Но ГОРАЗДО проще запросом к таблице с итогами и выгрузкой результата "с группировкой" дерево из колонок? интересно-интересно.
кто вкурил - отсыпьте поднатужился - получилось представить только колонки из дерева Применяешь глСгруппироватьПоПолюСТЗБыстр(Тз,Поле) к каждой группировке и заменяешь ТзПоГруппе на глСгруппироватьПоПолюСТЗБыстр(ТзПоГруппе,Поле) и так пока полей хватит

Процедурка СгруппироватьТз(Тз,СписокПолей,Индекс,КоличествоПолей)
Тз.ВыбратьСтроки();
Пока Тз.ПолучитьСтроку()=1 Цикл
Тз.ТзПоГруппе=глСгруппироватьПоПолюСТЗБыстр(Тз.ТзПоГруппе,СписокПолей.ПолучитьЗначение(Индекс);
Если Индекс<=КоличествоПолей Тогда
СгруппироватьТз(Тз.ТзПоГруппе,СписокПолей,Индекс+1,КоличествоПолей)
КонецЕсли;
КонецЦикла;
КонецПроцедурки

Сперва Нужно сделать первичную группировку, где тз это плоская таблица
Тз=СгруппироватьТз(Тз,СписокПолей,Индекс,КоличествоПолей)

Тьфу Сначала
Получить Первичную Группировочную Таблицу
Тз=глСгруппироватьПоПолюСТЗБыстр(,Поле);
А затем ее дербанить на оствшиеся поля
СгруппироватьТз(Тз,СписокПолей,1,КоличествоПолей) +12 Для отчета, можно еще Класс.ИтогиПоГруппировкам задействовать..

Посмотри такое. Внимательно не вчитывалась в условие, но вроде это то. ))

//************************************************************
Функция ИтоговаяТЗ(ТЗНач, СпКолонокГрупп, СпКолонокСумма, НачУровень = 0, СтруктураВнутр = "") Экспорт
Перем ТЗНачКопия, ТЗИтог, ТекТЗ, ВремТЗ;
ТЗНач.Выгрузить(ТЗНачКопия);
Если НачУровень = 0 Тогда
ТЗНачКопия.Сортировать(СпКолонокГрупп);
СтруктураВнутр = ЗначениеВСтрокуВнутр(СоздатьОбъект("ТаблицаЗначений"));
КонецЕсли;
ТЗНачКопия.Выгрузить(ТЗИтог);
ТЗНачКопия.Выгрузить(ВремТЗ);
Поз = Найти(СпКолонокГрупп, ",");
Если Поз > 0 Тогда
ТекИзм = СокрЛП(Лев(СпКолонокГрупп, Поз - 1));
ОстИзм = СокрЛП(Сред(СпКолонокГрупп, Поз + 1));
Иначе
ТекИзм = СокрЛП(СпКолонокГрупп);
ОстИзм = "";
КонецЕсли;
ТЗИтог.Свернуть(ТекИзм, СпКолонокСумма);
Если ОстИзм = "" Тогда
// по строкам - заполнить таблицы значений
ТЗИтог.НоваяКолонка("ТаблицаЗначений");
ТЗИтог.ВыбратьСтроки();
Пока ТЗИтог.ПолучитьСтроку() = 1 Цикл
ТЗИтог.ТаблицаЗначений = ЗначениеИзСтрокиВнутр(СтруктураВнутр);
КонецЦикла;
Возврат ТЗИтог;
КонецЕсли;
Если ТЗИтог.КоличествоСтрок() = 0 Тогда
Возврат ТЗИтог;
КонецЕсли;
ТЗИтог.НоваяКолонка("ТаблицаЗначений");
ТЗИтог.НоваяКолонка("СлужебнаяНач","Число");
ТЗИтог.НоваяКолонка("СлужебнаяКон" ,"Число");
ТЗИтог.ВыбратьСтроки();
Пока ТЗИтог.ПолучитьСтроку() = 1 Цикл
НомСтр = 0;
ВремТЗ.НайтиЗначение(ТЗИтог.ПолучитьЗначение(ТЗИтог.НомерСтроки, ТекИзм), НомСтр, ТекИзм);
ТЗИтог.СлужебнаяНач = НомСтр;
Если ТЗИтог.НомерСтроки <> 1 Тогда
ТЗИтог.УстановитьЗначение(ТЗИтог.НомерСтроки - 1, "СлужебнаяКон", НомСтр - 1);
КонецЕсли;
КонецЦикла;
ТЗИтог.УстановитьЗначение(ТЗИтог.КоличествоСтрок(), "СлужебнаяКон", ВремТЗ.КоличествоСтрок());
ТЗИтог.ВыбратьСтроки();
Пока ТЗИтог.ПолучитьСтроку() = 1 Цикл
ТЗИтог.Выгрузить(ТекТЗ, 1, 1, 1);
ВремТЗ.Выгрузить(ТекТЗ, ТЗИтог.СлужебнаяНач, ТЗИтог.СлужебнаяКон, ОстИзм + "," + СпКолонокСумма);
ТекТЗ.Свернуть(ОстИзм, СпКолонокСумма);
ТЗИтог.ТаблицаЗначений = ИтоговаяТЗ(ТекТЗ, ОстИзм, СпКолонокСумма, 1, СтруктураВнутр);
КонецЦикла;
ТЗИтог.УдалитьКолонку("СлужебнаяНач");
ТЗИтог.УдалитьКолонку("СлужебнаяКон");
Возврат ТЗИтог;
КонецФункции

Сделать запрос к исходной таблице значений, и в запросе указать раздел итоги, куда расписать всю иерархию колонок. Результат запроса выгрузить:

// Функция формирует значение нового ключа строки табличной части.
//
// Параметры:
// Дерево - дерево значений
//
Функция ПолучитьНовыйКлючСтрокиДерева ( Дерево , СписокКлючей = Неопределено) Экспорт

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

// Процедура обновляет ключи связи в дереве значений
//
Процедура ОбновитьКлючиСвязиВДеревеЗначений ( Дерево ) Экспорт

Для Каждого СтрокаДерева Из Дерево . Строки Цикл
Попытка
СтрокаДерева . КлючСвязи = СтрокаДерева . Родитель . КлючСтроки ;
Исключение
СтрокаДерева . КлючСвязи = 0 ;
КонецПопытки;
ОбновитьКлючиСвязиВДеревеЗначений ( СтрокаДерева );
КонецЦикла;

// Процедура обновляет ключи связи в дереве значений
//
Процедура ОбновитьКлючиСтрокВДеревеЗначений ( Дерево , КлючСтроки = 1 ) Экспорт

Для Каждого СтрокаДерева Из Дерево . Строки Цикл
СтрокаДерева . КлючСтроки = КлючСтроки ;
КлючСтроки = КлючСтроки + 1 ;
ОбновитьКлючиСтрокВДеревеЗначений ( СтрокаДерева , КлючСтроки );
КонецЦикла;

// Процедура выгружает данные из дерева значений в таблицу значений
// данные выгружаются только в таблицу со сходным набором реквизитов
//
Функция ВыгрузитьДеревоЗначенийВТаблицуЗначений ( Дерево , Таблица = Неопределено) Экспорт

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

// Процедура выгружает данные из таблицы значений в дерево значений
// данные выгружаются только в таблицу со сходным набором реквизитов
//
// Параметры:
//
// КлючСтроки - имя колонки ТаблицыЗначений - уникальный идентификатор
// КлючСвязи - имя колонки ТаблицыЗначений - указатель привязки к строке Дерева,
// своего рода указатель на "Родителя"
//
Функция ВыгрузитьТаблицуЗначенийВДеревоЗначений ( Таблица , КлючСтроки = "КлючСтроки" , КлючСвязи = "КлючСвязи" ) Экспорт

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

// Процедура устанавливает значение во всем дереве значений
//
Процедура УстановитьЗначениеКолонкиДерева ( Дерево , Колонка , Значение ) Экспорт

Для каждого СтрокаДерева Из Дерево . Строки Цикл
СтрокаДерева [ Колонка ] = Значение ;
УстановитьЗначениеКолонкиДерева ( СтрокаДерева , Колонка , Значение );
КонецЦикла;

// Процедура копирует подчиненные строки дерева значений
//
Процедура СкопироватьПодчиненныеСтроки ( СтрокаПриемник , СтрокаИсточник )

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

// Процедура переносит выделенные строки дерева значений в указанную ветку
//
Процедура ПеренестиСтрокиДереваЗначений ( СтрокаПриемник , ВыделенныеСтроки ) Экспорт

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

В последнее время аномально часто мне в работе попадалось дерево значений, поэтому решил написать на эту тему статью.

Дерево значений

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

Дерево значений на форме

Дерево значений на обычной форме Дерево значений на управляемой форме

Заполнение дерева значений

Небольшой пример программного заполнения таблицы значений для управляемых форм:

Обход дерева значений

Обход всех строк дерева значений делается при помощи рекурсии, вот так будет выглядеть код для обхода дерева созданного в примере выше:

Как свернуть и развернуть дерево значений

Сворачивается и разворачивается дерево значений очень просто.

Привел три примера: для сворачивания текущей строки, для сворачивания строк верхнего уровня, для сворачивания вообще всех строк (рекурсия).

Элементы.Дерево.Развернуть(Элементы.Дерево.ТекущаяСтрока, Истина); Элементы.Дерево.Развернуть(тСтр.ПолучитьИдентификатор(), Истина);

Как удалить строку и очистить дерево значений

Тут опять же все просто, нужно помнить, что при удалении/очистке строки, все подчиненные строки удаляются.

Очистить дерево значений:

Точно также можно очистить от подчиненных элементов другую другую строку.

Запрос и дерево значений

Запрос.Текст crayon-line" > | Тест.Колонка1 КАК Колонка1, Выгрузка = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);

Дерево значений в таблицу значений и обратно

Отбор в дереве значений

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

Таким образом, если Вам нужно реализовать отбор в дереве значений, то начать нужно с решения именно этой проблемы. А уже после этого можно придумать несколько способов реализовать задуманное.

На этом все, рассказал все, что знал, надеюсь мне удалось сэкономить Вам немного времени.

Если Вы нашли ошибку или неточность, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

(оценок: 29, средняя оценка: 4,90 из 5)

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

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

В 1С:классификации Таблица Значений и Дерево Значений (ТЗ и ДЗ) представляют собой не сохраняемый в базе объект. В связи с этим, описание коллекций значений для программирования выполняется оперативно в момент обращения к ним.

Для сокращения трудозатрат программиста, в статье предложена универсальная процедура вывода ТаблицыЗначений или ДереваЗначений на экран. Эта процедура программно заполняет колонки реквизита управляемой формы, что весьма удобно при отладке.

На примерах показаны различия работы с КоллекциямиЗначений в толстом и тонком клиентах управляемой формы.

Из примеров следуют общие правила:

А) для толстого клиента ограничений нет. Примеры 1 и 4.

Б) для тонкого клиента – обработку коллекции необходимо выполнять на сервере, там же следует обеспечить вывод результата на экран.

Предложенная универсальная процедура СоздатьКолонкиУпр() программно добавляет колонки в реквизиты формы и преобразовывает коллекциюЗначений в ДанныеФормы.

Универсальную процедуру СоздатьКолонкиУпр() рекомендуется размещать в общем модуле конфигурации. Если это невозможно, то процедура успешно работает в модуле внешнего отчета.

В обычном приложение аналогом является процедура СоздатьКолонки(), которая удаляет старые колонки и загружает новые колонки из источника данных в табличное поле.

Примечание.

Разница между обычным и управляемым приложениями уже была изложена в аналогах.

Эта статья систематизирует методы работы с коллекциями значений и предлагает удобные для копирования варианты программного кода. Цель статьи – сократить трудозатраты программиста при выборе между толстым и тонким клиентами для использования таблицы (ТЗ) или дерева значений (ДЗ) в качестве источника данных для СистемыКомпоновкиДанных (СКД).

Блок-схема подготовки источника внешних данных для СКД на основании не сохраняемых в базе объектов приведена на прилагаемом рисунке.

Третья группа примеров на Видео демонстрирует реализацию всех веток блок – схемы.

Текст озвучки видео.

Сейчас будут показаны варианты программирования работы с таблицей и деревом значений в тонком и толстом клиентах управляемого приложения.

Откроем 1С:Предприятие в Тонком и Толстом клиентах.

Во всех примерах состав колонок Таблицы Значений или Дерева Значений произвольный, то есть заранее не известен. Программное заполнение реквизитов управляемой формы будет выполнено функцией СоздатьКолонкиУпр().

1) В толстом клиенте никаких ограничений нет. Пример №1 выводит на экран новую таблицу. Пример №4 редактирует существующую таблицу. Все операции можно выполнять на клиенте.

Толстый клиент закрываем.

Остальные примеры рассмотрим в тонком клиенте.

2) В тонком клиенте (пример №2) дерево создается на сервере. Пример №5 редактирует существующее дерево на сервере.

  1. Пример №6 преобразовывает ДеревоЗначений в таблицу. Это действие востребовано при передаче внешних данных в СКД.

3) Если программист вынужден передать в обработку КоллекциюЗначений через клиента, то это можно выполнить с помощью временного хранилища. Смотрим пример №3.

  1. Пример №7 показывает как таблицу преобразовать в дерево, используя макет ОсновнаяСхемаКомпоновкиДанных.

4) Заполним ТаблицуЗначений заново и в примере №8 преобразуем её в табличный документ. Теперь можно напечатать результат.

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

  1. Создаём таблицу значений (Пример.3)
    1. и добавляем строку вручную.
    1. и добавляем строки в последний уровень и первый,
    1. Меняем значение первой колонки

    6) Третья группа примеров посвящена применению Системы Компоновки Данных (СКД). Здесь будет продемонстрировано практическое использование ранее изложенных приемов для ввода данных в СКД.

    1. Примеры третьей группы полезны программисту в случаях, когда возникает необходимость применить методы обработки данных не доступные в СКД.
    2. Пример 10.1. Получаем табличный документ типовой работой СКД со справочником на основании макетаДЗ.Обращаем внимание, что макетДЗ не имеет настроек на ввод данных из внешнего набора, т.е макетДЗ можно построить конструктором.
    3. Пример 10.2. Получаем тоже самое в форме ДереваЗначений. Добавляем строку и меняем ей родителя на «Блузу».
    4. Пример 10.3. Возвращает изменённое ДеревоЗначений в формат ТабличногоДокумента по структуре, заданной в макетеДЗ. Такое преобразование востребовано, например, для печати результата типовыми методами.
    5. Видим, что в сложных для программиста случаях, данные табличного документа можно скорректировать либо вручную, либо программно, используя промежуточное дерево значений.
    6. Предварительно преобразуем ДЗ в ТЗ. (Пример.6)
    7. Пример 10.4. Повторяет то же самое для ТаблицыЗначений.
    8. Техническое решение примеров 10.3 и 10.4 обеспечивает функция ВернутьТабДокСервер(), которая:
      1. В пустой макет «СКДТонкийКлиент» программно устанавливает НаборДанныхОбъект, который заполняем внешними данными из отредактированной ТЗ.
      2. Настройки копируем из макетаДЗ.
      3. Результатом будет требуемый ТабличныйДокумент, учитывающий внесенные изменения в таблицу значений ТЗ.

      7) Заключение. Демонстрация показала:

      1. Процедура СоздатьКолонкиУпр() выполняет такие же функции как процедура. СоздатьКолонки() обычного приложения.
      2. Если исходная коллекция и результат её преобразования размещены в одной управляемой форме, то необходимо очищать колонки источника во избежание дублирования наименований в приёмнике. (Процедура ОчиститьКоллекциюЗначенийНаСервере()).
      3. В тонком клиенте модули управления коллекцией значений обязательно следует размещать на сервере.
      4. Для преобразования коллекции значений в табличной документ с независимым макетомСКД можно применить функцию Скд_ВнешниеДанные().
      5. Независимый макетСКД можно создать на основании другого макета, например, макетДЗ. Для решения этой задачи можно применить функцию ВернутьТабДокСервер().
      6. Примечание. Программный код представлен способом, повышающим удобство копирования в разработку. Размеры базовых блоков программного кода, назначенных к копированию в разработку, не превышают четырёх строк.

      Желаю успехов всем и каждому.

      Описание Процедуры СоздатьКолонкиУпр()

      Синтаксис:

      СоздатьКолонкиУпр(<ФормаЭта>, <ИмяРеквизита>, <КоллекцияЗначений>)

      Параметры:

      Тип:УправляемаяФорма. Форма, в реквизите которой требуется программно определить состав колонок.

      Тип:Строка. Имя реквизита как указано в управляемой форме. Этому реквизиту следует определить состав колонок. Тип реквизита должен быть либо ТаблицаЗначений, либо ДеревоЗначений.

      Тип:ТаблицаЗначений, ДеревоЗначений, АдресВременногоХранилища. Источник данных, который следует вывести на экран. Тип источника данных должен быть либо ТаблицаЗначений, либо ДеревоЗначений. Причем, для этого реквизита состав колонок указанный в управляемой форме должен быть пустым.

      Описание:

      Для любого прикладного объекта типа таблицаЗначений или деревоЗначений, программно создаётся состав колонок реквизита управляемой формы. Затем прикладной объект преобразовывается в данные формы и выводится на экран.

      Процедура применяется в случаях, когда состав колонок коллекцииЗначений заранее не определён.

      Доступность:

      Примечание:

      Описание Функции ВернутьТабДокСервер()

      Синтаксис:

      ВернутьТабДокСервер (<ТЗисточник >, < АдресМакетаСКД >, < НастройкиСКД_1>)

      Параметры:

      Тип:ТаблицаЗначений. Источник данных для формирования результата СКД.

      Тип:Строка. Адрес временного хранилища, в которое помещен макет схемы компоновки данных (Тип:СхемаКомпоновкиДанных).

      < НастройкиСКД _1> (обязательный)

      Тип:НастройкиКомпоновкиДанных. Текущие настройки макета СКД.

      Описание:

      Возвращает ТабличныйДокумент с данными из ТаблицыЗначений (ТЗисточник) преобразованными по структуре МакетаСКД

      Доступность:

      Примечание:

      Описание Функции скд_ВнешниеДанные ()

      Синтаксис:

      Скд_ВнешниеДанные (<ТЗ_внешниеДанные>, <ТипРезультата="ТабДок">, <АдресМакетаСКД="">, <НастройкиСКД=Неопределено>)

      Параметры:

      Тип:ТаблицаЗначений. ДанныеФормыКоллекция. Источник данных для формирования результата СКД.

      < ТипРезультата > (не обязательный)

      Тип:Строка. Допустимые значения: «ТабДок», «ТабличныйДокумент», «ДЗ», «ДеревоЗначений», «ТЗ», «ТаблицаЗначений».

      < АдресМакетаСКД > (не обязательный)

      < НастройкиСКД > (не обязательный)

      Тип:НастройкиКомпоновкиДанных. Текущие настройки макета СКД.

      Описание:

      Возвращает результат СКД заданного типа с данными из ТаблицыЗначений преобразованными по структуре МакетаСКД

      Читайте также: