Simple-Scada forum

Simple-Scada 2 => Ваши вопросы => Тема начата: alan54 от 01 Декабря 2018, 19:41:20

Название: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 01 Декабря 2018, 19:41:20
Есть отчет по изменению (см. вложение 1). Но такая детализация не нужна, нужны только итоговые строки по количеству выпущенных поддонов данного формата (см. вложение 2). Подскажите, пожалуйста, как это сделать?
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: Simple-Scada от 02 Декабря 2018, 20:34:11
Здравствуйте.
Обычно все подобные задачи решаются добавлением фильтров (https://www.stimulsoft.com/documentation/ru/user-manual/report_internals_creating_lists_data_filterting.htm) при помощи которых лишние строки удаляются при построении отчета. Но, насколько мы поняли, в имеющихся данных нет какой-то отметки по которой можно было бы понять, что одна строка итоговая, а другие нет. Поэтому можно попробовать следующий способ:

1. Над бэндом данных (и после бэнда Заголовок данных) разместить бэнд "Заголовок группы" (https://www.stimulsoft.com/documentation/ru/user-manual/report_internals_groups_groupheaderband.htm) и выбрать для него в качестве колонки данных, колонку "Формат поддона". Теперь данные будут автоматически разбиваться на группы по этой колонке. Т.е. все данные с форматом "780 Х 980" попадут в одну группу, а данные с форматом "770 Х 1200" в другую группу. Чтобы избежать смещений, высоту бэнда "Заголовок группы" делаем нулевой;

2. Под бэндом данных размещаем бэнд "Итог группы" (https://www.stimulsoft.com/documentation/ru/user-manual/report_internals_groups_groupfooterband.htm). В нём размещаем компоненты "Текст" для каждой колонки с выражением: {Last(ИмяИсточника.ИмяКолонки)}. Таким образом мы получаем для каждой группы последнюю строку;

3. Теперь нужно сделать так, чтобы бэнд данных не отображался и оставить только итоги группы. Для этого удаляем все компоненты вложенные в бэнд данных и уменьшаем его высоту до 0;

4. На этом этапе задача уже решена. Но в данных которые Вы прикрепили видно, что последняя строка группы "780 Х 980" имеет "Задание = 0" и "Выпущено поддонов = 0". Нужно исключить такие строки. Дважды кликаем бэнд данных и в открывшемся окне на вкладке Фильтр добавляем фильтр: Значение -> Числовой -> Колонка "Задание на выпуск" -> больше чем -> 0. Можно добавить ещё один такой фильтр для колонки "Выпущено поддонов".

см. скрины во вложении (на примере демо-отчета).
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 02 Декабря 2018, 21:44:54
Благодарность моя не имеет пределов  :)  Все оказывается просто, если консультирует грамотный специалист. Большое спасибо!
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 07 Декабря 2018, 10:32:24
Здравствуйте.
Возникла еще одна проблема. Как теперь получить итог по всему отчету (то есть просуммировать только итоги по группам)?
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: Simple-Scada от 07 Декабря 2018, 23:13:19
Здравствуйте.

Здесь нужно действовать по аналогии с одной из предыдущих задач:
Теперь при построении отчета в переменную vrTotalFinal будут просуммированы все итоговые значения всех групп. Значение переменной vrTotalFinal можно вынести в любое место отчета, в Вашем случае его скорее всего нужно вывести в бэнд "Итог данных" или "Итог отчета". И так для итога по каждой колонке.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 08 Декабря 2018, 08:26:12
Спасибо за ответ, попробую. Я делал немного по другому, поэтому итоги по отчету были неверные (видимо, суммировались все данные, а не только подитоги).
P.S. Попробовал, что-то все равно не то. Ругается на переменную TotalLevel. Что это - какая то системная переменная?
И мне надо не все итоги по группам свалить в одну кучу, а каждый итог в свою группу (сортировку по группам я отключил, поэтому идет сортировка по датам, и одна и та же группа встречается в отчете несколько раз, в разные даты).
Чтобы было понятнее, что нам надо, я вручную нарисовал требуемый отчет (см. вложение 2)
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: Simple-Scada от 09 Декабря 2018, 10:33:05
Цитировать
Попробовал, что-то все равно не то. Ругается на переменную TotalLevel. Что это - какая то системная переменная?
Это опечатка, исправили, там должна быть переменная vrTotalFinal.

Цитировать
И мне надо не все итоги по группам свалить в одну кучу, а каждый итог в свою группу (сортировку по группам я отключил, поэтому идет сортировка по датам, и одна и та же группа встречается в отчете несколько раз, в разные даты).
Если группы не используются то такой способ не подойдёт и нужно решать задачу по-другому. Можно просто разместить в отчете бэнд "Итог данных" и в него поместить компоненты текст с итогами для каждой группы поддонов. Для этого в условии итога нужно оставить какую-то одну группу, например так:
Код: (c#)
Данные.Формат_щита == "770 Х 1200"
Тогда итог будет подводиться только для поддонов с форматом "770 Х 1200". Аналогично для других форматов. Во вложении пример итога с условием (для другого отчета, но суть та же).
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 09 Декабря 2018, 18:52:45
Если группы не используются то такой способ не подойдёт и нужно решать задачу по-другому. Можно просто разместить в отчете бэнд "Итог данных" и в него поместить компоненты текст с итогами для каждой группы поддонов. Для этого в условии итога нужно оставить какую-то одну группу, например так:
Код: (c#)
Данные.Формат_щита == "770 Х 1200"
Тогда итог будет подводиться только для поддонов с форматом "770 Х 1200". Аналогично для других форматов. Во вложении пример итога с условием (для другого отчета, но суть та же).
Группы используются, только сортировка по группам выключена! Поэтому сортировка идет по дате-времени, и одна и та же группа встречается несколько раз. А в итоге отчета группы надо объединить, а результаты просуммировать. А Ваш рецепт дает какие-то сумасшедшие результаты.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 09 Декабря 2018, 19:48:22
...на событие "После печати" назначаем следующий код: vrTotalFinal += (double)Last(ИмяИсточника.ИмяКолонки)
мне кажется, что если на это суммирование наложить условие
 Данные.Формат_щита == "770 Х 1200"
то все получится. Но как? Синтаксиc C# для меня пока темный лес.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: Simple-Scada от 09 Декабря 2018, 20:18:03
Цитировать
Группы используются, только сортировка по группам выключена! Поэтому сортировка идет по дате-времени, и одна и та же группа встречается несколько раз. А в итоге отчета группы надо объединить, а результаты просуммировать. А Ваш рецепт дает какие-то сумасшедшие результаты.
Что в Вашем понимании означает фраза "Группы используются, только сортировка по группам выключена!"? Вы дали два файла, начальные данные "Форматы поддонов.txt" и то, что нужно получить "Форматы поддонов краткий.txt". В файле "Форматы поддонов.txt" видно, что сортировка по группа отключена, это понятно. Но как там используются группы? По какому столбцу идёт группировка? В файле не видно сгруппированных данных.
Если это чистые данные, без группировки по какому-либо столбцу, то для того чтобы из первого файла получить второй, можно не использовать никакие компоненты, кроме бэндов "Данные" и "Итог данных". В первый вывести данные в чистом виде (сортировка по-умолчанию по-времени), а в бэнде итогов разместить компоненты с суммированием и условием для каждого формата, как в примере из предыдущего сообщения.

Цитировать
мне кажется, что если на это суммирование наложить условие Данные.Формат_щита == "770 Х 1200"
Условие "если" выглядит так:
Код: (c#)
if (Данные.Формат_щита == "770 Х 1200") { 
  vrTotalFinal += (double)Last(ИмяИсточника.ИмяКолонки)
}
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 09 Декабря 2018, 22:23:54
Условие "если" выглядит так:
Код: (c#)
if (Данные.Формат_щита == "770 Х 1200") { 
  vrTotalFinal += (double)Last(ИмяИсточника.ИмяКолонки)
}
Ругается на нехватку ";" Куда ее забыли поставить?
P.S. Нашел методом научного тыка - в конце второй строки. Нужный результат получился.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 20 Декабря 2018, 21:44:15
Рано обрадовался - нужный результат пока не получен. Нельзя ли как-то исхитриться и вложить одну группу в другую? Первая группировка - по дате, вторая - по форматам поддонов внутри одной даты? Вот сегодня такой отчет получился, а за другую дату - почему-то нет, выдает только последний результат...
P.S. Ответ на свой вопрос нашел сам в руководстве по Стимулсофту, попробую.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 21 Декабря 2018, 19:44:33
Попробовал - получилось!
Но нужна еще помощь. В отчете в строке ИТОГО должны суммироваться не все значения последнего столбца (Выпущено щитов данного формата всего), а только максимальные, достигнутые перед переходом на другой формат.
Суммирование выполняется по такой формуле:
Код: (c#)
if (Источник_ФорматыПоддонов.Ширина_поддона == 770) {
  vrTotalFinal770 += (double)Last(Источник_ФорматыПоддонов.ShieldNum);
}
Пытался сюда воткнуть функцию Max, но что-то не получилось - выходит то ошибка, то 0, то вообще программа редактора отчетов зависает, приходится снимать ее из диспетчера задач... Как правильно подправить формулу, подскажите, пожалуйста.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: Simple-Scada от 23 Декабря 2018, 10:22:01
В словаре отчета, в разделе "Переменные" создаём переменную с именем vrTotalFormat, типом данных "uint" и начальным значением 0. В неё будем суммировать количество выпущенных щитов при смене формата. Далее в бэнде "Данные" выделяем ячейку "Формат щита" и на вкладке "Свойства" -> "События" на событие "После печати" назначаем следующий код:
Код: (c#)
/* получаем формат из текущей строки */
string aNowFormat = Данные.Формат_щита;

/* получаем формат из пред. строки */
string aPrevFormat = "";
if (!PreviousIsNull(Данные, "Формат_щита"))
  aPrevFormat = Previous(Данные, "Формат_щита").ToString();

/* получаем кол-во щитов из пред. строки */
uint aPrevCount = 0;
if (!PreviousIsNull(Данные, "Выпущено_щитов"))
  aPrevCount = (uint)Round((double)Previous(Данные, "Выпущено_щитов"));

/* суммируем, если формат щита изменился */
if (aPrevFormat != "")
  if (aNowFormat != aPrevFormat){
    vrTotalFormat += aPrevCount;
  }
Теперь при печати отчета переменная vrTotalFormat будет содержать сумму всех щитов выпущенных перед переходом на новый формат. Её можно отобразить в любом месте отчета.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 23 Декабря 2018, 20:14:32
...Далее в бэнде "Данные" выделяем ячейку "Формат щита" и на вкладке "Свойства" -> "События" на событие "После печати" назначаем следующий код...
У меня бэнд "Данные", согласно Вашим же рекомендациям (см выше), имеет высоту 0 и в нем нет никаких ячеек! Возможно, Вы имели в виду бэнд итогов группы? Я вставил рекомендованный код в событие соответствующей ячейки этого бэнда, но получил 0...
И зачем в строке12 кода оператор Round?
Насколько существенно объявление переменных vrTotalFormat и aPrevCount типа uint? Счетчик щитов данного формата ("Выпущено_щитов") у меня был объявлен как double.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: Simple-Scada от 23 Декабря 2018, 22:46:16
Да, бэнд итогов. Ячейка в которую выводится "Формат щита".
uint - это тип для целых чисел, т.к. насколько мы поняли не может быть выпущено 1.5 щита. Round используется для преобразования вещественного в целое число. При желании можете считать в double и типы переменных выбирать double, тогда код будет таким:
Код: (c#)
/* получаем формат из текущей строки */
string aNowFormat = Данные.Формат_щита;
 
/* получаем формат из пред. строки */
string aPrevFormat = "";
if (!PreviousIsNull(Данные, "Формат_щита"))
  aPrevFormat = Previous(Данные, "Формат_щита").ToString();   
 
/* получаем кол-во щитов из пред. строки */
double aPrevCount = 0;
if (!PreviousIsNull(Данные, "Выпущено_щитов"))
  aPrevCount = (double)Previous(Данные, "Выпущено_щитов");
 
/* суммируем, если формат щита изменился */
if (aPrevFormat != "")
  if (aNowFormat != aPrevFormat){
    vrTotalFormat += aPrevCount;
  }

Цитировать
Я вставил рекомендованный код в событие соответствующей ячейки этого бэнда, но получил 0...
Данный код работает очень примитивно (см. комментарии в коде), ошибок в нём нет. Проверен на отчете с итогами группы с бэндом Данных нулевой высоты. Можем только предположить, что либо Вы перенесли код неправильно, либо код не подходит для групп вложенных в группы (но других решений в системе отчетов для данной задачи нет). Вместо слова "Данные" у Вас должно быть имя источника данных, который используется в Вашем отчете.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 24 Декабря 2018, 10:47:43
Все проверил несколько раз. Все равно получается в сумме 0. Наверно, причина во вложенных группах, но без них тут не обойтись.
P.S. Убрал группу по дням, все равно 0.  Выключал условие в строке 15 - суммирует, но все подряд. Похоже, что переменная aPrevFormat остается пустой.
P.P.S. Действительно, при явном задании переменной aPrevFormat какого-либо значения, например, "800 X 1200", сумма получается ненулевой. Что-то не так в процедуре получения формата из предыдущей строки.
P.P.P.S. Проверил работу этого скрипта в отчете без групп вообще - результат тот же (vrTotalFormat = 0).
И еще. Форматов-то много, а переменная vrTotalFormat одна. Непонятно, где прописано, для какого формата происходит суммирование.
Короче, ваша рекомендация пока не работает.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: Simple-Scada от 25 Декабря 2018, 11:09:00
Мы можем точно сказать, что все функции приведённые в коде работают. Функция "Previous" просто берёт значение из предыдущей строки указанной колонки. Код работает и с группировкой дынных (используя бэнды "Заголовок группы" и "Итог группы") и без группировки. Также можем точно сказать, что если они у Вас не работают, то код либо был перенесён неправильно, либо данные в источнике имеют какой-то особый формат, который мы не можем учесть глядя на приведённый Вами скрин в предыдущем сообщении. Либо есть ещё какие-то причины связанные со структурой отчета.

Цитировать
И еще. Форматов-то много, а переменная vrTotalFormat одна. Непонятно, где прописано, для какого формата происходит суммирование.
Этот код не работает с конкретными форматами, прочтите предыдущие сообщения и наши пояснения к коду:
Цитировать
Теперь при печати отчета переменная vrTotalFormat будет содержать сумму всех щитов выпущенных перед переходом на новый формат.
Если нужно вести подсчет для какого-то определённого формата, то код нужно изменить так:
Код: (c#)
/* получаем формат из текущей строки */
string aNowFormat = Данные.Формат_щита;
 
/* получаем формат из пред. строки */
string aPrevFormat = "";
if (!PreviousIsNull(Данные, "Формат_щита"))
  aPrevFormat = Previous(Данные, "Формат_щита").ToString();   
 
/* получаем кол-во щитов из пред. строки */
double aPrevCount = 0;
if (!PreviousIsNull(Данные, "Выпущено_щитов"))
  aPrevCount = (double)Previous(Данные, "Выпущено_щитов");
 
/* суммируем, если формат щита изменился. Суммируем только строки формата "770 X 1200"  */
if (aPrevFormat == "770 X 1200")
  if (aNowFormat != aPrevFormat){
    vrTotalFormat += aPrevCount;
  }
Пожалуйста, постарайтесь хотя-бы немного разобраться с кодом и тем, как он работает. Для этого не нужно обладать серьёзными знаниями в программировании. Все условия примитивны и Вы без труда можете изменить их под свою задачу. Если есть подозрение что какое-то условие выполняется неправильно, либо функция возвращает что-то не то, то создайте свою строковую переменную и выведите в неё результат любой функции, например оставив только следующий код:
Код: (c#)
myVariable = Previous(Данные, "Выпущено_щитов").ToString();
Затем выведите в отчет переменную myVariable и проверьте результат. Если он равен 0, значит в пред. строке источника данных значение колонки "Данные.Выпущено_щитов" на 100% равно нулю и можно размышлять почему это так и вносить корректировки. Аналогично результат можно вывести для любых других условий и проверок.

Цитировать
Действительно, при явном задании переменной aPrevFormat какого-либо значения, например, "800 X 1200", сумма получается ненулевой. Что-то не так в процедуре получения формата из предыдущей строки.
Это совершенно не говорит о том, что с процедурой получения формата что-то не так. Выставляя принудительно значение переменной aPrevFormat Вы просто гарантируете проход условия по-изменению "if (aNowFormat != aPrevFormat){" и конечно результат становится ненулевым. Процедуры "PreviousIsNull" и "Previous", это обычные программы, которые всегда работают одинаково (независимо от отчета или структуры данных) и никогда не меняются. Они могут не сработать только если передать в них неправильные параметры, или данные с опечатками. Если параметры верны и данные функции всё равно возвращают нулевые значения, значит в предыдущей строке указанной колонки действительно значение равно нулю и нужно думать почему.

Если всё это слишком сложно, то можем только предложить следующий вариант: вышлите на support@simple-scada.com текущую версию проекта из папки "Projects\". Затем в редакторе отчетов постройте свой отчет. Кликните правой кнопкой мыши по источнику данных и выберите пункт "Просмотреть данные" и скопируйте всё содержимое открывшейся таблицы. Вставьте его в текстовый файл и вышлите его нам. Если источников данных несколько, то проделайте это для каждого источника.  Опишите максимально подробно все задачи (в том числе те, до которых Вы пока не дошли) которые нужно решить при построении отчета, условия подсчета итогов, группировок и т.д. Мы попробуем на основе данных из вашего источника данных решить все описанные задачи. Но это займёт время.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 25 Декабря 2018, 15:43:46
Спасибо за пространный ответ. В нем, правда, много само собой очевидных и даже немного обидных советов. Поверьте, с кодом я разобрался очень детально, и поэкспериментировал с ним вдоволь, в нем действительно ничего сложного нет, у меня все-таки более чем 25-летний опыт программирования на FoxPro и Visual Basic. Разберусь с синтаксисом C# и Delphi - все пойдет как по маслу. В самом отчете ничего особенного нет, почти все сделано мной по Вашим рекомендациям в этой теме. Сам я только добавил группировку по дням и вложенную по форматам щитов. Единственная особенность - количество щитов обнуляется при смене формата, суммируется и отражается в переменной, формируемой непосредственно в контроллере, нарастающим итогом до следующей смены формата. Вот мне и надо отловить, просуммировать за заданный период  и отразить в итогах отчета эти максимально достигнутые значения для каждого формата в отдельности.
Ответьте, пожалуйста, мне на вопрос - почему событие "После печати" используется для ячейки с форматом, а не с количеством щитов?
И второй вопрос - предложенный Вами код, как я понял, суммирует все максимальные значения количества щитов для всех форматов в одну переменную vrTotalFormat? Тогда тем более непонятно, почему у меня выходят нули...
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: Simple-Scada от 25 Декабря 2018, 17:21:45
Цитировать
Ответьте, пожалуйста, мне на вопрос - почему событие "После печати" используется для ячейки с форматом, а не с количеством щитов?
Потому что нужно отслеживать изменение формата, а количество щитов нужно только добавлять в vrTotalFormat, что и делает код.

Цитировать
И второй вопрос - предложенный Вами код, как я понял, суммирует все максимальные значения количества щитов для всех форматов в одну переменную vrTotalFormat? Тогда тем более непонятно, почему у меня выходят нули...
По высланному на почту отчету уже видно разницу с нашими отчетами, у Вас колонка "Формат щита" рассчитываемая, возможно это сказывается при взятии значения, возможно что-то ещё в структуре отчета. Нужна выборка из БД, чтобы правильно проверить. Отправили инструкции на почту.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 25 Декабря 2018, 18:40:05
А не проще ли для суммирования максимальных значений количества щитов написать скрипт в проекте? Только вот не соображу, как написать запрос на выборку  двух колонок значений - формата (ширины, ID=78) и количества (ID=80), соединенных по колонке timestamp?
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 25 Декабря 2018, 22:36:16
В результате многочисленных экспериментов получил, что в данной структуре отчета переменные aPrevFormat и aNowFormat всегда почему-то совпадают (если это числа, например, ширина щита) или aPrevFormat всегда пустая строка (если это строки). Отсюда и нулевая сумма.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: alan54 от 26 Декабря 2018, 11:11:14
Всё, проблему решил. Предложенный скрипт взял за основу, но существенно переработал и воткнул в другую ячейку (ShieldNum -
 количество выпущенных поддонов данного формата всего):
Код: (c#)
double aNowShieldNum = Источник_ФорматыПоддонов.ShieldNum;
double aNextShieldNum = 0;
double aNowShieldFormat = Источник_ФорматыПоддонов.Длина_поддона;
double aNextShieldFormat = 0;

if  (!NextIsNull(Источник_ФорматыПоддонов, "ShieldNum"))   
aNextShieldNum = (double)Next(Источник_ФорматыПоддонов, "ShieldNum");

if  (!NextIsNull(Источник_ФорматыПоддонов, "Длина_поддона"))   
aNextShieldFormat = (double)Next(Источник_ФорматыПоддонов, "Длина_поддона");       

if (Источник_ФорматыПоддонов.Ширина_поддона == 650)
{
if (aNowShieldNum != 0)
if ((aNextShieldNum < aNowShieldNum) || (aNextShieldFormat != aNowShieldFormat)) 
vrTotalFinal650 += aNowShieldNum;
}
и так для всех других форматов. Понимаю, что код далек от совершенства, но он работает.
Посмотрим, что порекомендуете Вы.
Название: Re: Как вывести в отчет только итоговые строки?
Отправлено: Simple-Scada от 26 Декабря 2018, 18:43:30
Учитывая рассчитываемую колонку для формата и взятие значений в итогах через "{Last(Источник.Колонка)}" нужно использовать собственные переменные для хранения значений. Создать в списке переменных следующие переменные:

Далее в бэнде "Итог группы" выделяем ячейку соответствующую "Формат щита" и на событие "Взять значение" ставим код:
Код: (c#)
vrFormat = Replace(e.Value, "#%#", "");

Выбираем ячейку соответствующую "Выпущено щитов данного формата всего" и на событие "Взять значение" ставим код:
Код: (c#)
vrValue = double.Parse(Replace(e.Value, "#%#", ""));

Выделяем сам бэнд "Итог группы" и на событие "После печати" ставим код:
Код: (c#)
if ((vrPrevFormat != "") && (vrFormat != vrPrevFormat)){
  /* вычисление формата "770 X 1200" */
  if (vrPrevFormat == "770 X 1200")
    vrTotalFinal770 += vrPrevValue;

  /* аналогично для всех остальных форматов, вот
      пример для "1000 X 1200" */
  if (vrPrevFormat == "1000 X 1200")
    vrTotalFinal1000 += vrPrevValue;

  /* и так далее */
}

vrPrevFormat = vrFormat;
vrPrevValue = vrValue;