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

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

Материал из Химсофт Вики
Нет описания правки
 
(не показаны 104 промежуточные версии этого же участника)
Строка 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]]


==ConcatFields()==
Язык для вкладки <code>Код</code> настраивается в меню <code>Отчет|Свойства...</code>.


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


<syntaxhighlight lang="vb">
[[Файл: code_obj_2.png | center | border]]
Public Function ConcatFields(separator As String, ParamArray fields() As Object) As String
 
If fields Is Nothing Then Return "-"
==Общая информация==
   
 
Dim list As New System.Collections.Generic.List(Of String)
Вкладка <code>Код</code> в дизайнере содержит только то, что написано вами.
   
 
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
*добавлять новые классы, если это необходимо (класс может быть добавлен как перед главным классом <code>ReportScript</code>, так и после него.
list.Add(elem)
 
Next
===Во вкладке нельзя===
      
*удалять, переименовывать или изменять область видимости главного класса <code>ReportScript</code>;
If list.Count = 0 Then
*переименовывать пространство имен, в котором находится главный класс.
Return "-"
 
Else
===Порядок действий дизайнера при запуске отчета===
Return String.Join(separator, list.ToArray())
*дизайнер добавляет в код список переменных, имена которых совпадают с именами объектов отчета; это делается перед компиляцией кода и позволяет обращаться к объектам отчета по их имени;
End If
*в код добавляются выражения, имеющиеся в отчете, в виде функций;
End Function
*выполняется компиляция кода, если главный класс не пустой;
*инициализируются переменные, которые были неявно добавлены в код;
*обработчики событий, определенные в коде, привязываются к объектам отчета;
*запускается отчет.
 
==Обработчики событий==
 
===Создание обработчика события===
*выделить нужный объект;
*в окне <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 lang="C#">
string hello = Demo.MyFunctions.Func1();
</syntaxhighlight>
 
Если добавить в скрипт директиву <code>using Demo</code>, это позволит укоротить форму обращения к функции:
 
<syntaxhighlight lang="C#">
string hello = MyFunctions.Func1();
</syntaxhighlight>
</syntaxhighlight>


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


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


===Алгоритм===
===Пример===
*<code>If fields Is Nothing Then Return "-"</code> - если массив аргументов вообще не передан, функция сразу возвращает дефис;
Следующий пример вернет высоту объекта <code>Text1</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 height = Text1.Height;
</syntaxhighlight>


Функция <code>YearsWithSuffix()</code> - предназначена для формирования строки, содержащей количество лет и правильное грамматическое окончание существительного «год» (год, года, лет) на основе разницы между переданной датой и текущим моментом.
<div style="background-color: #e7f3ff; border-left: 5px solid #2196f3; padding: 15px; margin: 10px 0;">
'''Примечание'''


<syntaxhighlight lang="vb">
"Родными" единицами измерения отчета являются экранные пиксели - это необходимо помнить при обращении к таким свойствам объектов, как <code>Left</code>, <code>Top</code>, <code>Width</code>, <code>Height</code>.  
Public Function YearsWithSuffix(inputDate As Date) As String
 
Dim yearsDiff As Long = DateDiff(DateInterval.Year, inputDate, Now())
Для перевода пикселей в сантиметры и обратно используются константы, определенные в классе <code>Units</code>:
Dim resultDate As Long = yearsDiff
 
Dim resultString As String = yearsDiff.ToString()
<syntaxhighlight lang="C#">
float heightInPixels = Text1.Height;
If (resultDate > 20) Then
float heightInCM = heightInPixels / Units.Centimeters;
resultDate = resultDate Mod 10
Text1.Height = Units.Centimeters * 5; // 5см
End If
Select Case resultDate
Case 1
resultString &= $" год"
Case 2 To 4
resultString &= $" года"
Case Else
resultString &= $" лет"
End Select
Return resultString
End Function
</syntaxhighlight>
</syntaxhighlight>
</div>
==[[Объекты Report и Engine]]==


===Входные параметры===
:[[Объекты Report и Engine#Report|Report]]
*<code>inputDate</code> (''Date'') - дата, от которой ведется отсчет.


===Выходные данные===
:*[[Объекты Report и Engine#Список методов|Список методов]]
*<code>String</code> - разница лет до текущего момента с текстом-суффиксом "21 год", "25 лет", "34 года".


===Алгоритм===
:[[Объекты Report и Engine#Engine|Engine]]
*вычисляется полное количество лет между <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>;
*возврат итоговой склеенной строки.


==FormatAsInitialsSurname()==
:*[[Объекты Report и Engine#Свойства объекта|Свойства объекта]]
:*[[Объекты Report и Engine#Формирование страниц готового отчета|Формирование страниц готового отчета]]
:*[[Объекты Report и Engine#Список методов|Список методов]]
:*[[Объекты Report и Engine#Применение методов|Применение методов]]


Функция преобразует полное имя (например, "Иванов Иван Иванович") в формат «Инициалы Фамилия» (И.И. Иванов). Она корректно обрабатывает лишние пробелы и работает как с именами из двух слов, так и из трёх.
==Обращение к источнику данных==


<syntaxhighlight lang="vb">
Для обращения к самому источнику данных используйте метод <code>GetDataSource</code> объекта <code>Report</code>:
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
<syntaxhighlight lang="C#">
Return fullName
DataSourceBase ds = Report.GetDataSource("Products");
End If
</syntaxhighlight>


Dim surname As String = nameParts(0)
Как правило, класс <code>DataSourceBase</code>  используется в скрипте следующим образом:
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}."
<syntaxhighlight lang="C#">
If middleNameInitial.HasValue Then
// получаем ссылку на источник данных
result &= $"{middleNameInitial}."
DataSourceBase ds = Report.GetDataSource("Products");
End If
// инициализируем его
result &= $" {surname}"
ds.Init();
// перебираем все записи в источнике
while (ds.HasMoreRows)
{
  // получаем значение поля для текущей записи источника
  string productName = (string)Report.GetColumnValue("Products.Name");
  // выполняем с ним какие-то действия...
  // ...
  // переходим на следующую запись
  ds.Next();
}
</syntaxhighlight>


Return result
==Обращение к данным отчета==
End Function
 
*во вкладке кода '''''нельзя использовать квадратные скобки''''' (в отличие от выражений) для обращения к данным отчета - вместо этого используется метод <code>GetColumnValue</code> объекта <code>Report</code>, возвращающий значение поля:
 
<syntaxhighlight lang="C#">
string productName = (string)Report.GetColumnValue("Products.Name");
</syntaxhighlight>
</syntaxhighlight>


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


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


===Алгоритм===
<div style="background-color: #e7f3ff; border-left: 5px solid #2196f3; padding: 15px; margin: 10px 0;">
*<code>trimmedName</code> - удаляет случайные пробелы в начале и конце строки;
'''Примечание'''
*строка разбивается на массив <code>nameParts</code>; используется <code>RemoveEmptyEntries</code>, чтобы лишние пробелы между словами не создавали пустых элементов;
 
*если в массиве меньше 2 слов (нет либо фамилии, либо имени), функция сразу прекращает работу и возвращает входную строку;
Для облегчения работы можно использовать окно <code>Данные</code> - из него можно перетаскивать элементы данных в скрипт, при этом дизайнер автоматически создает код для обращения к элементу.
*первое слово записывается как фамилия (<code>surname</code>);
</div>
*берется первый символ второго слова — инициал имени (<code>firstNameInitial</code>);
 
*если есть третье слово, берется его первый символ — инициал отчества (<code>middleNameInitial</code>);
==Обращение к системным переменным==
*записывается инициал имени с точкой;
 
*если отчество существует, к строке добавляется его инициал с точкой;
Для обращения к системной переменной используйте метод <code>GetVariableValue</code> объекта <code>Report</code>:
*в конце через пробел добавляется фамилия;
 
*функция возвращает итоговую строку.
<syntaxhighlight lang="C#">
DateTime date = (DateTime)Report.GetVariableValue("Date");
</syntaxhighlight>
 
Список системных переменных можно увидеть в окне <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> автоматически приводится к любому типу. Например:
 
<syntaxhighlight lang="C#">
float tax = Report.GetTotalValue("TotalSales") * 0.2f;
</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"))