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

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

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

&НаСервере Процедура ВыполнитьРезультатНаСервере() КоличествоУровней(ДеревоЗначений.СтрокиДЗ); КонецПроцедуры Функция КоличествоУровней(СтрокиДЗ) Если СтрокиДЗ.Количество() = 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),Истина); Для Каждого СтрокаДЗ Из МассивСтрок Цикл МаксУровень = Макс(МаксУровень, СтрокаДЗ.Уровень()); КонецЦикла; Возврат МаксУровень; КонецФункции

Источник

Читайте также:  Дерева из бумаги поделка

Дерево значений 1с. Описание и примеры использования

ДеревоЗначений — это программный объект встроенного языка, позволяющий строить произвольные иерархические наборы данных в памяти компьютера, отображать их в табличном и\или древовидном виде, а также программно и интерактивно манипулировать ими (добавлять, редактировать, удалять и сортировать строки).

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

Строки и колонки имеют индексы, по которым к ним можно обращаться напрямую (начинаются с 0). Кроме этого, к колонкам можно обращаться по идентификатору.

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

Дерево значений является полностью динамическим объектом, т.е. Вы можете манипулировать не только строками дерева, добавляя и удаляя их, но и колонками.

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

Создание дерева значений

Как и большинство объектов встроенного языка, новая дерево значений может быть создано с помощью оператора Новый :

Свойства и методы дерева значений

Имя Тип Описание
Свойства
Колонки КоллекцияКолонокДереваЗначений содержит коллекцию колонок дерева значений
Строки КоллекцияСтрокДереваЗначений содержит коллекцию корневых строк дерева значений
Методы
ВыбратьСтроку() СтрокаДереваЗначений открывает диалог для интерактивного выбора строки дерева значений
Скопировать() ДеревоЗначений создает новый объект копированием текущего (копируются все колонки и строки)

Колонки дерева значений

Прежде чем начать работу с деревом значений, необходимо создать структуру колонок. Каждая колонка характеризуется следующими свойствами:

Имя Тип Описание
Имя Строка символьный идентификатор колонки, по которому к ней можно обращаться из кода. Может содержать только алфавитные символы, цифры и знаки подчеркивания. Причем, начинаться имя колонки может только с буквы или символа подчеркивания
Заголовок Строка строковое представление колонки на форме. Может содержать произвольные символы
ТипЗначения ОписаниеТипов тип значения содержимого ячеек в этой колонке. Свойство ограничивает пространство доступных значений, которые можно указать в данной колонке
Ширина Число ширина колонки на форме (выражается в количестве символов)
Читайте также:  Деревья липецкой области названия

Доступ к колонкам производится через свойство Колонки объекта ДеревоЗначений . Для добавления новой колонки используется метод Колонки.Добавить():

дз.Колонки.Добавить("Наименование", Новый ОписаниеТипов("Строка")); дз.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число")); дз.Колонки.Добавить("Свойство");//можно хранить произвольные данные 

Для того, чтобы определить наличие колонки с нужным именем используется метод Колонки.Найти():

найдКолонка = дз.Колонки.Найти("Наименование"); Если найдКолонка = Неопределено Тогда Сообщить("Колонка не найдена!"); Иначе Сообщить("Индекс колонки color: red;">+ дз.Колонки.Индекс(найдКолонка)); КонецЕсли; 

Перебор колонок выполняется следующим образом:

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

Для удаления колонки используется метод Колонки.Удалить():

найдКолонка = дз.Колонки.Найти("Свойство"); Если НЕ найдКолонка = Неопределено Тогда дз.Колонки.Удалить(найдКолонка); КонецЕсли; 

Методы коллекции колонок дерева значений

Вставить() Вставляет новую колонку в указанную позицию коллекции
Добавить() Добавляет новую колонку в конец коллекции
Индекс() Возвращает индекс колонки в коллекции колонок
Получить() Возвращает колонку по ее индексу
Количество() Возвращает количество колонок в коллекции
Найти() Ищет колонку в коллекции по имени
Очистить() Удаляет все колонки из коллекции
Сдвинуть() Сдвигает колонку влево или вправо
Удалить() Удаляет колонку из коллекции

Строки дерева значений

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

В отличие от таблицы значений, доступ к строкам дерева значений производится через свойство Строки объекта ДеревоЗначений или объекта СтрокаДереваЗначений . Каждая строка является узлом иерархии, поэтому обладает следующими свойствами и методами:

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

Добавление и удаление строк

Для добавления новой строки используется метод Строки.Добавить(). Метод возвращает объект СтрокаДереваЗначений , с которым доступны дальнейшие манипуляции:

СтрокаДЗ = дз.Строки.Добавить(); 

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

СтрокаДЗ.Наименование = "Стул деревянный"; СтрокаДЗ.Количество = 1; СтрокаДЗ.Свойство = ТекущаяДата(); 

Для удаления строки используется метод Строки.Удалить(). Строку можно удалить передав методу либо саму строку, либо ее индекс:

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

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

Для перебора строк удобнее всего использовать оператор цикла Для Каждого . В редких случаях оправдано применение цикла Для :

Для Каждого СтрокаДЗ Из дз.Строки Цикл ИндСтроки = дз.Строки.Индекс(СтрокаДЗ); Сообщить("Строка[" + ИндСтроки + "]: " + СтрокаДЗ.Наименование); КонецЦикла; //в редких случаях Для ИндСтроки = 0 По дз.Строки.Количество() - 1 Цикл СтрокаДЗ = дз.Строки.Получить(ИндСтроки); Сообщить("Строка[" + ИндСтроки + "]: " + СтрокаДЗ.Наименование); КонецЦикла; 

Поиск строк

Поиск в дереве значений можно выполнять не только по значению в колонке (в этом случае будет возвращена первая найденная строка), но и по набору свойств (в этом случае возвращается массив строк).

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

Поиск возможен даже среди вложенных строк. Внимательно изучите документацию к методам Строки.Найти() и Строки.НайтиСтроки().

Читайте также:  Украшение деревьев на новый год

Все методы коллекции строк дерева значений:

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

Иерархию свойств и типов значений, связанных с деревом значений, схематически можно представить в виде дерева:

Источник

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