Здравствуйте.
Извините за задержку с ответом. Т.е. нужно вывести время прошедшее между временем предыдущей строки и временем текущей строки? Для этого можно в бэнде данных разместить компонент Текст, дважды кликнуть его для редактирования и использовать следующее выражение:
{DateDiff(Данные.Время, (System.DateTime)Previous(Данные, "Время"))} Данный код получает разницу во времени между текущей и предыдущей строкой. Также не забудьте выставить у компонента Текст формат "Время". Для этого кликните его ПКМ и выберите пункт "Формат".
Результатом функции DateDiff является структура TimeSpan (https://docs.microsoft.com/ru-ru/dotnet/api/system.timespan?view=netframework-4.7.2). Обращаясь к свойствам этой структуры, можно получить различные значения. Свойство Minutes для Вашей задачи не подходит и нужно использовать TotalMinutes:
РазницаВоВремени.TotalMinutes > 5
Как мы поняли, "Источник_1.ВремяМеждуВыходомЩитов" у Вас - это рассчитываемая колонка с типом данных TimeSpan? Из-за особенностей при взятии значения из рассчитываемых колонок источника данных, проще всего суммировать время следующим способом:
- размещаем объект текст в бэнде Итог отчета;
- выставляем формат "Время";
- дважды кликаем компонент и задаём выражение: {SumTime(DateDiff(Данные.Время, (System.DateTime)Previous(Данные, "Время")))}
Теперь в нём будет выводиться суммарное время для всех строк. Но если нужны условия (суммировать только интервалы больше 5 минут), то придется использовать более сложный способ:
- переходим на вкладку "Словарь" (https://www.stimulsoft.com/documentation/ru/user-manual/reports_designer_panels_dictionary.htm) и в разделе "Переменные" создаём новую переменную с типом TimeSpan и значением "0:00:00". Назовём её vrTotalTime;
- в бэнде данных на странице отчета выделяем ячейку в которую выводится значение "Источник_1.ВремяМеждуВыходомЩитов";
- переходим на вкладку "Свойства" (https://www.stimulsoft.com/documentation/ru/user-manual/reports_designer_panels_properties.htm) -> "События" (кнопка с иконкой молнии);
- на событие "После печати" назначаем следующий код:
if (!PreviousIsNull(Источник_1, "Время")){
TimeSpan aTime = Источник_1.ВремяМеждуВыходомЩитов;
if (aTime.TotalMinutes > 5)
vrTotalTime += aTime;
} Теперь при построении отчета в переменную vrTotalTime будут просуммированы все интервалы "Источник_1.ВремяМеждуВыходомЩитов" с значениями более 5 минут. Значение переменной vrTotalTime можно вынести в любое место отчета.
Можно выполнить совершенно любой SQL-запрос к любой таблице из БД (не важно сами Вы её создали, или она создана скадой), для этого используется процедура RunSQL, которая подробно описана в руководстве (https://simple-scada.com/help/script/workbd.html). Чтобы выбрать данные какой-то конкретной переменной, достаточно указать её ID в запросе. ID любой переменной можно посмотреть через Редактор, меню Переменные -> Редактировать (https://simple-scada.com/help/manual/variable-editor.html). После выполнения выборки из БД, результат можно как угодно обработать в скрипте с типом события "Выполнен SQL-запрос". Вот подробный пример выборки (https://simple-scada.com/help/script/getvardb.html) из руководства. Если результат выборки содержит множество строк, то пройти по ним можно в таком цикле:
begin
if DataSet.Tag = 1 then // если это результат выполнения запроса с тегом = 1
{ выполняем цикл пока не дойдём до конца набора данных }
while not DataSet.EOF do
begin
{ здесь можем работать с текущей строкой и её ячейками, для
примера обратимся к первой ячейке текущей строки }
Text1.Text := DataSet[0].AsUTF8String;
{ переходим на следующую строку набора данных }
DataSet.Next;
end;
end.
Здравствуйте.
Опять нужна ваша помощь. Данные я вытащил, но обработать их по алгоритму, аналогичному в отчете, затрудняюсь.
begin
if DataSet.Tag = 1 then // если это результат выполнения запроса с тегом = 1
{ выполняем цикл пока не дойдём до конца набора данных }
while not DataSet.EOF do
begin
{ здесь можем работать с текущей строкой и её ячейками, для
примера обратимся к первой ячейке текущей строки }
TimestampValue := DataSet[0].AsUTF8String;
CounterValue := DataSet[1].AsUTF8String;
???????????????????????????????????????
{ переходим на следующую строку набора данных }
DataSet.Next;
end;
end.
Тут (где знаки вопроса) нужен какой-то оператор, вычисляющий разницу времени текущей и предыдущей записи
TimestampCurrent - TimestampPrevious,
и если эта разница больше 5 минут, суммировать это время в некую переменную, например, IdleTime (время простоев).
Здравствуйте.
У Вас ведь колонка с датой и временем, поэтому её нужно переводить не в строку (DataSet[0].AsUTF8String), а в дату-время (DataSet[0].AsDateTime (https://simple-scada.com/help/script/tmdbfield.html)). Для работы с переменными даты-времени используются эти функции (https://simple-scada.com/help/script/datetime.html). Например:
var
aSeconds: Int64;
aTime, aPrevTime: TDateTime; // время в текущей и пред. строке
aIdleTime: Int64; // полученная сумма в секундах
aResultDateTime: TDateTime; // полученная сумма как дата-время
begin
if DataSet.Tag = 1 then // если это результат выполнения запроса с тегом = 1
begin
aIdleTime := 0; // обнуляем переменную в которую будем суммировать сремя
aPrevTime := -1; // "обнуляем" переменную времени предыдущей строки
{ выполняем цикл пока не дойдём до конца набора данных }
while not DataSet.EOF do
begin
{ берём время из текущей строки в переменную aTime }
aTime := DataSet[0].AsDateTime;
{ далее код для суммирования интервалов более 5 минут }
if aPrevTime > -1 then
begin
aSeconds := SecondsBetween(aTime, aPrevTime);
if aSeconds > 5 * 60 then
aIdleTime := aIdleTime + aSeconds;
end;
{ в переменную времени пред. строки записываем время текущей строки }
aPrevTime := aTime;
{ переходим на следующую строку набора данных }
DataSet.Next;
end;
{ расчеты окончены, в переменной aIdleTime будет сумма всех интервалов
более 5 минут (сумма будет в секундах!). При желании можем эти секунды
перевести в переменную даты-времени }
aResultDateTime := SecondsToDateTime(aIdleTime);
end;
end.
Как на этот код синтаксически правильно наложить условие, чтобы разница времени рассчитывалась только для строк с ненулевыми значениями счетчика (vrCounter != 0). Фильтр для DataBand не годится, так как первый нуль в начале смены надо учитывать.
Уникальные условия придется реализовывать через собственные переменные. Например:
1. создать в отчете новую переменную с типом данных "timespan". С именем, например, vrDiff;
2. выделить бэнд данных и на событие "перед печатью" описать нужные условия и вычисления, например:
if (!PreviousIsNull(Данные, "Время"))
if (vrCounter != 0) {
vrDiff = DateDiff(Данные.Время, (System.DateTime)Previous(Данные, "Время"));
} else {
vrDiff = new TimeSpan(0, 0, 0);
}
3. Вывести полученную переменную vrDiff в любом месте отчета.
Или, как вариант - можно ли выключить запись в архив нулевых показателей параметра с архивацией "по изменению" каждый час, и если да, то как?
Архивация "по-изменению" просто записывает каждое изменение переменной в архив. Если значение переменной не будет меняться на ноль, то и в архив нули не попадут. Исключить из архивации какие-то определённые изменения нельзя.
Спасибо за ответ. Я немного подправил код так:
if (!PreviousIsNull(Источник_1, "Время"))
{
if (Источник_1.vrCounter_Top != 0)
{
vrDiffTime = DateDiff(Источник_1.Время, (System.DateTime)Previous(Источник_1, "Время"));
}
else
{
vrDiffTime = new TimeSpan(0, 0, 0);
}
}
else
{ vrDiffTime = new TimeSpan(0, 0, 0);
}
А насчет архивации "по изменению" - переменная равна 0 и остается нулем, то есть не меняется, но все равно пишется в архив каждый час. Видимо от этого никак не избавиться.