Табличную часть в дерево значений
В вашем случае лучше всего собрать дерево значений в цикле.
Запросом без постобработки, тоже не получится, т.к. он не умеет группировать по двум полям. Можно еще схемой СКД, но это уже перебор.
(3)Можно, только зачем это делать, если все равно нужна постобработка, что бы удалить верхний уровень? Если автор получает данные запросом, то окей. но я так понимаю он в модуле формы или объекта и данные уже прочитаны.
(6)это будет документ
С таблично часть
Номенклатура
Характеристика
упаковка
факт
учёт
И реквизитом документ расходная накладная
По кнопке заполнить заполняется тч вида который я описал выше
А дерево значений нужно для визуализации скажем тоесть номенклатура состоит из 5 упаковок пока я их все не отсканирую не смогу отгрузить товар, а чтобы видно было сколько отсканировано упаковок нужно дерево
(3)Можно в запросе объединить в кортеж поля номенклатура и характеристика и получить итог по этому кортежу тогда будет только одна группировка итогов — то что нужно, не?
(11) проще говоря это соединение в уникальном выражении нескольких полей
Вот у вас есть поле номенклатура и поле характеристика. из которых в запросе вы можете выразить одно поле
номенклатура.код + характеристика как уникальный_ключ
И по нему уже получить итог как по одному полю вместо того чтобы добавлять в выражение итоги по номенклатуру и характеристику. Что приведет к образованию двухуровневого дерева результата.
(12)
Вариант, но все равно красиво выгрузить в дерево результат не получится, ведь в дереве будет присутствовать уникальный ключ, а он не нужен в выводе на форму.
(13) Ну это как подумать, Чем комбинация Номенклатура.наименование + «: » + Характеристика , если формировать кортеж так, а не по коду, как я предложил сначала, в одной колонке, органолептически для пользователя — хуже чем номенклатура и характеристика в разных колонках ? 🙂
(15)а потом обратно если в дереве значений таком что то поправили как будете обращаться? например
—номенклатура характеристика
——————упаковка1 1 шт
——————упаковка2 2 шт
я взял и поменял на упаковка2 10 шт трудность наверное возникнет с обратным переводом в таблицу значений
(20) Во первых: что мешает иметь в дереве значений колонок больше чем отображается на форму?
Во вторых: распарсить кортеж точно зная разделитель тоже вроде бы не сложно. Тут сложно только то что там будут строковые представления, а не ссылки. Если для номенклатуры наименования скорее уникальны то для характеристик скорее не уникальны. И потом по этим представлениям фиг определишь нужный элемент но это не точно.
Так что надежнее в дереве иметь колонки ссылок номенклатуры и характеристик но не отображать их на форму если вам в этом дереве надо менять данные для сохранения их в базе.
(13) Вот пример как выглядит в дереве кортеж наименование продукции / спецификация в одном из инструментов
Для Каждого Строка Из ТЧ Цикл СтрокаТовара = Дерево.Строки.Найти(Строка.Номенклатура, "Номенклатура"); Если СтрокаТовара = Неопределено Тогда СтрокаТовара = Дерево.Строки.Добавить(); СтрокаТовара.Номенклатура = Строка.Номенклатура; КонецЕсли; СтрокаСтроки = Строка.Строки.Найти("Упаковка", Строка.Упаковка); Если СтрокаСтроки = Неопределено Тогда СтрокаСтроки = СтрокаТовара.Строки.Добавить(); СтрокаСтроки = Строка.Упаковка; КонецЕсли; КонецЦикла;
это все написать — две минуты. На обсуждение потрачено намного больше. Вот так мы и получаем производительность труда как в Зимбабве, вместо того, чтобы сделать — болтаем.
(14) две минуты если бы не одно но
надо сразу по двум колонкам сделать
—Номенклатура характеристика
———Упаковка
// Процедура выгружает данные из таблицы значений в дерево значений // данные выгружаются только в таблицу со сходным набором реквизитов // // Параметры: // // КлючСтроки - имя колонки ТаблицыЗначений - уникальный идентификатор // КлючСвязи - имя колонки ТаблицыЗначений - указатель привязки к строке Дерева, // своего рода указатель на "Родителя" // Функция ВыгрузитьТаблицуЗначенийВДеревоЗначений(Таблица, КлючСтроки = "КлючСтроки", КлючСвязи = "КлючСвязи") Экспорт Дерево = Новый ДеревоЗначений; Для Каждого Колонка Из Таблица.Колонки Цикл Дерево.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения); КонецЦикла; Для Каждого СтрокаТаблицы Из Таблица Цикл СтрокаГруппировки = Дерево.Строки.Найти(СтрокаТаблицы[КлючСвязи], КлючСтроки,Истина); Если СтрокаГруппировки = Неопределено Тогда ЗаполнитьЗначенияСвойств(Дерево.Строки.Добавить(), СтрокаТаблицы); Иначе ЗаполнитьЗначенияСвойств(СтрокаГруппировки.Строки.Добавить(), СтрокаТаблицы); КонецЕсли; КонецЦикла; Возврат Дерево; КонецФункции //ВыгрузитьТаблицуЗначенийВДеревоЗначений()
&НаСервере Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) //. СтруктураДокументаПоказатьНаСервере(); КонецПроцедуры &НаСервере Процедура СтруктураДокументаПоказатьНаСервере() ТЗ=Объект.СтруктураДокумента.Выгрузить(); ДЗ=КФСервер.ВыгрузитьТаблицуЗначенийВДеревоЗначений(ТЗ); ЗначениеВРеквизитФормы(ДЗ,"ДЗСтруктураДокумента"); Элементы.ДЗСтруктураДокумента.Обновить(); Для каждого ИмяЭл Из СкрываемыеЭлементы Цикл Если ИмяЭл.Значение="" Тогда Продолжить; КонецЕсли; Эл=Элементы[ИмяЭл.Значение]; Эл.Видимость=Ложь; КонецЦикла; КонецПроцедуры
(17)это тоже только для одной колонке
—Номенклатура характеристика
———Упаковка
У меня сделано через СКД.
Я создал макет схему компановки данных и программно передавал в него данные ТЧ, на выходе получил готовое дерево, которое просто грузил в реквизит формы.
ПромДерево = Новый ДеревоЗначений; ТекОбъект = РеквизитФормыВЗначение("Объект"); НовыйСКД = ТекОбъект.ПолучитьМакет("МОЙ МАКЕТ СКД"); Настройки = НовыйСКД.НастройкиПоУмолчанию; НовыйОтбор = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных")); //////// программно устанавливаю отборы в СКД если просто ТЧ передать то этого не надо НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(" "); НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке; НовыйОтбор.ПравоеЗначение = ВыделенныеСтроки; НовыйОтбор.Использование = Истина; //// ДанныеРасшифровкиСКД = Новый ДанныеРасшифровкиКомпоновкиДанных; КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных; ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных; МакетКомпоновки = КомпоновщикМакета.Выполнить(НовыйСКД,Настройки, ДанныеРасшифровкиСКД,,Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений")); ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ,ДанныеРасшифровкиСКД); ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений; ПроцессорВывода.УстановитьОбъект(ПромДерево); ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных); ЗначениеВРеквизитФормы(ПромДерево, "РЕКВИЗИТ ФОРМЫ ДЕРЕВО");
Источник
Дерево значений в таблицу значений или в табличную часть и обратно
Для одной организации надо было реализовать документы, где вместо табличной части надо использовать дерево и все это на управляемых формах. Но дерево нельзя сохранить в базе в текущем виде. Пришлось использовать табличную часть документа для хранения данных дерева. И при открытии формы получать данные из ТЧ и выводить их в дерево. Далее все манипуляции производить с деревом и при сохранении документа помещать данные в обратно в ТЧ.
Поиск по интернету не дал нужного варианта, пришлось реализовавыть свой механизм, используя информацию которая была на просторах интернета.
Для реализации такого механизма в ТЧ был добавлен реквизит “КлючСвязи” (обязательный реквизит) с типом число, куда помещался “НомерСтроки” (стандартный реквизит ТЧ) родителя (верхний уровень). А самый верхний элемент дерева имеет “КлючСвязи” равный 0.
На картинке ниже видно структуру дерева и структуру ТЧ
Нагрузка на сервер осуществляется при окрытии и при сохранении документа. А с деревом работают уже на клиенте.
На рабочей базе обрабатывается около 200 строк в одном документе.
Открытие и сохранение документа происходит моментально. С большем количеством строк не тестировалось.
Чтобы алгорит правильно работал, у рекизита фомы с типом дерево значений должны быть все реквизиты табличной части, кроме “КлючСвязи” и “НомерСтроки”. Иначе платформа выдаст ошибку. В дерево можо добавлять свои реквизиты отличные от ТЧ, они будут использоваться только в дереве.
Ниже приведен код преобразования дерева в таблицу и обратно.
&НаКлиенте
Процедура КомандаТаблицуВДерево(Команда)
КомандаТаблицуВДеревоНаСервере();
КонецПроцедуры
&НаСервере
Процедура КомандаТаблицуВДеревоНаСервере()
Дерево = ТаблицаВДерево(РеквизитФормыВЗначение("Объект"), "Товары");//Товары - имя табличной части
ЗначениеВРеквизитФормы(Дерево, "ДеревоЗначений");//ДеревоЗначений - реквизит формы с типом дерево значений
Элементы.ДеревоЗначений.Обновить();
КонецПроцедуры
&НаКлиенте
Процедура КомандаДеревоВТаблицу(Команда)
КомандаДеревоВТаблицуНаСервере();
КонецПроцедуры
&НаСервере
Процедура КомандаДеревоВТаблицуНаСервере()
Объект.Товары.Очистить();
ДОбъект = РеквизитФормыВЗначение("Объект");
ДеревоВТаблицу(ДОбъект, РеквизитФормыВЗначение("ДеревоЗначений"), "Товары");
ЗначениеВРеквизитФормы(ДОбъект, "Объект");
КонецПроцедуры
Формирование дерева из таблицы значений
//ФОРМИРОВАНИЕ ДЕРЕВА ИЗ ТАБЛИЦЫ
&НаСервере
Функция ТаблицаВДерево(ДокОбъект, НаименованиеТабличнойЧастиДокумента, КлючСвязи = NULL, ЭлементРодитель = NULL) Экспорт
//ПОДГОТОВКА КОЛОНОК ДЕРЕВА
КолонкиТаблицы = ДокОбъект.Метаданные().ТабличныеЧасти[НаименованиеТабличнойЧастиДокумента].Реквизиты;
ДеревоЗначений2 = Новый ДеревоЗначений;
Для каждого Кол из КолонкиТаблицы Цикл
Если Кол.Имя = "НомерСтроки" ИЛИ Кол.Имя = "КлючСвязи" Тогда
Продолжить;
Иначе
ДеревоЗначений2.Колонки.Добавить(Кол.Имя, Новый ОписаниеТипов(Кол.Тип));
КонецЕсли;
КонецЦикла;//ДеревоЗначений.Строки.Очистить();
Если КлючСвязи = NULL И ЭлементРодитель = NULL Тогда
//ПЕРВЫЙ ВЫЗОВ ПРОЦЕДУРЫ (КОРНЕВЫЕ ЭЛЕМЕНТЫ)
ИсточникВыборки = ДеревоЗначений2.Строки;
КлючСвязи = 0; // ЭЛЕМЕНТ ВЕРХНЕГО УРОВНЯ ИМЕЕТ НОМЕР СТРОКИ РОДИТЕЛЯ 0 (ОБЯЗАТЕЛЬНЫЙ РЕКВИЗИТ)
Иначе
//ВНУТРЕННИЙ ВЫЗОВ ПРОЦЕДУРЫ (ПОДЧИНЕННЫЕ ЭЛЕМЕНТЫ)
ИсточникВыборки = ЭлементРодитель.Строки;
КонецЕсли;
Фильтр = Новый Структура("КлючСвязи", КлючСвязи);
М = ДокОбъект[НаименованиеТабличнойЧастиДокумента].НайтиСтроки(Фильтр);
Если М.Количество() = 0 Тогда
Возврат ДеревоЗначений2;
КонецЕсли;
Для каждого Стр из М Цикл
Элемент = ИсточникВыборки.Добавить();
Для каждого Кол из КолонкиТаблицы Цикл
Если Кол.Имя = "НомерСтроки" ИЛИ Кол.Имя = "КлючСвязи" Тогда
Продолжить;
Иначе
Элемент[Кол.Имя] = Стр[Кол.Имя];
КонецЕсли;
КонецЦикла;
ТаблицаВДерево(ДокОбъект, НаименованиеТабличнойЧастиДокумента, Стр.НомерСтроки, Элемент); //ДОБАВЛЕНИЕ ПОДЧИНЁННЫХ ЭЛЕМЕНТОВ В ДЕРЕВО
КонецЦикла;
Возврат ДеревоЗначений2;
КонецФункции
Формирование таблицы из дерева
//ФОРМИРОВАНИЕ ТАБЛИЦЫ ИЗ ДЕРЕВА
&НаСервере
Процедура ДеревоВТаблицу(ДокОбъект, ДеревоЗначений, НаименованиеТабличнойЧастиДокумента, СтрокаДерева = NULL, КлючСвязи = NULL) Экспорт
Если СтрокаДерева = NULL И КлючСвязи = NULL Тогда
//ПЕРВЫЙ ВЫЗОВ ПРОЦЕДУРЫ (КОРНЕВЫЕ ЭЛЕМЕНТЫ)
ПервыйВызов = Истина;
ДокОбъект[НаименованиеТабличнойЧастиДокумента].Очистить();
ИсточникВыборки = ДеревоЗначений.Строки;
КлючСвязи = 0; // ЭЛЕМЕНТ ВЕРХНЕГО УРОВНЯ ИМЕЕТ НОМЕР СТРОКИ РОДИТЕЛЯ 0 (ОБЯЗАТЕЛЬНЫЙ РЕКВИЗИТ)
Иначе
//ВНУТРЕННИЙ ВЫЗОВ ПРОЦЕДУРЫ (ПОДЧИНЕННЫЕ ЭЛЕМЕНТЫ)
ПервыйВызов = Ложь;
ИсточникВыборки = СтрокаДерева.Строки;
КонецЕсли;
Для каждого Стр из ИсточникВыборки Цикл
НС = ДокОбъект[НаименованиеТабличнойЧастиДокумента].Добавить();
Для каждого Кол из ДокОбъект.Метаданные().ТабличныеЧасти[НаименованиеТабличнойЧастиДокумента].Реквизиты Цикл
Если Кол.Имя = "КлючСвязи" Тогда
НС.КлючСвязи = КлючСвязи
ИначеЕсли Кол.Имя = "НомерСтроки" Тогда
Продолжить;
Иначе
НС[Кол.Имя] = Стр[Кол.Имя];
КонецЕсли;
КонецЦикла;
Если НЕ Стр.Строки.Количество() = 0 Тогда
ДеревоВТаблицу(ДокОбъект,,НаименованиеТабличнойЧастиДокумента, Стр, НС.НомерСтроки);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Источник