Который позволит найти максимальный уровень строк исходного дерева значений

Как найти максимальный уровень строк исходного дерева значений и вывести его на форму в реквизит «Уровень»?

Как найти максимальный уровень строк исходного дерева значений и вывести его на форму в реквизит «Уровень»? Во время отладки возникает ошибка Поле объекта не обнаружено (СтрокиДЗ)
: КоличествоУровней(ДеревоЗначений.СтрокиДЗ);
: ВыполнитьРезультатНаСервере();

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

(1) СтрокиДЗ есть Строки, а не строкиДЗ.

Если вы передаете строку в качестве параметра функции, должно быть

Для Каждого СтрокаДЗ ИЗ СтрокиДЗ.Строки Цикл

Я так понял там упр. формы, соответственно тип значения реквизита — ДанныеФормыДерево а не ДеревоЗначений.

ДеревоЗначений1 = РеквизитФормыВЗначение(ДеревоЗначений); //Получаем ДеревоЗначений
Далее обходите рекурсией как вы и делаете (только учтите первый комментарий, свойство «Строки» а не «СтрокиДЗ»).
Можно обходить и само ДанныеФормыДерево (метод ПолучитьЭлементы()). Но это долго, гораздо дольше чем ДеревоЗначений.

Вообще обходить дерево — долго. Лучше при добавлении строк запомнить максимальный уровень.

С деревьями на форме работают обычно РеквизитФормыВЗначение -> ДеревоЗначений -> ЗначениеВРеквизитФормы. Но при этом теряются идентификаторы строк, и слетает текущая строка дерева после серверного вызова :(. Что бы восстановить текущую строку я бы перед серверным вызовом записал некий адрес текущей строки [1,2,3] и потом установил бы туда текущую строку. Как их то красивых решений этой проблемы не находил.

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

Получается максимальный уровень = 3, а нужно КоличествоУровней = 4 в итоге. Как быть?

(4) Уж не знаю, на сколько актуально (ну мало ли, вдруг кому-то пригодится), но я бы сделал так – увеличивал уровень после определения, есть ли подчиненные строки и перед их обходом:

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

Источник

Читайте также:  Все функции листа дерева

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

(3) Что значит «дерево значений на форме обработки»? Это элемент формы?
Работать нужно с данными элемента, то что в поле ПутьКДанным в свойствах элементах, а не самим элементом.

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

На клиенте нет такого типа, как дерево значений. У топикастера какой-то изврат, который в переменной лежит общей. Я бы так не стал делать, да и уровень дерева в запросе можно получить (в ряде случаев).

(11), а я ничего не писал, что оно есть, на клиенте есть «неудобное» ДанныеФормыДерево.
Относительный аналог «Для Каждого стрДерева из ДеревоЗн.Строки Цикл» является «Для Каждого стрДерева из ДеревоЗн.ПолучитьЭлементы() Цикл»

как вариант: https://forum.infostart.ru/forum9/topic113341/ (сам принцип), понятно, что цикл можно можно сделать рекурсивно

в цикле считай всё, что хочешь

(14) Ну мало ли. Все таки арсенал методов для работы с прикладным ДЗ шире, чем с ДанныеФормыКоллекция. Все зависит от задачи и используемых данных.

Источник

Просто о дереве значений

  • 1.png
  • 2.png
  • 3.png

Цель данной статьи — изложить свой взгляд на такой объект 1С, как дерево значений. На данную тему написано уже достаточно статей, в особенности на предмет программной работы с этим объектом. Поэтому Америку не открою, лишь попытаюсь предложить начинающим программистам способ лёгкого освоения методики работы с деревом значений с помощью всего 3х важных моментов.

Для того, чтобы работать с этим объектом, нужно понимать, для чего он нужен. Он удобен, в первую очередь, для представления иерархических объектов – таких, как справочник Номенклатура. Мне встречалась также задача по представлению в виде дерева разнотипных подчинённых объектов, например ЗаказовПокупателя и Номенклатуры в Маршрутном Листе.

Читайте также:  Отделка кирпичных домов деревом внутри

Дерево Значений = Таблица Значений + колонка Родитель

Иерархия или подчинённость отражается в 1С с помощью дополнительного реквизита – Родитель. Именно наличие такого реквизита отличает объект ДеревоЗначений от объекта ТаблицаЗначений. Это первое, что нужно запомнить для работы с Деревом – ДеревоЗначений это ТаблицаЗначений с дополнительной колонкой Родитель.

Дерево Значений = работа с одним уровнем иерархии

Второй важный момент – при работе с деревом на Сервере, в отличие от ТаблицыЗначений, у которой можно получить произвольное количество строк методом НайтиСтроки(), получаемые строки ограничены текущим уровнем иерархии, то есть значением колонки Родитель. Во время первого обращения к объекту метод Строки() возвращает коллекцию (не массив, как в ТЗ) строк корневого уровня – строк с пустым значением колонки Родитель. В зависимости от типа иерархии таких строк может быть как одна, так и несколько. Далее вся работа с Деревом сводится к перебору циклом «Для Каждого Из» колллекции, полученной методом Строки(). Для каждого элемента коллекции метод Строки() возвращает коллекцию подчинённых строк – тех, у которых значение колонки Родитель равно данному элементу. Таким образом организуется рекурсивный обход дерева – примеры функций также есть в других статьях. Остальные методы работы с деревом аналогичны методам работы с таблицей значений (см. синтакс-помощник). Иначе говоря, коллекция строк дерева с одинаковым значением колонки Родитель представляет собой таблицу значений.

ДеревоЗначений на Сервере = ДанныеФормыДерево на Клиенте

Третий момент – передача данных Дерева между Клиентом и Сервером. На Клиенте объекту типа ДеревоЗначений соответствует объект ДанныеФормыДерево.

Для работы с Деревом Значений в клиент-серверном режиме необходимо использовать функции платформы – РеквизитФормыВЗначение (ДанныеФормыВЗначение) для передачи изменений с клиента на сервер и ЗначениеВРеквизитФормы (ЗначениеВДанныеФормы) для передачи с сервера на клиент. Эти функции облегчают жизнь разработчику, поскольку обрабатывают весь объект целиком, а не только один уровень иерархии, как это вынужден делать разработчик.

Читайте также:  Цвет лазурное дерево кухня

Напоследок, хотелось бы изложить свой взгляд на задачу позиционирования в Дереве, которая встречается достаточно часто. Раз у Дерева есть колонки, то для его отображения на клиенте используется объект ТаблицаФормы. Для решения задачи позиционирования в дереве используется свойство таблицы – ТекущаяСтрока. На просторах Интернета встречаются решения, когда для позиционирования происходит обращение к серверу. На мой взгляд, этого не требуется, поскольку объект ДанныеФормыДерево содержит все значения, при условии, что они переданы с помощью функций передачи (см. выше) и позиционирование заключается в поиске значения, получении идентификатора строки и установке свойства ТекущаяСтрока у элемента управляемой формы.

Пример клиентской функции поиска значения:

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

Комментарий: сначала получается коллекция элементов корневого уровня. Системная функция ПолучитьЭлементы() на клиенте соответствует функции Строки() на сервере. В цикле запускается перебор элементов коллекции, в котором присутствует рекурсивная функция НайтиВДереве(СтрокаДерева, Что_то), возвращающая найденную строку в случае успешного поиска , либо Неопределено, в противном случае. Если РезультатПоиска отличается от пустого значения Неопределено, то в ТаблицеФормы, отображающей Дерево, устанавливаются значения ТекущийЭлемент и ТекущаяСтрока по идентификатору строки дерева, получаемому системной функцией ПолучитьИдентификатор().

Это простой пример поиска по одному полю — Поле. Если имя поля передать в качестве второго параметра функции, то к нему можно будет обратиться следующим образом:

Если СтрокаДерева[Поле] = Что_то Тогда

и функция будет искать значения в любой колонке (по любому реквизиту) дерева.

Поскольку целью статьи было знакомство с объектом ДеревоЗначений других примеров кода не привожу. Надеюсь, что с помощью данной статьи вам будет легче понять приводимые в других статьях примеры и освоить самостоятельную работу с объектами типа ДеревоЗначений без каких-либо трудностей.

Источник

Оцените статью