Для одной организации надо было реализовать документы, где вместо табличной части надо использовать дерево и все это на управляемых формах. Но дерево нельзя сохранить в базе в текущем виде. Пришлось использовать табличную часть документа для хранения данных дерева. И при открытии формы получать данные из ТЧ и выводить их в дерево. Далее все манипуляции производить с деревом и при сохранении документа помещать данные в обратно в ТЧ.
Поиск по интернету не дал нужного варианта, пришлось реализовавыть свой механизм, используя информацию которая была на просторах интернета.
Для реализации такого механизма в ТЧ был добавлен реквизит “КлючСвязи” (обязательный реквизит) с типом число, куда помещался “НомерСтроки” (стандартный реквизит ТЧ) родителя (верхний уровень). А самый верхний элемент дерева имеет “КлючСвязи” равный 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 Тогда
ДеревоВТаблицу(ДокОбъект,,НаименованиеТабличнойЧастиДокумента, Стр, НС.НомерСтроки);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Пример выгрузки(помещения) справочника в Таблицу Значений (ТЗ):
Код 1C v 7.x // Параметры:
// ВидСправочника - Строка, указывающая вид справочника, как он задан в конфигураторе
// ДобавлятьЭлементыСправочника - 1- добавить колонку с наименованием "Элемент", содержащую элементы справочников, 0 - не добавлять колонку
// ИмяРеквизита - Имя реквизита, как он задан в конфигураторе. Используется при заполнении таблицы из выборки по значению реквизита.
// ЗначениеРеквизита - Значение реквизита, по которому надо построить выборку. Используется при заполнении таблицы из выборки по значению реквизита.
// ЭлементВладелец - Владелец, указывается для подчиненных справочников
// ЭлементРодитель - Родитель, используется в случае, если надо ограничить выборку условием принадлежности элементов одной группе
// ВключатьПодчиненные - Установить флаг выборки всех подчиненных элементов.
// Иерархия - Флаг указывающий на то как выбирать элементы (1 - выбирать элементы с учетом иерархии, 0 - выбирать элементы без учета иерархии)
// ВОбратномПорядке - Число: 1 - выбирать элементы справочника в обратном порядке; 0 - выбирать элементы справочника в прямом порядке
// ВключатьГруппы - 1 - выбирать среди групп справочника, 0 - выбирать только среди элементов
//
// Возвращает: Таблица значений, колонками которой, являются реквизиты справочника
Функция СправочникВТЗ(ВидСправочника, ДобавлятьЭлементыСправочника = 0,ИмяРеквизита = 0, ЗначениеРеквизита = 0, ЭлементВладелец = 0, ЭлементРодитель = 0, ВключатьПодчиненные = 1, Иерархия = 1, ВОбратномПорядке = 0, ВключатьГруппы = 0) Экспорт
ТаблицаСпр = СоздатьОбъект("ТаблицаЗначений");
мдСпр = Метаданные.Справочник(ВидСправочника);
ВсегоРеквизитовСпр = мдСпр.Реквизит();
Для индРекв = 1 по ВсегоРеквизитовСпр Цикл
Вид = мдСпр.Реквизит(индРекв).Вид;
ТаблицаСпр.НоваяКолонка(мдСпр.Реквизит(индРекв).Идентификатор, мдСпр.Реквизит(индРекв).Тип + ?(ПустоеЗначение(Вид) = 0, "." + Вид, ""), мдСпр.Реквизит(индРекв).Длина, мдСпр.Реквизит(индРекв).Точность);
КонецЦикла;
ТаблицаСпр.НоваяКолонка("Код", ?(мдСпр.ТипКода = "Текстовый", "Строка", "Число"), мдСпр.ДлинаКода);
ТаблицаСпр.НоваяКолонка("Наименование", "Строка", мдСпр.ДлинаНаименования);
Если ДобавлятьЭлементыСправочника = 1 тогда
ТаблицаСпр.НоваяКолонка("Элемент", "Справочник." + ВидСправочника);
КонецЕсли;
Спр = СоздатьОбъект("Справочник." + ВидСправочника);
Если ЭлементВладелец <> 0 тогда
Спр.ИспользоватьВладельца(ЭлементВладелец);
КонецЕсли;
Если ЭлементРодитель <> 0 тогда
Спр.ИспользоватьРодителя(ЭлементРодитель);
КонецЕсли;
Спр.ОбратныйПорядок(ВОбратномПорядке);
Спр.ВключатьПодчиненные(ВключатьПодчиненные);
Если ИмяРеквизита = 0 тогда
Спр.ВыбратьЭлементы(Иерархия);
Иначе
Спр.ВыбратьЭлементыПоРеквизиту(ИмяРеквизита, ЗначениеРеквизита, Иерархия, ВключатьГруппы);
КонецЕсли;
Пока Спр.ПолучитьЭлемент() = 1 Цикл
ТаблицаСпр.НоваяСтрока();
ТекущаяСтрока = ТаблицаСпр.НомерСтроки;
Для НомерКолонки= 1 по ВсегоРеквизитовСпр Цикл
ТаблицаСпр.УстановитьЗначение(ТекущаяСтрока, НомерКолонки, Спр.ПолучитьАтрибут(мдСпр.Реквизит(НомерКолонки)));
КонецЦикла;
ТаблицаСпр.Код = Спр.Код;
ТаблицаСпр.Наименование = Спр.Наименование;
Если ДобавлятьЭлементыСправочника = 1 тогда
ТаблицаСпр.УстановитьЗначение(ТекущаяСтрока, "Элемент", Спр.ТекущийЭлемент());
КонецЕсли;
КонецЦикла;
Возврат ТаблицаСпр;
КонецФункции
Новинки игровых автоматов с возможностью играть на
бездепозитный бонус за регистрацию в онлайн казино на деньги.