Перейти к содержанию

Scripts: различия между версиями

Материал из Химсофт Вики
 
(не показано 78 промежуточных версий этого же участника)
Строка 1: Строка 1:
==Общие сведения==
'''Вкладка <code>Код</code>''' – содержит программу на языке высокого уровня, которая является частью отчета.


Раздел <code>Scripts</code> предназначен для добавления программной логики непосредственно в файл макета отчета.
Программа может быть написана на одном из языков <code>.NET</code>:
*'''<code>C#</code>''' (предпочтительно);
*<code>VisualBasic.NET</code> (нежелательно).


Это позволяет отчету быть самодостаточным: код из раздела выполняется в процессе формирования отчета.
Область применения вкладки <code>Код</code> довольно обширна - она позволяет:
*выполнить обработку данных, которую невозможно сделать штатными средствами ядра дизайнера;
*управлять печатью страниц отчета и бэндов на странице;
*управлять взаимодействием элементов управления на диалоговых формах;
*управлять формированием динамических объектов <code>Таблица</code>;
*и многое другое.


Внутри раздела можно создавать собственные вспомогательные функции для выполнения сложных вычислений прямо «на лету».
Чтобы увидеть код отчета, переключитесь на закладку <code>Код</code> в дизайнере:


==GetOrDash()==
[[Файл: code_obj_1.png | center | border]]
Функция <code>GetOrDash()</code> - предназначена для обработки пустых значений (<code>NULL</code>, пустые строки, пробелы) в ячейках отчета.  


Она гарантирует, что вместо пустого места в таблице всегда будет отображаться визуальный маркер <code>-</code> (''дефис''), что улучшает читаемость документа.
Язык для вкладки <code>Код</code> настраивается в меню <code>Отчет|Свойства...</code>.  


<syntaxhighlight lang="vb">
Делать это желательно сразу после создания нового отчета, так как при смене языка существующий код очищается.
Public Function GetOrDash(field As Object) As String
 
If field Is Nothing OrElse IsDBNull(field) OrElse String.IsNullOrEmpty(field.ToString().Trim()) Then
[[Файл: code_obj_2.png | center | border]]
Return "-"
 
End If
==Общая информация==
   
 
Return field.ToString()
Вкладка <code>Код</code> в дизайнере содержит только то, что написано вами.
End Function
 
===Во вкладке можно===
*добавить в главный класс кода свои переменные, методы, свойства;
*создать обработчики событий объектов отчета;
*добавлять новые классы, если это необходимо (класс может быть добавлен как перед главным классом <code>ReportScript</code>, так и после него.
 
===Во вкладке нельзя===
*удалять, переименовывать или изменять область видимости главного класса <code>ReportScript</code>;
*переименовывать пространство имен, в котором находится главный класс.
 
===Порядок действий дизайнера при запуске отчета===
*дизайнер добавляет в код список переменных, имена которых совпадают с именами объектов отчета; это делается перед компиляцией кода и позволяет обращаться к объектам отчета по их имени;
*в код добавляются выражения, имеющиеся в отчете, в виде функций;
*выполняется компиляция кода, если главный класс не пустой;
*инициализируются переменные, которые были неявно добавлены в код;
*обработчики событий, определенные в коде, привязываются к объектам отчета;
*запускается отчет.
 
==Обработчики событий==
 
===Создание обработчика события===
*выделить нужный объект;
*в окне <code>Свойства</code> нажать кнопку [[Файл: event_btn.png|border]], чтобы переключиться на список событий:
 
[[Файл: event_handler_1.png|border|center]]
 
*выбрать интересующее событие и сделать на нем двойной щелчок мышью - дизайнер добавит в код отчета пустой обработчик события:
 
<syntaxhighlight lang="C#">
private void Text2_BeforePrint(object sender, EventArgs e)
{
 
}
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
===Удаление обработчика события===
*<code>field</code> (''Object'') - данные из поля набора данных (принимает любой тип данных, так как параметр объявлен как <code>Object</code>).
*выбрать событие в окне <code>Свойства</code>;
*выделить текст имени события и нажамть клавишу <code>Delete</code>:
 
[[Файл: event_handler_2.png|border|center]]
 
==События==
 
Каждый объект отчета имеет несколько '''событий''', которым можно назначить '''обработчик''' – метод из вкладки кода.
 
Чтобы максимально гибко управлять отчетом, нужно:
*четко представлять, в какой момент времени вызывается каждое из событий;
*использовать те события, которые соответствуют поставленной задаче.
 
===Пример===
Рассмотрим процесс формирования отчета и события, которые при этом генерируются.
 
В качестве примера возьмем простой отчет, содержащий одну страницу, один бэнд <code>Данные</code> и два объекта <code>Текст</code> на бэнде:
 
[[Файл: events_1.png|center|border]]
 
===Порядок событий===
#В начале отчета вызывается событие <code>StartReport</code> объекта <code>Отчет</code>.
#Перед формированием страницы вызывается событие страницы <code>StartPage</code>. Это событие вызывается один раз для каждой страницы шаблона отчета (не путать со страницами готового отчета!). В нашем случае, сколько бы ни было страниц в готовом отчете – событие вызовется один раз, т.к. шаблон отчета состоит из одной страницы.
#Затем вызывается событие <code>CreatePage</code>, которое происходит как раз в тот момент, когда страница создается в подготовленном отчете.
#Далее начинается печать строк бэнда <code>Данные</code>. Происходит это следующим образом:
#::4.1 вызывается событие бэнда <code>BeforePrint</code>;
#::4.2 вызываются события <code>BeforePrint</code> всех объектов, лежащих на бэнде;
#::4.3 все объекты заполняются данными;
#::4.4 вызываются события <code>AfterData</code> всех объектов, лежащих на бэнде;
#::4.5 вызывается событие бэнда <code>BeforeLayout</code>;
#::4.6 происходит размещение объектов на бэнде (если среди них есть растягиваемые объекты) и подсчет высоты бэнда и его растягивание (если бэнд растягиваемый);
#::4.7 вызывается событие бэнда <code>AfterLayout</code>;
#::4.8 если бэнд не помещается на свободном месте страницы, формируется новая страница;
#::4.9 бэнд и все его объекты выводятся на страницу готового отчета;
#::4.10 вызывается событие <code>AfterPrint</code> бэнда;
#::4.11 вызывается событие <code>AfterPrint</code> всех объектов бэнда.
#Печать строк бэнда происходит до тех пор, пока есть данные в источнике.
#После этого формирование отчета в нашем случае завершается и вызываются события <code>FinishPage</code> страницы отчета...
#...и наконец – событие <code>FinishReport</code> объекта <code>Отчет</code>.
 
===Выводы===
*используя события разных объектов, можно контролировать практически каждый момент формирования отчета;
*большинство действий можно выполнить, используя только событие бэнда <code>BeforePrint</code> – любые изменения, внесенные в объект, будут тут же отображены;
*в событии <code>BeforePrint</code> невозможно анализировать, на какой странице будет напечатан бэнд, если он растягиваемый – ведь подсчет высоты бэнда будет выполнен в пункте <code>4.6</code>;
*определить номер страницы для растягиваемого бэнда можно с помощью следующих событий
::*<code>AfterLayout</code> в пункте <code>4.7</code>;
::*<code>AfterPrint</code> в пункте <code>4.10</code> (правда, в этом случае бэнд уже будет напечатан и действия над объектами ничего не дадут).


===Выходные данные===
==Обращение к объектам .NET==
* <code>String</code> - строковое представление данных, если поле содержит значимую информацию;
===Сборки по умолчанию===
* <code>-</code> (''дефис'') - если входной параметр:
Из вкладки кода можно обращаться к любым объектам <code>.NET</code>, которые определены в сборках, подключаемых к новому отчету по умолчанию.  
**равен <code>Nothing</code> (не инициализирован);
**равен <code>DBNull.Value</code> (пустое значение из базы данных);
**является пустой строкой <code>""</code>;
**содержит только пробелы (метод <code>.Trim()</code>).


==GetOr()==
На момент создания описания к ним относятся:


<syntaxhighlight lang="vb">
<syntaxhighlight lang="C#">
Public Function GetOr(field As Object,
System.dll
Optional swap As String = "",
System.Xml.dll
Optional pref As String = "",
System.Data.dll
Optional suf As String = "") As String
System.Drawing.dll
   
System.Drawing.Primitives
If field Is Nothing OrElse IsDBNull(field) OrElse String.IsNullOrWhiteSpace(field.ToString()) Then
FastReport.Compat.dll
Return swap
FastReport.Forms.WPF.dll
End If
FastReport.DataVisualization.dll
   
Chemsoft.Triteia.ReportClasses.dll
Return pref & field.ToString().Trim() & suf
Chemsoft.Triteia.ReportFunctions.Cells.dll
End Function
Chemsoft.Triteia.ReportFunctions.Signatures.dll
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
Перечень доступных по умолчанию при создании нового отчета сборок может изменяться (чаще - при добавлении нового функционала).
*<code></code> ('''') -


===Выходные данные===
===Добавление сборки===
*
Если нужен доступ к другой сборке:
*перейти в свойства отчета <code>Отчет|Свойства…</code>;
*напротив свойства <code>Скрипт|ReferencedAssemblies|String[] Array</code> нажать на кнопку <code>...</code><br><br>
[[Файл: script_prop_1.png | center | border]]


===Алгоритм===
*в открывшемся окне <code>Редактор коллекции строк</code> перейти в конец списка и добавить (с клавиатуры или <code>Вставить</code>) название новой сборки в список сборок отчета:<br><br>
*
[[Файл: net_obj_1.png | center | border]]


==ConcatFields()==
===Использование сборки===
После добавления в список сборок отчета ссылки на сборку приложения (<code>.exe</code> или <code>.dll</code>) можно обращаться к функции, используя пространство имени (<code>namespace</code>) вашего приложения.


Функция <code>ConcatFields()</code> - предназначена для объединения нескольких текстовых значений в одну строку с использованием заданного разделителя.
===Пример===
Если в приложении определена следующая функция:


<syntaxhighlight lang="vb">
<syntaxhighlight lang="C#">
Public Function ConcatFields(separator As String, ParamArray fields() As Object) As String
namespace Demo
If fields Is Nothing Then Return "-"
{
   
  public static class MyFunctions
Dim list As New System.Collections.Generic.List(Of String)
  {
      
     public static string Func1()
For Each f As Object In fields
     {
If f Is Nothing Then Continue For
      return "Hello!";
Dim elem As String = f.ToString().Trim()
    }
If String.IsNullOrEmpty(elem) Then Continue For
  }
list.Add(elem)
}
Next
      
If list.Count = 0 Then
Return "-"
Else
Return String.Join(separator, list.ToArray())
End If
End Function
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
Обратиться к ней в скрипте можно так:
*<code>separator</code> (''String'') - символ или текст, который будет стоять между элементами (например - запятая, или пробел, или перенос на следующую строку);
 
*<code>ParamArray fields()</code> (''Object'') - список аргументов любого количества, перечисляется через запятую (также можно передать массив).
<syntaxhighlight lang="C#">
string hello = Demo.MyFunctions.Func1();
</syntaxhighlight>


===Выходные данные===
Если добавить в скрипт директиву <code>using Demo</code>, это позволит укоротить форму обращения к функции:
*<code>String</code> - одна строка из объединенных элементов.
*<code>-</code> (''дефис'') - если данных нет.


===Алгоритм===
<syntaxhighlight lang="C#">
*<code>If fields Is Nothing Then Return "-"</code> - если массив аргументов вообще не передан, функция сразу возвращает дефис;
string hello = MyFunctions.Func1();
*<code>Dim list As New System.Collections.Generic.List(Of String)</code> - создается временный список для хранения "чистых" строковых элементов;
</syntaxhighlight>
*<code>For Each f As Object In fields</code> - цикл по каждому полученному на входе значению;
*<code>If f Is Nothing Then Continue For</code> - если текущий элемент пуст (null), он пропускается;
*<code>Dim elem As String = f.ToString().Trim()</code> - значение переводится в строковый элемент и очищается от лишних пробелов по краям;
*<code>If String.IsNullOrEmpty(elem) Then Continue For</code> - если после удаления пробелов строковый элемент оказался пустым, он пропускается;
*<code>list.Add(elem)</code> - корректный строковый элемент добавляется в итоговый список;
*<code>If list.Count = 0 Then Return "-"</code> - если после проверки всех элементов список пуст (все было null или пробелы), возвращается дефис;
*<code>Return String.Join(separator, list.ToArray())</code> - все накопленные в списке элементы склеиваются в одну строку через указанный разделитель.


==GetExperience()==
==Обращение к объектам отчета==


Функция <code>GetExperience()</code> рассчитывает и форматирует строку о стаже работы сотрудника на основе даты получения диплома.  
Для обращения к объектам отчета (например, объекту <code>Текст</code>) используется имя объекта.  


Она выводит количество лет с правильным суффиксом (через вспомогательную функцию <code>YearsWithSuffix</code>) и указывает временной интервал от даты диплома до сегодняшнего дня.
===Пример===
Следующий пример вернет высоту объекта <code>Text1</code>:


<syntaxhighlight lang="vb">
<syntaxhighlight lang="C#">
Public Function GetExperience(diplomDate As Object) As String
float height = Text1.Height;
If IsDBNull(diplomDate) OrElse diplomDate Is Nothing Then
Return "-"
End If
   
Return YearsWithSuffix(diplomDate) & vbLF & Format(diplomDate, "dd.MM.yyyy") & " - по текущую дату"
End Function
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
<div style="background-color: #e7f3ff; border-left: 5px solid #2196f3; padding: 15px; margin: 10px 0;">
*<code>diplomDate</code> (''Object'') - дата выдачи диплома.
'''Примечание'''
 
"Родными" единицами измерения отчета являются экранные пиксели - это необходимо помнить при обращении к таким свойствам объектов, как <code>Left</code>, <code>Top</code>, <code>Width</code>, <code>Height</code>.  


===Выходные данные===
Для перевода пикселей в сантиметры и обратно используются константы, определенные в классе <code>Units</code>:
*<code>String</code>  
 
**<code>-</code> - если дата не указана;
<syntaxhighlight lang="C#">
**многострочный текст, если дата есть; например:
float heightInPixels = Text1.Height;
<syntaxhighlight>
float heightInCM = heightInPixels / Units.Centimeters;
5 лет
Text1.Height = Units.Centimeters * 5; // 5см
15.05.2018 - по текущую дату
</syntaxhighlight>
</syntaxhighlight>
</div>


===Алгоритм===
==[[Объекты Report и Engine]]==
*проверка на пустоту - является ли входное значение пустым (<code>IsDBNull</code>) или отсутствующим (<code>Nothing</code>); если данных нет, возвращается прочерк;
*расчет лет - вызывается внешняя функция <code>YearsWithSuffix(diplomDate)</code>, которая вычисляет разницу между текущей датой и датой диплома, добавив правильное окончание (<code>год</code> / <code>года</code> / <code>лет</code>);
*форматирование даты - исходная дата преобразуется в стандартный формат <code>дд.мм.гггг.</code>;
*сборка результата - все части склеиваются в одну строку, символ <code>vbLF</code> переносит информацию о датах на новую строку.


==YearsWithSuffix()==
:[[Объекты Report и Engine#Report|Report]]


Функция <code>YearsWithSuffix()</code> - предназначена для формирования строки, содержащей количество лет и правильное грамматическое окончание существительного «год» (год, года, лет) на основе разницы между переданной датой и текущим моментом.
:*[[Объекты Report и Engine#Список методов|Список методов]]


<syntaxhighlight lang="vb">
:[[Объекты Report и Engine#Engine|Engine]]
Public Function YearsWithSuffix(inputDate As Date) As String
 
Dim yearsDiff As Long = DateDiff(DateInterval.Year, inputDate, Now())
:*[[Объекты Report и Engine#Свойства объекта|Свойства объекта]]
Dim resultDate As Long = yearsDiff
:*[[Объекты Report и Engine#Формирование страниц готового отчета|Формирование страниц готового отчета]]
Dim resultString As String = yearsDiff.ToString()
:*[[Объекты Report и Engine#Список методов|Список методов]]
:*[[Объекты Report и Engine#Применение методов|Применение методов]]
If (resultDate > 20) Then
 
resultDate = resultDate Mod 10
==Обращение к источнику данных==
End If
 
Для обращения к самому источнику данных используйте метод <code>GetDataSource</code> объекта <code>Report</code>:
Select Case resultDate
 
Case 1
<syntaxhighlight lang="C#">
resultString &= $" год"
DataSourceBase ds = Report.GetDataSource("Products");
Case 2 To 4
resultString &= $" года"
Case Else
resultString &= $" лет"
End Select
Return resultString
End Function
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
Как правило, класс <code>DataSourceBase</code> используется в скрипте следующим образом:
*<code>inputDate</code> (''Date'') - дата, от которой ведется отсчет.


===Выходные данные===
<syntaxhighlight lang="C#">
*<code>String</code> - разница лет до текущего момента с текстом-суффиксом "21 год", "25 лет", "34 года".
// получаем ссылку на источник данных
DataSourceBase ds = Report.GetDataSource("Products");
// инициализируем его
ds.Init();
// перебираем все записи в источнике
while (ds.HasMoreRows)
{
  // получаем значение поля для текущей записи источника
  string productName = (string)Report.GetColumnValue("Products.Name");
  // выполняем с ним какие-то действия...
  // ...
  // переходим на следующую запись
  ds.Next();
}
</syntaxhighlight>


===Алгоритм===
==Обращение к данным отчета==
*вычисляется полное количество лет между <code>inputDate</code> и текущей датой <code>Now()</code> с помощью функции <code>DateDiff</code>;
*<code>resultDate</code> -  техническая переменная для определения логики окончания;
*<code>resultString</code> - строковое представление числа лет;
*обработка исключений (20+ лет) - если число больше 20, применяется операция <code>Mod 10</code> (остаток от деления на 10), чтобы привести числа вроде 21, 22, 25 к виду 1, 2, 5 для подбора окончания;
*<code>Select Case</code> - блок выбора окончания;
*<code>Case 1</code> - если число (или его остаток) равно 1, добавляется слово <code> год</code>;
*<code>Case 2 To 4</code> - если число (или его остаток) в диапазоне от 2 до 4 включительно, добавляется слово <code> года</code>;
*<code>Case Else</code> - в остальных случаях (для 0, 5–19 и специфических остатков) добавляется слово <code> лет</code>;
*возврат итоговой склеенной строки.


==GetNorms()==
*во вкладке кода '''''нельзя использовать квадратные скобки''''' (в отличие от выражений) для обращения к данным отчета - вместо этого используется метод <code>GetColumnValue</code> объекта <code>Report</code>, возвращающий значение поля:


<syntaxhighlight lang="vb">
<syntaxhighlight lang="C#">
Public Function GetNorms(lowLimit As Double, upLimit As Double) As String
string productName = (string)Report.GetColumnValue("Products.Name");
If upLimit <> 0 Then
Return "не менее " & lowLimit & vbLF & "не более " & upLimit
End If
If lowLimit <> 0 Then
Return "не менее " & lowLimit
End If
   
Return ""
End Function
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
*имя источника данных и его поля указываются через точку; имя источника может быть составным в случае, если мы обращаемся к источнику данных, используя связь источников данных:
*<code></code> ('''') -


===Выходные данные===
<syntaxhighlight lang="C#">
*
string categoryName = (string)Report.GetColumnValue("Products.Categories.CategoryName");
</syntaxhighlight>


===Алгоритм===
<div style="background-color: #e7f3ff; border-left: 5px solid #2196f3; padding: 15px; margin: 10px 0;">
*
'''Примечание'''


==NormProcessing()==
Для облегчения работы можно использовать окно <code>Данные</code> - из него можно перетаскивать элементы данных в скрипт, при этом дизайнер автоматически создает код для обращения к элементу.
<syntaxhighlight lang="vb">
</div>
Function NormProcessing(ByVal min  As String, ByVal max As String) As String
 
Dim result As String = ""
==Обращение к системным переменным==
 
Dim hasMin As Boolean = Not String.IsNullOrEmpty(min) AndAlso min <> "0"
Для обращения к системной переменной используйте метод <code>GetVariableValue</code> объекта <code>Report</code>:
Dim hasMax As Boolean = Not String.IsNullOrEmpty(max) AndAlso max <> "0"
 
<syntaxhighlight lang="C#">
If hasMin And hasMax Then
DateTime date = (DateTime)Report.GetVariableValue("Date");
result = min & "-" + max
Else If hasMin Then
result = "≥" & min
Else If hasMax Then
result = "≤" & max
Else
result = "-"
End If
Return result
End Function
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
Список системных переменных можно увидеть в окне <code>Данные</code> - из него можно перетаскивать переменные в скрипт, при этом дизайнер автоматически создает код для обращения к переменной.
*<code></code> ('''') -
 
==Обращение к итоговым значениям==
 
Для обращения к итоговому значению используйте метод <code>GetTotalValue</code> объекта <code>Report</code>:
 
<syntaxhighlight lang="C#">
float sales = Report.GetTotalValue("TotalSales");
</syntaxhighlight>


===Выходные данные===
Список итогов можно увидеть в окне <code>Данные</code> - из него можно перетаскивать итоги в скрипт, при этом дизайнер автоматически создает код для обращения к итогу.
*


===Алгоритм===
Итоговое значение имеет тип <code>FastReport.Variant</code>. Оно может быть напрямую использовано в любых выражениях, потому что тип <code>FastReport.Variant</code> автоматически приводится к любому типу. Например:
*


==RemoveTagsSimple()==
<syntaxhighlight lang="C#">
<syntaxhighlight lang="vb">
float tax = Report.GetTotalValue("TotalSales") * 0.2f;
Function RemoveTagsSimple(ByVal input As String) As String
Dim tags() As String = {"<span>", "</span>", "<sub>", "</sub>", "<sup>", "</sup>"}
Dim txt As String = input
   
For Each tag As String In tags
txt = Replace(txt, tag, "", , , CompareMethod.Text)
Next
   
Return txt
End Function
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
Обращаться к итоговому значению можно в тот момент, когда оно вычислено. Обычно итог "готов к употреблению" в момент печати бэнда, на котором он располагается в отчете.
*<code></code> ('''') -


===Выходные данные===
==Обращение к параметрам отчета==
*


===Алгоритм===
Для обращения к параметру отчета используйте его имя:
*


==FormatFio()==
<syntaxhighlight lang="C#">
[Parameter1]
</syntaxhighlight>


<syntaxhighlight lang="vb">
Параметры могут быть вложенными. В этом случае указывается имя родительского параметра и через точку имя дочернего параметра:
Function FormatFio(surname As String, name As String, patronymic As String, mode As Integer) As String
Dim f = Trim(surname)
Dim i = Trim(name)
Dim o = Trim(patronymic)
   
Dim i_init = ""
Dim o_init = ""
If Len(i) > 0 Then i_init = Left(i, 1) & "."
If Len(o) > 0 Then o_init = Left(o, 1) & "."
Dim result = ""
Select Case mode
Case 0 ' Фамилия Имя Отчество
result = Trim(f & " " & i & " " & o)
Case 1 ' Фамилия И.О.
result = Trim(f & " " & i_init & o_init)
Case 2 ' И.О. Фамилия
result = Trim(i_init & o_init & " " & f)
End Select


Return GetOrDash(result)
<syntaxhighlight lang="C#">
End Function
[ParentParameter.ChildParameter]
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
Параметры, как и поля данных, и системные переменные, имеют определенный тип данных. Он задается в свойстве <code>DataType</code> параметра.
*<code></code> ('''') -


===Выходные данные===
От того, какой тип данных имеет параметр, зависит, как его можно использовать в выражении.
*


===Алгоритм===
Дизайнер преобразует обращение к параметру отчета в следующий вид (на примере строкового параметра):
*
 
<syntaxhighlight lang="C#">
((string)Report.GetParameterValue("Parameter1"))
</syntaxhighlight>

Текущая версия от 04:20, 20 октября 2026

Вкладка Код – содержит программу на языке высокого уровня, которая является частью отчета.

Программа может быть написана на одном из языков .NET:

  • C# (предпочтительно);
  • VisualBasic.NET (нежелательно).

Область применения вкладки Код довольно обширна - она позволяет:

  • выполнить обработку данных, которую невозможно сделать штатными средствами ядра дизайнера;
  • управлять печатью страниц отчета и бэндов на странице;
  • управлять взаимодействием элементов управления на диалоговых формах;
  • управлять формированием динамических объектов Таблица;
  • и многое другое.

Чтобы увидеть код отчета, переключитесь на закладку Код в дизайнере:

Язык для вкладки Код настраивается в меню Отчет|Свойства....

Делать это желательно сразу после создания нового отчета, так как при смене языка существующий код очищается.

Общая информация

Вкладка Код в дизайнере содержит только то, что написано вами.

Во вкладке можно

  • добавить в главный класс кода свои переменные, методы, свойства;
  • создать обработчики событий объектов отчета;
  • добавлять новые классы, если это необходимо (класс может быть добавлен как перед главным классом ReportScript, так и после него.

Во вкладке нельзя

  • удалять, переименовывать или изменять область видимости главного класса ReportScript;
  • переименовывать пространство имен, в котором находится главный класс.

Порядок действий дизайнера при запуске отчета

  • дизайнер добавляет в код список переменных, имена которых совпадают с именами объектов отчета; это делается перед компиляцией кода и позволяет обращаться к объектам отчета по их имени;
  • в код добавляются выражения, имеющиеся в отчете, в виде функций;
  • выполняется компиляция кода, если главный класс не пустой;
  • инициализируются переменные, которые были неявно добавлены в код;
  • обработчики событий, определенные в коде, привязываются к объектам отчета;
  • запускается отчет.

Обработчики событий

Создание обработчика события

  • выделить нужный объект;
  • в окне Свойства нажать кнопку , чтобы переключиться на список событий:
  • выбрать интересующее событие и сделать на нем двойной щелчок мышью - дизайнер добавит в код отчета пустой обработчик события:
private void Text2_BeforePrint(object sender, EventArgs e)
{

}

Удаление обработчика события

  • выбрать событие в окне Свойства;
  • выделить текст имени события и нажамть клавишу Delete:

События

Каждый объект отчета имеет несколько событий, которым можно назначить обработчик – метод из вкладки кода.

Чтобы максимально гибко управлять отчетом, нужно:

  • четко представлять, в какой момент времени вызывается каждое из событий;
  • использовать те события, которые соответствуют поставленной задаче.

Пример

Рассмотрим процесс формирования отчета и события, которые при этом генерируются.

В качестве примера возьмем простой отчет, содержащий одну страницу, один бэнд Данные и два объекта Текст на бэнде:

Порядок событий

  1. В начале отчета вызывается событие StartReport объекта Отчет.
  2. Перед формированием страницы вызывается событие страницы StartPage. Это событие вызывается один раз для каждой страницы шаблона отчета (не путать со страницами готового отчета!). В нашем случае, сколько бы ни было страниц в готовом отчете – событие вызовется один раз, т.к. шаблон отчета состоит из одной страницы.
  3. Затем вызывается событие CreatePage, которое происходит как раз в тот момент, когда страница создается в подготовленном отчете.
  4. Далее начинается печать строк бэнда Данные. Происходит это следующим образом:
    4.1 вызывается событие бэнда BeforePrint;
    4.2 вызываются события BeforePrint всех объектов, лежащих на бэнде;
    4.3 все объекты заполняются данными;
    4.4 вызываются события AfterData всех объектов, лежащих на бэнде;
    4.5 вызывается событие бэнда BeforeLayout;
    4.6 происходит размещение объектов на бэнде (если среди них есть растягиваемые объекты) и подсчет высоты бэнда и его растягивание (если бэнд растягиваемый);
    4.7 вызывается событие бэнда AfterLayout;
    4.8 если бэнд не помещается на свободном месте страницы, формируется новая страница;
    4.9 бэнд и все его объекты выводятся на страницу готового отчета;
    4.10 вызывается событие AfterPrint бэнда;
    4.11 вызывается событие AfterPrint всех объектов бэнда.
  5. Печать строк бэнда происходит до тех пор, пока есть данные в источнике.
  6. После этого формирование отчета в нашем случае завершается и вызываются события FinishPage страницы отчета...
  7. ...и наконец – событие FinishReport объекта Отчет.

Выводы

  • используя события разных объектов, можно контролировать практически каждый момент формирования отчета;
  • большинство действий можно выполнить, используя только событие бэнда BeforePrint – любые изменения, внесенные в объект, будут тут же отображены;
  • в событии BeforePrint невозможно анализировать, на какой странице будет напечатан бэнд, если он растягиваемый – ведь подсчет высоты бэнда будет выполнен в пункте 4.6;
  • определить номер страницы для растягиваемого бэнда можно с помощью следующих событий
  • AfterLayout в пункте 4.7;
  • AfterPrint в пункте 4.10 (правда, в этом случае бэнд уже будет напечатан и действия над объектами ничего не дадут).

Обращение к объектам .NET

Сборки по умолчанию

Из вкладки кода можно обращаться к любым объектам .NET, которые определены в сборках, подключаемых к новому отчету по умолчанию.

На момент создания описания к ним относятся:

System.dll
System.Xml.dll
System.Data.dll
System.Drawing.dll
System.Drawing.Primitives
FastReport.Compat.dll
FastReport.Forms.WPF.dll
FastReport.DataVisualization.dll
Chemsoft.Triteia.ReportClasses.dll
Chemsoft.Triteia.ReportFunctions.Cells.dll
Chemsoft.Triteia.ReportFunctions.Signatures.dll

Перечень доступных по умолчанию при создании нового отчета сборок может изменяться (чаще - при добавлении нового функционала).

Добавление сборки

Если нужен доступ к другой сборке:

  • перейти в свойства отчета Отчет|Свойства…;
  • напротив свойства Скрипт|ReferencedAssemblies|String[] Array нажать на кнопку ...

  • в открывшемся окне Редактор коллекции строк перейти в конец списка и добавить (с клавиатуры или Вставить) название новой сборки в список сборок отчета:

Использование сборки

После добавления в список сборок отчета ссылки на сборку приложения (.exe или .dll) можно обращаться к функции, используя пространство имени (namespace) вашего приложения.

Пример

Если в приложении определена следующая функция:

namespace Demo
{
  public static class MyFunctions
  {
    public static string Func1()
    {
      return "Hello!";
    }
  }
}

Обратиться к ней в скрипте можно так:

string hello = Demo.MyFunctions.Func1();

Если добавить в скрипт директиву using Demo, это позволит укоротить форму обращения к функции:

string hello = MyFunctions.Func1();

Обращение к объектам отчета

Для обращения к объектам отчета (например, объекту Текст) используется имя объекта.

Пример

Следующий пример вернет высоту объекта Text1:

float height = Text1.Height;

Примечание

"Родными" единицами измерения отчета являются экранные пиксели - это необходимо помнить при обращении к таким свойствам объектов, как Left, Top, Width, Height.

Для перевода пикселей в сантиметры и обратно используются константы, определенные в классе Units:

float heightInPixels = Text1.Height;
float heightInCM = heightInPixels / Units.Centimeters;
Text1.Height = Units.Centimeters * 5; // 5см
Report
Engine

Обращение к источнику данных

Для обращения к самому источнику данных используйте метод GetDataSource объекта Report:

DataSourceBase ds = Report.GetDataSource("Products");

Как правило, класс DataSourceBase используется в скрипте следующим образом:

// получаем ссылку на источник данных
DataSourceBase ds = Report.GetDataSource("Products");
// инициализируем его
ds.Init();
// перебираем все записи в источнике
while (ds.HasMoreRows)
{
  // получаем значение поля для текущей записи источника
  string productName = (string)Report.GetColumnValue("Products.Name");
  // выполняем с ним какие-то действия...
  // ...
  // переходим на следующую запись
  ds.Next();
}

Обращение к данным отчета

  • во вкладке кода нельзя использовать квадратные скобки (в отличие от выражений) для обращения к данным отчета - вместо этого используется метод GetColumnValue объекта Report, возвращающий значение поля:
string productName = (string)Report.GetColumnValue("Products.Name");
  • имя источника данных и его поля указываются через точку; имя источника может быть составным в случае, если мы обращаемся к источнику данных, используя связь источников данных:
string categoryName = (string)Report.GetColumnValue("Products.Categories.CategoryName");

Примечание

Для облегчения работы можно использовать окно Данные - из него можно перетаскивать элементы данных в скрипт, при этом дизайнер автоматически создает код для обращения к элементу.

Обращение к системным переменным

Для обращения к системной переменной используйте метод GetVariableValue объекта Report:

DateTime date = (DateTime)Report.GetVariableValue("Date");

Список системных переменных можно увидеть в окне Данные - из него можно перетаскивать переменные в скрипт, при этом дизайнер автоматически создает код для обращения к переменной.

Обращение к итоговым значениям

Для обращения к итоговому значению используйте метод GetTotalValue объекта Report:

float sales = Report.GetTotalValue("TotalSales");

Список итогов можно увидеть в окне Данные - из него можно перетаскивать итоги в скрипт, при этом дизайнер автоматически создает код для обращения к итогу.

Итоговое значение имеет тип FastReport.Variant. Оно может быть напрямую использовано в любых выражениях, потому что тип FastReport.Variant автоматически приводится к любому типу. Например:

float tax = Report.GetTotalValue("TotalSales") * 0.2f;

Обращаться к итоговому значению можно в тот момент, когда оно вычислено. Обычно итог "готов к употреблению" в момент печати бэнда, на котором он располагается в отчете.

Обращение к параметрам отчета

Для обращения к параметру отчета используйте его имя:

[Parameter1]

Параметры могут быть вложенными. В этом случае указывается имя родительского параметра и через точку имя дочернего параметра:

[ParentParameter.ChildParameter]

Параметры, как и поля данных, и системные переменные, имеют определенный тип данных. Он задается в свойстве DataType параметра.

От того, какой тип данных имеет параметр, зависит, как его можно использовать в выражении.

Дизайнер преобразует обращение к параметру отчета в следующий вид (на примере строкового параметра):

((string)Report.GetParameterValue("Parameter1"))