Pewnego dnia, podczas pracy nad aplikacją dla naszego klienta, pojawiła się potrzeba, która polegała na konwersji wartości liczbowej na tekst reprezentujący tę wartość. To znaczy, aby przedstawić 345,60 jako "trzy tysiące czterdzieści pięć 60/100" na przykład. Podczas generowania dokumentów kosztowych aplikacja miała wstawiać tekst w polu "cena" oprócz wartości liczbowej. Cały projekt, jak to zwykle u nas bywa, oparty był o Google Workspace. Aplikacja została stworzona przy pomocy platformy AppSheet. Napisanie formuły w AppSheet, która wykonałaby to zadanie, było ostatnią rzeczą, o której myślałem. Będąc zaznajomionym z Apps Script (JS) pomyślałem, że wystawię taki endpoint, który zwróci podaną wartość liczbową w postaci tekstu, a na dodatek przetłumaczoną na wybrany język. Jeśli chcesz zobaczyć jak to zrobiłem, przeczytaj artykuł do końca.
Wszystko zaczęło się jak zwykle od tego miejsca, Google Apps Script IDE. Może on wyglądać tak jak na zdjęciu, ale nie musi. Ja na przykład korzystam z dodatku do Google Chrome 👉 Black Apps Script, który zamienia standardowy edytor w potężne narzędzie z ciemnym tłem - polecam 😎
Google Apps Script daje nieszablonowe, niesamowite możliwości przy stosunkowo niewielkim nakładzie czasu i pracy. Znając JavaScript, HTML i CSS, można napisać w pełni funkcjonalne rozwiązania webowe w kilka godzin. Tak właśnie powstał projekt "Kwoty słownie".
"Kwoty słownie" jest samodzielnym skryptem hostowanym na Dysku Google, do którego dostęp mam tylko ja, natomiast z zaimplementowanej na jego podstawie aplikacji może korzystać każdy, kto posiada konto Google.
Na początek rozłożyłem przykład pewnej kwoty na części pierwsze, dzięki czemu wyodrębniłem i zdefiniowałem odpowiednio setki, dziesiątki, jedności, grupy, itp. Jestem Polakiem, więc kod wygląda następująco:
var jednosci = ["", " jeden", " dwa", " trzy", " cztery", " pięć", " sześć", " siedem", " osiem", " dziewięć"];
var nascie = ["", " jedenaście", " dwanaście", " trzynaście", " czternaście", " piętnaście", " szesnaście", " siedemnaście", " osiemnaście", " dziewietnaście"];
var dziesiatki = ["", " dziesięć", " dwadzieścia", " trzydzieści", " czterdzieści", " pięćdziesiąt", " sześćdziesiąt", " siedemdziesiąt", " osiemdziesiąt", " dziewięćdziesiąt"];
var setki = ["", " sto", " dwieście", " trzysta", " czterysta", " pięćset", " sześćset", " siedemset", " osiemset", " dziewięćset"];
var grupy = [
["", "", ""],
[" tysiąc", " tysiące", " tysięcy"],
[" milion", " miliony", " milionów"],
[" miliard", " miliardy", " miliardów"],
[" bilion", " biliony", " bilionów"],
[" biliard", " biliardy", " biliardów"],
[" trylion", " tryliony", " trylionów"]
];
Następnie za pomocą metody floor() interfejsu Math przekształcam przekazaną wartość w liczbę całkowitą, a za pomocą metody round((value - integer) * 100) interfejsu Math w liczbę dziesiętną.
var calkowita = Math.floor(liczba);
var dziesietna = Math.round((liczba - calkowita) * 100);
Jeśli liczba całkowita i dziesiętna są równe zero, ostateczna odpowiedź również będzie równa "zero":
if (calkowita == 0 && dziesietna == 0) {
wynik = "zero";
}
Jeśli przekazana wartość jest mniejsza od zera, definiuję zmienną "sign" równą "minus" i neguję ją → "-liczba":
if (liczba < 0) {
znak = "minus";
liczba = -liczba;
calkowita = -calkowita;
}
Następnym krokiem jest obsługa części całkowitej:
var g = 0;
while (calkowita > 0) {
var s = Math.floor((calkowita % 1000) / 100);
var n = 0;
var d = Math.floor((calkowita % 100) / 10);
var j = Math.floor(calkowita % 10);
if (d == 1 && j > 0) {
n = j;
d = 0;
j = 0;
}
var k = 2;
if (j == 1 && s + d + n == 0)
k = 0;
if (j == 2 || j == 3 || j == 4)
k = 1;
if (s + d + n + j > 0)
wynik = setki[s] + dziesiatki[d] + nascie[n] + jednosci[j] + grupy[g][k] + wynik;
g++;
calkowita = Math.floor(calkowita / 1000);
}
Kod iteruje przez cyfry liczby, grupując je w zestawy po trzy. Dla każdej grupy określa odpowiednią reprezentację tekstową na podstawie reguł specyficznych dla języka zakodowanych w tablicach. Ostateczna reprezentacja tekstowa jest tworzona przez połączenie reprezentacji tekstowych każdej grupy. Na przykład, jeśli liczbą wejściową jest 1234567, kod podzieli ją na trzy grupy: 1, 234 i 567. Następnie przekonwertowałby każdą grupę na jej tekstowy odpowiednik (np. "milion", "dwieście trzydzieści cztery tysiące", "pięćset sześćdziesiąt siedem") i połączył je, tworząc ostateczny wynik.
Następnie musimy zająć się obsługą części dziesiętnej:
if (dziesietna > 0) {
wynik += " " + dziesietna + "/100";
}
Na koniec konstruuje przekazaną wartość do postaci tekstowej:
var result = znak + wynik;
Z kolei na podstawie wybranego języka tłumaczę tekst za pomocą interfejsu LanguageApp w Apps Script:
if (jezyk && typeof jezyk === "string") {
var resultTranslated = LanguageApp.translate(result, "pl", jezyk, {contentType: 'text'})
}
Następnie zwracam wynik końcowy:
return ContentService.createTextOutput(result + " | " + resultTranslated);
Sposób, w jaki przekazuję parametry do mojej funkcji, polega na użyciu ciągu zapytania. Implementując projekt Apps Script jako aplikację internetową, otrzymujemy adres URL, za pomocą którego otwieramy projekt. Za każdym razem, gdy próbujemy uruchomić ten link, wykonywana jest napisana przeze mnie funkcja "doGet(e)", do której przekazywany jest parametr "e". Wyciągam z niego wartość liczbową i język, na który ma zostać przetłumaczony końcowy tekst.
function doGet(e) {
var jezyk = e.parameter.language;
var liczba = JSON.parse(e.parameter.number);
...
Przykładowy adres URL, którego używam, wygląda następująco:
{{apps_script_deployment_url}} + "?" + "number=90456.70" + "&" + "language=en"
Tutaj możesz wypróbować ten projekt. Baw się parametrami w ciągu zapytania, a uzyskasz różne wyniki. Powodzenia!