Получение дерева подчиненности.

26.04.11

Разработка - Универсальные функции

Одна функция и 3 процедуры, которые следует разместить в общем модуле (клиент, сервер). Возвращает дерево значений родительских и подчиненных документов от переданного документа через входной параметр "Ссылка". Выполняться может на сервере.

 

 

 

// Получение дерева подчиненности (родительские и подчиненные документы)
Функция ДеревоПодчиненности(Ссылка) Экспорт

   
ДеревоДокументов = Новый ДеревоЗначений;
   
ДеревоДокументов.Колонки.Добавить("Ссылка");
   
ДеревоДокументов.Колонки.Добавить("ДокументПредставление");
   
ДеревоДокументов.Колонки.Добавить("Проведен");
   
ДеревоДокументов.Колонки.Добавить("ПометкаУдаления");
   
ДеревоДокументов.Колонки.Добавить("ВидДокумента");
   
мУжеВСписке = Новый Соответствие;

    мДерево = ДеревоДокументов;
   
ВывестиРодительскиеДокументы(Ссылка, мУжеВСписке, мДерево);
   
ВывестиПодчиненныеДокументы(мДерево, мУжеВСписке);

    Возврат
ДеревоДокументов;

КонецФункции
//
Процедура ВывестиРодительскиеДокументы(ДокументСсылка, мУжеВСписке, мДерево)

   
МетаданныеДокумента = ДокументСсылка.Метаданные();
   
СписокРеквизитов = Новый СписокЗначений;

    Для Каждого
Реквизит ИЗ МетаданныеДокумента.Реквизиты Цикл
       
ТипыРеквизита = Реквизит.Тип.Типы();
        Для Каждого
ТекущийТип ИЗ ТипыРеквизита Цикл
           
МетаданныеРеквизита = Метаданные.НайтиПоТипу(ТекущийТип);

            Если
МетаданныеРеквизита<>Неопределено И Метаданные.Документы.Содержит(МетаданныеРеквизита)
                И
ПравоДоступа("Чтение", МетаданныеРеквизита) Тогда
                Попытка
                   
ЗначениеРеквизита = ДокументСсылка[Реквизит.Имя];
                Исключение
                    Прервать;
                КонецПопытки;
                ЕСли
ЗначениеРеквизита<>Неопределено И НЕ ЗначениеРеквизита.Пустая() И ТипЗнч(ЗначениеРеквизита) = ТекущийТип
                    И мУжеВСписке[ЗначениеРеквизита] = Неопределено И СписокРеквизитов.НайтиПоЗначению(ДокументСсылка[Реквизит.Имя]) = Неопределено Тогда
                   
СписокРеквизитов.Добавить(ЗначениеРеквизита,Формат(ЗначениеРеквизита.Дата,"ДФ=yyyyMMddЧЧММсс"));
                КонецЕсли;
            КонецЕсли;

        КонецЦикла;
    КонецЦикла;

    Для Каждого
ТЧ Из МетаданныеДокумента.ТабличныеЧасти Цикл
       
СтрРеквизитов = "";

        Попытка
           
СодержимоеТЧ = ДокументСсылка[ТЧ.Имя].Выгрузить();
        Исключение
            Прервать;
        КонецПопытки;

        Для Каждого
Реквизит ИЗ ТЧ.Реквизиты Цикл
           
ТипыРеквизита = Реквизит.Тип.Типы();
            Для Каждого
ТекущийТип ИЗ ТипыРеквизита Цикл
               
МетаданныеРеквизита = Метаданные.НайтиПоТипу(ТекущийТип);
                Если
МетаданныеРеквизита<>Неопределено И Метаданные.Документы.Содержит(МетаданныеРеквизита)
                    И
ПравоДоступа("Чтение", МетаданныеРеквизита) Тогда
                   
СтрРеквизитов = СтрРеквизитов + ?(СтрРеквизитов = "", "", ", ") + Реквизит.Имя;
                    Прервать;
                КонецЕсли;
            КонецЦикла;
        КонецЦикла;

       
СодержимоеТЧ.Свернуть(СтрРеквизитов);
        Для Каждого
КолонкаТЧ ИЗ СодержимоеТЧ.Колонки Цикл
            Для Каждого
СтрокаТЧ ИЗ СодержимоеТЧ Цикл
                Попытка
                   
ЗначениеРеквизита = СтрокаТЧ[КолонкаТЧ.Имя];
                Исключение
                    Продолжить;
                КонецПопытки;
               
МетаданныеЗначения = Метаданные.НайтиПоТипу(ТипЗнч(ЗначениеРеквизита));
                Если
МетаданныеЗначения = Неопределено Тогда
                   
// базовый тип
                   
Продолжить;
                КонецЕсли;

                ЕСли
ЗначениеРеквизита<>Неопределено И НЕ ЗначениеРеквизита.Пустая()
                    И
Метаданные.Документы.Содержит(МетаданныеЗначения)
                    И
мУжеВСписке[ЗначениеРеквизита] = Неопределено Тогда
                    Если
СписокРеквизитов.НайтиПоЗначению(ЗначениеРеквизита) = Неопределено Тогда
                       
СписокРеквизитов.Добавить(ЗначениеРеквизита,Формат(ЗначениеРеквизита.Дата,"ДФ=yyyyMMddЧЧММсс"));
                    КонецЕсли;
                КонецЕсли;
            КонецЦикла;
        КонецЦикла;
    КонецЦикла;
   
СписокРеквизитов.СортироватьПоПредставлению();
   
мУжеВСписке.Вставить(ДокументСсылка, Истина);

    Если
СписокРеквизитов.Количество() = 1 Тогда
       
ВывестиРодительскиеДокументы(СписокРеквизитов[0].Значение, мУжеВСписке, мДерево);
    ИначеЕсли
СписокРеквизитов.Количество() > 1 Тогда
       
ВывестиБезРодителей(СписокРеквизитов, мУжеВСписке, мДерево);
    КонецЕсли;


   
СтрокаДерева = мДерево.Строки.Добавить();
   
Запрос = Новый Запрос("ВЫБРАТЬ РАЗРЕШЕННЫЕ Ссылка, Проведен, ПометкаУдаления, Представление, """ + МетаданныеДокумента.Имя + """ КАК Метаданные
    | ИЗ Документ."
+МетаданныеДокумента.Имя + " ГДЕ Ссылка = &Ссылка");

   
Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);

   
Выборка  = Запрос.Выполнить().Выбрать();
    Если
Выборка.Следующий() Тогда
       
СтрокаДерева.Ссылка = Выборка.Ссылка;
       
СтрокаДерева.ДокументПредставление = Выборка.Ссылка.Метаданные().Синоним + " " + Выборка.Ссылка.Номер;
       
СтрокаДерева.Проведен = Выборка.Проведен;
       
СтрокаДерева.ПометкаУдаления = Выборка.ПометкаУдаления;
       
СтрокаДерева.ВидДокумента = Выборка.Метаданные;
    Иначе
       
СтрокаДерева.Ссылка= ДокументСсылка;
    КонецЕсли;

   
мДерево = СтрокаДерева;

КонецПроцедуры
//
Процедура ВывестиПодчиненныеДокументы(СтрокаДерева, мУжеВСписке)

   
ТекущийДокумент = СтрокаДерева.Ссылка;
   
ТипДокумента = ТипЗнч(ТекущийДокумент);
   
СтруктураРеквизитов = Новый ТаблицаЗначений;
   
СтруктураРеквизитов.Колонки.Добавить("ПутьКДанным");
   
СтруктураРеквизитов.Колонки.Добавить("ИмяРеквизита");

    Для каждого
Док ИЗ Метаданные.Документы Цикл
        Если НЕ
ПравоДоступа("Чтение", Док) Тогда
            Продолжить;
        КонецЕсли;

        Для Каждого
Реквизит Из Док.Реквизиты Цикл
            Если
Реквизит.Тип.СодержитТип(ТипДокумента) Тогда
               
НовСтр = СтруктураРеквизитов.Добавить();
               
НовСтр.ПутьКДанным = Док.Имя;
               
НовСтр.ИмяРеквизита = Реквизит.Имя;
            КонецЕсли;
        КонецЦикла;

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

    КонецЦикла;
   
ТекстЗапроса = "";
    Для Каждого
КлючИЗначение Из СтруктураРеквизитов Цикл

        Если
Найти(КлючИЗначение.ПутьКДанным, ".") = 0 Тогда

           
ТекстЗапроса = ТекстЗапроса + "
            |Выбрать "
+ ?(ТекстЗапроса="", "РАЗРЕШЕННЫЕ ", "") + "Ссылка, Ссылка.Дата Как ДатаДок, Представление, Проведен, ПометкаУдаления, """+ КлючИЗначение.ПутьКДанным +""" КАК ВидДокумента ИЗ Документ."+КлючИЗначение.ПутьКДанным+"
            |ГДЕ "
+КлючИЗначение.ИмяРеквизита+"=&ДокументОснование
            |ОБЪЕДИНИТЬ ВСЕ
            |"
;

        Иначе
           
ПозицияТочки = Найти(КлючИЗначение.ПутьКДанным, ".");
           
ТекстЗапроса = ТекстЗапроса + "
            |Выбрать "
+ ?(ТекстЗапроса="", "РАЗРЕШЕННЫЕ ", "") + "Ссылка, Ссылка.Дата Как ДатаДок, Ссылка.Представление,  Ссылка.Проведен, Ссылка.ПометкаУдаления, """+ Лев(КлючИЗначение.ПутьКДанным, ПозицияТочки-1) +""" КАК ВидДокумента ИЗ Документ."+КлючИЗначение.ПутьКДанным+"
            |ГДЕ "
+КлючИЗначение.ИмяРеквизита+"=&ДокументОснование
            |ОБЪЕДИНИТЬ ВСЕ
            |"
;

        КонецЕсли;
    КонецЦикла;

    Если
ТекстЗапроса="" Тогда
        Возврат;
    КонецЕсли;

   
ТекстЗапроса = Лев (ТекстЗапроса, СтрДлина(ТекстЗапроса)-15);
   
ТекстЗапроса = ТекстЗапроса+ "
    |УПОРЯДОЧИТЬ ПО  ДатаДок"
;

   
Запрос = Новый Запрос(ТекстЗапроса);
   
Запрос.УстановитьПараметр("ДокументОснование", ТекущийДокумент);
   
Выборка = Запрос.Выполнить().Выбрать();


    Пока
Выборка.Следующий() Цикл
        Если
мУжеВСписке[Выборка.Ссылка] = Неопределено Тогда
           
НоваяСтрока = СтрокаДерева.Строки.Добавить();
           
НоваяСтрока.Ссылка = Выборка.Ссылка;
           
НоваяСтрока.ДокументПредставление = Выборка.Ссылка.Метаданные().Синоним + " " + Выборка.Ссылка.Номер;
           
НоваяСтрока.Проведен = Выборка.Проведен;
           
НоваяСтрока.ПометкаУдаления = Выборка.ПометкаУдаления;
           
НоваяСтрока.ВидДокумента = Выборка.ВидДокумента;
           
мУжеВСписке.Вставить(Выборка.Ссылка, Истина);
           
ВывестиПодчиненныеДокументы(НоваяСтрока, мУжеВСписке);
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры
//
Процедура ВывестиБезРодителей(СписокДокументов, мУжеВСписке, мДерево)

    Для Каждого
ЭлементСписка Из СписокДокументов Цикл

       
МетаданныеДокумента = ЭлементСписка.Значение.Метаданные();

       
Запрос = Новый Запрос("ВЫБРАТЬ РАЗРЕШЕННЫЕ Ссылка, Проведен, ПометкаУдаления, Представление, """ + МетаданныеДокумента.Имя + """ КАК Метаданные
        | ИЗ Документ."
+МетаданныеДокумента.Имя + " ГДЕ Ссылка = &Ссылка");

       
Запрос.УстановитьПараметр("Ссылка", ЭлементСписка.Значение);

       
Выборка  = Запрос.Выполнить().Выбрать();
        ЕСли
Выборка.Следующий() Тогда
            Если
мУжеВСписке[Выборка.Ссылка] = Неопределено Тогда
               
СтрокаДерева = мДерево.Строки.Добавить();
               
СтрокаДерева.Ссылка= Выборка.Ссылка;
               
СтрокаДерева.ДокументПредставление = Выборка.Ссылка.Метаданные().Синоним + " " + Выборка.Ссылка.Номер;
               
СтрокаДерева.Проведен = Выборка.Проведен;
               
СтрокаДерева.ПометкаУдаления = Выборка.ПометкаУдаления;
               
СтрокаДерева.ВидДокумента = Выборка.Метаданные;
               
мУжеВСписке.Вставить(Выборка.Ссылка, Истина);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;

   
мДерево = СтрокаДерева;

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


См. также

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

21.05.2024    20954    dimanich70    81    

145

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    4148    3    John_d    11    

57

Универсальные функции Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    19184    atdonya    24    

58

Универсальные функции Программист Платформа 1С v8.3 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    5588    ke.92@mail.ru    16    

65

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    15057    YA_418728146    7    

169

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    3659    57    progmaster    8    

4

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    18605    172    sapervodichka    112    

135
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. OLEG4120 165 27.04.11 09:00 Сейчас в теме
2. vladnet 367 27.04.11 11:13 Сейчас в теме
По мне так нет такого понятия как дерево подчиненных документов, есть граф подчиненных документов http://infostart.ru/public/20369/
3. sbv2005 348 27.04.11 12:08 Сейчас в теме
(2) Писал как вариант для оперативного алгоритма, поэтому и делал под сервер тоже, без форм.
4. w-divin 27.04.11 14:12 Сейчас в теме
(2) По мне - так есть дерево подчиненных документов, имеющее корень(родительский, первый документ) и ветви (всё что на него ссылается). а по графу - я в Вашей теме оставил пару комментов (((
5. w-divin 27.04.11 14:22 Сейчас в теме
(2) и опять же производительность:
Данный вариант:
Замер:
Результат:

И Ваш вариант (дубль из коммента в Вашей теме):
Замер:
Результат:
6. w-divin 27.04.11 14:25 Сейчас в теме
(0) за "под сервер" плюсеГ ))) все леньки было самому рисовать ))) как оказалось не зря ленился )))
Оставьте свое сообщение