Страница 1 из 1

Десятичное (дробное) число прописью - возможно ли?

Добавлено: 20 сен 2011, 10:54
Eugene A. Bykov
Здравствуйте,
Скажите, пожалуйста, есть ли возможность в отчёте преобразования десятичного (дробного) значения числа в его текстовое представление.
Скажем, "10.2", чтобы выглядело как "десять целых две десятых", или 120.47 - "сто двадцать целых сорок семь сотых". Да, есть преобразователи валюты, но они значения копеек в текст не преобразуют. Задача весьма похожа на деньги прописью, возможно, я просто не могу найти нужную функцию?
Спасибо!

Десятичное (дробное) число прописью - возможно ли?

Добавлено: 20 сен 2011, 20:23
Ivan
Здравствуйте.

Требуемой готовой функции в нашем продукте нет: функция ToWordsRu() выводит только целую часть числа, функция ToCurrencyWordsRu() количество копеек выводит цифрами.
Эта функция не востребована, поэтому пока мы не планируем заниматься этой задачей.
Однако вы можете использовать в отчете свои самописные функции, загружая их из готовых внешних сборок, или размещая текст функции прямо в самом отчете (на закладке Code дизайнера).
Если вы пришлёте нам текст функции (желательно на C# или VB), мы можем включить эту функцию в наш продукт.

Спасибо.

Re: Десятичное (дробное) число прописью - возможно ли?

Добавлено: 30 июл 2016, 11:56
fuerto
Здравствуйте! Не появилась ли возможность количество копеек выводить цифрами?

Re: Десятичное (дробное) число прописью - возможно ли?

Добавлено: 03 авг 2016, 13:03
Aleksey
Здравствуйте,

К сожалению, нет. Никто данный функицонал не спрашивал больше.

Спасибо.

Re: Десятичное (дробное) число прописью - возможно ли?

Добавлено: 03 авг 2016, 14:21
Леонид
Добрый день!

Внесу свои два цента. Разумеется, это нестандартный функционал, но если "горит", то в приложении тестовый полностью рабочий отчёт с тремя процедурами. Основная DecimalToWords(decimal number), вызываете так {DecimalToWords(241.762m)}.

В самом отчёте во вкладке Code, в using добавляем using System.Collections.Generic;, т.к. использовал в процедуре List, и далее вставляем в отчёт три процедуры ниже, а затем в отчёте вызываем по имени (как описано чуть выше).

Процедуры:

Код: Выделить всё

		private string GetEnding(string number, bool isFractionalPart)
		{
			if (number == string.Empty)
				return string.Empty;

			// get last fraction digit (to detect correct ending)
			string s = number.Substring(number.Length - 1, 1);
			int lastDigit = int.Parse(s);

			// decimal part
			if (!isFractionalPart)
			{
				if (lastDigit == 1) // 1
					return "целая";
				else
					return "целых"; // 0, 2, 3, 4, etc.
			}

			// fractional part
			List<string[]> endings = new List<string[]>()
			{
			new string[] { "десятая", "десятых" },
			new string[] { "сотая", "сотых" },
			new string[] { "тысячная", "тысячных" },
			new string[] { "десятитысячная", "десятитысячных" }
			};

			int idx = number.Length - 1; // get ending index
			if (idx > endings.Count)
				return "Слишком большое число";

			string[] fractionalEnding = endings[idx];

			if (lastDigit == 1) // 1
				return fractionalEnding[0];
			else
				return fractionalEnding[1];
			}
		
		private string CorrectLastEnding(string text)
		{
			string[] words = text.Split(' ');
			
			if (words.Length == 0)
				return string.Empty;
			
			// take the last word
			string word = words[words.Length - 1];
			
			string newWord = string.Empty;
			switch (word.ToLower())
			{
				case "один" : newWord = "одна"; break;
				case "два" : newWord = "две"; break;
			}

			// check if original letter was in uppercase
			if (char.IsUpper(word[0]))
			{
				string s1 = newWord.Substring(1, newWord.Length - 1); // second part of word
				string s2 = char.ToUpper(newWord[0]).ToString(); // convert first letter to uppercase
				newWord = s2 + s1; // combine together
			}
			
			// combine back all words, but the last one
			string result = string.Empty;
			for (byte i = 0; i < words.Length - 1; i++)
				result += words[i] + " ";

			result += newWord; // plus final word
			return result;
		}		
		
		public string DecimalToWords(decimal number)
		{		
			int whole = (int)decimal.Truncate(number);
			decimal precision = (number - whole);

			string fraction = precision.ToString();
			decimal fractionToWords = decimal.Parse(fraction, System.Globalization.CultureInfo.InvariantCulture.NumberFormat);			

			// check if fractional part is at least has zero
			if (fraction.Length >= 3)
				fraction = fraction.Substring(2, fraction.Length - 2); // cut "0."
			else
			  fraction = string.Empty; // set length zero
		
			string wholeText = Stimulsoft.Report.Dictionary.StiFunctionsStrings.ToWordsRu(whole); // convert decimal to words
			wholeText = CorrectLastEnding(wholeText); // make ending correction
			
			string precisionText = string.Empty;
			if (fraction != string.Empty)
			{
				precisionText = Stimulsoft.Report.Dictionary.StiFunctionsStrings.ToWordsRu(fractionToWords).ToLower();
				precisionText = CorrectLastEnding(precisionText); // make ending correction too
			}
			
			string wholeTextEnding = GetEnding(whole.ToString(), false);
			string precisionEnding = GetEnding(fraction, true);   

			// return final result
			string result = string.Format("{0} {1} {2} {3}", wholeText, wholeTextEnding, precisionText, precisionEnding).TrimEnd();				
			return result;
		}
Хорошего дня.

Re: Десятичное (дробное) число прописью - возможно ли?

Добавлено: 04 авг 2016, 13:07
Леонид
Забыл добавить, что вся "фишка" в том, что там нужно учитывать склонения, когда цифры заканчиваются на один или два, остальные, как обычно.
Если необходимо выводить больше тысячных, то просто добавьте в List<string[]> endings соответствующие строки.

Результат {DecimalToWords(241.762m)} как на скриншоте в приложении.