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

Глобальные функции

Материал из Химсофт Вики
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)

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

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