Запрос по уровням номенклатуры

Иногда 1С меня удивляет своей медвежьей услужливостью, т.е. делает контроль там, где он не требуется.

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

Все работало, но я составил текст вручную для 6 уровней номенклатуры, а со временем клиент добавил уровней и попросил меня сделать доработку, чтобы работало и для 9 уровней.

В итоге я не стал заниматься copy-paste, а написал программный генератор запроса на 12 уровней (с запасом на будущее):

    З = Новый Запрос(
    "ВЫБРАТЬ
    |    Т.Ссылка,
    |    Т.Наименование,
    |    Т.Наименование КАК Порядок,
    |    0 КАК Уровень,
    |    Т.ЭтоГруппа
    |ПОМЕСТИТЬ Т0
    |ИЗ
    |    Справочник.Номенклатура КАК Т
    |ГДЕ
    |    Т.Родитель = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
    |    И &УсловиеЭлементов
    |");
    
    //Осипов - для 12 уровней отчета  
    ВсегоУровней = 10; //от 0 до 11 - 12 уровней
    
    Для Инд = 1 По ВсегоУровней  Цикл
        
        ТекТекст =
        "ВЫБРАТЬ
        |    Т.Ссылка,
        |    Т.Наименование,
        |    ЕСТЬNULL(Т0.Порядок, """") + ""."" + Т.Наименование КАК Порядок,
        |    &Уровень1 КАК Уровень,
        |    Т.ЭтоГруппа
        |ПОМЕСТИТЬ Т1
        |ИЗ
        |    Справочник.Номенклатура КАК Т
        |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Т0 КАК Т0
        |        ПО (Т0.Ссылка = Т.Родитель)
        |ГДЕ
        |    &УсловиеЭлементов";                         
        
        ИндСтрокой = XMLСтрока(Инд);
        ПредИндСтрокой = XMLСтрока(Инд-1);              
        
        ТекТекст = СтрЗаменить(ТекТекст, "&Уровень1", ИндСтрокой);
        ТекТекст = СтрЗаменить(ТекТекст, "Т1", "Т" + ИндСтрокой);
        ТекТекст = СтрЗаменить(ТекТекст, "Т0", "Т" + ПредИндСтрокой);

        З.Текст = З.Текст + ";" + Символы.ПС + ТекТекст;
        
    КонецЦикла;

    //Осипов - для 12 уровней отчета
    
    Для Инд = 0 По  ВсегоУровней Цикл
        
        ТекТекст =  
        "ВЫБРАТЬ
        |    Т.Ссылка КАК Номенклатура,
        |    Т.Наименование,
        |    ЕСТЬNULL(Т.Порядок, """") КАК Порядок,
        |    Т.Уровень,
        |    Т.ЭтоГруппа,
        |    ЛОЖЬ КАК ЭтоИтого
        |ИЗ
        |    Т0 КАК Т
        |ГДЕ
        |    &УсловиеГруппы1";
        
        
        ИндСтрокой = XMLСтрока(Инд);
        ПредИндСтрокой = XMLСтрока(Инд-1);              
        
        ТекТекст = СтрЗаменить(ТекТекст, "&УсловиеГруппы1", "ИСТИНА");
        ТекТекст = СтрЗаменить(ТекТекст, "Т0", "Т" + ИндСтрокой);

        З.Текст = З.Текст + ?(Инд = 0, ";", " ОБЪЕДИНИТЬ ВСЕ ") + Символы.ПС + ТекТекст;
        
    КонецЦикла;
    

    З.Текст = З.Текст + " ОБЪЕДИНИТЬ ВСЕ " +
    "
    |ВЫБРАТЬ
    |    ""ИТОГО"",
    |    ""ИТОГО"",
    |    """",
    |    1,
    |    ИСТИНА,
    |    ИСТИНА
    |";

Однако я столкнулся с проблемой, что если делал отчет на 10 уровней, то он работал, а вот если на 12 — то уже нет.

Я долго ломал голову, что ему не нравится.

Обратил внимание, что при большом количестве уровне тип поля Порядок начинает содержать не только Строка, но и Null.

Таким образом я понял, что 1С не может соединить много строк длиной 150 символов в одну большую строку, т.к. может быть превышение 1024 символов.

В итоге я оставил 10 уровней. Т.к. я хотел использовать эту таблицу дальше, я убрал тип Null путем несложной обработки:

    ТЗ = З.Выполнить().Выгрузить();      
    ТЗ.Колонки.Добавить("ПорядокНовый", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(1024)));
    М = ТЗ.ВыгрузитьКолонку("Порядок");
    ТЗ.ЗагрузитьКолонку(М, "ПорядокНовый");
    ТЗ.Колонки.Удалить("Порядок");
    ТЗ.Колонки.ПорядокНовый.Имя = "Порядок";
    ТЗ.Сортировать("ЭтоГруппа, Порядок");
    Возврат ТЗ;

Причем если использовал длинную строку, например, 4096, то по ней не получалось сортировать таблицу. А вот строка до 1024 символов работала нормально.

Вот такие неявные нюансы. Из-за этой особенности потерял достаточно времени, пытаясь разобраться.

Среда: УТ10.
Объем: 1 час.

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

Добавить комментарий

Ваш адрес email не будет опубликован.