Имя: Пароль:
1C
1С v8
Запрос интервалов последовательности
0 Valentus
 
17.01.18
15:46
Добрый день. Есть справочник, необходимо сделать объединение в отчете по интервалам кода. Подскажите как правильно написать запрос на  таблицу интервалов последовательности кодов справочника(последовательно идущие коды (шаг +1) объединить в интервал)
- код начала последовательности
-код конца последовательности

Например 1,2,3,4 1-4
         6,7,8,9 6-9

Заранее спасибо
1 azernot
 
17.01.18
15:48
Код в справочнике числовой или текстовый?
2 Valentus
 
17.01.18
16:02
Код в справочнике числовой
3 azernot
 
17.01.18
16:06
(0) В каком виде заданы интервалы? Строкой через запятую? Или могут быть заданы как-то иначе?
4 Valentus
 
17.01.18
16:12
Строкой через запятую  1,2,3,4,5,7,8,9,12,15,16,17,20,25,26,27,28,29
т.е. мне нужно получить 1-5
                        7-9
                        12
                        15-17
                        20
                        25-29
5 azernot
 
17.01.18
16:28
(4) надо сначала отпарсить эту строку интервалов, динаимчески сформировать текст запроса временной таблицы интервалов (имя интервала, код) и дальше уже соединяться справочником с этой ВТ по коду

Но, куча нюансов.. Что, например, если строка будет такая
29, 28, 27, 14, 15, 16, 1, 2, 3 (т.е. номера не по возрастанию)?
или
1-3, 4, 5, 10, 15 (т.е. содержит не только числа и разделитель)?
6 Valentus
 
17.01.18
16:31
29, 28, 27, 14, 15, 16, 1, 2, 3 (т.е. номера не по возрастанию)?
или
1-3, 4, 5, 10, 15 (т.е. содержит не только числа и разделитель)?

номера строго по возрастанию и разделителей не будет.
7 Valentus
 
17.01.18
16:33
надо сначала отпарсить эту строку интервалов, динаимчески сформировать текст запроса временной таблицы интервалов (имя интервала, код) и дальше уже соединяться справочником с этой ВТ по коду


Как это примерно выглядит в запросе?

Я просто руками запросы раньше не писал, обходился конструктором.
8 Timon1405
 
17.01.18
16:48
если все равно парсить строку зачем тогда потом именно запрос?
9 azernot
 
17.01.18
16:50
Вот функция, которая отпарсит строку и выдаст тебе текст генерирующий ВТ_Интервалы

Функция СформироватьТекстЗапросаПоИнтервалам(СтрокаИнтерваловЗаданнаяПользователем) Экспорт
    
    НомерИнтервала = 1;
    МинИнтервала = 0;
    МаксИнтервала = 0;
    ПредыдущийКод = Неопределено;
    Разделитель = ",";
    СтрокаИнтервалов = СтрокаИнтерваловЗаданнаяПользователем+Разделитель;
    
    ТекстЗапросаИнтервалов = "";
    
    Пока СтрНайти(СтрокаИнтервалов, Разделитель)> 0 Цикл
        
        ТекКодСтрокой = СокрЛП(Лев(СтрокаИнтервалов,СтрНайти(СтрокаИнтервалов, Разделитель)-1));
        
        СтрокаИнтервалов = Сред(СтрокаИнтервалов,СтрНайти(СтрокаИнтервалов, Разделитель)+1);
        
        Если НЕ ЗначениеЗаполнено(ТекКодСтрокой) Тогда
            Продолжить;
        КонецЕсли;
        
        Попытка
            ТекКод = Число(ТекКодСтрокой);
        Исключение
            //В строке интервалов - не число
            Возврат "";
        КонецПопытки;
        
        Если ПредыдущийКод = Неопределено Тогда
            МинИнтервала = ТекКод;
            МаксИнтервала = ТекКод;
            ПредыдущийКод = ТекКод-1;
        КонецЕсли;
        
        Если НЕ ПредыдущийКод+1 = ТекКод Тогда
            
            ТекстЗапросаИнтервалов = СтрЗаменить(ТекстЗапросаИнтервалов, "Интервал "+Формат(НомерИнтервала, "ЧГ="), "Интервал "+Формат(МинИнтервала, "ЧГ=")+"-"+Формат(МаксИнтервала, "ЧГ="));
            
            НомерИнтервала = НомерИнтервала+1;        
            МинИнтервала = ТекКод;
            МаксИнтервала = ТекКод;
        КонецЕсли;
        
        МинИнтервала = Мин(МинИнтервала, ТекКод);
        МаксИнтервала = Макс(МаксИнтервала, ТекКод);
        
        Если  ТекстЗапросаИнтервалов = "" Тогда
            ТекстЗапросаИнтервалов = "Выбрать    ""Интервал "+Формат(НомерИнтервала, "ЧГ=")+ """ как ИмяИнтервала, "+Формат(ТекКод, "ЧГ=")+ " как Код"+Символы.ПС + " Поместить ВТ_Интервалы ";
        Иначе
            ТекстЗапросаИнтервалов = ТекстЗапросаИнтервалов+ Символы.ПС + " ОБЪЕДИНИТЬ ВСЕ "+Символы.ПС+ "Выбрать    ""Интервал "+Формат(НомерИнтервала, "ЧГ=")+ """, "+Формат(ТекКод, "ЧГ=");
        КонецЕсли;    
        
        ПредыдущийКод = ТекКод;
    КонецЦикла;    
    
    ТекстЗапросаИнтервалов = СтрЗаменить(ТекстЗапросаИнтервалов, "Интервал "+Формат(НомерИнтервала, "ЧГ="), "Интервал "+Формат(МинИнтервала, "ЧГ=")+"-"+Формат(МаксИнтервала, "ЧГ="));
    
    Возврат ТекстЗапросаИнтервалов;
    
КонецФункции

У меня на строке из (4) получилось
ИмяИнтервала    Код
Интервал 1 - 5    1
Интервал 1 - 5    2
Интервал 1 - 5    3
Интервал 1 - 5    4
Интервал 1 - 5    5
Интервал 7 - 9    7
Интервал 7 - 9    8
Интервал 7 - 9    9
Интервал 12 - 12    12
Интервал 15 - 17    15
Интервал 15 - 17    16
Интервал 15 - 17    17
Интервал 20 - 20    20
Интервал 25 - 29    25
Интервал 25 - 29    26
Интервал 25 - 29    27
Интервал 25 - 29    28
Интервал 25 - 29    29


Дальше уже можно скомпоновать запрос

Запрос.Текст = ТекстЗапросаИнтервалов +";"

Запрос.Текст = Запрос.Текст+"
"ВЫБРАТЬ
|    ВТ_Интервалы.ИмяИнтервала КАК ИмяИнтервала,
|    Склады.Ссылка,
|    Склады.Код
|ИЗ
|    Справочник.Склады КАК Склады
|        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Интервалы КАК ВТ_Интервалы
|        ПО Склады.Код = ВТ_Интервалы.Код"

(я использовал Склады как пример)
10 Valentus
 
17.01.18
16:58
Большое спасибо! Буду пробовать!
11 Valentus
 
17.01.18
17:16
Добавил функцию в модуль, запрос написал, ругается:

Ошибка получения информации набора данных
по причине:
Ошибка в запросе набора данных
по причине:
{(7, 20)}: Таблица не найдена "ВТ_Интервалы"
ЛЕВОЕ СОЕДИНЕНИЕ <<?>>ВТ_Интервалы КАК ВТ_Интервалы
12 Valentus
 
17.01.18
19:00
Ругается на временную таблицу ВТ_Интервалы
13 azernot
 
18.01.18
11:06
(11) Мда, я в (9) сделал за вас 98% требуемого, вы умудрились запутаться в оставшихся 2%...

Давайте весь код, найдём, где вы ошиблись.
ХотяЮ я и так знаю. Вы ошиблись здесь:

Запрос.Текст = ТекстЗапросаИнтервалов +";"

Запрос.Текст = Запрос.Текст+"
"ВЫБРАТЬ
|    ВТ_Интервалы.ИмяИнтервала КАК ИмяИнтервала,
|    Склады.Ссылка,
|    Склады.Код
|ИЗ
|    Справочник.Склады КАК Склады
|        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Интервалы КАК ВТ_Интервалы
|        ПО Склады.Код = ВТ_Интервалы.Код"
14 Valentus
 
18.01.18
11:12
В общем-то у меня все так же, проверял несколько раз(
Все как у Вас, только справочник у меня Номенклатура.

Функция СформироватьТекстЗапросаПоИнтервалам(СтрокаИнтерваловЗаданнаяПользователем) Экспорт
    
    НомерИнтервала = 1;
    МинИнтервала = 0;
    МаксИнтервала = 0;
    ПредыдущийКод = Неопределено;
    Разделитель = ",";
    СтрокаИнтервалов = СтрокаИнтерваловЗаданнаяПользователем+Разделитель;
    
    ТекстЗапросаИнтервалов = "ВТ_Интервалы";
    
    
    
    Пока СтрНайти(СтрокаИнтервалов, Разделитель)> 0 Цикл
        
        ТекКодСтрокой = СокрЛП(Лев(СтрокаИнтервалов,СтрНайти(СтрокаИнтервалов, Разделитель)-1));
        
        СтрокаИнтервалов = Сред(СтрокаИнтервалов,СтрНайти(СтрокаИнтервалов, Разделитель)+1);
        
        Если НЕ ЗначениеЗаполнено(ТекКодСтрокой) Тогда
            Продолжить;
        КонецЕсли;
        
        Попытка
            ТекКод = Число(ТекКодСтрокой);
        Исключение
            //В строке интервалов - не число

            Возврат "";
        КонецПопытки;
        
        Если ПредыдущийКод = Неопределено Тогда
            МинИнтервала = ТекКод;
            МаксИнтервала = ТекКод;
            ПредыдущийКод = ТекКод-1;
        КонецЕсли;
        
        Если НЕ ПредыдущийКод+1 = ТекКод Тогда
            
            ТекстЗапросаИнтервалов = СтрЗаменить(ТекстЗапросаИнтервалов, "Интервал "+Формат(НомерИнтервала, "ЧГ="), "Интервал "+Формат(МинИнтервала, "ЧГ=")+"-"+Формат(МаксИнтервала, "ЧГ="));
            
            НомерИнтервала = НомерИнтервала+1;        
            МинИнтервала = ТекКод;
            МаксИнтервала = ТекКод;
        КонецЕсли;
        
        МинИнтервала = Мин(МинИнтервала, ТекКод);
        МаксИнтервала = Макс(МаксИнтервала, ТекКод);
        
        Если  ТекстЗапросаИнтервалов = "ВТ_Интервалы" Тогда
            ТекстЗапросаИнтервалов = "Выбрать    ""Интервал "+Формат(НомерИнтервала, "ЧГ=")+ """ как ИмяИнтервала, "+Формат(ТекКод, "ЧГ=")+ " как Код"+Символы.ПС + " Поместить ВТ_Интервалы ";
        Иначе
            ТекстЗапросаИнтервалов = ТекстЗапросаИнтервалов+ Символы.ПС + " ОБЪЕДИНИТЬ ВСЕ "+Символы.ПС+ "Выбрать    ""Интервал "+Формат(НомерИнтервала, "ЧГ=")+ """, "+Формат(ТекКод, "ЧГ=");
        КонецЕсли;    
        
        ПредыдущийКод = ТекКод;
    КонецЦикла;    
    
    ТекстЗапросаИнтервалов = СтрЗаменить(ТекстЗапросаИнтервалов, "Интервал "+Формат(НомерИнтервала, "ЧГ="), "Интервал "+Формат(МинИнтервала, "ЧГ=")+"-"+Формат(МаксИнтервала, "ЧГ="));
    
    Возврат ТекстЗапросаИнтервалов;
    
  
КонецФункции

Запрос.Текст = ТекстЗапросаИнтервалов +";"
Запрос.Текст = Запрос.Текст+"
"ВЫБРАТЬ
|    ВТ_Интервалы.ИмяИнтервала КАК ИмяИнтервала,
|    Номенклатура.Ссылка,
|    Номенклатура.Код
|ИЗ
|    Справочник.Номенклатура КАК Номенклатура
|        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Интервалы КАК ВТ_Интервалы
|        ПО Номенклатура.Код = ВТ_Интервалы.Код"
15 azernot
 
18.01.18
12:04
(14) Значит у вас на момент компоновки запроса не заполнена переменная ТекстЗапросаИнтервалов.
Т.е. вы не вызываете собственно функцию, или она возвращает пустую строку (например, потому что не может преобразовать значение в число).

Приведите полный код, как инициируете запрос, как компонуете текст, как выполняете.
И укажите строку интервалов, заданную пользователем.
16 azernot
 
18.01.18
12:09
(14) А это что?!
  ТекстЗапросаИнтервалов = "ВТ_Интервалы";

Что за самоуправство? :)
Именно это изменение приводит к проблеме!
17 azernot
 
18.01.18
12:11
+(16)  Хотя нет, вы и дальше поправили.. только смысл не понятен. Ну да ладно. нужен полный код.
18 Valentus
 
18.01.18
13:14
Запрос я добавил через СКД а функцию в модуль объекта отчета, там больше ничего нет.

не заполнена переменная ТекстЗапросаИнтервалов - я правильно понимаю что запрос не может найти временную таблицу ВТ_Интервалы и необходимо в модуле добавить Перем?
19 azernot
 
18.01.18
13:29
(18) Боюсь, я вынужден признать, что вашего уровня компетенции на текущий момент недостаточно, чтобы решить поставленную задачу. Делать это ЗА вас я не буду (во всяком случае бесплатно), а для того, чтобы вам помочь - вы должны задавать вопросы. А этого вы сделать не можете, поскольку не понимаете что и как вы должны сделать.
Мало того, судя по всему, вы не понимаете базовых принципов работы запросов с временными таблицами, не знаете принципы работы схемы компоновки данных, а эти знания просто необходимы, потому как простым конструктором запроса в отчёте на СКД здесь не обойтись.

Вам нужно фактически при компоновке результата внести изменения в схему: получить строку интервалов заданную пользователем, выполнить мой функцию и получить запрос по формированию таблицы интервалов, внести изменения в источник данных СКД (поместить туда запрос по формированию временной таблицы интервалов) или каким-то иным образом передать в СКД таблицу интервалов, чтобы с ней соединить свой справочник.
20 Ненавижу 1С
 
гуру
18.01.18
13:34
ВЫБРАТЬ
    1 КАК Ч
ПОМЕСТИТЬ Т

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    4

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    7

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    8

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    9
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Т.Ч
ПОМЕСТИТЬ ЛТ
ИЗ
    Т КАК Т
        ЛЕВОЕ СОЕДИНЕНИЕ Т КАК Т1
        ПО (Т.Ч = Т1.Ч + 1)
ГДЕ
    Т1.Ч ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Т.Ч
ПОМЕСТИТЬ ПТ
ИЗ
    Т КАК Т
        ЛЕВОЕ СОЕДИНЕНИЕ Т КАК Т1
        ПО (Т.Ч = Т1.Ч - 1)
ГДЕ
    Т1.Ч ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ЛТ.Ч,
    МИНИМУМ(ПТ.Ч) КАК Ч1
ИЗ
    ЛТ КАК ЛТ
        ЛЕВОЕ СОЕДИНЕНИЕ ПТ КАК ПТ
        ПО ЛТ.Ч <= ПТ.Ч

СГРУППИРОВАТЬ ПО
    ЛТ.Ч
Компьютеры — это как велосипед. Только для нашего сознания. Стив Джобс