Дерево значений в управляемой форме
Дерево значений в 1С (тип значения «ДеревоЗначений») – это Универсальная коллекция значений в системе 1С, где Элементы упорядочены по Индексу (нумерация начинается с 0). Каждое значение Элемента содержит в себе Коллекцию подчиненных Строк, где у каждой Строки коллекции указывается Родитель – Элемент, находящийся на уровень выше. У корневого Элемента (элемент первого уровня) Родитель отсутствует. Доступ к Элементам осуществляется через Индекс, по номеру которого можно получить доступ к значению Элемента и коллекции подчиненных ему Строк. Описание из Синтакс-помощника: используется для доступа к свойствам и методам дерева значений 1С в целом. Объект, представляющий собой древовидную структуру, обладает сходной функциональностью с таблицей значений, а также обладает возможностью добавлять подчиненные строки к какой-либо строке дерева. Внимание! В толстом клиенте (обычное приложение) передача значений данного типа с клиента на сервер и обратно приводит к возникновению исключения. Доступность: сервер, толстый клиент, внешнее соединение, мобильное приложение (сервер), мобильный автономный сервер. Сериализуется: данный объект может быть сериализован в/из XDTO. Тип XDTO, соответствующий данному объекту, определяется в пространстве имен . Имя типа XDTO: ValueTree.
2. Как создать дерево значений в 1C 8.3
Так как Дерево значений в 1С 8.3 является усложненной конструкцией с точки зрения программной реализации, и достаточно ресурсоемкой, её не часто используют в разработках. Однако, она очень удобна для реализации нестандартных задач, в том числе, когда требуется отобразить множество значений с возможностью группировки по Родителю. Необходимо однозначно разделять Дерево значений как объявленную переменную (через конструктор «Новый ДеревоЗначений») и как Реквизит Формы 1С 8.3 (обратите внимание, что ДЗ нельзя выбрать как тип данных Реквизита Объекта). Если объявленное (далее – ОП) ДЗ можно читать НаКлиенте, передавать НаСервере для обработки и возвращать обратно, то ДЗ как Реквизит Формы 1С 8.3 (далее – РФ) будет читабельным только НаКлиенте. НаСервере даже при попытке чтения дерево выдаст Исключение, а изменять данные, конечно же, не позволит вообще. Далее рассмотрим поведение одинаковых действий при условии объявления переменной (в рамках одной процедуры/функции) и условиях добавленного реквизита формы 1С 8.3. Варианты работы с глобальными переменными, экспортными или не экспортными переменными модуля мы рассматривать не будем, так как применение зависит от контекста задачи и Вашей веры в объявление глобальных и внеконтекстных переменных. У ДЗ как РФ есть свое преимущество: вы можете задать колонки и тип данных в самом РФ и программно обращаться к данным из любой процедуры или функции модуля формы (не забывая о директивах компиляции). Для ДЗ как ОП требуется описать все необходимые колонки (для начинающих это может быть проблематично, если нет четкого представления того, что это за «зверь» такой), а также понимать, что по окончании процедуры/функции кончается и жизненный цикл переменной (конечно, если мы не объявили ее глобальной, но это уже совсем другая история). Пример описания ДЗ программе 1С Предприятие 8:
Как видно из примера, в ДЗ задаются колонки, где будут размещаться данные, но чтобы добавить это данные, необходимо обратиться к Коллекции Строк: ДеревоДанных.Строки.Добавить(). Таким образом добавляются строки первого уровня, после чего в строку первого уровня добавляем коллекцию строк и так далее. При этом, используя метод Добавить(), Родитель присваивается автоматически, но, конечно, его можно изменить. Так и строится дерево, однако не стоит забывать, что чем больше данных, тем больше потребление ресурсов. Пример ДЗ как РФ:
Добавление данных происходит, в сущности, таким же образом, как при описании, но есть программные различия. Опишем основные:
** Пример работы «преобразование-запись-преобразование»:
Развернутое дерево значений по своей сути напоминает Результат запроса с группировками, где чем больше группировок, тем больше совокупное количество строк. Поэтому если требуется результат запроса (где данные сгруппированы) загрузить в ДЗ, необходимо:
1. (необязательно) преобразовать из реквизита формы; 2. загрузить результат; 3. преобразовать в реквизит формы.
При необходимости загрузки данных в ДЗ из табличной части 1С можно воспользоваться несколькими способами:
1. Запись с помощью циклов: тут нужно помнить, что есть строки «корневые», и надо их каким-то образом найти, чтобы правильно построить связь Корень-Подчиненный.
2. Загрузить с помощью Запроса (и здесь есть два варианта):
a. выгрузить табличную часть 1С во временную переменную, передать ее как параметр, сформировать результат с использованием иерархии и загрузить результат в дерево;
b. сформировать запрос, в который передаем как параметр ссылку принятого к обработке документа в 1С 8.3, после чего формируем результат с использованием иерархии и загружаем его в дерево.
*Варианты 2а и 2b кажутся похожими. Однако разница между ними есть. Она заключается в производительности, которая зависит от контекста использования (количество данных, количество пользователей, нагрузка на сервер и другое). С одной стороны, при использовании директивы НаСервере у нас уже есть табличная часть 1С (конечно, на стороне сервера, но она уже загружена), которую мы можем без потерь и других действий передать в Запрос и выполнить его. С другой стороны, обращаясь по ссылке в результате выполнения Запроса, система повторно обратится к БД, но, возможно, сделает это быстрее, чем в первом случае. Этот момент требует исследования уже на конкретной БД. Для записи данных в табличную часть 1С или Таблицу значений потребуется построить цикл, который будет выполнять запись в Приемник по следующим правилам:
1. обход дерева выполняется от Корня к Подчиненным до последнего уровня вложенности;
2. если у Корня есть Подчиненные элементы, то количество результирующих строк в Таблице высчитывается по формуле: , где n – количество элементов на заданном уровне, m — количество уровней (глубина вложенности дерева);
3. рекомендуется записывать Корень – Подчиненный элемент, в связи с этим требуется запись рекурсивным методом. Пример рекурсивной записи из ДЗ в Табличную часть Товары:
Для чтения данных все немного проще: читать можно как НаКлиенте, так и НаСервере. Разница только в том, что для директивы НаКлиенте потребуется сначала вызвать метод ПолучитьЭлемент(), чего не требуется для серверной директивы. Внимание! Не забудьте, что чтение в процедуре/функции с директивой НаКлиентеНаСервереБезКонтекста компилируется одновременно на клиенте и на сервере, а это значит, что описав Чтение как для клиента при вызове исполнения из процедуры/функции с директивой сервера, программа выдаст исключение (и наоборот). При необходимости вызова чтения как НаКлиенте, так и НаСервере рекомендуется создавать обработчики с соответствующими директивами. Кроме всего прочего, ДЗ можно использовать в особо изощренном способе работы. Допустим, поставили задачу, что необходимо иметь на форме две таблицы, таблица слева – дерево, в котором есть все уровни, кроме последнего; справа – таблица, в которой отображаются данные последнего уровня вложенности. Таким образом активация строки в Дереве приведет к отображению всех подчиненных элементов.
Реализованный пример такой задачи:
*Естественно, текущие данные тестовые. Задачей предполагалось, что корневых уровней может быть до 15, второй уровень – примерно так же, а вот на последнем уровне может быть до 50 строк. В такой компоновке удобно видеть все элементы нижнего уровня, переключаясь между Родителями. Использование Дерева значений — это достаточно нетривиальный и филигранный способ, который имеет свои плюсы (особенно когда группы товаров можно сворачивать). Использовать его для больших таблиц (где более 100 строк) можно, но важно исследовать производительность в каждом конкретном случае.
Специалист компании ООО «Кодерлайн» Каплин Иван Александрович
Источник
ДеревоЗначений нет иерархии, подскажите как сделать
. .
.
|УПОРЯДОЧИТЬ ПО
|ТЗКонечная.Номенклатура ИЕРАРХИЯ»;
Результат = Запрос.Выполнить();
ЭлементыФормы.ДеревоЗначений.Значение = Результат.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
ЭлементыФормы.ДеревоЗначений.СоздатьКолонки();
https://ibb.co/ktuj3R
(6)
ЭлементыФормы.ДеревоЗначений.СоздатьКолонки();
ЭлементыФормы.ДеревоЗначений.Колонки.Номенклатура.ОтображатьИерархию = Истина;
|ВЫБРАТЬ
| ПродажиОбороты.Подразделение КАК Подразделение,
| ПродажиОбороты.Номенклатура КАК Номенклатура,
| NULL КАК КоличествоВыпуск,
| NULL КАК ПланКоличествоВыпуск,
| NULL КАК ПланКоличествоПродаж,
| NULL КАК ПланСтоимостьПродаж,
| СУММА(ПродажиОбороты.КоличествоОборот) КАК КоличествоПродаж,
| СУММА(ПродажиОбороты.СтоимостьОборот) КАК СтоимостьПродаж,
| NULL КАК КоличествоПродажПП,
| NULL КАК СтоимостьПродажПП
|ПОМЕСТИТЬ Продажи
|ВЫБРАТЬ
| ПродажиОбороты.Подразделение КАК Подразделение,
| ПродажиОбороты.Номенклатура КАК Номенклатура,
| NULL КАК КоличествоВыпуск,
| NULL КАК ПланКоличествоВыпуск,
| NULL КАК ПланКоличествоПродаж,
| NULL КАК ПланСтоимостьПродаж,
| СУММА(ПродажиОбороты.КоличествоОборот) КАК КоличествоПродаж,
| СУММА(ПродажиОбороты.СтоимостьОборот) КАК СтоимостьПродаж,
| NULL КАК КоличествоПродажПП,
| NULL КАК СтоимостьПродажПП
|ПОМЕСТИТЬ Продажи
|ИЗ
| РегистрНакопления.Продажи.Обороты(
| &ДатаНачала,
| &ДатаКонца,
| Регистратор,
| Номенклатура.Наименование <> «»(10) Сырье и материалы»»
| И Номенклатура.ЦеноваяГруппа.Наименование = «»Сырая продукция»»
| ИЛИ Номенклатура.ЦеноваяГруппа.Наименование = «»Готовая продукция»») КАК ПродажиОбороты
|
|СГРУППИРОВАТЬ ПО
| ПродажиОбороты.Подразделение,
| ПродажиОбороты.Номенклатура
|
|ОБЪЕДИНИТЬ ВСЕ
но с ПОМЕСТИТЬ это не работает
Источник
Не отображается иерархия в дереве значений
Обычные формы. Никак не могу отобразить иерархию в дереве значений на форме. У табличного поля стоит галочка «Дерево». У колонки склад стоит галочка «Отображать иерархию», но все равно отображается линейный список (см. скрин). В чем тут еще может быть дело?
Дерево формирую следующим образом:
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | ТЗОстатки.ГруппаСклада, | ТЗОстатки.Склад, | ТЗОстатки.КоличествоОстаток |ПОМЕСТИТЬ ВТ_Остатки |ИЗ | &ТЗОстатки КАК ТЗОстатки |ГДЕ | ТЗОстатки.Товар = &Товар |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | ВТ_Остатки.ГруппаСклада КАК ГруппаСклада, | ВТ_Остатки.Склад КАК Склад, | ВТ_Остатки.КоличествоОстаток КАК Остаток |ИЗ | ВТ_Остатки КАК ВТ_Остатки |ИТОГИ | СУММА(Остаток) |ПО | ГруппаСклада"; Запрос.УстановитьПараметр("ТЗОстатки", ВирТаблОстатков); Запрос.УстановитьПараметр("Товар", ТекущаяНоменклатура); РезультатЗапроса = Запрос.Выполнить(); ВыборкаГруппаСклада = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); Пока ВыборкаГруппаСклада.Следующий() Цикл Если ВыборкаГруппаСклада.ГруппаСклада = null Тогда Продолжить; КонецЕсли; СтрокаГруппаСкладов = мДеревоОстатков.Строки.Добавить(); СтрокаГруппаСкладов.Склад = ВыборкаГруппаСклада.ГруппаСклада; СтрокаГруппаСкладов.Остаток = ВыборкаГруппаСклада.Остаток; ВыборкаДетальныеЗаписи = ВыборкаГруппаСклада.Выбрать(); Пока ВыборкаДетальныеЗаписи.Следующий() Цикл СтрокаСклад = мДеревоОстатков.Строки.Добавить(); ЗаполнитьЗначенияСвойств(СтрокаСклад,ВыборкаДетальныеЗаписи); КонецЦикла; КонецЦикла;
Источник