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

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

Материал из Химсофт Вики
Нет описания правки
 
(не показано 98 промежуточных версий этого же участника)
Строка 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>
 
===Удаление обработчика события===
*выбрать событие в окне <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>.NET</code>, которые определены в сборках, подключаемых к новому отчету по умолчанию.
 
На момент создания описания к ним относятся:
 
<syntaxhighlight lang="C#">
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
</syntaxhighlight>
 
Перечень доступных по умолчанию при создании нового отчета сборок может изменяться (чаще - при добавлении нового функционала).
 
===Добавление сборки===
Если нужен доступ к другой сборке:
*перейти в свойства отчета <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]]
 
===Использование сборки===
После добавления в список сборок отчета ссылки на сборку приложения (<code>.exe</code> или <code>.dll</code>) можно обращаться к функции, используя пространство имени (<code>namespace</code>) вашего приложения.
 
===Пример===
Если в приложении определена следующая функция:
 
<syntaxhighlight lang="C#">
namespace Demo
{
  public static class MyFunctions
  {
     public static string Func1()
    {
      return "Hello!";
    }
  }
}
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
Обратиться к ней в скрипте можно так:
*<code>field</code> (''Object'') - данные из поля набора данных (принимает любой тип данных, так как параметр объявлен как <code>Object</code>).


===Выходные данные===
<syntaxhighlight lang="C#">
* <code>String</code> - строковое представление данных, если поле содержит значимую информацию;
string hello = Demo.MyFunctions.Func1();
* <code>-</code> (''дефис'') - если входной параметр:
</syntaxhighlight>
**равен <code>Nothing</code> (не инициализирован);
**равен <code>DBNull.Value</code> (пустое значение из базы данных);
**является пустой строкой <code>""</code>;
**содержит только пробелы (метод <code>.Trim()</code>).


==GetOr()==
Если добавить в скрипт директиву <code>using Demo</code>, это позволит укоротить форму обращения к функции:


<syntaxhighlight lang="vb">
<syntaxhighlight lang="C#">
Public Function GetOr(field As Object,
string hello = MyFunctions.Func1();
Optional swap As String = "",
Optional pref As String = "",
Optional suf As String = "") As String
   
If field Is Nothing OrElse IsDBNull(field) OrElse String.IsNullOrWhiteSpace(field.ToString()) Then
Return swap
End If
   
Return pref & field.ToString().Trim() & suf
End Function
</syntaxhighlight>
</syntaxhighlight>


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


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


<syntaxhighlight lang="vb">
===Пример===
Public Function ConcatFields(separator As String, ParamArray fields() As Object) As String
Следующий пример вернет высоту объекта <code>Text1</code>:
If fields Is Nothing Then Return "-"
 
   
<syntaxhighlight lang="C#">
Dim list As New System.Collections.Generic.List(Of String)
float height = Text1.Height;
   
For Each f As Object In fields
If f Is Nothing Then Continue For
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>


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


===Выходные данные===
"Родными" единицами измерения отчета являются экранные пиксели - это необходимо помнить при обращении к таким свойствам объектов, как <code>Left</code>, <code>Top</code>, <code>Width</code>, <code>Height</code>.  
*<code>String</code> - одна строка из объединенных элементов.
*<code>-</code> (''дефис'') - если данных нет.


===Алгоритм===
Для перевода пикселей в сантиметры и обратно используются константы, определенные в классе <code>Units</code>:
*<code>If fields Is Nothing Then Return "-"</code> - если массив аргументов вообще не передан, функция сразу возвращает дефис;
*<code>Dim list As New System.Collections.Generic.List(Of String)</code> - создается временный список для хранения "чистых" строковых элементов;
*<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> - все накопленные в списке элементы склеиваются в одну строку через указанный разделитель.


==YearsWithSuffix()==
<syntaxhighlight lang="C#">
float heightInPixels = Text1.Height;
float heightInCM = heightInPixels / Units.Centimeters;
Text1.Height = Units.Centimeters * 5; // 5см
</syntaxhighlight>
</div>


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


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


===Алгоритм===
<syntaxhighlight lang="C#">
*вычисляется полное количество лет между <code>inputDate</code> и текущей датой <code>Now()</code> с помощью функции <code>DateDiff</code>;
string productName = (string)Report.GetColumnValue("Products.Name");
*<code>resultDate</code> -  техническая переменная для определения логики окончания;
</syntaxhighlight>
*<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>;
*возврат итоговой склеенной строки.


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


Функция преобразует полное имя (например, "Иванов Иван Иванович") в формат «Инициалы Фамилия» (И.И. Иванов). Она корректно обрабатывает лишние пробелы и работает как с именами из двух слов, так и из трёх.
<syntaxhighlight lang="C#">
string categoryName = (string)Report.GetColumnValue("Products.Categories.CategoryName");
</syntaxhighlight>


<syntaxhighlight lang="vb">
<div style="background-color: #e7f3ff; border-left: 5px solid #2196f3; padding: 15px; margin: 10px 0;">
Public Function FormatAsInitialsSurname(fullName As String) As String
'''Примечание'''
Dim trimmedName As String = fullName.Trim()
Dim nameParts() As String = trimmedName.Split(New Char() {" "c}, StringSplitOptions.RemoveEmptyEntries)


If nameParts.Length < 2 Then
Для облегчения работы можно использовать окно <code>Данные</code> - из него можно перетаскивать элементы данных в скрипт, при этом дизайнер автоматически создает код для обращения к элементу.
Return fullName
</div>
End If


Dim surname As String = nameParts(0)
==Обращение к системным переменным==
Dim firstNameInitial As Char = nameParts(1)(0)
Dim middleNameInitial As Char? = Nothing
If nameParts.Length >= 3 Then
middleNameInitial = nameParts(2)(0)
End If


Dim result As String = $"{firstNameInitial}."
Для обращения к системной переменной используйте метод <code>GetVariableValue</code> объекта <code>Report</code>:
If middleNameInitial.HasValue Then
result &= $"{middleNameInitial}."
End If
result &= $" {surname}"


Return result
<syntaxhighlight lang="C#">
End Function
DateTime date = (DateTime)Report.GetVariableValue("Date");
</syntaxhighlight>
</syntaxhighlight>


===Входные параметры===
Список системных переменных можно увидеть в окне <code>Данные</code> - из него можно перетаскивать переменные в скрипт, при этом дизайнер автоматически создает код для обращения к переменной.
*<code>fullName</code> (''String'') - исходная строка, содержащая полные ФИО (ожидается формат «Фамилия Имя» или «Фамилия Имя Отчество»).
 
==Обращение к итоговым значениям==
 
Для обращения к итоговому значению используйте метод <code>GetTotalValue</code> объекта <code>Report</code>:


===Выходные данные===
<syntaxhighlight lang="C#">
*<code>String</code> - строка в формате И.О. Фамилия; если во входной строке меньше двух слов, функция вернет исходный текст без изменений.
float sales = Report.GetTotalValue("TotalSales");
</syntaxhighlight>


===Алгоритм===
Список итогов можно увидеть в окне <code>Данные</code> - из него можно перетаскивать итоги в скрипт, при этом дизайнер автоматически создает код для обращения к итогу.
*<code>trimmedName</code> - удаляет случайные пробелы в начале и конце строки;
 
*строка разбивается на массив <code>nameParts</code>; используется <code>RemoveEmptyEntries</code>, чтобы лишние пробелы между словами не создавали пустых элементов;
Итоговое значение имеет тип <code>FastReport.Variant</code>. Оно может быть напрямую использовано в любых выражениях, потому что тип <code>FastReport.Variant</code> автоматически приводится к любому типу. Например:
*если в массиве меньше 2 слов (нет либо фамилии, либо имени), функция сразу прекращает работу и возвращает входную строку;
 
*первое слово записывается как фамилия (<code>surname</code>);
<syntaxhighlight lang="C#">
*берется первый символ второго слова — инициал имени (<code>firstNameInitial</code>);
float tax = Report.GetTotalValue("TotalSales") * 0.2f;
*если есть третье слово, берется его первый символ — инициал отчества (<code>middleNameInitial</code>);
</syntaxhighlight>
*записывается инициал имени с точкой;
 
*если отчество существует, к строке добавляется его инициал с точкой;
Обращаться к итоговому значению можно в тот момент, когда оно вычислено. Обычно итог "готов к употреблению" в момент печати бэнда, на котором он располагается в отчете.
*в конце через пробел добавляется фамилия;
 
*функция возвращает итоговую строку.
==Обращение к параметрам отчета==
 
Для обращения к параметру отчета используйте его имя:
 
<syntaxhighlight lang="C#">
[Parameter1]
</syntaxhighlight>
 
Параметры могут быть вложенными. В этом случае указывается имя родительского параметра и через точку имя дочернего параметра:
 
<syntaxhighlight lang="C#">
[ParentParameter.ChildParameter]
</syntaxhighlight>
 
Параметры, как и поля данных, и системные переменные, имеют определенный тип данных. Он задается в свойстве <code>DataType</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"))