Попробовал, что-то все равно не то. Ругается на переменную TotalLevel. Что это - какая то системная переменная?
Это опечатка, исправили, там должна быть переменная vrTotalFinal.
И мне надо не все итоги по группам свалить в одну кучу, а каждый итог в свою группу (сортировку по группам я отключил, поэтому идет сортировка по датам, и одна и та же группа встречается в отчете несколько раз, в разные даты).
Если группы не используются то такой способ не подойдёт и нужно решать задачу по-другому. Можно просто разместить в отчете бэнд "Итог данных" и в него поместить компоненты текст с итогами для каждой группы поддонов. Для этого в условии итога нужно оставить какую-то одну группу, например так:
Данные.Формат_щита == "770 Х 1200"
Тогда итог будет подводиться только для поддонов с форматом "770 Х 1200". Аналогично для других форматов. Во вложении пример итога с условием (для другого отчета, но суть та же).
Группы используются, только сортировка по группам выключена! Поэтому сортировка идет по дате-времени, и одна и та же группа встречается несколько раз. А в итоге отчета группы надо объединить, а результаты просуммировать. А Ваш рецепт дает какие-то сумасшедшие результаты.
Что в Вашем понимании означает фраза "Группы используются, только сортировка по группам выключена!"? Вы дали два файла, начальные данные "Форматы поддонов.txt" и то, что нужно получить "Форматы поддонов краткий.txt". В файле "Форматы поддонов.txt" видно, что сортировка по группа отключена, это понятно. Но как там используются группы? По какому столбцу идёт группировка? В файле не видно сгруппированных данных.
Если это чистые данные, без группировки по какому-либо столбцу, то для того чтобы из первого файла получить второй, можно не использовать никакие компоненты, кроме бэндов "Данные" и "Итог данных". В первый вывести данные в чистом виде (сортировка по-умолчанию по-времени), а в бэнде итогов разместить компоненты с суммированием и условием для каждого формата, как в примере из предыдущего сообщения.
мне кажется, что если на это суммирование наложить условие Данные.Формат_щита == "770 Х 1200"
Условие "если" выглядит так:
if (Данные.Формат_щита == "770 Х 1200") {
vrTotalFinal += (double)Last(ИмяИсточника.ИмяКолонки)
}
Попробовал - получилось!
Но нужна еще помощь. В отчете в строке ИТОГО должны суммироваться не все значения последнего столбца (Выпущено щитов данного формата всего), а только максимальные, достигнутые перед переходом на другой формат.
Суммирование выполняется по такой формуле:
if (Источник_ФорматыПоддонов.Ширина_поддона == 770) {
vrTotalFinal770 += (double)Last(Источник_ФорматыПоддонов.ShieldNum);
} Пытался сюда воткнуть функцию Max, но что-то не получилось - выходит то ошибка, то 0, то вообще программа редактора отчетов зависает, приходится снимать ее из диспетчера задач... Как правильно подправить формулу, подскажите, пожалуйста.
В словаре отчета, в разделе "Переменные" создаём переменную с именем vrTotalFormat, типом данных "uint" и начальным значением 0. В неё будем суммировать количество выпущенных щитов при смене формата. Далее в бэнде "Данные" выделяем ячейку "Формат щита" и на вкладке "Свойства" -> "События" на событие "После печати" назначаем следующий код:
/* получаем формат из текущей строки */
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 будет содержать сумму всех щитов выпущенных перед переходом на новый формат. Её можно отобразить в любом месте отчета.
Да, бэнд итогов. Ячейка в которую выводится "Формат щита".
uint - это тип для целых чисел, т.к. насколько мы поняли не может быть выпущено 1.5 щита. Round используется для преобразования вещественного в целое число. При желании можете считать в double и типы переменных выбирать double, тогда код будет таким:
/* получаем формат из текущей строки */
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...
Данный код работает очень примитивно (см. комментарии в коде), ошибок в нём нет. Проверен на отчете с итогами группы с бэндом Данных нулевой высоты. Можем только предположить, что либо Вы перенесли код неправильно, либо код не подходит для групп вложенных в группы (но других решений в системе отчетов для данной задачи нет). Вместо слова "Данные" у Вас должно быть имя источника данных, который используется в Вашем отчете.
Мы можем точно сказать, что все функции приведённые в коде работают. Функция "Previous" просто берёт значение из предыдущей строки указанной колонки. Код работает и с группировкой дынных (используя бэнды "Заголовок группы" и "Итог группы") и без группировки. Также можем точно сказать, что если они у Вас не работают, то код либо был перенесён неправильно, либо данные в источнике имеют какой-то особый формат, который мы не можем учесть глядя на приведённый Вами скрин в предыдущем сообщении. Либо есть ещё какие-то причины связанные со структурой отчета.
И еще. Форматов-то много, а переменная vrTotalFormat одна. Непонятно, где прописано, для какого формата происходит суммирование.
Этот код не работает с конкретными форматами, прочтите предыдущие сообщения и наши пояснения к коду:
Теперь при печати отчета переменная vrTotalFormat будет содержать сумму всех щитов выпущенных перед переходом на новый формат.
Если нужно вести подсчет для какого-то определённого формата, то код нужно изменить так:
/* получаем формат из текущей строки */
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;
}
Пожалуйста, постарайтесь хотя-бы немного разобраться с кодом и тем, как он работает. Для этого не нужно обладать серьёзными знаниями в программировании. Все условия примитивны и Вы без труда можете изменить их под свою задачу. Если есть подозрение что какое-то условие выполняется неправильно, либо функция возвращает что-то не то, то создайте свою строковую переменную и выведите в неё результат любой функции, например оставив только следующий код:
myVariable = Previous(Данные, "Выпущено_щитов").ToString();
Затем выведите в отчет переменную myVariable и проверьте результат. Если он равен 0, значит в пред. строке источника данных значение колонки "Данные.Выпущено_щитов" на 100% равно нулю и можно размышлять почему это так и вносить корректировки. Аналогично результат можно вывести для любых других условий и проверок.
Действительно, при явном задании переменной aPrevFormat какого-либо значения, например, "800 X 1200", сумма получается ненулевой. Что-то не так в процедуре получения формата из предыдущей строки.
Это совершенно не говорит о том, что с процедурой получения формата что-то не так. Выставляя принудительно значение переменной aPrevFormat Вы просто гарантируете проход условия по-изменению "if (aNowFormat != aPrevFormat){" и конечно результат становится ненулевым. Процедуры "PreviousIsNull" и "Previous", это обычные программы, которые всегда работают одинаково (независимо от отчета или структуры данных) и никогда не меняются. Они могут не сработать только если передать в них неправильные параметры, или данные с опечатками. Если параметры верны и данные функции всё равно возвращают нулевые значения, значит в предыдущей строке указанной колонки действительно значение равно нулю и нужно думать почему.
Если всё это слишком сложно, то можем только предложить следующий вариант: вышлите на support@simple-scada.com текущую версию проекта из папки "Projects\". Затем в редакторе отчетов постройте свой отчет. Кликните правой кнопкой мыши по источнику данных и выберите пункт "Просмотреть данные" и скопируйте всё содержимое открывшейся таблицы. Вставьте его в текстовый файл и вышлите его нам. Если источников данных несколько, то проделайте это для каждого источника. Опишите максимально подробно все задачи (в том числе те, до которых Вы пока не дошли) которые нужно решить при построении отчета, условия подсчета итогов, группировок и т.д. Мы попробуем на основе данных из вашего источника данных решить все описанные задачи. Но это займёт время.
Всё, проблему решил. Предложенный скрипт взял за основу, но существенно переработал и воткнул в другую ячейку (ShieldNum -
количество выпущенных поддонов данного формата всего):
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;
}
и так для всех других форматов. Понимаю, что код далек от совершенства, но он работает.
Посмотрим, что порекомендуете Вы.
Учитывая рассчитываемую колонку для формата и взятие значений в итогах через "{Last(Источник.Колонка)}" нужно использовать собственные переменные для хранения значений. Создать в списке переменных следующие переменные:
- vrValue: double, значение 0;
- vrPrevValue: double, значение 0;
- vrFormat: string, значение - пустая строка;
- vrPrevFormat: string, значение - пустая строка;
Далее в бэнде "Итог группы" выделяем ячейку соответствующую "Формат щита" и на событие "Взять значение" ставим код:
vrFormat = Replace(e.Value, "#%#", "");
Выбираем ячейку соответствующую "Выпущено щитов данного формата всего" и на событие "Взять значение" ставим код:
vrValue = double.Parse(Replace(e.Value, "#%#", ""));
Выделяем сам бэнд "Итог группы" и на событие "После печати" ставим код:
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;