PDA

View Full Version : تبدیل عدد به حروف؟



safa55
دوشنبه 17 فروردین 1394, 22:17 عصر
سلام
دوستان من در database ام چند فیلد دارم که باهم جمع می شوند و یک عددی را به خروجی می فرستند و بعد این عدد در کریستال ریپورت چاپ می شود
به نظرتون بهترین راه برای تبدیل این اعداد به حروف چی است؟ در خود c# یا به کمک Dll یا در همون کریستال. ؟؟؟
لطفا جواب تون رو توضیح هم دهید.
مرسی
منتظرم...

ashkufaraz
دوشنبه 17 فروردین 1394, 23:02 عصر
از این تابع استفاده کن
فقط زحمت فارسی کردنشو بکش!


public static string NumberToWords(int number)
{
if (number == 0)
return "zero";

if (number < 0)
return "minus " + NumberToWords(Math.Abs(number));

string words = "";

if ((number / 1000000) > 0)
{
words += NumberToWords(number / 1000000) + " million ";
number %= 1000000;
}

if ((number / 1000) > 0)
{
words += NumberToWords(number / 1000) + " thousand ";
number %= 1000;
}

if ((number / 100) > 0)
{
words += NumberToWords(number / 100) + " hundred ";
number %= 100;
}

if (number > 0)
{
if (words != "")
words += "and ";

var unitsMap = new[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
var tensMap = new[] { "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };

if (number < 20)
words += unitsMap[number];
else
{
words += tensMap[number / 10];
if ((number % 10) > 0)
words += "-" + unitsMap[number % 10];
}
}

return words;
}

am_al_59
دوشنبه 17 فروردین 1394, 23:05 عصر
http://barnamenevis.org/showthread.php?364999-تابع-تبدیل-عدد-به-حروف-در-سی-شارپ

safa55
سه شنبه 18 فروردین 1394, 21:11 عصر
ممنون دوستان
ولی با این چیزا مشکل حل نمی شه.
من گفتم که اطلاعات را از دیتابیس می گیرم مثلا 1000 رکورد
توی دستورات sql چطوری برای هر رکورد معادلش رو هم بدست بیارم.
در کریستال ریپورت می شه انجام داد ولی مشکل این است که چون بازگشتی نمی شه کد زیاد می شه و....
در دستورات sql هم نمی دونم چطور این کار رو بکنم ، اصلا می شه؟

امیر مهرشاد
سه شنبه 18 فروردین 1394, 21:38 عصر
مگه دیتاست بخورد کریستال بدید (اطلاعاتی که سلکت میشن با یه حلقه و کلاس تبدیل اینکار رو میتونید انجام دهید ولی توصیه نمیکنم چون معمولا ارقام نهایی رو این شکلی میزنن) احتمالا درگیر ترد هم بشید بسته به سلکت های سنگین تر ---چه دلیلی برای این کار دارید ؟

ghasem110deh
سه شنبه 18 فروردین 1394, 21:49 عصر
با اجازه دوستان ...
اگه توی برنامه نیازی به اون عدد خاص ... به حروف ندارید ، توی همون کریستال تبدیل کنید بنظرم بهتره !
البته من این کار رو با استیمول سافت انجام میدم ... حتی جمع اون اعداد رو تو خود استیمول انجام میدم .

safa55
چهارشنبه 19 فروردین 1394, 09:08 صبح
مرسی بابت توجه تان
استفاده از حلقه و کلاس در زمان گرفتن داده ها از دیتابیس فکر نکنم روش خوبی باشد.
من در حال حاضر داده ها رو به کریستال می دم و بعد چند عدد باهم جمع و ضرب می شود و آخر توی کریستال به کمک تابع به حروف تبدیل می کنم. ولی مشکل من این است که چون نمی شود در کریستال تابع بازگشتی درست کرد باعث می شه که تابع تبدیل عدد به حروف خیلی طولانی بشه (کدش). به همین خاطر گفتم شاید روش بهینه و بهتری باشد که من ندیده ام.
فکر کنم باید همان روش غیر بازگشتی در کریستال رو تکمیل کنم.

am_al_59
چهارشنبه 19 فروردین 1394, 10:19 صبح
کلی نمونه براش هست این یکیش





CREATE FUNCTION dbo.GetPersianString(@Number Numeric (38, 0))
RETURNS NVARCHAR(4000)
AS BEGIN
DECLARE @inputNumber NVARCHAR(38)
DECLARE @NumbersTable TABLE (number CHAR(2), word NVARCHAR(10))
DECLARE @outputString NVARCHAR(4000)
DECLARE @length INT
DECLARE @counter INT
DECLARE @loops INT
DECLARE @position INT
DECLARE @chunk CHAR(3)
DECLARE @tensones CHAR(2)
DECLARE @hundreds CHAR(1)
DECLARE @tens CHAR(1)
DECLARE @ones CHAR(1)
IF @Number = 0 Return 'صفر'
SELECT @inputNumber = CONVERT(NVARCHAR(38), @Number)
, @outputString = ''
, @counter = 1
SELECT @length = LEN(@inputNumber)
, @position = LEN(@inputNumber) - 2
, @loops = LEN(@inputNumber)/3
IF LEN(@inputNumber) % 3 <> 0 SET @loops = @loops + 1
INSERT INTO @NumbersTable SELECT '00', ''
UNION ALL SELECT '01', N'يك' UNION ALL SELECT '02', N'دو'
UNION ALL SELECT '03', N'سه' UNION ALL SELECT '04', N'چهار'
UNION ALL SELECT '05', N'پنج' UNION ALL SELECT '06', N'شش'
UNION ALL SELECT '07', N'هفت' UNION ALL SELECT '08', N'هشت'
UNION ALL SELECT '09', N'نه' UNION ALL SELECT '10', N'ده'
UNION ALL SELECT '11', N'يازده' UNION ALL SELECT '12', N'دوازده'
UNION ALL SELECT '13', N'سيزده' UNION ALL SELECT '14', N'چهاده'
UNION ALL SELECT '15', N'پانزده' UNION ALL SELECT '16', N'شانزده'
UNION ALL SELECT '17', N'هفده' UNION ALL SELECT '18', N'هيجده'
UNION ALL SELECT '19', N'نوزده' UNION ALL SELECT '20', N'بيست'
UNION ALL SELECT '30', N'سي' UNION ALL SELECT '40', N'چهل'
UNION ALL SELECT '50', N'پنجاه' UNION ALL SELECT '60', N'شصت'
UNION ALL SELECT '70', N'هفتاد' UNION ALL SELECT '80', N'هشتاد'
UNION ALL SELECT '90', N'نود'
WHILE @counter <= @loops BEGIN
SET @chunk = RIGHT('000' + SUBSTRING(@inputNumber, @position, 3), 3)
IF @chunk <> '000' BEGIN
SELECT @tensones = SUBSTRING(@chunk, 2, 2)
, @hundreds = SUBSTRING(@chunk, 1, 1)
, @tens = SUBSTRING(@chunk, 2, 1)
, @ones = SUBSTRING(@chunk, 3, 1)
IF CONVERT(INT, @tensones) <= 20 OR @Ones='0' BEGIN
SET @outputString = (SELECT word
FROM @NumbersTable
WHERE @tensones = number)
+ CASE @counter WHEN 1 THEN N'' -- No name
WHEN 2 THEN N' هزار ' WHEN 3 THEN N' ميليون '
WHEN 4 THEN N' میلیارد '
ELSE '' END
+ @outputString
END
ELSE BEGIN
SET @outputString = ' '
+ (SELECT word
FROM @NumbersTable
WHERE @tens + '0' = number)
+ N' و '
+ (SELECT word
FROM @NumbersTable
WHERE '0'+ @ones = number)
+ CASE @counter WHEN 1 THEN ''
WHEN 2 THEN N' هزار ' WHEN 3 THEN N' ميليون '
WHEN 4 THEN N' ميليارد '
ELSE '' END
+ @outputString
END
IF @hundreds <> '0' BEGIN
SET @outputString = (SELECT word
FROM @NumbersTable
WHERE '0' + @hundreds = number)
+ N' صد '
+ @outputString
END
END
SELECT @counter = @counter + 1
, @position = @position - 3
END
SET @outputString = LTRIM(RTRIM(REPLACE(@outputString, ' ', ' ')))
SET @outputstring = UPPER(LEFT(@outputstring, 1)) + SUBSTRING(@outputstring, 2, 8000)
RETURN @outputString
END

safa55
چهارشنبه 19 فروردین 1394, 11:58 صبح
ممنون بابت جوابتون
بله خیلی نمونه است و خیلی ها کامل نیستند و یا درست نیستند
مثلا همین نمونه شما دویست و سیصد و... رو نداره و ..
مثلا برای 200 می نویسه دو صد.

به هر حال این درست شدنی است ، ولی من نمی خواستم مثلا برای هر رکورد عمل جمع و ضرب انجام دهم تا یک عدد رو بدست بیارم و حالا باید برای حروف نیز دوباره این عمل را انجام دهم ، اگر می شد از همون عدد بدست آمده به عنوان ورودی به تابع می داد سرعت هم بالا می رفت و ....

مثلا
select (x*y/10*85) as adad , dbo.tohorof(adad) as "عدد به حروف"