helpf.pro
Регистрация
 +8 
Распечатать

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

Для одной организации надо было реализовать документы, где вместо табличной части надо использовать дерево и все это на управляемых формах. Но дерево нельзя сохранить в базе в текущем виде. Пришлось использовать табличную часть документа для хранения данных дерева. И при открытии формы получать данные из ТЧ и выводить их в дерево. Далее все манипуляции производить с деревом и при сохранении документа помещать данные в обратно в ТЧ.

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

Для реализации такого механизма в ТЧ был добавлен реквизит “КлючСвязи” (обязательный реквизит) с типом число, куда помещался “НомерСтроки” (стандартный реквизит ТЧ) родителя (верхний уровень). А самый верхний элемент дерева имеет “КлючСвязи” равный 0.

На картинке ниже видно структуру дерева и структуру ТЧ

Нагрузка на сервер осуществляется при окрытии и при сохранении документа. А с деревом работают уже на клиенте.

На рабочей базе обрабатывается около 200 строк в одном документе.

Открытие и сохранение документа происходит моментально. С большем количеством строк не тестировалось.

Чтобы алгорит правильно работал, у рекизита фомы с типом дерево значений должны быть все реквизиты табличной части, кроме “КлючСвязи” и “НомерСтроки”. Иначе платформа выдаст ошибку. В дерево можо добавлять свои реквизиты отличные от ТЧ, они будут использоваться только в дереве.

Ниже приведен код преобразования дерева в таблицу и обратно.

Код 1C v 8.2 УП
 &НаКлиенте
Процедура КомандаТаблицуВДерево(Команда)
КомандаТаблицуВДеревоНаСервере();
КонецПроцедуры


&НаСервере
Процедура КомандаТаблицуВДеревоНаСервере()
Дерево = ТаблицаВДерево(РеквизитФормыВЗначение("Объект"), "Товары");//Товары - имя табличной части
ЗначениеВРеквизитФормы(Дерево, "ДеревоЗначений");//ДеревоЗначений - реквизит формы с типом дерево значений
Элементы.ДеревоЗначений.Обновить();
КонецПроцедуры


&НаКлиенте
Процедура КомандаДеревоВТаблицу(Команда)
КомандаДеревоВТаблицуНаСервере();
КонецПроцедуры


&НаСервере
Процедура КомандаДеревоВТаблицуНаСервере()
Объект.Товары.Очистить();
ДОбъект = РеквизитФормыВЗначение("Объект");
ДеревоВТаблицу(ДОбъект, РеквизитФормыВЗначение("ДеревоЗначений"), "Товары");
ЗначениеВРеквизитФормы(ДОбъект, "Объект");
КонецПроцедуры

Формирование дерева из таблицы значений

Код 1C v 8.2 УП
 //ФОРМИРОВАНИЕ ДЕРЕВА ИЗ ТАБЛИЦЫ
&НаСервере
Функция ТаблицаВДерево(ДокОбъект, НаименованиеТабличнойЧастиДокумента, КлючСвязи = NULL, ЭлементРодитель = NULL) Экспорт
//ПОДГОТОВКА КОЛОНОК ДЕРЕВА
КолонкиТаблицы = ДокОбъект.Метаданные().ТабличныеЧасти[НаименованиеТабличнойЧастиДокумента].Реквизиты;
ДеревоЗначений2 = Новый ДеревоЗначений;
Для каждого Кол из КолонкиТаблицы Цикл
Если Кол.Имя = "НомерСтроки" ИЛИ Кол.Имя = "КлючСвязи" Тогда
Продолжить;
Иначе
ДеревоЗначений2.Колонки.Добавить(Кол.Имя, Новый ОписаниеТипов(Кол.Тип));
КонецЕсли;
КонецЦикла;//ДеревоЗначений.Строки.Очистить();

Если КлючСвязи = NULL И ЭлементРодитель = NULL Тогда
//ПЕРВЫЙ ВЫЗОВ ПРОЦЕДУРЫ (КОРНЕВЫЕ ЭЛЕМЕНТЫ)
ИсточникВыборки = ДеревоЗначений2.Строки;
КлючСвязи = 0; // ЭЛЕМЕНТ ВЕРХНЕГО УРОВНЯ ИМЕЕТ НОМЕР СТРОКИ РОДИТЕЛЯ 0 (ОБЯЗАТЕЛЬНЫЙ РЕКВИЗИТ)
Иначе
//ВНУТРЕННИЙ ВЫЗОВ ПРОЦЕДУРЫ (ПОДЧИНЕННЫЕ ЭЛЕМЕНТЫ)
ИсточникВыборки = ЭлементРодитель.Строки;
КонецЕсли;
Фильтр = Новый Структура("КлючСвязи", КлючСвязи);
М = ДокОбъект[НаименованиеТабличнойЧастиДокумента].НайтиСтроки(Фильтр);
Если М.Количество() = 0 Тогда
Возврат ДеревоЗначений2;
КонецЕсли;
Для каждого Стр из М Цикл
Элемент = ИсточникВыборки.Добавить();
Для каждого Кол из КолонкиТаблицы Цикл
Если Кол.Имя = "НомерСтроки" ИЛИ Кол.Имя = "КлючСвязи" Тогда
Продолжить;
Иначе
Элемент[Кол.Имя] = Стр[Кол.Имя];
КонецЕсли;
КонецЦикла;
ТаблицаВДерево(ДокОбъект, НаименованиеТабличнойЧастиДокумента, Стр.НомерСтроки, Элемент); //ДОБАВЛЕНИЕ ПОДЧИНЁННЫХ ЭЛЕМЕНТОВ В ДЕРЕВО
КонецЦикла;
Возврат ДеревоЗначений2;
КонецФункции

Формирование таблицы из дерева

Код 1C v 8.2 УП
 //ФОРМИРОВАНИЕ ТАБЛИЦЫ ИЗ ДЕРЕВА
&НаСервере
Процедура ДеревоВТаблицу(ДокОбъект, ДеревоЗначений, НаименованиеТабличнойЧастиДокумента, СтрокаДерева = NULL, КлючСвязи = NULL) Экспорт
Если СтрокаДерева = NULL И КлючСвязи = NULL Тогда
//ПЕРВЫЙ ВЫЗОВ ПРОЦЕДУРЫ (КОРНЕВЫЕ ЭЛЕМЕНТЫ)
ПервыйВызов = Истина;
ДокОбъект[НаименованиеТабличнойЧастиДокумента].Очистить();
ИсточникВыборки = ДеревоЗначений.Строки;
КлючСвязи = 0; // ЭЛЕМЕНТ ВЕРХНЕГО УРОВНЯ ИМЕЕТ НОМЕР СТРОКИ РОДИТЕЛЯ 0 (ОБЯЗАТЕЛЬНЫЙ РЕКВИЗИТ)
Иначе
//ВНУТРЕННИЙ ВЫЗОВ ПРОЦЕДУРЫ (ПОДЧИНЕННЫЕ ЭЛЕМЕНТЫ)
ПервыйВызов = Ложь;
ИсточникВыборки = СтрокаДерева.Строки;
КонецЕсли;
Для каждого Стр из ИсточникВыборки Цикл
НС = ДокОбъект[НаименованиеТабличнойЧастиДокумента].Добавить();
Для каждого Кол из ДокОбъект.Метаданные().ТабличныеЧасти[НаименованиеТабличнойЧастиДокумента].Реквизиты Цикл
Если Кол.Имя = "КлючСвязи" Тогда
НС.КлючСвязи = КлючСвязи
ИначеЕсли Кол.Имя = "НомерСтроки" Тогда
Продолжить;
Иначе 
НС[Кол.Имя] = Стр[Кол.Имя];
КонецЕсли;
КонецЦикла;
Если НЕ Стр.Строки.Количество() = 0 Тогда
ДеревоВТаблицу(ДокОбъект,,НаименованиеТабличнойЧастиДокумента, Стр, НС.НомерСтроки);
КонецЕсли;
КонецЦикла;
КонецПроцедуры 
Разместил:   Версии: | 8.2 УП | 8.3 |  Дата:   Прочитано: 71599
 +8 
Распечатать
Возможно, вас также заинтересует
Внутреннее устройство PostgreSQL, в помощь администраторам 1С 1
Понимание архитектуры используемой СУБД очень важно для правильной эксплуатации, но местами переоценено: администратору, DevOps-специалисту или разработчику прикладных систем вовсе необязательно знать подробности внутреннего устройства B-дерева или
Вывод отчета СКД в коллекцию значений - Дерево Значений 5
В системе компоновки данных существует возможность выводить отчет не только в табличный документ, но и в коллекции значений (таблица значений, дерево значений). Для вывода отчета в коллекцию предназначен объект ПроцессорВыводаРезультатаКомпоновкиВК
Выгрузить результат запроса в Дерево Значений, Дерево Значений на форме 9
// Вывод результата запроса в Табличное Поле - Дерево значений Запрос=Новый Запрос; Запрос.Текст=" ВЫБРАТЬ | ВзаиморасчетыСРаботникамиОрганизацийОстатки.ПериодВзаиморасчетов КАК ЗаМесяц, | ВзаиморасчетыСРаботникамиОрганизацийОстатки.Физлицо КАК
Выгрузка результата запроса в Таблицу и Дерево значений 0
Результат запроса может быть выгружен в таблицу значений или дерево значений с помощью метода Выгрузить. Затем над ними могут быть произведены другие операции: сортировка, свертка, перебор строк и другие действия. Следующий пример выгружает результ
Выгрузка табличного документа в Google таблицу 0
Надумал когда-то задачу себе: выгрузить содержимое табличного документа в Google Document . Одним из вариантов использования данного функционала может быть выгрузка состояния заказов пользователей из базы в 1с в google spreadsheet. Если клиент знает
Посмотреть все результаты поиска похожих
Комментарии
webresurs
13.08.2019 08:06Комментарий: 3
webresurs

если брать это

Код 1C v 8.3
 &НаКлиенте
Процедура ДеревоНаФормеПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
ПереместитьСтрокуДерева(ДеревоНаФорме, ПараметрыПеретаскивания.Значение, Строка);
КонецПроцедуры


&НаКлиенте
Процедура ДеревоНаФормеПроверкаПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
СтандартнаяОбработка = Ложь;
КонецПроцедуры


&НаСервере
Процедура ПереместитьСтрокуДерева(Дерево, ПеремещаемаяСтрока, НовыйРодитель, Уровень = 0)

Если Уровень = 0 Тогда

НоваяСтрока = НовыйРодитель.Строки.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ПеремещаемаяСтрока);
ПереместитьСтрокуДерева(Дерево, ПеремещаемаяСтрока, НоваяСтрока, Уровень + 1);

Если ПеремещаемаяСтрока.Родитель = Неопределено Тогда
Дерево.Строки.Удалить(ПеремещаемаяСтрока);
Иначе
ПеремещаемаяСтрока.Родитель.Строки.Удалить(ПеремещаемаяСтрока);
КонецЕсли;

Иначе

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

КонецЕсли;

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


<br>

то пишет ошибка "Значение не является значением объектного типа (Строки)

НоваяСтрока = НовыйРодитель.Строки.Добавить();"

webresurs
13.08.2019 06:48Комментарий: 2
webresurs

если брать это

Код 1C v 8.3
 
&НаКлиенте
Процедура ДеревоНаФормеПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
  ПереместитьСтрокуДерева(ДеревоНаФорме, ПараметрыПеретаскивания.Значение, Строка);
КонецПроцедуры


&НаКлиенте
Процедура ДеревоНаФормеПроверкаПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
    СтандартнаяОбработка = Ложь;
КонецПроцедуры


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


то пишет ошибка "Значение не является значением объектного типа (Строки)

НоваяСтрока = НовыйРодитель.Строки.Добавить();"

webresurs
13.08.2019 04:57Комментарий: 1
webresurs

в дереве значений не всегда срабатывает перетаскивание - подскажите в чем причина ?

Вы не можете отправить комментарий анонимно, пожалуйста войдите или зарегистрируйтесь.