Пользовательские функции
Внимание!
Это описание - для старой версии дизайнера документов (AR).
В ближайшее время страница будет обновлена на описание настройки в FastReports.
Общие сведения
Функции, вынесенные в глобальную видимость через объект Code, позволяют централизованно управлять логикой форматирования данных.
Это избавляет от необходимости дублировать код в каждом отдельном макете и обеспечивает единообразие расчетов во всех отчетах.
Rounding.RoundBase()
Предназначена для гибкого округления числовых значений.
В отличие от стандартных функций, она поддерживает работу с отрицательными разрядами и округление до значащих цифр.
Входные параметры
value(Double) - исходное число для обработки;digits(Object)- при
Mode = 1- количество знаков после запятой (положительное) или до запятой (отрицательное); - при
Mode = 0- количество значащих цифр;
- при
mode(Object) - режим работы:1(ToDecimalPlace) - десятичное округление;0(ToSignificantPlace) - значащие цифры.
Выходные параметры
String- возвращает строковое представление числа.
Алгоритм
Функция работает по методу Away From Zero (округление от нуля).
Режим 1 (десятичное округление):
- вычисляется множитель;
- число умножается на множитель, округляется до целого и делится обратно;
- при положительном n результат форматируется с фиксированным количеством нулей после запятой.
Режим 0 (значащие цифры):
- определяется порядок числа через десятичный логарифм;
- вычисляется масштабный коэффициент, чтобы оставить ровно
nцифр; - число масштабируется, округляется и возвращается в исходный порядок;
- результат преобразуется в компактную строку (удаляются лишние нули в конце).
Примеры использования внутри ячейки
| Исходное значение | Синтаксис в соответствии с формулой =Code.Rounding.RoundBase(x, n, m)
|
Результат |
|---|---|---|
| 12345 | =Code.Rounding.RoundBase(ReportItems!variable.Value, 2, 1)
|
12345,00 |
| 12345.00 | =Code.Rounding.RoundBase(ReportItems!variable.Value, 0, 1)
|
12345 |
| 12345.01 | =Code.Rounding.RoundBase(ReportItems!variable.Value, -2, 1)
|
12300 |
| 555.55 | =Code.Rounding.RoundBase(ReportItems!variable.Value, 1, 0)
|
600 |
Примеры использования во вкладке Scripts
Return New Triteia.Rounding().RoundBase(variable, 2, 1)
или
Dim rounder As New Triteia.Rounding()
Return rounder.RoundBase(variable, 2, 1)
Предварительный вариант на VB.NET
Public Function RoundBase(ByVal xValue As Double, ByVal nDigits As Integer, ByVal mMode As Integer) As String
If xValue = 0 Then Return "0"
'Проверка аргумента nDigits, является ли пустым, остутствующим в БД или пустой строкой
Dim nDigitsFlag As Boolean = True
If nDigits Is Nothing OrElse IsDBNull(nDigits) OrElse String.IsNullOrEmpty(nDigits.ToString().Trim()) Then
nDigitsFlag = False
End If
'Проверка аргумента mMode, является ли пустым, остутствующим в БД или пустой строкой
Dim mModeFlag As Boolean = True
If mMode Is Nothing OrElse IsDBNull(mMode) OrElse String.IsNullOrEmpty(mMode.ToString().Trim()) Then
mModeFlag = False
End If
'Если хотя бы один из параметров (nDigits или mMode) отсутствует, возвращается исходное число xValue
If (nDigitsFlag = False) Or (mModeFlag = False)
Return xValue
End If
If mMode = 1 Then
' Округление до n знаков после запятой
' В отличие от стандартной функции Math.Round(value, digits, MidpointRounding.AwayFromZero)
' может работать с отрицательными digits за счет сдвига
' Вычисление множителя
Dim factor As Double = Math.Pow(10, nDigits)
' Свдиг запятой на расстояние множителя, округление до целого, обратный сдвиг
' Направление сдвига зависит от знака (+-) в nDigits
Dim result As Double = Math.Round(xValue * factor, 0, MidpointRounding.AwayFromZero) / factor
' Форматирование результата (либо до целого(0), либо по положительному nDigits)
Return result.ToString("F" & Math.Max(0, nDigits))
End If
If mMode = 0 Then
' Округление до n значащих цифр
' Определение порядка числа (до запятой)
Dim scale As Double = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(xValue))) + 1 - nDigits)
' Свдиг запятой влево (уменьшение порядка числа), округление, сдвиг вправо (увеличение порядка числа)
Dim result As Double = Math.Round(xValue / scale, 0, MidpointRounding.AwayFromZero) * scale
' Форматирование результата в компактную строку (удаление лишних нулей, научная нотация)
Return result.ToString("G")
End If
' При некорректном значении режима mMode
Return ""
End Function
Итоговый вариант на С#
public class Rounding
{
public string RoundBase(double value, int digits, RoundMode mode)
{
if (value == 0)
return "0";
double result;
switch (mode)
{
case RoundMode.ToDecimalPlace:
double factor = Math.Pow(10, digits);
result = Math.Round(value * factor, 0, MidpointRounding.AwayFromZero) / factor;
return result.ToString("F" + Math.Max(0, digits));
case RoundMode.ToSignificantPlace:
double scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(value))) + 1 - digits);
result = Math.Round(value / scale, 0, MidpointRounding.AwayFromZero) * scale;
return result.ToString("G");
default:
throw new ArgumentOutOfRangeException(nameof(mode), "Некорректный режим округления");
}
}
public string RoundBase(double value, int digits, int mode) => RoundBase(value, digits, (RoundMode)mode);
}
GetOrDash()
Функция GetOrDash() - предназначена для обработки пустых значений (NULL, пустые строки, пробелы) в ячейках отчета.
Она гарантирует, что вместо пустого места в таблице всегда будет отображаться визуальный маркер - (дефис), что улучшает читаемость документа.
Public Function GetOrDash(field As Object) As String
If field Is Nothing OrElse IsDBNull(field) OrElse String.IsNullOrEmpty(field.ToString().Trim()) Then
Return "-"
End If
Return field.ToString()
End Function
Входные параметры
field(Object) - данные из поля набора данных (принимает любой тип данных, так как параметр объявлен какObject).
Выходные данные
String- строковое представление данных, если поле содержит значимую информацию;-(дефис) - если входной параметр:- равен
Nothing(не инициализирован); - равен
DBNull.Value(пустое значение из базы данных); - является пустой строкой
""; - содержит только пробелы (метод
.Trim()).
- равен
GetOr()
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
Входные параметры
field(Object) - проверяемое поле (может быть числом, строкой или объектом базы данных);swap(String, необязательно) - значение «подмены», которое вернется, если поле пустое; по умолчанию — пустая строка;pref(String, необязательно) - префикс, который добавится перед значением;suf(String, необязательно) - суффикс, который добавится после значения.
Выходные данные
String- отформатированная строка с префиксом и суффиксом, либо значениеswap;
Алгоритм
- проверка на пустоту - функция проверяет объект
fieldна три условия: равен ли онNothing, является ли онDBNull(пустота из базы данных) или состоит ли он только из пробелов; - обработка пустого значения - если хотя бы одно условие истинно, возвращается значение параметра
swap; - форматирование - если поле содержит данные, функция обрезает лишние пробелы по краям (
Trim), добавляет к нему заданные префикс (pref) и суффикс (suf) и возвращает результат.
ConcatFields()
Функция ConcatFields() - предназначена для объединения нескольких текстовых значений в одну строку с использованием заданного разделителя.
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)
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
Входные параметры
separator(String) - символ или текст, который будет стоять между элементами (например - запятая, или пробел, или перенос на следующую строку);ParamArray fields()(Object) - список аргументов любого количества, перечисляется через запятую (также можно передать массив).
Выходные данные
String- одна строка из объединенных элементов.-(дефис) - если данных нет.
Алгоритм
If fields Is Nothing Then Return "-"- если массив аргументов вообще не передан, функция сразу возвращает дефис;Dim list As New System.Collections.Generic.List(Of String)- создается временный список для хранения "чистых" строковых элементов;For Each f As Object In fields- цикл по каждому полученному на входе значению;If f Is Nothing Then Continue For- если текущий элемент пуст (null), он пропускается;Dim elem As String = f.ToString().Trim()- значение переводится в строковый элемент и очищается от лишних пробелов по краям;If String.IsNullOrEmpty(elem) Then Continue For- если после удаления пробелов строковый элемент оказался пустым, он пропускается;list.Add(elem)- корректный строковый элемент добавляется в итоговый список;If list.Count = 0 Then Return "-"- если после проверки всех элементов список пуст (все было null или пробелы), возвращается дефис;Return String.Join(separator, list.ToArray())- все накопленные в списке элементы склеиваются в одну строку через указанный разделитель.
GetExperience()
Функция GetExperience() рассчитывает и форматирует строку о стаже работы сотрудника на основе даты получения диплома.
Она выводит количество лет с правильным суффиксом (через вспомогательную функцию YearsWithSuffix) и указывает временной интервал от даты диплома до сегодняшнего дня.
Public Function GetExperience(diplomDate As Object) As String
If IsDBNull(diplomDate) OrElse diplomDate Is Nothing Then
Return "-"
End If
Return YearsWithSuffix(diplomDate) & vbLF & Format(diplomDate, "dd.MM.yyyy") & " - по текущую дату"
End Function
Входные параметры
diplomDate(Object) - дата выдачи диплома.
Выходные данные
String-- если дата не указана;- многострочный текст, если дата есть; например:
5 лет 15.05.2018 - по текущую дату
Алгоритм
- проверка на пустоту - является ли входное значение пустым (
IsDBNull) или отсутствующим (Nothing); если данных нет, возвращается прочерк; - расчет лет - вызывается внешняя функция
YearsWithSuffix(diplomDate), которая вычисляет разницу между текущей датой и датой диплома, добавив правильное окончание (год/года/лет); - форматирование даты - исходная дата преобразуется в стандартный формат
дд.мм.гггг.; - сборка результата - все части склеиваются в одну строку, символ
vbLFпереносит информацию о датах на новую строку.
YearsWithSuffix()
Функция YearsWithSuffix() - предназначена для формирования строки, содержащей количество лет и правильное грамматическое окончание существительного «год» (год, года, лет) на основе разницы между переданной датой и текущим моментом.
Public Function YearsWithSuffix(inputDate As Date) As String
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
Входные параметры
inputDate(Date) - дата, от которой ведется отсчет.
Выходные данные
String- разница лет до текущего момента с текстом-суффиксом "21 год", "25 лет", "34 года".
Алгоритм
- вычисляется полное количество лет между
inputDateи текущей датойNow()с помощью функцииDateDiff; resultDate- техническая переменная для определения логики окончания;resultString- строковое представление числа лет;- обработка исключений (20+ лет) - если число больше 20, применяется операция
Mod 10(остаток от деления на 10), чтобы привести числа вроде 21, 22, 25 к виду 1, 2, 5 для подбора окончания; Select Case- блок выбора окончания;Case 1- если число (или его остаток) равно 1, добавляется словогод;Case 2 To 4- если число (или его остаток) в диапазоне от 2 до 4 включительно, добавляется словогода;Case Else- в остальных случаях (для 0, 5–19 и специфических остатков) добавляется словолет;- возврат итоговой склеенной строки.
GetNorms()
Public Function GetNorms(lowLimit As Double, upLimit As Double) As String
If upLimit <> 0 Then
Return "не менее " & lowLimit & vbLF & "не более " & upLimit
End If
If lowLimit <> 0 Then
Return "не менее " & lowLimit
End If
Return ""
End Function
Входные параметры
lowLimit(Double) - нижняя граница нормы;upLimit(Double) - верхняя граница нормы.
Выходные данные
Stringтекстовое описание диапазона; возвращает пустую строку, если оба параметра равны нулю.
Алгоритм
- проверка верхней границы - если
upLimitне равен0, функция возвращает строку с обоими пределами (не менее X, не более Y), разделяя их переносом строки (vbLF); - проверка нижней границы - если верхний предел равен
0, ноlowLimitне равен0, возвращается только нижний порог (не менее X); - значение по умолчанию - если оба параметра равны
0, функция возвращает пустую строку.
NormProcessing()
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
Входные параметры
min(String) - строковое значение нижней границы;max(String) - строковое значение верхней границы.
Выходные данные
String- форматированная строка диапазона, либо символ прочерка (-).
Алгоритм
- проверка наличия данных - определяются два флага (
hasMinиhasMax); значение считается валидным, если оно не пустое и не равно строке0; - выбор формата:
- если есть оба значения - возвращается диапазон через дефис (
min-max); - если есть только
min- возвращается значение с символом «больше или равно» (≥min); - если есть только max - возвращается значение с символом «меньше или равно» (
≤max);
- если есть оба значения - возвращается диапазон через дефис (
- значение по умолчанию - если оба входа пустые или равны
0, возвращается дефис (-).
RemoveTagsSimple()
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
Входные параметры
input(String) - исходная строка, содержащая HTML-подобные теги.
Выходные данные
String- очищенный текст без специфических тегов.
Алгоритм
- определение списка - создается массив
tags, содержащий конкретные строковые теги -<span>,<sub>,<sup>(открывающие и закрывающие); - циклическая замена - функция перебирает каждый тег из списка и удаляет его из строки, заменяя на пустую строку;
- игнорирование регистра - используется метод
CompareMethod.Text, что позволяет удалять теги независимо от того, написаны они заглавными или строчными буквами (например, удалит и<span>, и<SPAN>).
FormatFio()
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)
End Function
Входные параметры
surname(String) - фамилия,name(String) - имя,patronymic(String) - отчество;mode(Integer) - режим форматирования (0, 1 или 2).
Выходные данные
String- ФИО в выбранном формате; если результат пуст, вызывается внешняя функцияGetOrDash(возвращает прочерк).
Алгоритм
- очистка - удаляются лишние пробелы из всех входящих строк (
Trim); - подготовка инициалов - для имени и отчества берутся первые буквы с точкой (i., o.), если соответствующие строки не пустые;
- Выбор формата (по mode):
0- полное ФИО через пробел (Фамилия Имя Отчество);1- фамилия и инициалы слитно (Фамилия И.О.);2- инициалы и фамилия через пробел (И.О. Фамилия);
- финальная обработка - результат обрезается от лишних крайних пробелов и передается в
GetOrDash.
CollapseNumbers()
Функция CollapseNumbers() свертывает массив чисел в компактную строку, заменяя последовательные числовые ряды диапазонами.
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
For i As Integer = 0 To inputNums.Length - 1
nums(i) = CInt(inputNums(i))
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 = ""
If endNum - startNum = 0 Then
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
End Function
Входные параметры
inputNums(Object()) - массив объектов (чисел), которые нужно сгруппировать.
Выходные данные
String- строка с перечисленными числами, где последовательные ряды заменены на диапазоны (например,1, 2, 3, 5превратится в1-3, 5).
Алгоритм
- подготовка - входные объекты преобразуются в массив целых чисел (Integer) и сортируются по возрастанию;
- поиск последовательностей - цикл проходит по массиву, определяя блоки идущих подряд чисел (где каждое следующее больше предыдущего на 1);
- форматирование группы:
- если число одиночное - записывается просто число;
- если в ряду два числа - записываются через запятую (
1, 2); - если в ряду три и более чисел - записываются через дефис как диапазон (
1-3);
- сборка - все обработанные группы объединяются в одну строку через запятую с пробелом.
AddIndents()
Добавление абзацев (на перспективу).
Public Function AddIndents(ByVal text As String) As String
If String.IsNullOrEmpty(text) Then Return ""
Dim indentedText As String = text.Replace(vbCrLf, vbLf & " ")
Return " " & indentedText
End Function
Входные параметры
text(String) - исходный многострочный текст.
Выходные данные
String- текст, в котором каждая строка начинается с отступа (4 пробела).
Алгоритм
- проверка на пустоту - если входящая строка пустая или
Nothing, возвращается пустая строка; - обработка переносов - функция находит все стандартные символы переноса строки (
vbLf) и заменяет их на перенос, за которым сразу следуют 4 пробела; это создает отступы для всех строк, кроме первой; - обработка первой строки - в начало всей полученной строки принудительно добавляются 4 пробела, чтобы первая строка также имела отступ.