<< Click to Display Table of Contents >> Navigation: Проект > Документы объектов > Генератор отчетов > Примеры построения отчетов > Отчет с колонками > Одностраничный отчет |
Для получения данных о расходе электроэнергии будет использоваться счетчик "Меркурий 230-ART". Счетчик подключен к электросети через трансформаторы тока и напряжения. Суммарный коэффициент трансформации составляет 1000, то есть реальное значение мощности в 1000 раз больше измеренного счетчиком. Счетчик будет опрашиваться через драйверный интерфейс MasterSCADA – используя Windows-контроллер.
Значения архива расхода электроэнергии хранятся в группе "Текущая запись профиля мощности". Из этой группы нам потребуется только одна переменная "Прямая_Активная_Мощность_A+", остальные переменные нам не нужны. Ранее данные из счетчика были считаны и записались в архив MasterSCADA – теперь с ними можно работать, в том числе в режиме разработки.
В дереве объектов также добавлена команда "Начало" типа Время - с помощью данной команды мы будем устанавливать месяц, за который нужно построить отчет. Значения для параметра "Конец" мы сформируем в самом редакторе отчетов - в этом случае оператору потребуется ввести только одну дату, что снизит вероятность ошибки и упростит ввода. У команды заданы значения до опроса, у команды "Начало" - 13.09.2011, дата специально установлена не ровная - в редакторе отчетов мы специально обработаем это и сформируем начало месяца.
Рассмотрим данные полученные от счетчика. Выделим переменную "Активная мощность" и перейдем на закладку Данные, введем время выборки данных из архива и нажмем кнопку Получить.
Со счетчика поступают значения расхода энергии за каждые полчаса. 1 сентября в полночь значение расхода составляет 0.0917 кВт, именно это значение архива и будет текущим на следующие полчаса. То есть в интервале времени 00:00 – 00:30, значение расхода будет составлять 0.0917 кВт. Но на самом деле это не совсем корректно.
Каждые полчаса, счетчик записывает себе в память расход электроэнергии за этот интервал. То есть на интервале времени 00:00 – 00:30 значение расхода на самом деле составляет 0.0967 кВт, то есть значение в архиве в момент времени 00:30. Таким образом, чтобы получить корректное значение мощности в каждой ячейке отчета, нам нужно строить отчет как бы с опозданием на полчаса – в параметр "Начало" установить 01.09.2011 00:30, а в параметр "Конец" установить 01.10.2011 00:30. Тогда реальное значение расхода будет совпадать с рассчитанным.
Примечание. Данная особенность связана с организацией собственного архива счетчика. Если в архиве MasterSCADA у вас будут находиться действующие значение расхода (например, полученные от контроллера под управлением MasterPLC), то смещать время построения отчета не нужно.
Создадим отчет. Добавим в него источник данных, назовем его "Расход". Добавим в него колонку "Активная_мощность" - перетащим ее из дерева объектов.
Перетащим команду "Начало" в раздел Переменные, и переименуем ее в "Год_Месяц":
Мы создадим две внутренние переменные отчета "Начало" и "Конец" с помощью которых и сформируем значения для одноименных параметров источника данных. Вызываем контекстное меню словаря и выбираем пункт Новая переменная. Дадим ей имя "Начало", тип данных - datetime, способ инициализации укажем - Выражение.
Если переменная в выражении инициализации обращается к переменным, добавленным из дерева объектов MasterSCADA (как в нашем случае, – к переменной "Год_месяц"), то у этой переменной нужно обязательно установить галочку Только чтение - сделаем это.
Теперь нужно создать код выражения. Для этого нажмем на кнопку - откроется редактор текста, с которым мы ранее уже работали. Пропишем в нем текст:
new DateTime(Год_Месяц.Value.Year, Год_Месяц.Value.Month, 1,00,30,00);
И нажмем ОК. Окно настройки переменной "Начало" будет выглядеть так:
Данный код обращается к переменной Год_Месяц (которая у нас связана с командой "Начало"), берет из него год и месяц, а день, час, минуты и секунды устанавливает как константы. При этом минуты указывает - 30, по описанной ранее причине.
Теперь сделаем аналогично вторую переменную, дадим ей имя "Конец", но в ней укажем другой код:
Начало.AddMonths(1);
Данный код берет значение переменной "Начало", и прибавляет к нему ровно 1 месяц.
Переменные "Начало" и "Конец" созданы и теперь нужно связать их с параметрами источника данных. Выделим параметр Начало и перейдем на вкладку Свойства. Включим настройку Функция и зададим Значение - пропишем в поле имя нашей переменной - Начало.
Теперь параметр возьмет значения данной переменной. Аналогично сделаем с параметром Конец.
Ранее мы устанавливали связь между командами в дереве объектов и параметрами "Начало" и "Конец" напрямую – перетаскивания команды на параметры. В создании отдельных переменных в словаре отчетов есть дополнительные преимущества, о них мы расскажем подробнее позже.
Включим в свойствах источника способ формирования – Периодический. Нам нужно выводить строки с интервалом в один час, поэтому зададим значение параметра "Интервал" - 3600, т.е. установим ему количество секунд в часе.
Ранее мы уже создавали отчет, в котором вычисляли расход газа по действующему значению. Для этого мы использовали обработку параметра "Интеграл" (см. главу 18.5 "Отчет четвертый. Расход газа"). Но в данном примере в архиве у нас уже хранится вычисленное значение расхода энергии за полчаса, то есть оно уже проинтегрировано. Кроме того, нам нужно выводить строки с интервалом каждый час, то есть в ячейку таблицы должна быть выведена сумма двух значений расхода за полчаса.
Чтобы получить сумму двух значений за интервал времени, мы воспользуемся обработкой "Интеграл". Но сначала разберем принцип работы данного метода обработки.
Обработка "Интеграл", позволяет получить площадь фигуры, сверху ограниченную графиком из архивных значений, а снизу – осью абсцисс. Интервал времени вывода строки у нас составляет 3600 секунд (1 час).
За этот интервал у нас в архиве содержится два значения (рис) – X1Y1 и X2Y2.
Редактор отчетов вычисляет интеграл, как сумму площадей прямоугольников. В данном случае интеграл S равен:
Но поскольку , то формула интеграла в данном случае будет выглядеть так.
Или
Таким образом, сумма значений будет равна ∙
То есть, чтобы получить сумму двух значений расхода электроэнергии за интервал времени, нужно разделить результат обработки "Интеграл" на 1800.
Примечание. Длительность периода интегрирования равное 30 минутам, это заводское значение счетчика "Меркурий 230". Пользователь может изменить это значение. Если установить длительность интегрирования 60 минут, то обработка значения в редакторе отчетов упростится. Способ обработки параметра в этом случае нужно установить "Последнее значение", задавать другие настройки не требуется. Смещение времени на полчаса также задавать не нужно.
Включим у колонки "Активная мощность" обработку "Интеграл".
Результат нам нужно разделить на 1800. Ранее мы писали, что деление можно произвести, задав значение в поле Параметр обработки. Но поскольку результат потребуется умножать на коэффициент трансформации, то мы будем использовать рассчитываемую колонку. Рассчитываемую колонку также удобно использовать, если в отчете требуется выводить сумму активной и реактивной мощности, или производить другие операции – например, вычислить суммарный расход энергии нескольких счетчиков.
Добавим в источник данных Рассчитываемую колонку. Назовем ее "Расход энергии", тип установим double(Nullable). Введем формулу
Расход.Активная_мощность/1800*1000
В результате на выходе рассчитываемой колонки будет реальное значение расхода электроэнергии за час.
Проверим построение отчета. Вытащим на страницу источник данных "Расход" - создадим бэнд "Данные". Отметим галочкой вывод в бэнд колонки "Расход энергии". Создавать итог и заголовок данных не будем.
Бэнд добавился на страницу
Запустим построения расчета
Данные выводятся корректные, но по заданию нам нужно построить отчет в виде таблицы.
Предыдущие варианты создания отчетов не подходят – данные должны построчно выводиться в столбец, затем должен создаться следующий столбец, и так до тех пор, пока данные не закончатся. Для этого необходимо использовать колонки.
Вернемся в режим разработки отчета. Включим альбомную ориентацию страницы. Для этого щелкнем мышью в свободном месте страницы, и на закладке свойство установим "Альбом".
Удалим с бэнда текстовое поле – оставим бэнд чистым, немного уменьшим его высоту.
Теперь включим использование колонок. Выделим бэнд, и рассмотрим закладку свойств.
Для задания настроек колонок есть специальная группа.
Зададим количество колонок – 31, и ширину колонки – 0,82. Также включим направление колонок – "Вниз, затем вправо". Также нужно задать количество строк в поле Минимальное количество строк в колонке - 24. Если оставить это значение равным нулю, то генератор отчета распределит данные поровну между всеми колонками. У нас создана 31 колонка, а в сентябре только 30 дней, но редактор отчетов будет пытаться заполнить все колонки данными. В итоге в часть ячеек будут пустыми, но будет заполнена колонка за 31 число, которого в этом месяце нет. Если же установить в поле Максимальное количество строк в колонке значение 24, то редактор отчетов не будет создавать новую колонку пока не заполнит в текущей все 24 строки.
На бэнде появились красные линии - разметка колонок.
Теперь если поместить на бэнд любой элемент, например текстовое поле, он будет выводиться в колонках. Добавим на бэнд текстовое поле
Подгоним ее размер и положение – для этого воспользуемся панелью свойств. Зададим ширину равную – 1,62
Добавим еще одно текстовое поле и расположим его правее уже добавленного. Также подгоним положение поля – зададим координату Слева равную 1,62, а Ширину зададим равную ширине колонки – 0,82
Теперь на бэнде у нас находится рядом два поля. Левое поле ("Text1") будет первым столбцом, в который мы выведем номер часа (от 1 до 24). В правом поле ("Text2") мы будем выводить значения расхода энергии.
Сначала привяжем поле "Text2" к переменной "Расход энергии". Для этого наведем мышью на поле – появится маленькая кнопка, нажмем на нее – появилось меню, в котором выберем переменную "Расход энергии".
Сделаем выравнивание текста по центру, а также включим границу ячейки, чтобы получить эффект таблицы.
Запустим построение отчета. Таблица значений построилась корректно.
Теперь начнем оформлять таблицу. Слева от таблицы, должен находиться столбец, в котором будет выводиться номер часа. Щелкнем дважды на поле "Text1", и в редактор текста добавим переменную Line из группы "Системные переменные". Переменная Line хранит текущий номер строки данных. Нажмем кнопку ОК.
Сделаем выравнивание текста по центру, и включим границы поля. Запустим построение отчета.
В первом столбце, как мы и планировали, выведены часы суток. Но затем, в следующих столбцах, произошло наложение одного значения на другое. Как мы писали ранее, все элементы, положенные на бэнд с колонками выводятся в колонки. Чтобы текстовое поле "Text1" не перекрывало поле "Text2", мы будем его скрывать.
Ранее мы уже познакомились с инструментом Условное выделение, предназначенным для изменения состояния элемента отчета, в зависимости от каких-либо условий. С помощью данного инструмента мы задавали другой цвет текста и заливку. Но используя этот же инструмент можно скрыть элемент полностью.
Выделим поле "Text1", и вызовем окно Условия, нажав на соответствующую кнопку в панели форматирования. Добавим условие, включим режим Выражение, введем в поле условие:
Line >24
Снимем галочку Компонент включен.
Теперь, когда системная переменная Line превысит 24, поле будет скрыто, и оно не будет перекрывать поле "Text2". Зададим также более крупный размер шрифта поля. Проверим построение отчета.
Теперь поля не перекрывают друга, и у нас есть столбец с номером часа.
Нам также требуется сделать заголовок таблицы, содержащий числа месяца. Наиболее простой способ это сделать – воспользоваться бэндом "Заголовок колонки". Добавим его на страницу, используя панель инструментария.
Разместим этот бэнд выше бэнда "Данные".
Добавим на бэнд "Заголовок колонки" текстовое поле. Сделаем, чтобы по ширине оно совпадало с полем "Text2", и находилось над ним. Установим также границу поля и более крупный шрифт, чем у поля "Text2".
Откроем редактор текста двойным щелчком мыши. Добавим в поле текста системную переменную Column – данная переменная хранит номер колонки.
Запустим построение отчета.
Теперь в верхней части таблицы есть строка с заголовками столбцов. Поскольку у нас установлена 31 колонка, то и в заголовке таблицы числа также идут до 31, но в сентябре только 30 дней – то есть заголовок для последнего столбца лишний. Его также можно скрыть, используя условное выделение. Но чтобы скрыть поле по условию, нам нужно определить количество дней в текущем месяце.
Заведем специальную переменную – добавим ее в словарь. Назовем ее "Кол_во_дней", тип установим целый – long. Эту переменную мы будем инициализировать при старте – присваивать вычисленное количество дней, поэтому выбираем способ инициализации – Выражение и откроем окно редактора текста выражения.
Введем в окно функцию, которая вернет количество дней в месяце. Для этого в редакторе отчетов есть специальная функция – DaysInMonth. Функция возвращает количество дней в заданном месяце. Данная функция может принимать либо два целых числа – год и месяц:
DaysInMonth ( long year, long month )
Либо переменную типа DateTime (дата и время) – в этом случае вычисляется количество дней месяца из полученной переменной:
DaysInMonth ( DateTime date)
Именно этой функцией мы и воспользуемся. Мы передадим в функцию переменную "Год_Месяц". Таким образом, код будет выглядеть следующим образом:
DaysInMonth(Год_Месяц);
Теперь в переменную "Кол_во_дней" в начале построения отчета запишется значение количества дней в месяце за который строится отчет. Теперь можно использовать данную переменную в операции условного выделения.
Выделим текстовое поле "Text3" в бэнде "Заголовок колонки", и применим к нему функцию условного выделения. Добавим новое условие и напишем условие скрытия элемента:
Column>Кол_во_дней
Примечание. Можно было использовать функцию DaysInMonth непосредственно в поле условия и не создавать дополнительную переменную "Кол_во_дней".
Проверим построение отчета.
Теперь лишнее поле в строке заголовка больше не добавляется.
Сделаем подведение итогов. Для этого сначала добавим на страницу бэнд "Итог колонки".
Этот бэнд также имеет разметку для колонок. Разместим на бэнде два текстовых поля – одно для подписи строки итога, второе – для вывода значения итога. Можно, например, скопировать и вставить поля из бэнда "Данные". В первое поле введем текст - Сумма:. Используя механизм условного выделения, сделаем чтобы поле выводилось только один раз - скрывалось, если Column>1. Второе поле очистим.
Сделаем также поля для итога "Максимум" - скопируем уже добавленные поля, растянем бэнд и вставим.
Теперь нужно вычислить итог по каждой колонке.
Но прежде чем вычислять итог, нам нужно обеспечить, чтобы во всех колонках присутствовали данные. Сейчас при построении у нас есть данные во всех ячейках, однако на реальных объектах мы не всегда можем их получить. Например – в конце месяца (перед формированием отчета) счетчик был выключен и данные из него получены не были. В этом случае архив не будет содержать данных.
У нас используется тип колонки double(nullable) – это тип который может иметь "пустое" значение – null. Переменные типа Nullable содержат два свойства: HasValue – для проверки наличия значения, и Value – для получения значения. Подробнее про типы Nullable можно прочитать здесь:
http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx
Таким образом, можно вручную проверить наличие значения у колонки (переменной) проверяя свойство HasValue, например, через тернарный оператор. Если же нужно просто преобразовать nulls в нули то можно включить в свойствах отчета настройку "Преобразовывать Nulls" в Да. Сделаем это в нашем отчете.
Теперь все значения null будут преобразованы в ноль.
Мы будем производить расчет итога по следующему алгоритму. Мы создадим три переменных типа Список (массив), в одну переменную, при построении, мы будет записывать значение каждой ячейки из колонки, когда колонка закончится, мы вычислим сумму и максимум элементов массива и запишем эти значения в соответствующие переменные-массивы. Элементы из этих массивов мы и будем добавлять в итог колонки.
Добавим в словарь новую переменную.
Дадим ей латинское имя, назовем ее "Arch". Установим тип – Double и режим "Список". Если мы установим "Список", то данная переменная будет являться динамическим массивом (в языке C# она называется коллекция). В этот массив при помощи специальных методов можно будет добавлять значения.
Создадим еще две аналогичные переменные – "Sum" и "Max", в которые мы будет добавлять соответственно суммарное и максимальное значение колонки.
Выделим бэнд данных "DataРасход" и в панели свойств перейдем на закладку событий. Откроем редактор события "После печати".
Введем в редактор код:
Arch.Add(Расход.Расход_энергии.Value);
Рассмотрим этот код. Arch – это переменная-список в которую мы будем записывать значение из ячейки каждой колонки. Add( ) – это метод добавления значения в коллекцию (массив). В скобках метода указывается добавляемое значение - Расход.Расход_энергии.Value, где Расход.Расход_энергии – это рассчитываемая колонка источника данных( можно не вводить это имя вручную, а перетащить переменную из словаря в поле кода), а Value – это свойство для получения значения этой колонки. Свойство Value необходимо использовать, потому что переменная-список имеет тип double, а рассчитываемая колонка – double(nullable).
Введем следующий код:
Arch.Add(Расход.Расход_энергии.Value);
if (Line % 24 == 0)
{
//подсчет суммарного расхода за колонку
double SumColumn = 0;
for (int i = 0; i < 24; i++) SumColumn = SumColumn + Arch[i];
Sum.Add(SumColumn);
//вычисление максимума
Arch.Sort();
Max.Add(Arch[23]);
Arch.Clear();
}
Рассмотрим его построчно.
В второй строчке вычисляется остаток от деления системной переменной "Line" (номер строки) на 24. Если остаток равен нулю, значит, мы находимся в конце колонки.
В этом случае можно провести обработку данных колонки. Сначала вычислим суммарный расход электроэнергии за колонку – то есть за день. Вначале объявляется переменная "SumColumn" и инициализируется нулем.
Затем, используя цикл for, этой переменной поочередно прибавляется каждый элемент из колонки (из переменной "Arch").
После этого вычисленная сумма добавляется в коллекцию "Sum".
Теперь вычисляем максимум. Чтобы вычислять максимум, сначала вызывается метод сортировки – Sort( ). Теперь в переменной "Arch" значения отсортированы по возрастанию, а значит в самом последнем элементе – в 23 (нумерация коллекции идет с нуля), находится максимальное значение за день. Это значение и добавляется в коллекцию "Max".
Затем коллекция "Arch" очищается, при помощи метода Clear().
В результате, к концу вывода данных, мы получим две сформированных коллекции "Max" и "Sum" со значениями максимума и суммы.
Завершим ввод кода, нажав на кнопку ОК. Теперь эти значения можно выводить в ячейки итога.
Сначала выделим бэнд "Итог колонки" и установим свойство "Печатать если нет данных" в Да.
Выделим ячейку для вывода суммы.
Откроем редактор текста двойным щелком мыши. В эту ячейку мы будем выводить значение из переменной-списка "Sum", в зависимости от номера колонки. Введем код:
{Sum[Column-1]}
Обращение к элементу колонки осуществляется через индекс заданный в квадратных скобках. Поскольку нумерация элементов в коллекции идет с нуля, а нумерация столбцов – с единицы, то, чтобы обратится к нужному элементу, вычтем эту единицу.
Аналогично поступим с ячейкой для вывода максимума.
Также как для ячеек заголовка колонок, сделаем, чтобы ячейки не выводились, если их количество превышает количество дней в месяце. Для этого используем функцию условного выделения.
Также сделаем другой стиль ячеек – "двойную линию".
Запустим построение отчета.
Создание таблицы завершено. Теперь оформим отчет. Добавим в левый верхний угол ячейку для подписи столбцов и колонок и сделаем, чтобы она выводилась один раз - также используя условное выделение.
В конце нам нужно подвести общий итог за месяц – суммарный расход. Добавим бэнд "Итог отчета".
На бэнд добавим два тектовых поля, одно – с подписью, другое для значения.
Для вычисления суммарного значения за месяц воспользуемся функционалом подведения итогов.
Запустим построение отчета
Теперь сделаем заголовок отчета – выведем название отчета, и за какой месяц он строится.
Добавим бэнд "Заголовок отчета". А на него два текстовых поля. В одно введем статичный текст:
"Фактическое потребление за"
Во втором мы будем выводить месяц и год.
Вызовем редактор текста второго поля. В редактор текста добавим переменную "Начало"
Запустим построение отчета
Нам необходимо сделать, чтобы из переменной даты остался только год и месяц, и чтобы месяц выводился в виде его названия. Для этого воспользуемся форматированием текста.
В окне "Формат" выберем форматирование "По выбору" - в этом режиме можно задать собственную маску форматирования. Маска форматирования задается в поле "Маска". Введем следующую маску:
MMMM yyyy г.
Первые буквы MMMM – это формат для месяца, в таком формате он отображается в виде строкового имени. yyyy – это формат года, в таком формате будет отображаться год в полном формате (4 цифры). Запустим построение отчета:
Добавим также одну строку над колонками – например, сделаем подпись "Расход кВт*ч". Для этого добавим бэнд "Заголовок данных". И расположим на нем текстовое поле с надписью, и включим у него границу.
Запустим построение отчета.
Подпись добавилась, но она шире чем таблица – поскольку у нас только 30 дней, то не все колонки выведены в отчет. Поэтому нам нужно чтобы ширина текстового поля автоматически менялась перед построением. Для этого можно использовать скрипты событий – с их помощью можно задавать значения свойств. Для получения или записи значения ширины поля нужно использовать его свойство Width.
Примечание. Чтобы узнать английское название свойств, можно вызвать контекстное меню панели свойств и снять галочку "Переводить имена свойств".
Сначала определимся с нужной нам шириной поля. Ширина поля должна быть равна ширине первой колонки (колонка подписи времени - в нашем отчете это поле имеет имя поле Text1), плюс ширина остальных колонок (в нашем отчете это поле имеет имя Text2), умноженная на их количество, то есть на количество дней в месяце.
Щелкнем по полю, и перейдем на закладку событий. Вызовем событие "Перед печатью".
Напишем код, который задаст ширину текстового поля:
Text13.Width=Text1.Width+Text2.Width*Кол_во_дней;
Text13 – это имя нашего поля. Его свойству Width присваивается результат вычисления ширины на основе значений ширины полей Text1 и Text2.
Снова запустим построение отчета.
Теперь ширина поля равна ширине таблицы. Теперь наш отчет построен согласно заданной форме. Закроем редактор отчетов.
Примечание. Готовый отчет можно посмотреть в проекте "Отчет с колонками" в объекте "Профиль мощности" - "Одностраничный отчет"
Теперь настроим ввод даты на мнемосхеме. Для этого выделим объект "Профиль мощности" и, на закладке Окна, создадим мнемосхему. Вытащим на мнемосхему команду "Начало".
Настроим формат отображения и ввода – оставим только год и месяц (месяц в виде названия). Для этого вызовем контекстное меню контрола команды, и вызовем окно свойств. В окне свойств перейдем на закладку Дата/время.
Включим режима вывода – "только дату", шаблон даты введем MMMM yyyy
Именно в таком виде теперь будут отображаться и вводится данные в этот контрол. Применим изменения и закроем окно. При таких настройках окно ввода даты будет иметь следующий вид:
Теперь добавим кнопку открытия отчета. Для этого просто вытащим на мнемосхему объект "Профиль мощности" правой кнопкой мыши. В появившемся окне выберем "Отчет".
Сменим подпись кнопки, введем – Построить отчет.
По нажатию кнопки в режиме исполнения будет запущено построение отчета.
Примечание. Готовый отчет можно посмотреть в проекте "Отчет с колонками" в объекте "Профиль мощности" - "Одностраничный отчет"