И снова здравствуйте! Уважаемые гуру, помогите, пожалуйста, разобраться в создании запросов. Хочу понять основные принципы и закрепить на практике. Вопросов будет несколько, но все по запросам. И все практические. Уважаемые Модераторы, прошу разрешить обсудить эти вопросы в одной теме. Думаю, так будет лучше. Они все будут касаться процедуры формирования запросов. Но если администрация сайта посчитает, что, все же, нужно по каждому вопросу создавать отдельную тему, я беспрекословно подчинюсь. Итак.
У меня есть РасходныеНакладные по ремонтам техники. В табличной части этих накладных есть есть Товары с реквизитом ВидТовара = Товар, а есть различные виды выполняемых работ, которые в справочнике числятся как товар с реквизитом ВидТовара = Услуга. Мне нужно в отчете по всем проведенным накладным просуммировать все виды работ. Без, собственно, товаров. Например, есть товар с видом Услуга, который называется "Чистка бойлера". Или "ЗаменаНагревателя". Ясно, что это работа. Поэтому этот товар имеет ВидТовара = Услуга. Остальные же товары, например, Выключатель, Прокладка и т.д. имеет ВидТовара = Товар. После многих попыток я пришел к следующему коду, который работает:
Процедура Сформировать()
НужныйТовар = Константа.НужныйТовар;
ВидТовараУм = Константа.ВидТовараУм;
ЗапросСуммы = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Товар = Документ.РасходнаяНакладная.Товар;
|ВидТовара = Справочник.Номенклатура.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Группировка Товар Без Групп;
|Условие (ВидТовара = ВидТовараУм);";
ЗапросСуммы.Выполнить(ТекстЗапроса);
Пока ЗапросСуммы.Группировка() = 1 Цикл
СуммаУслуг = ЗапросСуммы.Сум;
КонецЦикла;
Сообщить("Сумма:"+СуммаУслуг);
КонецПроцедуры
ZUBR @ Сегодня, 1:14
,
А ВидТовара
|Товар = Документ.РасходнаяНакладная.Товар.ВидТовара; //вместо |ВидТовара = Справочник.Номенклатура.ВидТовара;
|Условие (ВидТовара = ВидТовараУм);";
Процедура Сформировать()
НужныйТовар = Константа.НужныйТовар;
ВидТовараУм = Константа.ВидТовараУм;
ЗапросСуммы = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Товар = Документ.РасходнаяНакладная.Товар;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Группировка Товар Без Групп;
|Условие (ВидТовара = ВидТовараУм);";
ЗапросСуммы.Выполнить(ТекстЗапроса);
Пока ЗапросСуммы.Группировка() = 1 Цикл
СуммаУслуг = ЗапросСуммы.Сум;
КонецЦикла;
Сообщить("Сумма:"+СуммаУслуг);
КонецПроцедуры
andrew76 @ Сегодня, 6:42
, да, так как Вы предложили, работает. Интересно, что я вчера примерно так же пробовал сделать, но, видимо, какую-то мелочь прописал неправильно. Спасибо!
Здравствуйте. Возникла необходимость посчитать стоимость услуг для отдельного инженера по выданным аппаратам. Для этого мне нужно ввести в текст запроса еще одно условие. Даже два. Не могу сформировать этот проклятущий запрос. Никак не въеду. Мне программа выдает ошибку, что агрегатное поле объекта ТекущийЭлемент не обнаружено. А, кроме того, я не могу вывести Сообщить, потому что выскакивает ошибка, что переменная Инженер не определена. Как это лучше сделать?(
Процедура Сформировать()
НужныйТовар = Константа.НужныйТовар;
ВидТовараУм = Константа.ВидТовараУм;
Спр = СоздатьОбъект("Справочник.Сотрудники");
ЗапросСуммы = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Товар = Документ.РасходнаяНакладная.Товар;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|Инженер = Документ.РасходнаяНакладная.Инженер;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Группировка Товар Без Групп;
|Условие (Инженер = Спр.ТекущийЭлемент);
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд));
|Условие (ВидТовара = ВидТовараУм);";
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент()=1 Цикл
ЗапросСуммы.Выполнить(ТекстЗапроса);
Пока ЗапросСуммы.Группировка() = 1 Цикл
СуммаУслуг = ЗапросСуммы.Сум;
КонецЦикла;
Сообщить(Инженер+СуммаУслуг);
КонецЦикла;
КонецПроцедуры
Процедура Сформировать()
НужныйТовар = Константа.НужныйТовар;
ВидТовараУм = Константа.ВидТовараУм;
Спр = СоздатьОбъект("Справочник.Сотрудники");
ЗапросСуммы = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Товар = Документ.РасходнаяНакладная.Товар;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Группировка Товар Без Групп;
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд));
|Условие (ВидТовара = ВидТовараУм);";
ЗапросСуммы.Выполнить(ТекстЗапроса);
Пока ЗапросСуммы.Группировка() = 1 Цикл
СуммаУслуг = ЗапросСуммы.Сум;
КонецЦикла;
Сообщить(СуммаУслуг);
КонецПроцедуры
Все, решил. После долгих попыток код следующий:
Процедура Сформировать()
Спр = СоздатьОбъект("Справочник.Сотрудники");
ЗапросСуммы = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Инженер = Документ.РасходнаяНакладная.Инженер;
|Товар = Документ.РасходнаяНакладная.Товар;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Группировка Товар Без Групп;
|Условие (Инженер = Сотрудник);
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд));
|Условие (ВидТовара = Перечисление.ВидыТоваров.Услуга);";
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент()=1 Цикл
Сотрудник = Спр.ТекущийЭлемент();
ЗапросСуммы.Выполнить(ТекстЗапроса);
Пока ЗапросСуммы.Группировка() = 1 Цикл
СуммаУслуг = ЗапросСуммы.Сум;
КонецЦикла;
Сообщить(Сотрудник);
Сообщить(СуммаУслуг);
КонецЦикла;
КонецПроцедуры
Нашел неплохую статью по запросам. Не знаю, можно ли дать ссылку.
ZUBR @ Сегодня, 0:28
,
Представь результат выборки запроса в виде таблицы, потом эту таблицу свернули по полям, указанным в Группировка а по формулам Функция вычислили значения для этих группировок. Потом оператором Запрос.Группировка() мы перемещаемся по значениям группировок.
"Без Групп" работает для значений типа "Справочник", исключает из выборки элементы - группы, потому как по умолчанию если группировка делается по справочнику, то система собирает в выборку все элементы с иерархией и вычисляет функции и для групп, т.е. при переборе Запрос.Группировка() будем получать группу, элемент и т.д. Если нам группы не нужны, пишем "Без групп".
mut @ Вчера, 13:26
, хочу уточнить - правильно ли я понял, что "Без групп" к собственно Группировке отношения не имеет. То есть, Группировка - это не группы в справочниках? И Без групп можно писать отдельно?
Информация по запросам. С разрешения модератора.
https://pro1c.org.ua/redirect.php?http://anatoly4xs.narod.ru/manual/lang/lang0342.htm
Еще по запросам. Это начало
https://pro1c.org.ua/redirect.php?http://anatoly4xs.narod.ru/manual/lang/lang0341.htm#3130
Теперь я дополнил текст запроса функцией Счетчик для подсчета количества сделанных систем. Запрос не работает. Выскакивает ошибка "Неожиданное выражение Счетчик()" и "Ошибка условия" во всех условиях, хотя я в условиях ничего не менял. Как правильно использовать функцию Счетчик?
Процедура Сформировать()
Спр = СоздатьОбъект("Справочник.Сотрудники");
ЗапросСуммы = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Инженер = Документ.РасходнаяНакладная.Инженер;
|Товар = Документ.РасходнаяНакладная.Товар;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Функция КолСис = Счетчик();
|Группировка Товар Без Групп;
|Условие (Инженер = Сотрудник);
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд));
|Условие (ВидТовара = Перечисление.ВидыТоваров.Услуга);";
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент()=1 Цикл
Сотрудник = Спр.ТекущийЭлемент();
ЗапросСуммы.Выполнить(ТекстЗапроса);
Пока ЗапросСуммы.Группировка() = 1 Цикл
СуммаУслуг = ЗапросСуммы.Сум;
КолСис = ЗапросСуммы.КолСис;
КонецЦикла;
Сообщить(Сотрудник);
Сообщить(СуммаУслуг);
Сообщить(КолСис);
КонецЦикла;
ZUBR @ Сегодня, 2:11
,
Попробуйте
|Функция КолСис = Счетчик(Товар);
|Функция КолСис = Счётчик(Товар);
Процедура Сформировать()
ЗапросСуммы = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Инженер = Документ.РасходнаяНакладная.Инженер;
|Товар = Документ.РасходнаяНакладная.Товар;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Функция КолСис = Счётчик(Товар);
|Группировка Инженер;
|Группировка Товар Без Групп;
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд));
|Условие (ВидТовара = Перечисление.ВидыТоваров.Услуга);";
Если ЗапросСуммы.Выполнить(ТекстЗапроса) <> 1 Тогда
// если по какой-то причине запрос не выполнился
Сообщить("Ошибка выполнения запроса");
Возврат;
КонецЕсли;
Пока ЗапросСуммы.Группировка(1) = 1 Цикл // обходим первую по порядку группировку "Инженер"
Сотрудник = ЗапросСуммы.Инженер;
// на этом этапе выражение ЗапросСуммы.Сум будет равна сумме всех услуг оказанных данным инженером
Пока ЗапросСуммы.Группировка(2) = 1 Цикл // для каждого инженера обходим группировку "Товар"
СуммаУслуг = ЗапросСуммы.Сум;
КолСис = ЗапросСуммы.КолСис;
Услуга = ЗапросСуммы.Товар;
Сообщить(Сотрудник);
Сообщить(Услуга);
Сообщить(СуммаУслуг);
Сообщить(КолСис);
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Даааа, ребята. Я в скобках Счетчика указывал и Товар, и Документ, и все равно запрос не работал, а то, что в слове Счётчик должна быть буква ЙО, а не Е, в голову не пришло! В этом моя основная ошибка. Тем не менее я вам всем благодарен за предложения по оптимизации запроса. Ваши критические советы очень мне помогают в изучении и освоении этого раздела! Очень интересно. Спасибо!
Макс1С @ Вчера, 14:37
, Ваш вариант более профессионален, чем мой. Но и в моем, и в Вашем варианте есть проблема. Для меня. Функция КолСис считает количество сделанных аппаратов по товарам с типом Услуга. Но в одном аппарате в расходной накладной может присутствовать несколько типов товаров вида Услуга. Например, инженер сделал 1 аппарат. Сделал Ремонт и Чистку. И функция КолСис выдает 2. А нужно, чтобы она выдала 1 - он сделал 1 аппарат. Я пробовал считать по документам. Все равно запрос 2 раза проходит документ и КолСис выдает 2. Как можно решить эту проблему? Можно ли поставить функции КолСис условие товар = ремонт, например? Хотя, в некоторых документах может быть чистка и не быть ремонта. Как заставить функцию считать даный аппарат только раз, не зависимо от количества проходов?
ZUBR @ Сегодня, 1:54
,
Верно, условия для функции есть, просто вы не писали о таком условии раньше )))) Зато хороший опыт получился с разными примерами .
Можно попробовать так:
ЗапросСуммы = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Инженер = Документ.РасходнаяНакладная.Инженер;
|ТекДок = Документ.РасходнаяНакладная.ТекущийДокумент;
|Товар = Документ.РасходнаяНакладная.Товар;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Функция КолСис = Счётчик(ТекДок) когда (ВидТовара = Перечисление.ВидыТоваров.Услуга);
|Группировка Инженер;
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд));";
|Функция СуммаУслуг = Сумма(СуммаСНДС) когда (ВидТовара = Перечисление.ВидыТоваров.Услуга);
|Функция СуммаСистемы = Сумма(СуммаСНДС) когда (ВидТовара = Перечисление.ВидыТоваров.Товар);
Макс1С @ Вчера, 9:29
, нет, результат такой же. Текущий документ считает столько раз, сколько товара с видом Услуга. Думаю, для подсчета количества надо делать отдельный запрос.
ZUBR @ 21.09.19, 0:58
,
Тогда так:
Добавим группировку по документу
|Группировка Инженер;
|Группировка ТекДок;
Пока ЗапросСуммы.Группировка(1) = 1 Цикл // обходим первую по порядку группировку "Инженер"
Сотрудник = ЗапросСуммы.Инженер;
КвоДок = СоздатьОбъект("ТаблицаЗначений");
КвоДок.НоваяКолонка ("Док");
Пока ЗапросСуммы.Группировка(2) = 1 Цикл
КвоДок.НоваяСтрока();
КвоДок.Док = ЗапросСуммы.ТекДок;
КонецЦикла;
КвоДок.Свернуть("Док");
КвоСистем = КвоДок.КоличествоСтрок();
КонецЦикла;
Может проще будет выгрузить весь запрос в Таблицу Значений, и далее свернуть (и просуммировать) по нужным колонкам ?
andrew76 @ Сегодня, 5:58
,
Может и проще, но ТС в каждой новой теме добавляет вводные по частям для этой задачи, поэтому на этом этапе трудно сказать как лучше ))
ТС решил сделать так:
Процедура Сформировать()
ЗапросСуммыУслуг = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Инженер = Документ.РасходнаяНакладная.Инженер;
|Товар = Документ.РасходнаяНакладная.Товар;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Группировка Товар Без Групп;
|Условие (Инженер = Сотрудник);
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд)или(СтатусЗаказа = Перечисление.Статусы.ВыдОтказ));
|Условие (ВидТовара = Перечисление.ВидыТоваров.Услуга);";
Спр = СоздатьОбъект("Справочник.Сотрудники");
Расх = СоздатьОбъект("Документ.РасходнаяНакладная");
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка ("Сотрудник");
ТЗ.НоваяКолонка ("КолСис"); // количество систем
ТЗ.НоваяКолонка ("ОР"); // стоимость основной работы
....................................................................................
....................................................................................
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент()=1 Цикл
ТЗ.НоваяСтрока();
ТЗ.Сотрудник = Спр.Наименование;
....................................................
....................................................
К = 0;
ОР = 0;
Расх.ВыбратьДокументы(НачДата,КонДата);
Пока Расх.ПолучитьДокумент()=1 Цикл
Если (ТЗ.Сотрудник = Расх.Инженер.Наименование) и
((Расх.СтатусЗаказа = Перечисление.Статусы.Выдан)
или(Расх.СтатусЗаказа = Перечисление.Статусы.Выезд)или(Расх.СтатусЗаказа = Перечисление.Статусы.ВыдОтказ)) Тогда
К=К+1;
КонецЕсли;
КонецЦикла;
Сотрудник = Спр.ТекущийЭлемент();
ЗапросСуммыУслуг.Выполнить(ТекстЗапроса);
Пока ЗапросСуммыУслуг.Группировка() = 1 Цикл
СуммаУслуг = ЗапросСуммыУслуг.Сум;
КонецЦикла;
// Сообщить(ТЗ.Сотрудник);
// Сообщить(СуммаУслуг);
ТЗ.КолСис = К;
ТЗ.ОР = СуммаУслуг;
................................
................................
КонецЦикла;
ТЗ.ВыбратьСтроку();
КонецПроцедуры
ЗапросСуммыУслуг = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Док = Документ.РасходнаяНакладная.ТекущийДокумент;
|Инженер = Документ.РасходнаяНакладная.Инженер;
|Товар = Документ.РасходнаяНакладная.Товар;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Группировка Док;
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд)или(СтатусЗаказа = Перечисление.Статусы.ВыдОтказ));
|Условие (ВидТовара = Перечисление.ВидыТоваров.Услуга);";
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка ("Сотрудник");
ТЗ.НоваяКолонка ("КолСис"); // количество систем
ТЗ.НоваяКолонка ("ОР"); // стоимость основной работы
ЗапросСуммыУслуг.Выполнить(ТекстЗапроса);
Пока ЗапросСуммыУслуг.Группировка() = 1 Цикл
ТЗ.НоваяСтрока();
ТЗ.Сотрудник=ЗапросСуммыУслуг.Инженер;
ТЗ.ОР=ЗапросСуммыУслуг.СуммаСНДС;
ТЗ.КолСис=1;
КонецЦикла;
ТЗ.Свернуть("Сотрудник","КолСис,ОР");
andrew76 @ Вчера, 6:09
,
запрос считает неправильно. И суммы неправильно, и количество систем неправильно.
Мой гибридный код, приведенный ранее, считает все четко. Почему Ваш не считает, я так и не разобрался. Не знаю, как строится в данном случае группировка по документам... Думаю, причина в том, что при данных условиях выборки товара посчитать количество аппаратов в одном запросе программно невозможно. Остаюсь пока на своем варианте. Тем более, что мне нужно выбирать несколько параметров из справочника Сотрудники. Так что справочник мне все равно нужен. Благодарю Вас за участие!
Я благодарю Вас не в смысле прощаюсь, а просто благодарю. Если есть решение этих двух задач одним запросом, это будет интересно. Я пока не могу найти логического построения такого запроса. Короче, если суммировать услуги не по товару, а по видам товаров, тогда не получается вычислить количество систем. А если считать количество систем, тогда нужно суммировать по одному товару, а не по виду. То есть, в моем случае нужны, как минимум, два запроса. Во всяком случае, я так думаю.
ZUBR @ Сегодня, 3:52
,
Будем разбираться,раз такое дело.
Вот Ваш запрос ,без условия по Сотруднику.Попробуйте такой вариант.
ЗапросСуммыУслуг = СоздатьОбъект("Запрос");
ТекстЗапроса =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|Инженер = Документ.РасходнаяНакладная.Инженер;
|Товар = Документ.РасходнаяНакладная.Товар;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Группировка Товар Без Групп;
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд)или(СтатусЗаказа = Перечисление.Статусы.ВыдОтказ));
|Условие (ВидТовара = Перечисление.ВидыТоваров.Услуга);";
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка ("Сотрудник");
ТЗ.НоваяКолонка ("КолСис"); // количество систем
ТЗ.НоваяКолонка ("ОР"); // стоимость основной работы
ЗапросСуммыУслуг.Выполнить(ТекстЗапроса);
Пока ЗапросСуммыУслуг.Группировка() = 1 Цикл
ТЗ.НоваяСтрока();
ТЗ.Сотрудник=ЗапросСуммыУслуг.Инженер;
ТЗ.ОР=ЗапросСуммыУслуг.СуммаСНДС;
ТЗ.КолСис=1;
КонецЦикла;
ТЗ.Свернуть("Сотрудник","КолСис,ОР");
andrew76 @ Сегодня, 8:19
,
Если число Инженеров в выборке в моем варианте совпадает с Вашим отчетом,значит,где-то здесь в моём варианте проблема:
ТЗ.ОР=ЗапросСуммыУслуг.СуммаСНДС;
ТЗ.КолСис=1;
ТЗ.ОР=ЗапросСуммыУслуг.Сум;
andrew76 @ Сегодня, 9:01
, у меня в тестовом режиме два инженера. В Вашем варианте отчета отображается почему-то один. Правильность суммы забыл проверить. Наверное, свертка. Сейчас нет времени, посмотрю позже
Я пытаюсь анализировать последний предложенный вариант, но не могу, потому что не понимаю до конца, что такое группировка. Вот если, например, Группировка Товар, и идет оператор
Пока ЗапросСуммыУслуг.Группировка() = 1 Цикл
, что происходит в цикле? Что значит Группировка Товар? Что значит Группировка()? Что значит Группировка (2)? Что значит Группировка(1)? Объясните, пожалуйста, кратко, кто может. Потому что без понимания этого нет смысла пытаться найти причину неправильной работы запроса! Для того, чтобы найти причину некорректной работы системы, нужно четко понимать, КАК она работает.andrew76 @ Сегодня, 5:36
, про группировки я читал. Сам давал эту ссылку. Но, не сочтите за тупого, мне не понятен сам термин Группировка. Что это значит физически? Конкретно. Как это происходит в деталях?
Вто например, Группировка Товар. Что это значит? Как группируются данные? И где?
ZUBR @ Сегодня, 20:39
,
группировки можно представить в виде дерева или вот таких "группировок" таблицы которая получается в результате выполнения запроса
в 7.7 в запросе должна быть как минимум одна группировка - это будет соответствовать простой таблице без "вложенностей".
2 группировки будут означать "дерево" из 2х уровней вложенности, 3 - из 3х и т.д.
Несмотря на то, что картинка из 1С8 и там принцип чуть другой, результат в отчете примерно такой же.
Также для каждой группировки рассчитываются функции запроса. На картинке например это Количество и Сумма
Примерно такой запрос мог быть для отчета как на картинке:
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с ВыбНачПериода по ВыбКонПериода;
|Контрагент = Документ.РасходнаяНакладная.Контрагент;
|ТМЦ = Документ.РасходнаяНакладная.ТМЦ;
|ТекущийДокумент = Документ.РасходнаяНакладная.ТекущийДокумент;
|Кво = Документ.РасходнаяНакладная.Кво;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Родитель = Документ.РасходнаяНакладная.Контрагент.Родитель;
|Функция ИтогКоличество = Сумма(Кво);
|Функция ИтогСумма = Сумма(СуммаСНДС);
|Группировка Родитель;
|Группировка Контрагент;
|Группировка ТМЦ;
|Группировка ТекущийДокумент;
|Условие(ТМЦ в ВыбТМЦ);
|"//}}ЗАПРОС
;
// Если ошибка в запросе, то выход из процедуры
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
Возврат;
КонецЕсли;
Пока Запрос.Группировка(1) = 1 Цикл
// Заполнение полей Родитель
Пока Запрос.Группировка(2) = 1 Цикл
// Заполнение полей Контрагент
Пока Запрос.Группировка(3) = 1 Цикл
// Заполнение полей ТМЦ
Пока Запрос.Группировка(4) = 1 Цикл
// Заполнение полей ТекущийДокумент
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЦикла;
Пока Запрос.Группировка(1) = 1 Цикл
КонецЦикла;
Макс1С @ Сегодня, 21:27
, так, немного яснее. А как выводятся результаты? Они где-то хранятся, или при каждом прохождении цикла их надо выводить? Чтобы получилась таблица отчета.
ZUBR @ Вчера, 22:24
,
Для каждой группировки итоги (функции запроса) рассчитаны и доступны при обходе циклами.
Вот такую таблицу генерирует конструктор запроса:
и обработку результата запроса:
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("Сформировать"); // это имя макета
// Заполнение полей "Заголовок"
Таб.ВывестиСекцию("Заголовок");
Таб.Опции(0, 0, Таб.ВысотаТаблицы(), 0);
Пока Запрос.Группировка(1) = 1 Цикл
// Заполнение полей Родитель
Таб.ВывестиСекцию("Родитель");
Пока Запрос.Группировка(2) = 1 Цикл
// Заполнение полей Контрагент
Таб.ВывестиСекцию("Контрагент");
Пока Запрос.Группировка(3) = 1 Цикл
// Заполнение полей ТМЦ
Таб.ВывестиСекцию("ТМЦ");
Пока Запрос.Группировка(4) = 1 Цикл
// Заполнение полей ТекущийДокумент
Таб.ВывестиСекцию("ТекущийДокумент");
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЦикла;
// Заполнение полей "Итого"
Таб.ВывестиСекцию("Итого");
// Вывод заполненной формы
Таб.ТолькоПросмотр(1);
Таб.Показать("Сформировать", "");
Доброй ночи! Сегодня создал нужній мне отчет. Небольшой. Состоит из 3 текстов запросов. Работает))) Очень Прошу профессуру посмотреть и дать свои замечания. Можно ли его сократить? Оптимизировать? Спасибо!
Процедура Сформировать()
Запрос = СоздатьОбъект("Запрос");
ТекстЗапросаС =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|Товар = Документ.РасходнаяНакладная.Товар;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Функция СумУс = Сумма(СуммаСНДС) когда (ВидТовара = Перечисление.ВидыТоваров.Услуга);
|Группировка Товар Без Групп;
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд)или(СтатусЗаказа = Перечисление.Статусы.ВыдОтказ));";
ТекстЗапросаК =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|ТекДок = Документ.РасходнаяНакладная.ТекущийДокумент;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|Функция КолСис = Счётчик(ТекДок);
|Группировка ТекДок;
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд)или(СтатусЗаказа = Перечисление.Статусы.ВыдОтказ));";
ТекстЗапросаАкс =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|Товар = Документ.РасходнаяНакладная.Товар;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция СумАкс = Сумма(СуммаСНДС);
|Группировка Товар Без Групп;
|Условие (СтатусЗаказа = Перечисление.Статусы.Акс);";
Запрос.Выполнить(ТекстЗапросаС);
Пока Запрос.Группировка() = 1 Цикл
Вал = Запрос.Сум;
СумУс = Запрос.СумУс;
КонецЦикла;
Запрос.Выполнить(ТекстЗапросаК);
КолСис = Запрос.КолСис;
Запрос.Выполнить(ТекстЗапросаАкс);
Пока Запрос.Группировка() = 1 Цикл
СумАкс = Запрос.СумАкс;
КонецЦикла;
Сообщить("Количество систем:"+КолСис);
Сообщить("Сумма:"+Вал);
Сообщить("Сумма услуг:"+СумУс);
Сообщить("Сумма акс:"+СумАкс);
КонецПроцедуры
ZUBR @ Сегодня, 0:55
,
Предлагаю для начал изложить цель этой процедуры, пользовательскую историю, так сказать. Чего хочется получить, какова конечная цель отчета? Потому что первое впечатление, что оно работает не так )))
СумУс=0;
КолСис=0;
СумАкс=0;
Расх = СоздатьОбъект("Документ.РасходнаяНакладная");
Расх.ВыбратьДокументы(НачДата,КонДата);
Пока Расх.ПолучитьДокумент()=1 Цикл
Если (Расх.СтатусЗаказа = Перечисление.Статусы.Выдан) или (Расх.СтатусЗаказа = Перечисление.Статусы.Выезд) или (Расх.СтатусЗаказа =
Перечисление.Статусы.ВыдОтказ) тогда
КолСис=КолСис+1;
Если Расх.ВидТовара = Перечисление.ВидыТоваров.Услуга тогда
СумУс=СумУс+Расх.СуммаСНДС;
КонецЕсли;
КонецЕсли;
Если Расх.СтатусЗаказа = Перечисление.Статусы.Акс тогда
СумАкс =СумАкс+Рас.СуммаСНДС;
КонецЕсли;
КонецЦикла;
СумУс=0;
КолСис=0;
СумАкс=0;
Вал=0;
Расх = СоздатьОбъект("Документ.РасходнаяНакладная");
Расх.ВыбратьДокументы(НачДата,КонДата);
Пока Расх.ПолучитьДокумент()=1 Цикл
Если (Расх.СтатусЗаказа = Перечисление.Статусы.Выдан) или (Расх.СтатусЗаказа = Перечисление.Статусы.Выезд) или (Расх.СтатусЗаказа =
Перечисление.Статусы.ВыдОтказ) тогда
КолСис=КолСис+1;
Вал=Вал+Расх.СуммаСНДС;
Если Расх.ВидТовара = Перечисление.ВидыТоваров.Услуга тогда
СумУс=СумУс+Расх.СуммаСНДС;
КонецЕсли;
КонецЕсли;
Если Расх.СтатусЗаказа = Перечисление.Статусы.Акс тогда
СумАкс =СумАкс+Рас.СуммаСНДС;
КонецЕсли;
КонецЦикла;
Сообщить("Количество систем:"+КолСис);
Сообщить("Сумма:"+Вал);
Сообщить("Сумма услуг:"+СумУс);
Сообщить("Сумма акс:"+СумАкс);
andrew76 @ Сегодня, 16:03
, у меня вопрос тогда. Как к профессору. Какой вариант забирает меньше ресурсов и более быстродейственен? Вариант запросов? Или предложенный Вами? Вопрос чисто академический для лучшего понимания оптимальных методов программирования. Осмелюсь предположить, что Ваш вариант проще и лучше.
andrew76 @ Вчера, 16:03
,
но как минимум вот такие конструкции надо поменять:
Пока Запрос.Группировка() = 1 Цикл
Вал = Запрос.Сум;
СумУс = Запрос.СумУс;
КонецЦикла;
.............
Пока Запрос.Группировка() = 1 Цикл
СумАкс = Запрос.СумАкс;
КонецЦикла;
Вал = 0;
СумУс = 0;
СумАкс = 0;
Пока Запрос.Группировка() = 1 Цикл
Вал = Вал + Запрос.Сум;
СумУс = СумУс + Запрос.СумУс;
КонецЦикла;
.............
Пока Запрос.Группировка() = 1 Цикл
СумАкс = СумАкс + Запрос.СумАкс;
КонецЦикла;
а2=_GetPerformanceCounter();
а2=_GetPerformanceCounter();
а=а2-а1;
сек=а/1000;
Сообщить("Тривалысть формування= "+сек);
Макс1С @ Сегодня, 9:22
, я не понял, в чем проблема. Отчет формируется нормально. Можете объяснить?
ZUBR @ Вчера, 17:43
,
На примере этого запроса:
ТекстЗапросаАкс =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|Товар = Документ.РасходнаяНакладная.Товар;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция СумАкс = Сумма(СуммаСНДС);
|Группировка Товар Без Групп;
|Условие (СтатусЗаказа = Перечисление.Статусы.Акс);";
Запрос.Выполнить(ТекстЗапросаАкс); //*1
Пока Запрос.Группировка() = 1 Цикл //*2
СумАкс = Запрос.СумАкс;
КонецЦикла;
Сообщить("Сумма акс:"+СумАкс); //*3
СумАкс = 0;
Пока Запрос.Группировка() = 1 Цикл
СумАкс = СумАкс + Запрос.СумАкс;
КонецЦикла;
Сообщить("Сумма акс:"+СумАкс);
Макс1С @ Сегодня, 15:36
,
Я сейчас проверю и сообщу результат
Макс1С @ Сегодня, 15:36
,
У меня все считает правильно. Товары со статусом заказа АКС (Это аксессуары) разные и в разных количествах. Услуги тоже разные. Видов 4 или 5. В разных документах могут быть разные товары и услуги. Привожу реально работающую часть кода еще раз.
Процедура Сформировать()
Запрос = СоздатьОбъект("Запрос");
ТЗ = СоздатьОбъект ("ТаблицаЗначений");
//Создание колонок
ТЗ.НоваяКолонка("НачДата");
ТЗ.НоваяКолонка("КонДата");
ТЗ.НоваяКолонка("КолСис"); //Количество систем
ТЗ.НоваяКолонка("Вал"); //Общая стоимость работ
ТЗ.НоваяКолонка("СумУс"); //Стоимость услуг
ТЗ.НоваяКолонка("ЗЧ"); //Стоимость запчастей
ТЗ.НоваяКолонка("СумАкс"); //Стоимость аксессуаров
ТекстЗапросаС =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|Товар = Документ.РасходнаяНакладная.Товар;
|ВидТовара = Документ.РасходнаяНакладная.Товар.ВидТовара;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция Сум = Сумма(СуммаСНДС);
|Функция СумУс = Сумма(СуммаСНДС) когда (ВидТовара = Перечисление.ВидыТоваров.Услуга);
|Группировка Товар Без Групп;
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд)или(СтатусЗаказа = Перечисление.Статусы.ВыдОтказ));";
ТекстЗапросаК =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|ТекДок = Документ.РасходнаяНакладная.ТекущийДокумент;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|Функция КолСис = Счётчик(ТекДок);
|Группировка ТекДок;
|Условие ((СтатусЗаказа = Перечисление.Статусы.Выдан)или(СтатусЗаказа = Перечисление.Статусы.Выезд)или(СтатусЗаказа = Перечисление.Статусы.ВыдОтказ));";
ТекстЗапросаАкс =
"
|Период с НачДата по КонДата;
|ОбрабатыватьДокументы Проведенные;
|СтатусЗаказа = Документ.РасходнаяНакладная.СтатусЗаказа;
|Товар = Документ.РасходнаяНакладная.Товар;
|СуммаСНДС = Документ.РасходнаяНакладная.СуммаСНДС;
|Функция СумАкс = Сумма(СуммаСНДС);
|Группировка Товар Без Групп;
|Условие (СтатусЗаказа = Перечисление.Статусы.Акс);";
Запрос.Выполнить(ТекстЗапросаС);
Пока Запрос.Группировка() = 1 Цикл
Вал = Запрос.Сум;
СумУс = Запрос.СумУс;
КонецЦикла;
Запрос.Выполнить(ТекстЗапросаК);
КолСис = Запрос.КолСис;
Запрос.Выполнить(ТекстЗапросаАкс);
Пока Запрос.Группировка() = 1 Цикл
СумАкс = Запрос.СумАкс;
КонецЦикла;
Сообщить("Количество систем:"+КолСис);
Сообщить("Сумма:"+Вал);
Сообщить("Сумма услуг:"+СумУс);
Сообщить("Сумма акс:"+СумАкс);
ТЗ.НоваяСтрока();
ТЗ.НачДата = НачДата;
ТЗ.КонДата = КонДата;
ТЗ.КолСис = КолСис;
ТЗ.Вал = Вал;
ТЗ.СумУс = СумУс;
ТЗ.ЗЧ = Вал - СумУс;
// и т.д. Дальше идут колонки, данные в которые заносятся на основании предыдущих колонок
КонецПроцедуры
Процедура Сформировать()
ТЗ = СоздатьОбъект ("ТаблицаЗначений");
Расх = СоздатьОбъект("Документ.РасходнаяНакладная");
//Создание колонок
ТЗ.НоваяКолонка("НачДата");
ТЗ.НоваяКолонка("КонДата");
ТЗ.НоваяКолонка("КолСис"); //Количество систем
ТЗ.НоваяКолонка("Вал"); //Общая стоимость работ
ТЗ.НоваяКолонка("СумУс"); //Стоимость услуг
//и т.д.
СумУс=0;
КолСис=0;
СумАкс=0;
Вал=0;
Расх.ВыбратьДокументы(НачДата,КонДата);
Пока Расх.ПолучитьДокумент()=1 Цикл
Если (Расх.СтатусЗаказа = Перечисление.Статусы.Выдан) или (Расх.СтатусЗаказа = Перечисление.Статусы.Выезд) или (Расх.СтатусЗаказа =
Перечисление.Статусы.ВыдОтказ) тогда
КолСис=КолСис+1;
Вал=Вал+Расх.Итог("СуммаСНДС");
Расх.ВыбратьСтроки();
Пока Расх.ПолучитьСтроку() = 1 Цикл
Если Расх.Товар.ВидТовара = Перечисление.ВидыТоваров.Услуга тогда
СумУс=СумУс+Расх.СуммаСНДС;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Расх.СтатусЗаказа = Перечисление.Статусы.Акс тогда
СумАкс =СумАкс+Расх.Итог("СуммаСНДС");
КонецЕсли;
КонецЦикла;
Сообщить("Количество систем:"+КолСис);
Сообщить("Сумма:"+Вал);
Сообщить("Сумма услуг:"+СумУс);
Сообщить("Сумма акс:"+СумАкс);
КонецПроцедуры
Доброе утро !
Оказывается в накладной есть Табличная часть, она же многострочная.Цикл я писал не учитывая это обстоятельство.
Тогда конечно , такой вариант должен работать правильно.
Если (Расх.СтатусЗаказа = Перечисление.Статусы.Выдан) или (Расх.СтатусЗаказа = Перечисление.Статусы.Выезд) или (Расх.СтатусЗаказа =
Перечисление.Статусы.ВыдОтказ) тогда
КолСис=КолСис+1;
Вал=Вал+Расх.Итог("СуммаСНДС");
Расх.ВыбратьСтроки();
Пока Расх.ПолучитьСтроку() = 1 Цикл
Если Расх.Товар.ВидТовара = Перечисление.ВидыТоваров.Услуга тогда
СумУс=СумУс+Расх.СуммаСНДС;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7
https://pro1c.org.ua