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 |  Дата:   Прочитано: 79901
 +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

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

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