Modul:Formattal
Udseende
![]() | Dette Lua-modul bruges på ca. 8.500 sider, og derfor vil ændringer blive bemærket af mange. Vær venlig at afprøve enhver ændring i modulets /sandkasse eller /test-undersider, eller i din egen module sandkasse. Du bør også overveje at diskutere ændringer på diskussionssiden før du implementerer dem. |
Utilstrækkelig vejledning Dette modul bør have en (bedre) vejledning, helst med eksempler på anvendelse. Hvis andre moduler er nyere og/eller bedre, bør der henvises til dem. |
Brug
{{#invoke:Formattal|function_name}}
local p = {}
p.angivFejlMedRoedStjerneOgFejlbeskrivelse = false
local fejlkategorikode = "[[Kategori:Sider med tal hvis format ikke kendes af formattal]]"
--[[
formattal(frame)
Formaterer et ikke-negativt tal med højst to decimaler på dansk. Det
oprindelige tal kan enten bruge punktum som decimaladskiller og komma som
tusindadskiller ("123,456,789.12"), eller komma som decimaladskiller og
punktum som tusindadskiller ("123.456.789,12").
Uanset hvordan tallet var formateret i input, formateres det i output på dansk
vis med punktum som tusindadskiller og komma som decimaladskiller.
Eksempler:
Opfattes som 6-cifret heltal, da tallet ikke må have mere end to decimaler:
formattal("123456") = "123.456"
formattal("123,456") = "123.456"
formattal("123.456") = "123.456"
Opfattes som 5-cifret tal med 2 decimaler:
formattal("123,45) = "123,45"
formattal("123.45") = "123,45"
Giver fejl for ukendt format (negativt tal):
formattal("-123") = "-123"
Giver fejl for ukendt format (tusindadskiller og decimaltegn er ens):
formattal("123.456.7") = "123.456.7"
Giver fejl for ukendt format (bruger forskellige tusindadskillere eller
har for mange decimaler):
formattal("123.456,789") = "123.456,789"
Alle HTML-kommentarer og visse blanktegn i tallet ignores; andre uvedkommende
tegn vil give fejl.
Ved fejl returneres tallet uændret samtidig med at artiklen placeres i
fejlkategorien "Sider med tal hvis format ikke kendes af formattal".
]]
function p.formattal (frame)
local originaltInput = (frame.args[1] or "")
-- Fjern HTML-kommentarer og ydre blanktegn.
local inputUdenEventuelleHtmlKommentarerOgBlanktegn
= p.fjernHtmlkommentarerOgYdreBlanktegn(originaltInput)
-- Opdel i inputtal (fx "-1.234.553,43" eller "")
-- og inputrest (fx "<ref>…</ref>" eller "").
local inputtal, inputrest
= p.opdelInputITalOgRest(inputUdenEventuelleHtmlKommentarerOgBlanktegn)
-- Opdel tallet (inputtal) i enkeltdele.
-- Dette kan fejle, og så vil fejltekstEllerNil være ikke-nil og indeholde
-- en fejlbeskrivelse.
local eventueltFortegnEllerTom, heltalsdelUdenTusindadskillere,
decimalerEllerNil, fejltekstEllerNil = p.opdelTal(inputtal)
-- Returner output (enten formateret tal eller fejl).
if not fejltekstEllerNil then
-- Succes. Tallet er fuldt fortolket og opdelt i enkeltdele.
local outputtal
= p.danOutputtal(
eventueltFortegnEllerTom,
heltalsdelUdenTusindadskillere,
decimalerEllerNil)
return outputtal .. inputrest
else
-- Fejlsituation.
local fejltekst = fejltekstEllerNil -- Den kan ikke længere være nil.
return p.danSamletFejlreturstreng(inputtal, inputrest, fejltekst,
p.angivFejlMedRoedStjerneOgFejlbeskrivelse)
end
end
function p.opdelInputITalOgRest(s)
-- Opdel i inputtal (fx "-1.234.553,43") og inputrest (fx "<ref>…</ref>" eller "").
-- Mønsteret er designet, så det ikke kan fejle.
local inputtal, inputrest = s:match("^([+-]?[%d,.]*)(.*)$")
return inputtal, inputrest
end
function p.fjernHtmlkommentarerOgYdreBlanktegn(s)
-- Fjern HTML-kommentarer
local sUdenEventuelleHtmlKommentarer
= string.gsub(s, "<!%-%-.-%-%->", "")
-- Fjern blanktegn i enderne
local sUdenEventuelleHtmlKommentarerOgBlanktegn
= mw.text.trim(sUdenEventuelleHtmlKommentarer)
return sUdenEventuelleHtmlKommentarerOgBlanktegn
end
function p.danOutputtal(eventueltFortegnEllerTom,
heltalsdelUdenTusindadskillere, decimalerEllerNil)
local heltalsdelMedTusindadskillere = p.indsaetTusindadskillere(heltalsdelUdenTusindadskillere)
local decimaldel = p.danDecimaldel(decimalerEllerNil) -- "" eller ",12"
local samletTal
= eventueltFortegnEllerTom .. heltalsdelMedTusindadskillere .. decimaldel
return samletTal
end
function p.danDecimaldel(decimalerEllerNil)
if decimalerEllerNil then
return "," .. decimalerEllerNil
else
return ""
end
end
function p.fejlangivelseskode(fejltekst, angivFejlMedRoedStjerneOgFejlbeskrivelse)
if angivFejlMedRoedStjerneOgFejlbeskrivelse then
return '<sup><span style="color:red" title="Skabelonen Formattal kan ikke konvertere dette tal: ' .. fejltekst .. '">*</span></sup>'
else
return ""
end
end
function p.danSamletFejlreturstreng(inputtal, inputrest, fejltekst,
angivFejlMedRoedStjerneOgFejlbeskrivelse)
return
inputtal
.. p.fejlangivelseskode(fejltekst, angivFejlMedRoedStjerneOgFejlbeskrivelse)
.. inputrest
.. fejlkategorikode
end
--[[
Returnerer
eventueltFortegnEllerTom, heltalsdelUdenTusindadskillere, decimaler, fejltekstEllerNil.
Hvis fejltekstEllerNil ikke er nil, gik det godt. Ellers indeholder fejltekstEllerNil en
beskrivelse af fejlen.
Decimaler er nil, hvis der ingen decimaler er.
]]
function p.opdelTal(inputtal)
local fejltekstEllerNil = nil
local heltalsdelUdenTusindadskillere = nil
-- Fjern et evt. fortegn på første position og husk det.
local eventueltFortegnEllerTom, inputtaldelUdenEventueltFortegn
= p.opsplitIFortegnOgRest(inputtal)
-- Prøv at matche et kommatal med 1 eller 2 decimaler.
local heltalsdelMedEventuelleTusindadskillere, decimaladskiller, decimaler
= inputtaldelUdenEventueltFortegn:match("^([%d,.]-)([,.])(%d%d?)$")
-- Afgør om der var et match.
-- Hvis ikke der er et match, vil både heltalsdel, decimaladskiller
-- og decimaler være nil.
local derVarEtMatch = (heltalsdelMedEventuelleTusindadskillere ~= nil)
if derVarEtMatch then
-- Der var et match: Tallet er et kommatal med 1 eller 2 decimaler.
-- Bestemt tusindadskillertegnet.
-- Bemærk at decimaladskiller logisk kun kan være "." eller ","
-- pga. mønsteret ovenfor.
local tusindadskillertegnIInput = p.modsatAdskillertegn(decimaladskiller)
-- Fjern alle tusindadskillertegn fra heltalsdel.
heltalsdelUdenTusindadskillere
= p.removeAll(heltalsdelMedEventuelleTusindadskillere, "[" .. tusindadskillertegnIInput .. "]")
else
-- Der var ikke et match. Hvis tallet er på korrekt form, er det et heltal.
local heltalsdelMedEventuellePunktumtusindadskillere
= inputtaldelUdenEventueltFortegn:match("^([%d.]+)$")
if heltalsdelMedEventuellePunktumtusindadskillere then
heltalsdelUdenTusindadskillere
= p.removeAll(heltalsdelMedEventuellePunktumtusindadskillere, "%.")
else
local heltalsdelMedEventuelleKommatusindadskillere
= inputtaldelUdenEventueltFortegn:match("^([%d,]+)$")
if heltalsdelMedEventuelleKommatusindadskillere then
heltalsdelUdenTusindadskillere
= p.removeAll(heltalsdelMedEventuelleKommatusindadskillere, ",")
else
-- Angiv fejl.
heltalsdelUdenTusindadskillere = nil
if inputtal == "" then
fejltekstEllerNil = "Tallet er tomt."
else
fejltekstEllerNil = "Kunne ikke fortolke tallet '" .. inputtal .. "'."
end
end
end
end
if not fejltekstEllerNil then
-- Håndter situationer som ".12" = 0,12.
if heltalsdelUdenTusindadskillere == "" then
heltalsdelUdenTusindadskillere = "0"
end
-- Tjek for ugyldige tusindadskillere.
if heltalsdelUdenTusindadskillere:match("%D") then
-- Fejlsituation: Heltalsdelen uden tusindadskillere indeholder
-- mindst ét ikke-ciffer (%D), som kun kan være en forkert
-- tusindadskiller.
fejltekstEllerNil = "Heltalsdelen '" .. heltalsdelUdenTusindadskillere .. "' indeholder ugyldige tusindadskillere; hele tallet er '" .. inputtal .. "'."
eventueltFortegnEllerTom = ""
heltalsdelUdenTusindadskillere = nil
decimaler = nil
end
end
return eventueltFortegnEllerTom, heltalsdelUdenTusindadskillere, decimaler, fejltekstEllerNil
end
function p.removeAll(s, pattern)
return s:gsub(pattern, "")
end
--[[
Returner det modsatte adskillertegn til det givne.
adskillertegn:
Enten "." eller ",".
Returværdi:
"." hvis adskillertegn er ",".
"," hvis adskillertegn er ".".
]]
function p.modsatAdskillertegn(adskillertegn)
if adskillertegn == "." then
return ","
else
return "."
end
end
function p.opsplitIFortegnOgRest(s)
local eventueltFortegnEllerTom, reststrengUdenFortegn = s:match("^([+-]?)(.*)$")
return eventueltFortegnEllerTom, reststrengUdenFortegn
end
--[[
p.indsaetTusindadskillere(heltalsStreng)
Hjælpefunktion.
Indsæt tusindadskillere i en given streng af cifre.
Eksempler:
p.indsaetTusindadskillere("") == ""
p.indsaetTusindadskillere("1") == "1"
p.indsaetTusindadskillere("12") == "12"
p.indsaetTusindadskillere("123") == "123"
p.indsaetTusindadskillere("1234") == "1.234"
p.indsaetTusindadskillere("123456789") == "123.456.789"
]]
function p.indsaetTusindadskillere(heltalsstreng)
local akkumulator = heltalsstreng -- Heltal uden tusindadskillere, fx "123456789".
local antalTusindAdskillereIndsat
repeat
akkumulator, antalTusindAdskillereIndsat
= string.gsub(akkumulator, "^(%d+)(%d%d%d)", '%1.%2')
until antalTusindAdskillereIndsat == 0
return akkumulator -- Heltal med tusindadskillere, fx "123.456.789".
end
return p