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

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

Материал из Химсофт Вики
 
(не показано 67 промежуточных версий этого же участника)
Строка 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>String</code> - строковое представление данных, если поле содержит значимую информацию;
*четко представлять, в какой момент времени вызывается каждое из событий;
* <code>-</code> (''дефис'') - если входной параметр:
*использовать те события, которые соответствуют поставленной задаче.
**равен <code>Nothing</code> (не инициализирован);
**равен <code>DBNull.Value</code> (пустое значение из базы данных);
**является пустой строкой <code>""</code>;
**содержит только пробелы (метод <code>.Trim()</code>).


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


<syntaxhighlight lang="vb">
В качестве примера возьмем простой отчет, содержащий одну страницу, один бэнд <code>Данные</code> и два объекта <code>Текст</code> на бэнде:
Public Function GetOr(field As Object,
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>


===Входные параметры===
[[Файл: events_1.png|center|border]]
*<code>field</code> (''Object'') - проверяемое поле (может быть числом, строкой или объектом базы данных);
*<code>swap</code> (''String'', необязательно) - значение «подмены», которое вернется, если поле пустое; по умолчанию — пустая строка;
*<code>pref</code> (''String'', необязательно) - префикс, который добавится перед значением;
*<code>suf</code> (''String'', необязательно) - суффикс, который добавится после значения.


===Выходные данные===
===Порядок событий===
*<code>String</code> - отформатированная строка с префиксом и суффиксом, либо значение <code>swap</code>;  
#В начале отчета вызывается событие <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>field</code> на три условия: равен ли он <code>Nothing</code>, является ли он <code>DBNull</code> (пустота из базы данных) или состоит ли он только из пробелов;
*используя события разных объектов, можно контролировать практически каждый момент формирования отчета;
*обработка пустого значения - если хотя бы одно условие истинно, возвращается значение параметра <code>swap</code>;
*большинство действий можно выполнить, используя только событие бэнда <code>BeforePrint</code> – любые изменения, внесенные в объект, будут тут же отображены;
*форматирование - если поле содержит данные, функция обрезает лишние пробелы по краям (<code>Trim</code>), добавляет к нему заданные префикс (<code>pref</code>) и суффикс (<code>suf</code>) и возвращает результат.
*в событии <code>BeforePrint</code> невозможно анализировать, на какой странице будет напечатан бэнд, если он растягиваемый – ведь подсчет высоты бэнда будет выполнен в пункте <code>4.6</code>;  
*определить номер страницы для растягиваемого бэнда можно с помощью следующих событий
::*<code>AfterLayout</code> в пункте <code>4.7</code>;
::*<code>AfterPrint</code> в пункте <code>4.10</code> (правда, в этом случае бэнд уже будет напечатан и действия над объектами ничего не дадут).


==ConcatFields()==
==Обращение к объектам .NET==
===Сборки по умолчанию===
Из вкладки кода можно обращаться к любым объектам <code>.NET</code>, которые определены в сборках, подключаемых к новому отчету по умолчанию.


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


<syntaxhighlight lang="vb">
<syntaxhighlight lang="C#">
Public Function ConcatFields(separator As String, ParamArray fields() As Object) As String
System.dll
If fields Is Nothing Then Return "-"
System.Xml.dll
   
System.Data.dll
Dim list As New System.Collections.Generic.List(Of String)
System.Drawing.dll
   
System.Drawing.Primitives
For Each f As Object In fields
FastReport.Compat.dll
If f Is Nothing Then Continue For
FastReport.Forms.WPF.dll
Dim elem As String = f.ToString().Trim()
FastReport.DataVisualization.dll
If String.IsNullOrEmpty(elem) Then Continue For
Chemsoft.Triteia.ReportClasses.dll
list.Add(elem)
Chemsoft.Triteia.ReportFunctions.Cells.dll
Next
Chemsoft.Triteia.ReportFunctions.Signatures.dll
   
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'') - список аргументов любого количества, перечисляется через запятую (также можно передать массив).
===Добавление сборки===
Если нужен доступ к другой сборке:
*перейти в свойства отчета <code>Отчет|Свойства…</code>;
*напротив свойства <code>Скрипт|ReferencedAssemblies|String[] Array</code> нажать на кнопку <code>...</code><br><br>
[[Файл: script_prop_1.png | center | border]]


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


===Алгоритм===
===Использование сборки===
*<code>If fields Is Nothing Then Return "-"</code> - если массив аргументов вообще не передан, функция сразу возвращает дефис;
После добавления в список сборок отчета ссылки на сборку приложения (<code>.exe</code> или <code>.dll</code>) можно обращаться к функции, используя пространство имени (<code>namespace</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> - все накопленные в списке элементы склеиваются в одну строку через указанный разделитель.


==GetExperience()==
===Пример===
Если в приложении определена следующая функция:


Функция <code>GetExperience()</code> рассчитывает и форматирует строку о стаже работы сотрудника на основе даты получения диплома.
<syntaxhighlight lang="C#">
namespace Demo
{
  public static class MyFunctions
  {
    public static string Func1()
    {
      return "Hello!";
    }
  }
}
</syntaxhighlight>


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


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


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


===Выходные данные===
<syntaxhighlight lang="C#">
*<code>String</code>
string hello = MyFunctions.Func1();
**<code>-</code> - если дата не указана;
**многострочный текст, если дата есть; например:
::{| style="border-collapse: collapse;"
|
<syntaxhighlight>
5 лет
15.05.2018 - по текущую дату
</syntaxhighlight>
</syntaxhighlight>
|}


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


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


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


<syntaxhighlight lang="vb">
<syntaxhighlight lang="C#">
Public Function YearsWithSuffix(inputDate As Date) As String
float height = Text1.Height;
Dim yearsDiff As Long = DateDiff(DateInterval.Year, inputDate, Now())
Dim resultDate As Long = yearsDiff
Dim resultString As String = yearsDiff.ToString()
If (resultDate > 20) Then
resultDate = resultDate Mod 10
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 style="background-color: #e7f3ff; border-left: 5px solid #2196f3; padding: 15px; margin: 10px 0;">
*<code>inputDate</code> (''Date'') - дата, от которой ведется отсчет.
'''Примечание'''  


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


===Алгоритм===
Для перевода пикселей в сантиметры и обратно используются константы, определенные в классе <code>Units</code>:
*вычисляется полное количество лет между <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()==
<syntaxhighlight lang="C#">
float heightInPixels = Text1.Height;
float heightInCM = heightInPixels / Units.Centimeters;
Text1.Height = Units.Centimeters * 5; // 5см
</syntaxhighlight>
</div>


<syntaxhighlight lang="vb">
==[[Объекты Report и Engine]]==
Public Function GetNorms(lowLimit As Double, upLimit As Double) As String
 
If upLimit <> 0 Then
:[[Объекты Report и Engine#Report|Report]]
Return "не менее " & lowLimit & vbLF & "не более " & upLimit
 
End If
:*[[Объекты Report и Engine#Список методов|Список методов]]
 
If lowLimit <> 0 Then
:[[Объекты Report и Engine#Engine|Engine]]
Return "не менее " & lowLimit
End If
   
Return ""
End Function
</syntaxhighlight>


===Входные параметры===
:*[[Объекты Report и Engine#Свойства объекта|Свойства объекта]]
*<code>lowLimit</code> (''Double'') - нижняя граница нормы;
:*[[Объекты Report и Engine#Формирование страниц готового отчета|Формирование страниц готового отчета]]
*<code>upLimit</code> (''Double'') - верхняя граница нормы.
:*[[Объекты Report и Engine#Список методов|Список методов]]
:*[[Объекты Report и Engine#Применение методов|Применение методов]]


===Выходные данные===
==Обращение к источнику данных==
*<code>String</code> текстовое описание диапазона; возвращает пустую строку, если оба параметра равны нулю.


===Алгоритм===
Для обращения к самому источнику данных используйте метод <code>GetDataSource</code> объекта <code>Report</code>:
*проверка верхней границы - если <code>upLimit</code> не равен <code>0</code>, функция возвращает строку с обоими пределами (<code>не менее X, не более Y</code>), разделяя их переносом строки (<code>vbLF</code>);
*проверка нижней границы - если верхний предел равен <code>0</code>, но <code>lowLimit</code> не равен <code>0</code>, возвращается только нижний порог (<code>не менее X</code>);
*значение по умолчанию - если оба параметра равны <code>0</code>, функция возвращает пустую строку.


==NormProcessing()==
<syntaxhighlight lang="C#">
<syntaxhighlight lang="vb">
DataSourceBase ds = Report.GetDataSource("Products");
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"
Dim hasMax As Boolean = Not String.IsNullOrEmpty(max) AndAlso max <> "0"
If hasMin And hasMax Then
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>DataSourceBase</code> используется в скрипте следующим образом:
*<code>min</code> (''String'') - строковое значение нижней границы;
 
*<code>max</code> (''String'') - строковое значение верхней границы.
<syntaxhighlight lang="C#">
// получаем ссылку на источник данных
DataSourceBase ds = Report.GetDataSource("Products");
// инициализируем его
ds.Init();
// перебираем все записи в источнике
while (ds.HasMoreRows)
{
  // получаем значение поля для текущей записи источника
  string productName = (string)Report.GetColumnValue("Products.Name");
  // выполняем с ним какие-то действия...
  // ...
  // переходим на следующую запись
  ds.Next();
}
</syntaxhighlight>


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


===Алгоритм===
*во вкладке кода '''''нельзя использовать квадратные скобки''''' (в отличие от выражений) для обращения к данным отчета - вместо этого используется метод <code>GetColumnValue</code> объекта <code>Report</code>, возвращающий значение поля:
*проверка наличия данных - определяются два флага (<code>hasMin</code> и <code>hasMax</code>); значение считается валидным, если оно не пустое и не равно строке <code>0</code>;
*выбор формата:
**если есть оба значения - возвращается диапазон через дефис (<code>min-max</code>);
**если есть только <code>min</code> - возвращается значение с символом «больше или равно» (<code>≥min</code>);
**если есть только max - возвращается значение с символом «меньше или равно» (<code>≤max</code>);
*значение по умолчанию - если оба входа пустые или равны <code>0</code>, возвращается дефис (<code>-</code>).


==RemoveTagsSimple()==
<syntaxhighlight lang="C#">
<syntaxhighlight lang="vb">
string productName = (string)Report.GetColumnValue("Products.Name");
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> ('''') -


===Выходные данные===
<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;">
*
'''Примечание'''


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


<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)
Для обращения к системной переменной используйте метод <code>GetVariableValue</code> объекта <code>Report</code>:
End Function
 
<syntaxhighlight lang="C#">
DateTime date = (DateTime)Report.GetVariableValue("Date");
</syntaxhighlight>
</syntaxhighlight>


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


===Выходные данные===
<syntaxhighlight lang="C#">
*
float sales = Report.GetTotalValue("TotalSales");
</syntaxhighlight>


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


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


<syntaxhighlight lang="vb">
<syntaxhighlight lang="C#">
Public Function AddIndents(ByVal text As String) As String
float tax = Report.GetTotalValue("TotalSales") * 0.2f;
    If String.IsNullOrEmpty(text) Then Return ""
    ' Заменяем стандартный перенос строки на перенос с пробелами
    Dim indentedText As String = text.Replace(vbCrLf, vbCrLf & "   ")
    ' Добавляем отступ для самой первой строки
    Return "    " & indentedText
End Function
</syntaxhighlight>
</syntaxhighlight>


==CollapseNumbers()==
Обращаться к итоговому значению можно в тот момент, когда оно вычислено. Обычно итог "готов к употреблению" в момент печати бэнда, на котором он располагается в отчете.
<syntaxhighlight lang="vb">
 
Public Function CollapseNumbers(inputNums As Object()) As String
==Обращение к параметрам отчета==
If inputNums Is Nothing OrElse inputNums.Length = 0 Then Return ""
 
Для обращения к параметру отчета используйте его имя:


Dim nums(inputNums.Length - 1) As Integer
<syntaxhighlight lang="C#">
For i As Integer = 0 To inputNums.Length - 1
[Parameter1]
nums(i) = CInt(inputNums(i))
</syntaxhighlight>
Next
Array.Sort(nums)
Dim result As String = ""
Dim index As Integer = 0
While index < nums.Length
Dim startNum As Integer = nums(index)
Dim endNum As Integer = startNum


While index + 1 < nums.Length AndAlso nums(index + 1) = nums(index) + 1
Параметры могут быть вложенными. В этом случае указывается имя родительского параметра и через точку имя дочернего параметра:
index += 1
endNum = nums(index)
End While


Dim currentStr As String = ""
<syntaxhighlight lang="C#">
[ParentParameter.ChildParameter]
</syntaxhighlight>


If endNum - startNum = 0 Then
Параметры, как и поля данных, и системные переменные, имеют определенный тип данных. Он задается в свойстве <code>DataType</code> параметра.  
currentStr = startNum.ToString()
ElseIf endNum - startNum = 1 Then
currentStr = startNum.ToString() & ", " & endNum.ToString()
Else
currentStr = startNum.ToString() & "-" & endNum.ToString()
End If


If result = "" Then
От того, какой тип данных имеет параметр, зависит, как его можно использовать в выражении.
result = currentStr
Else
result &= ", " & currentStr
End If


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


Return result
<syntaxhighlight lang="C#">
End Function
((string)Report.GetParameterValue("Parameter1"))
</syntaxhighlight>
</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"))