Jump to content

Rēķina summa vārdiem latviski - automātiski


halaac
 Share

Recommended Posts

Labdien.

Tātad top interneta veikals.

Tajā brīdi, kad klients apstiprina savu pasūtījumu, viņam tiek ģenerēts rēķins un izsūtīts e-pasts.

Tik tālu viss ir ok.

Bet vajag ģenerēt arī summu vārdiem latviski. Varūt kādam ir paraugs?

Rēķins html.

Link to comment
Share on other sites

tehniķis

Brutāls delphi piemērs.

Prasās smaga optimizācija, bet strādā

Reģions no 0.00 līdz 9999.99

unit summInWordsU;

interface
uses Registry, Windows, SysUtils;
type
 Tsumma = array[1..10] of String;

 const
a: Tsumma =('nulle', 'viens', 'divi', 'trīs', 'četri', 'pieci', 'seši', 'septiņi','astoņi','deviņi');
b: Tsumma =('desmit', 'vienpadsmit', 'divpadsmit', 'trīspadsmit', 'četrpadsmit', 'piecpadsmit', 'sešpadsmit', 'septiņpadsmit','astoņpadsmit','deviņpadsmit');
c: Tsumma =('', 'desmit ', 'divdesmit ', 'trīsdesmit ', 'četrdesmit ', 'piecdesmit ', 'sešdesmit ', 'septiņdesmit ','astoņdesmit ','deviņdesmit ');
d: Tsumma =('', 'viens simts ', 'divi simti ', 'trīs simti ', 'četri simti ', 'pieci simti ', 'seši simti ', 'septiņi simti ','astoņi simti ','deviņi simti ');
e: Tsumma =('', 'viens tūkstotis ', 'divi tūkstoši ', 'trīs tūkstoši ', 'četri tūkstoši ', 'pieci tūkstoši ', 'seši tūkstoši ', 'septiņi tūkstoši ','astoņi tūkstoši ','deviņi tūkstoši ');
function summInWords(summa:Double):String;
function numberInwords(num,reference:Integer):String;
function getnumberInPos(number,pos:Integer):Integer;
function formatSummInWorsText(siw:String):String;

implementation

function summInWords(summa:Double):String;
var sumstr,sumInwords:String;
lati,santimi:Integer;
latstr,santStr:String;
latName,santName:String;
ln,sn,tx,ty:String;
begin

sumstr := Format('%8.2f', [summa]);
lati := StrToIntDef(copy(sumstr,1,pos('.',sumstr)-1),0);
santimi := strToIntDef(copy(sumstr,pos('.',sumstr)+1,maxint),0);

latstr := numberInwords(lati,0);
santStr := numberInwords(santimi,0);

latName := ' lati, ';
santName :=  ' santīmi';

{if lati = 1 then
latName := ' lats, ';
if santimi = 1 then
santName := ' santīms ';}

ln := IntToStr(lati);
sn := IntToStr(santimi);

tx := copy(ln, length(ln)-1, 1) ;
ty := copy(ln, length(ln)-2, 2);

if ((tx = '1') and (ty <> '11')) then
latName := ' lats, ';

if ((copy(sn, length(sn)-1, 1) = '1') and (copy(IntToStr(santimi), length(sn)-2, 2) <> '11')) then
santName := ' santīms ';

if lati = 100 then
latName := ' lati, ';//' latu ';

if trim(latstr) <> '' then
sumInwords := latstr + latName;
if trim(santStr) <> '' then
sumInwords := sumInwords + santStr + santName;

result :=   formatSummInWorsText(sumInwords);
end;

function formatSummInWorsText(siw:String):String;
var tStr:String;
begin
//Pirmais lielais burts
tstr := UpperCase(siw[1]) + copy(siw,2,maxint);
//Izvāc liekās atstarpes
tstr := stringReplace(tstr,'  ',' ',[rfReplaceAll]);
result := tstr;
end;


function numberInwords(num,reference:Integer):String;
begin
if ((reference = 1) and (num = 0)) then
result := ''
else
if num < 10 then
  result := a[num+1]
else
if ((num < 20) and (num > 9)) then
  result := b[getnumberInPos(num,2)+1]
else
if ((num > 19) and (num < 100)) then
  result := c[getnumberInPos(num,1)+1] + numberInwords(num- (getnumberInPos(num,1)*10),1)
else
if ((num > 99) and (num < 1000)) then
  result := d[getnumberInPos(num,1)+1] + numberInwords(num- (getnumberInPos(num,1)*100),1)
else
if ((num > 999) and (num < 10000)) then
  result := e[getnumberInPos(num,1)+1] + numberInwords(num- (getnumberInPos(num,1)*1000),1)
else
if (num > 9999)  then
  result := intToStr(num);
end;

function getnumberInPos(number,pos:Integer):Integer;
var s:string;
begin
s := copy(inttostr(number),pos,1);
result := strToInt(s);
end;

end.

Link to comment
Share on other sites

Ekselī kādreiz taisīts makrosiņš

 

Sub NumberToString()
'
' NumberToString Macro
' Macro recorded 2007.08.13 by RegOnC
'

a0 = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)
A1 = Array("simt", "desmit")
b0 = Array(0, 0, 0)
b1 = ""

x0 = Array("", "viens", "divi", "trīs", "četri", "pieci", "seši", "septiņi", "astoņi", "deviņi")
x1 = Array("", "vien", "div", "trīs", "četr", "piec", "seš", "septiņ", "astoņ", "deviņ")

aResGroup = Array(b0, b0, b0, b0, b0, b0, b0, b0, b0)

ch0 = Selection.Value

If IsNull(ch0) Or _
   Not IsNumeric(ch0) Or _
   ch0 = "" Then
   MsgBox "Not Numeric or empty!"
   Exit Sub
Else
   ch0 = FormatNumber(Selection.Value, 2, vbFalse, vbFalse, vbFalse)
   If InStr(ch0, ".") Then
       aVal = Split(ch0, ".", -1, vbBinaryCompare)
   ElseIf InStr(ch0, ",") Then
       aVal = Split(ch0, ",", -1, vbBinaryCompare)
   Else
       aVal = Array(0, 0)
       aVal(0) = ch0
       aVal(1) = "00"
   End If
End If

aResGroup(8) = aVal(1)

Dim sTmp As String
sTmp = StrReverse(aVal(0))
iMod = 3 - (Len(sTmp) Mod 3)
For i = 1 To iMod
   sTmp = sTmp & "0"       'Pievieno nulles galā, lai ciparu rinda dalaas uz 3 bez atlikuma
Next

i = 1
n = 1
m = Len(sTmp)
Do While i < m
   For j = 0 To 2
       aResGroup(n)(j) = Mid(sTmp, m - i + 1, 1)
       i = i + 1
       If i > m Then
           Exit For
           Exit Do
       End If
   Next
   n = n + 1
Loop

m = n
sTmp = ""

For i = 1 To n - 1
   'MsgBox "aResGroup(i)(0): " & aResGroup(i)(0)
   If aResGroup(i)(0) = 0 Then
       s100 = 0
   Else
       s100 = CInt(aResGroup(i)(0))
   End If

   'MsgBox "aResGroup(i)(1): " & aResGroup(i)(1)
   If aResGroup(i)(1) = 0 Then
       s10 = 0
   Else
       s10 = CInt(aResGroup(i)(1))
   End If

   'MsgBox "aResGroup(i)(2): " & aResGroup(i)(2)
   If aResGroup(i)(2) = 0 Then
       s1 = 0
   Else
       s1 = CInt(aResGroup(i)(2))
   End If

   'MsgBox "Digit group " & i & " = " & s100 & s10 & s1

   Select Case s100
       Case 0: sRes100 = ""
       Case 1: sRes100 = "simts"
       Case Else: sRes100 = x0(s100) & " simti"
   End Select

   Select Case s10
       Case 0:
               sRes10 = ""
               sPadsmit = False
       Case 1:
           Select Case s1
               Case 0:
                   sRes10 = "desmit"
                   sPadsmit = False
               Case Else:
                   sRes10 = x1(s1) & "padsmit"
                   sPadsmit = True
           End Select
       Case Else:
               sRes10 = x1(s10) & "desmit"
               sPadsmit = False
   End Select

   Select Case s1
       Case 0: sRes1 = ""
       Case Else:
           Select Case sPadsmit
               Case False: sRes1 = x0(s1)
               Case True: sRes1 = ""
           End Select
   End Select

   m = m - 1

   If aResGroup(i)(0) = 0 And _
      aResGroup(i)(1) = 0 And _
      aResGroup(i)(2) = 0 Then
       sTmp = ""
   Else
       Select Case m
            Case 6:
               Select Case s1
                   Case 1: sTmp = "kvadriljons"
                   Case Else: sTmp = "kvadriljoni"
               End Select
           Case 5:
               Select Case s1
                   Case 1: sTmp = "triljons"
                   Case Else: sTmp = "triljoni"
           End Select
           Case 4:
               Select Case s1
                   Case 1: sTmp = "miljards"
                   Case Else: sTmp = "miljardi"
               End Select
           Case 3:
               Select Case s1
                   Case 1: sTmp = "miljons"
                   Case Else: sTmp = "miljoni"
               End Select
           Case 2:
               Select Case s1
               Case 1: sTmp = "tūkstotis"
               Case Else: sTmp = "tūkstoši"
           End Select
           Case Else: sTmp = ""
       End Select
   End If
   sResAll = sResAll & sRes100 & " " & sRes10 & " " & sRes1 & " " & sTmp & " "
Next

sTmp = Trim(aResGroup(8))
iLen = Len(sTmp)

iMod = 2 - (Len(sTmp) Mod 2)
For i = 1 To iMod
   sTmp = sTmp & "0"
Next

iDec = 10
sSant = 0
For i = 1 To 2
   sSant = sSant + iDec * Mid(sTmp, i, 1)
   iDec = iDec / 10
Next

sResAll = sResAll & "Ls, " & sSant & " sant"

For i = 1 To Len(sResAll)
   sResAll = Replace(sResAll, "  ", " ", 1, 1, 1)
Next

sResAll = LTrim(sResAll)

UserForm1.TextBox1 = sResAll
UserForm1.Show

End Sub

 

Palaižot makrosu skaitlis, kas atrodas aktīvajā/iezīmētajā šūnā, tiek pārveidots tekstā (lati, santīmi) un izvadīts formas logā no kurienes tad copy/paste kur lietotājam vajag.

 

Piemēram, aktīvajā šūnā ir skaitlis:

718 961 233 692,06

Rezultāts:

septiņi simti astoņpadsmit miljardi deviņi simti sešdesmit viens miljons divi simti trīsdesmit trīs tūkstoši seši simti deviņdesmit divi Ls, 6 sant

Labots - RegOnC
Link to comment
Share on other sites

Kāda atšķirība, kurā valodā vajag?

Nav nekāda raķešzinātne pārrakstīt no vienas valodas uz otru, pat ja vienu vai otru redzi pirmo reizi mūžā.

Link to comment
Share on other sites

  • 2 years later...
Mezavecis

Paceļu augšā mironi, bet vajag nedaudz aktualizēt un precizēt, kāds ir pareizais formāts jābūt rēķinu izdrukā:

 

Piemēram, cipars 11120.30 = Vienpadsmit tūkstoši viens simts divdesmit lati 30 santīmi

 

 

Kaut kur manīju šādu citātu, bet praksē neesmu redzējis un nevaru atcerēties, ka tāda lieta gramatikā bija:

 

Ja skaitlis beidzas ar 0 (vai dalās ar 10 bez atlikuma) tad lieto galotni "u", piemēram, 50 santīmu, 100 latu, 10 latu.

Bet visi citi, kas nebeidzas ar 1 (kam galotne ir "s" -> viens lats), beidzas ar "i" -> pieci lati, 3 lati, 21 lats, 27 lati, 30 latu... utt.

 

Pats cepu skriptu T-SQL reportiem.

Link to comment
Share on other sites

marrtins

Tev kāds reāli piesienas par tām galotnēm? :D

Link to comment
Share on other sites

Mezavecis

marrtins, gribu precizēt, lai kāds valodnieks nesāk ļečīt, ka daru nepareizi :)

Link to comment
Share on other sites

martinno

Paskaties uz LVL naudas zīmēm :)

5 lati

10 latu

20 latu

....

Izskatās, ka tas citāts ir pareizs :)

Labots - DAFUQ
Link to comment
Share on other sites

Mezavecis

DAFUQ, pareizi ir pēc gramatikas kanoniem, tikai praksē uz neviena rēķina neesmu šādi redzējis :)

Link to comment
Share on other sites

marrtins

Pēc manas ūberf-ijas tas cipars sanāk:

vienpadsmit tūkstoši simt divdesmit lati 30 santīmi

Nez, ja nepatīk tāds rēķins, var maksāt skaidrā :D

Link to comment
Share on other sites

Ne sūda nejēdzu par šo tēmu, bet viedoklis ir! :D

 

Man tas šķiet maigi jocīgi - kāpēc jāizmanto cits locījums vārdam, ja konteksts nemainās? Mēģinot atsvaidzināt atmiņu par latviešu valodas locījumiem:

  • Nominatīvs (kas?): lati;
  • Ģenitīvs (kā?): latu;
  • Datīvs (kam?): latiem;
  • Akuzatīvs (ko?): latus;
  • Instrumentālis (ar ko?): ar latiem;
  • Lokatīvs (kur): latos;
  • Vokatīvs (!): lati!

Manuprāt, locījumam vajadzētu būt atkarīgam no tā, kā to izmanto teikumā. "A nu ka atdod man piecus latus!" "Cik labi, ka man līdzi ir tieši pieci lati!" Ja summa ir viena pati, bez konteksta, tad... nominatīvs, man domāt. Bet mainīt atkarībā no summas... jocīgi.

Labots - Vilx-
Link to comment
Share on other sites

Mezavecis

Es pielāgoju vienu angļu T-SQL skriptu, kas paredzēts tikai skaitļiem, lai strādā priekš summām. Tomēr no javas vai php to cept būtu baiss marazms zinot sintakses atšķirības :)

 

IF (OBJECT_ID('dbo.Sum_ToWords') IS NOT NULL) BEGIN
  drop function dbo.Sum_ToWords
END
GO
CREATE FUNCTION dbo.Sum_ToWords (
  @Sum money,
  @Currency varchar(10)
) RETURNS NVARCHAR(MAX)
AS BEGIN
DECLARE @inputNumber NVARCHAR(38)
DECLARE @NumbersTable TABLE (number CHAR(2), word NVARCHAR(50))
DECLARE @outputString NVARCHAR(max)
DECLARE @length INT
DECLARE @counter INT
DECLARE @loops INT
DECLARE @position INT
DECLARE @chunk CHAR(3) -- for chunks of 3 numbers
DECLARE @tensones CHAR(2)
DECLARE @hundreds CHAR(1)
DECLARE @hundredstring NVARCHAR(max)
DECLARE @tentonesstring NVARCHAR(max)
DECLARE @tens CHAR(1)
DECLARE @ones CHAR(1)
DECLARE @SumText VARCHAR(50);
DECLARE @NumberText VARCHAR(50);
DECLARE @NumberTextDecimal VARCHAR(2);
DECLARE @CurrencyBig NVARCHAR(20);
DECLARE @CurrencySmall NVARCHAR(20);
DECLARE @MinusText NVARCHAR(7);

set @SumText = convert(varchar(50), @Sum);

set @NumberText = substring(@SumText, 0 , CHARINDEX('.',@SumText));
set @NumberTextDecimal = substring(@SumText, CHARINDEX('.',@SumText) + 1 , LEN(@SumText)  - CHARINDEX('.',@SumText));
if @Currency = 'Ls'
begin
  if substring(@NumberText, LEN(@NumberText),1) = '1' and substring(@NumberText, LEN(@NumberText) - 1, 2) <> '11'
		set @CurrencyBig = N'lats'
  else
		set @CurrencyBig = N'lati'
  if substring(@NumberTextDecimal, LEN(@NumberTextDecimal),1) = '1' and substring(@NumberTextDecimal, LEN(@NumberTextDecimal) - 1, 2) <> '11'
		set @CurrencySmall = N'santīms'
  else
		set @CurrencySmall = N'santīmi'							
end

if @Sum < 0
begin
  set @MinusText = N'mīnus ';
  set @NumberText = REPLACE(@NumberText, '-','');
end
else set @MinusText = '';

-- initialize the variables
SELECT @inputNumber = @NumberText  
   ,@outputString = ''
 , @counter = 1
SELECT @length   = LEN(@inputNumber)
 , @position = LEN(@inputNumber) - 2
 , @loops	= LEN(@inputNumber)/3

-- make sure there is an extra loop added for the remaining numbers
IF LEN(@inputNumber) % 3 <> 0 SET @loops = @loops + 1
-- insert data for the numbers and words
INSERT INTO @NumbersTable   SELECT '00', N''
UNION ALL SELECT '01', N'viens'	  UNION ALL SELECT '02', N'divi'
UNION ALL SELECT '03', N'trīs'	UNION ALL SELECT '04', N'četri'
UNION ALL SELECT '05', N'pieci'	 UNION ALL SELECT '06', N'seši'
UNION ALL SELECT '07', N'septiņi'	UNION ALL SELECT '08', N'astoņi'
UNION ALL SELECT '09', N'deviņi'	 UNION ALL SELECT '10', N'desmit'
UNION ALL SELECT '11', N'vienpadsmit'   UNION ALL SELECT '12', N'divpadsmit'
UNION ALL SELECT '13', N'trīspadsmit' UNION ALL SELECT '14', N'četrpadsmit'
UNION ALL SELECT '15', N'piecpadsmit'  UNION ALL SELECT '16', N'sešpadsmit'
UNION ALL SELECT '17', N'septiņpadsmit' UNION ALL SELECT '18', N'astoņpadsmit'
UNION ALL SELECT '19', N'deviņpadsmit' UNION ALL SELECT '20', N'divdesmit'
UNION ALL SELECT '30', N'trīsdesmit'   UNION ALL SELECT '40', N'četrdesmit'
UNION ALL SELECT '50', N'piecdesmit'	UNION ALL SELECT '60', N'sešdesmit'
UNION ALL SELECT '70', N'septiņdesmit'  UNION ALL SELECT '80', N'astoņdesmit'
UNION ALL SELECT '90', N'deviņdesmit'  

IF @NumberText = '0' SET @outputString = 'nulle'
ELSE
WHILE @counter <= @loops BEGIN

  -- get chunks of 3 numbers at a time, padded with leading zeros
  SET @chunk = RIGHT('000' + SUBSTRING(@inputNumber, @position, 3), 3)
  IF @chunk <> '000' BEGIN
		if SUBSTRING(@chunk, len(@chunk) - 1, 2) = '01'
			  set @tentonesstring = CASE @counter
							 WHEN 1 THEN '' -- No name
				   WHEN 2 THEN N' tūkstotis '
				   WHEN 3 THEN N' milions '
				   WHEN 4 THEN N' miljards '
				   WHEN 5 THEN N' triljons '
				   WHEN 6 THEN N' kvadriljons '
				   WHEN 7 THEN N' kvintiljons '
				   WHEN 8 THEN N' sekstiljons '
				   WHEN 9 THEN N' septiljons '
				   WHEN 10 THEN N' octillion '
				   WHEN 11 THEN N' nonillion '
				   WHEN 12 THEN N' decillion '
				   WHEN 13 THEN N' undecillion '
				   ELSE '' END;
		else						
			  set @tentonesstring = CASE @counter
							 WHEN 1 THEN '' -- No name
				   WHEN 2 THEN N' tūkstoši '
				   WHEN 3 THEN N' milioni '
				   WHEN 4 THEN N' miljardi '
				   WHEN 5 THEN N' triljoni '
				   WHEN 6 THEN N' kvadriljoni '
				   WHEN 7 THEN N' kvintiljoni '
				   WHEN 8 THEN N' sekstiljoni '
				   WHEN 9 THEN N' septiljoni '
				   WHEN 10 THEN N' octillios '
				   WHEN 11 THEN N' nonillion '
				   WHEN 12 THEN N' decillion '
				   WHEN 13 THEN N' undecillion '
				   ELSE '' END;

	--set @tentonesstring = @tentonesstring + ' -' + @chunk + '- ';

		SELECT @tensones = SUBSTRING(@chunk, 2, 2)
			 , @hundreds = SUBSTRING(@chunk, 1, 1)
			 , @tens = SUBSTRING(@chunk, 2, 1)
			 , @ones = SUBSTRING(@chunk, 3, 1)		
		-- If twenty or less, use the word directly from @NumbersTable
		IF CONVERT(INT, @tensones) <= 20 OR @Ones='0' BEGIN
			  SET @outputString = (SELECT word
								  FROM @NumbersTable
								  WHERE @tensones = number)
			   + @tentonesstring + @outputString
			END
		ELSE BEGIN -- break down the ones and the tens separately
		 SET @outputString = ' '
						+ (SELECT word
								FROM @NumbersTable
								WHERE @tens + '0' = number)
								   + ' '
						 + (SELECT word
								FROM @NumbersTable
								WHERE '0'+ @ones = number)
			   + @tentonesstring + @outputString
		END

		IF @hundreds = '1' set @hundredstring = 'simts'
		else set @hundredstring = 'simti'

		-- now get the hundreds
		IF @hundreds <> '0' BEGIN
			  SET @outputString  = (SELECT word
								  FROM @NumbersTable
								  WHERE '0' + @hundreds = number)
									  + ' ' + @hundredstring + ' '
							+ @outputString
		END
  END
  SELECT @counter = @counter + 1
	   , @position = @position - 3
END
set @outputString = @MinusText + @outputString;
-- Remove any double spaces
SET @outputString = LTRIM(RTRIM(REPLACE(@outputString, '  ', ' ')))
SET @outputstring = UPPER(LEFT(@outputstring, 1)) + SUBSTRING(@outputstring, 2, 8000)
set @outputString = @outputString + ' ' + @Currencybig + ' ' + @NumberTextDecimal + ' ' + @CurrencySmall
RETURN @outputString -- return the result
END
GO

Labots - Mr.Līkrocis
Link to comment
Share on other sites

Kur tik garš? Man excelī iekš VBA bija debīls un līks, lā arī tikai līdz 1 000 000 (neieskaitot) strādāja, bet paskatoties pēc daudziem gadiem kodu, biku šokēts kur tik vienkārši sanācis... Pameklēt un iedot?

Link to comment
Share on other sites

Neaizmirstiet tik:

1 lats

11 lati

21 lats

101 lats

111 lati

 

Un šaubos par "latu" pareizību.

Labots - japets
Link to comment
Share on other sites

Izveido kontu, vai pieraksties esošajā, lai komentētu

Jums ir jābūt šī foruma biedram, lai varētu komentēt tēmas

Izveidot jaunu kontu

Piereģistrējies un izveido jaunu kontu, tas būs viegli!

Reģistrēt jaunu kontu

Pierakstīties

Jums jau ir konts? Pierakstieties tajā šeit!

Pierakstīties tagad!
 Share

×
×
  • Izveidot jaunu...