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

Глобальные функции: различия между версиями

Материал из Химсофт Вики
 
(не показано 6 промежуточных версий этого же участника)
Строка 13: Строка 13:
===Входные параметры===
===Входные параметры===
*<code>value</code> (''Double'') - исходное число для обработки;
*<code>value</code> (''Double'') - исходное число для обработки;
*<code>digits</code> (''Integer'')  
*<code>digits</code> (''Object'')  
**при <code>Mode = 1</code> - количество знаков после запятой (положительное) или до запятой (отрицательное);
**при <code>Mode = 1</code> - количество знаков после запятой (положительное) или до запятой (отрицательное);
**при <code>Mode = 0</code> - количество значащих цифр;
**при <code>Mode = 0</code> - количество значащих цифр;
*<code>mode</code> (''Integer'') - режим работы:
*<code>mode</code> (''Object'') - режим работы:
**<code>1</code> (''ToDecimalPlace'') - десятичное округление;
**<code>1</code> (''ToDecimalPlace'') - десятичное округление;
**<code>0</code> (''ToSignificantPlace'') - значащие цифры.
**<code>0</code> (''ToSignificantPlace'') - значащие цифры.
Строка 26: Строка 26:
Функция работает по методу <code>Away From Zero</code> (округление от нуля).
Функция работает по методу <code>Away From Zero</code> (округление от нуля).


Режим 1 (Десятичное округление):
'''Режим 1''' (''десятичное округление''):
*вычисляется множитель;
*вычисляется множитель;
*число умножается на множитель, округляется до целого и делится обратно;
*число умножается на множитель, округляется до целого и делится обратно;
*при положительном n результат форматируется с фиксированным количеством нулей после запятой.
*при положительном n результат форматируется с фиксированным количеством нулей после запятой.


Режим 0 (Значащие цифры):
'''Режим 0''' (''значащие цифры''):
*определяется порядок числа через десятичный логарифм;
*определяется порядок числа через десятичный логарифм;
*вычисляется масштабный коэффициент, чтобы оставить ровно <code>n</code> цифр;
*вычисляется масштабный коэффициент, чтобы оставить ровно <code>n</code> цифр;
Строка 37: Строка 37:
*результат преобразуется в компактную строку (удаляются лишние нули в конце).
*результат преобразуется в компактную строку (удаляются лишние нули в конце).


===Примеры использования в дизайнере-конструкторе===
===Примеры использования внутри ячейки===


{|class="wikitable" style="margin:auto; background-color: #fff; width:100%"  
{|class="wikitable" style="margin:auto; background-color: #fff; width:100%"  
Строка 62: Строка 62:
|-
|-
|}
|}
===Примеры использования во вкладке <code>Scripts</code>===
<syntaxhighlight lang="vb">
Return New Triteia.Rounding().RoundBase(variable, 2, 1)
</syntaxhighlight>
или
<syntaxhighlight lang="vb">
Dim rounder As New Triteia.Rounding()
Return rounder.RoundBase(variable, 2, 1)
</syntaxhighlight>


===Предварительный вариант на VB.NET===
===Предварительный вариант на VB.NET===
Строка 68: Строка 82:
If xValue = 0 Then Return "0"
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
If mMode = 1 Then

Текущая версия от 07:22, 26 марта 2026

Общие сведения

Функции, вынесенные в глобальную видимость через объект 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);
}