Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?

Официальный форум Simple-Scada.

Автор Тема: Как вывести в отчет только итоговые строки?  (Прочитано 8786 раз)

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3215
    • Просмотр профиля
    • Simple-Scada
Re: Как вывести в отчет только итоговые строки?
« Ответ #15 : 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...
Данный код работает очень примитивно (см. комментарии в коде), ошибок в нём нет. Проверен на отчете с итогами группы с бэндом Данных нулевой высоты. Можем только предположить, что либо Вы перенесли код неправильно, либо код не подходит для групп вложенных в группы (но других решений в системе отчетов для данной задачи нет). Вместо слова "Данные" у Вас должно быть имя источника данных, который используется в Вашем отчете.

alan54

  • Постоялец
  • ***
  • Сообщений: 145
    • Просмотр профиля
Re: Как вывести в отчет только итоговые строки?
« Ответ #16 : 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 одна. Непонятно, где прописано, для какого формата происходит суммирование.
Короче, ваша рекомендация пока не работает.
« Изменён: 24 Декабря 2018, 22:53:57 от alan54 »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3215
    • Просмотр профиля
    • Simple-Scada
Re: Как вывести в отчет только итоговые строки?
« Ответ #17 : 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\". Затем в редакторе отчетов постройте свой отчет. Кликните правой кнопкой мыши по источнику данных и выберите пункт "Просмотреть данные" и скопируйте всё содержимое открывшейся таблицы. Вставьте его в текстовый файл и вышлите его нам. Если источников данных несколько, то проделайте это для каждого источника.  Опишите максимально подробно все задачи (в том числе те, до которых Вы пока не дошли) которые нужно решить при построении отчета, условия подсчета итогов, группировок и т.д. Мы попробуем на основе данных из вашего источника данных решить все описанные задачи. Но это займёт время.

alan54

  • Постоялец
  • ***
  • Сообщений: 145
    • Просмотр профиля
Re: Как вывести в отчет только итоговые строки?
« Ответ #18 : 25 Декабря 2018, 15:43:46 »
Спасибо за пространный ответ. В нем, правда, много само собой очевидных и даже немного обидных советов. Поверьте, с кодом я разобрался очень детально, и поэкспериментировал с ним вдоволь, в нем действительно ничего сложного нет, у меня все-таки более чем 25-летний опыт программирования на FoxPro и Visual Basic. Разберусь с синтаксисом C# и Delphi - все пойдет как по маслу. В самом отчете ничего особенного нет, почти все сделано мной по Вашим рекомендациям в этой теме. Сам я только добавил группировку по дням и вложенную по форматам щитов. Единственная особенность - количество щитов обнуляется при смене формата, суммируется и отражается в переменной, формируемой непосредственно в контроллере, нарастающим итогом до следующей смены формата. Вот мне и надо отловить, просуммировать за заданный период  и отразить в итогах отчета эти максимально достигнутые значения для каждого формата в отдельности.
Ответьте, пожалуйста, мне на вопрос - почему событие "После печати" используется для ячейки с форматом, а не с количеством щитов?
И второй вопрос - предложенный Вами код, как я понял, суммирует все максимальные значения количества щитов для всех форматов в одну переменную vrTotalFormat? Тогда тем более непонятно, почему у меня выходят нули...
« Изменён: 25 Декабря 2018, 15:48:34 от alan54 »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3215
    • Просмотр профиля
    • Simple-Scada
Re: Как вывести в отчет только итоговые строки?
« Ответ #19 : 25 Декабря 2018, 17:21:45 »
Цитировать
Ответьте, пожалуйста, мне на вопрос - почему событие "После печати" используется для ячейки с форматом, а не с количеством щитов?
Потому что нужно отслеживать изменение формата, а количество щитов нужно только добавлять в vrTotalFormat, что и делает код.

Цитировать
И второй вопрос - предложенный Вами код, как я понял, суммирует все максимальные значения количества щитов для всех форматов в одну переменную vrTotalFormat? Тогда тем более непонятно, почему у меня выходят нули...
По высланному на почту отчету уже видно разницу с нашими отчетами, у Вас колонка "Формат щита" рассчитываемая, возможно это сказывается при взятии значения, возможно что-то ещё в структуре отчета. Нужна выборка из БД, чтобы правильно проверить. Отправили инструкции на почту.
« Изменён: 25 Декабря 2018, 17:22:49 от Simple-Scada »

alan54

  • Постоялец
  • ***
  • Сообщений: 145
    • Просмотр профиля
Re: Как вывести в отчет только итоговые строки?
« Ответ #20 : 25 Декабря 2018, 18:40:05 »
А не проще ли для суммирования максимальных значений количества щитов написать скрипт в проекте? Только вот не соображу, как написать запрос на выборку  двух колонок значений - формата (ширины, ID=78) и количества (ID=80), соединенных по колонке timestamp?
« Изменён: 25 Декабря 2018, 18:43:22 от alan54 »

alan54

  • Постоялец
  • ***
  • Сообщений: 145
    • Просмотр профиля
Re: Как вывести в отчет только итоговые строки?
« Ответ #21 : 25 Декабря 2018, 22:36:16 »
В результате многочисленных экспериментов получил, что в данной структуре отчета переменные aPrevFormat и aNowFormat всегда почему-то совпадают (если это числа, например, ширина щита) или aPrevFormat всегда пустая строка (если это строки). Отсюда и нулевая сумма.
« Изменён: 25 Декабря 2018, 22:49:57 от alan54 »

alan54

  • Постоялец
  • ***
  • Сообщений: 145
    • Просмотр профиля
Re: Как вывести в отчет только итоговые строки?
« Ответ #22 : 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;
}
и так для всех других форматов. Понимаю, что код далек от совершенства, но он работает.
Посмотрим, что порекомендуете Вы.
« Изменён: 16 Февраля 2019, 15:49:50 от Simple-Scada »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 3215
    • Просмотр профиля
    • Simple-Scada
Re: Как вывести в отчет только итоговые строки?
« Ответ #23 : 26 Декабря 2018, 18:43:30 »
Учитывая рассчитываемую колонку для формата и взятие значений в итогах через "{Last(Источник.Колонка)}" нужно использовать собственные переменные для хранения значений. Создать в списке переменных следующие переменные:
  • vrValue: double, значение 0;
  • vrPrevValue: double, значение 0;
  • vrFormat: string, значение - пустая строка;
  • vrPrevFormat: string, значение - пустая строка;

Далее в бэнде "Итог группы" выделяем ячейку соответствующую "Формат щита" и на событие "Взять значение" ставим код:
Код: (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;