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

26.04.11

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

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

 

 

 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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


См. также

Печать любых непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

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

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

3480 руб.

22.08.2023    808    1    0    

1

Валидация JSON через XDTO (включая массивы)

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

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

28.08.2023    3234    YA_418728146    3    

86

Расширение: Быстрые отборы через буфер [Alt+C] Копировать список, [Alt+V] Вставить список, [Ctrl+C] Копировать из файлов

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

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

1 стартмани

13.10.2022    13264    102    sapervodichka    106    

118

Система контроля ведения учета [БСП]

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

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    6346    quazare    8    

103

Хитрости СКД. Часть 3

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

Столкнулся с тем, что мне приходится писать гору отчетов. Во многих приходится использовать повторяющиеся приемы. Решил написать шпаргалку, которая, надеюсь пригодится не только мне. В этой статье: Объединение ячеек в отчете только на определенном уровне иерархии, Постобработка итогов в табличном документе, Скрытие колонок в зависимости от количества месяцев в периоде.

28.05.2022    7710    milkers    11    

87

Базовые принципы работы с регламентными заданиями подсистем БСП

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

В очередной публикации рассмотрим некоторые базовые приемы работы с регламентными заданиями в рамках библиотеки стандартных подсистем

22.05.2022    12622    quazare    25    

57
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. OLEG4120 162 27.04.11 09:00 Сейчас в теме
Пожалуйста, раскрасте код http://www.infostart.ru/public/19856
2. vladnet 358 27.04.11 11:13 Сейчас в теме
По мне так нет такого понятия как дерево подчиненных документов, есть граф подчиненных документов http://infostart.ru/public/20369/
3. sbv2005 345 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) за "под сервер" плюсеГ ))) все леньки было самому рисовать ))) как оказалось не зря ленился )))
Оставьте свое сообщение