Office Guru

Alfanumerikus randomizálás - avagy véletlen generálás betűkkel és egyéb karakterekkel

2017. november 05. - Office Guru

Azt ugyebár a legtöbb Excel-felhasználó tudja, hogyan generálhat véleletlenszerűen számokat, többek között például a RANDBETWEEN vagy éppen a RAND függvények segítségével - előbbinél ugyebár a tartományt tudjuk megadni, utóbbinál pedig 0 és 1 között fogunk számot generálni, amit aztán megszorozhatunk mondjuk százzal, kerekíthetjük egészre és így tovább. Na de mi van akkor, ha alfanumerikus értéket szeretnénk véletlenszerűen generálni? Ez tipikusan egy olyan példa, hogy ha a formulás megoldást ismerjük, akkor nagyjából ismerjük a VBA-s megoldás logikáját is, hiszen teljesen ugyanúgy gondolkodunk mindkét esetben.

Elsőként lássuk a függvényes megoldást! Mielőtt ugyebár meg akarjuk alkotni a kis függvényünket, tudnunk kell, hogy mit is szeretnénk - kisbetűt, nagybetűt, speciális karaktert, számokat stb.. Tegyük fel mostani példánknál, hogy számokat és kis- valamint nagybetűket szeretnénk majd mondjuk 8 karakter hosszúságban generálni.

Ez azt jelenti számunkra, hogy három lehetőségünk van minden karakter esetében: kisbetű, nagybetű vagy éppen szám. Hogy melyik legyen, azt véletlenül kell eldöntenünk, tehát a függvényünk egyik eleme biztosan egy

RANDBETWEEN(1,3)

lesz. Ha ennek eredménye mondjuk egy, akkor legyen szám, ha kettő, akkor nagybetű, ha három, akkor kisbetű - melyik függvény tud az első paramétere alapján választani a további paraméterei között? A CHOOSE a mi barátunk, ami ugyebár az első paramétereként megadott index alapján választja ki, hogy a további paramétereinként megadott értékek/formulák közül melyiket adja vissza.

Még egy fontos dolgot érdemes előkeresnünk nagy hirtelen a függvény összepakolása előtt - ez pedig egy ASCII táblázat, hogy tudjuk mely ASCII értékek adnak vissza számot és melyek betűt. Azaz valószínűleg függvényünknek egy számjegyet kell visszaadnia és ezt a számjegyet egy CHAR függvény segítségével fogjuk értékké alakítani. Ennyi bevezető után ez lenne a megoldás egy karakterre:

=CHAR(CHOOSE(RANDBETWEEN(1,3),RANDBETWEEN(48,57),

RANDBETWEEN(65,90),RANDBETWEEN(97,122)))

A fentiek alapján azért elég egyértelmű, hogy mi is történik itt, a CHOOSE első paramétereként megadott RANDBETWEEN visszaad egy értéket 1 és 3 között, majd ezen érték alapján fogja visszaadni nekünk az adott számú paraméterben lévő RANDBETWEEN eredményét. Ezek a RANDBETWEEN függvények és számaik pedig az ASCII táblából fogják megadni a szükséges karaktert, legyen az kisbetű, nagybetű avagy szám (ugyebár az ASCII táblában 48 és 57 között vannak a számok, 65 és 90 között a nagybetűk, 97 és 122 között pedig a kisbetűk). Egy 8 karakterből álló érték esetén pedig a fenti formulát kell megismételnünk nyolcszor, tehát az látható, hogy bár megoldásnak megoldás, elég munkás is lehet, ha sok karakterről beszélünk.

Ebből a szempontból tehát mindenképpen jobb a VBA-s megoldás, ami egyébként hasonló logikával működik. Az egyszerűség kedvéért most csak számokkal és nagybetűkkel dolgozom, illetve egy változóba be is fogjuk pakolni a teljes, 8 karakterből álló értéket, de értelemszerűen még egy IF segítségével a kisbetűt is be tudjuk tenni könnyedén.

Első lépésként a szokott módon definiálunk két változót, egyet a végeredmény tárolására, egyet pedig a ciklushoz:

Sub randomizer()
Dim random As String
Dim i As Integer
Randomize

A Randomize funkció meghívása azért szükséges a kódunkban, mert ennek segítségével fogjuk biztosítani, hogy a későbbiekben használt Rnd funkció tényleg véletlen számokat generáljon és ne legyen ismétlődés. Innentől kezdve pedig jön a ciklus:

For i = 1 To 8
If Int((2 * Rnd) + 1) = 1 Then
random = random & Chr(Int(26 * Rnd + 65))
Else
random = random & Int(10 * Rnd)
End If
Next i

Elsőre tűnik csak komplexnek, pedig nem az, nagyjából ugyanaz van itt, mint a RANDBETWEEN és CHOOSE formuláknál, azaz elsőként csinál egy "RANDBETWEENT" VBA-ban is (If Int((2 *Rnd) + 1) = 1), azaz az Rnd funkció standard utasításával generálunk vagy egy egyest vagy egy kettest. Amennyiben egyes az eredmény, akkor a következő fog történni:

random = random & Chr(Int(26 * Rnd + 65))

Azaz a random változóban eddig szereplő értékhez hozzáad egy olyan karaktert, amelyet egy 65 és 91 között generált egész szám jelent az ASCII táblában. Ugyebár az Int azért kell, hogy egész számról legyen szó, a Chr pedig azért kell, hogy az ASCII táblából adja vissza az értékünket.

Az Rnd funkcióval számot egyébként a következőképp tudunk generálni véletlenszerűen:

Int ((Felső értékhatár - Alsó értékhatár + 1) * Rnd + Alsó értékhatár)

Szóval visszatérve a kódunkhoz, amennyiben az első feltétel nem teljesül, tehát kettest generáltunk, akkor az Else-re ugrunk:

random = random & Int(10 * Rnd)

Ezzel pedig a random változónkba fog bekerülni az eddigi értékek mellé egy szám 1 és 10 között - vegyük észre, hogy itt nincs Char utasítás, hiszen csak egy egész számra van szükségünk, nem pedig speciális karakterre, betűre.

Sub randomizer()
Dim random As String
Dim i As Integer
Randomize
For i = 1 To 8
If Int((2 * Rnd) + 1) = 1 Then
random = random & Chr(Int(26 * Rnd + 65))
Else
random = random & Int(10 * Rnd)
End If
Next i
ActiveSheet.Range("A1").Formula = random
End Sub

És ezzel egyébként kész is a kód, hiszen utolsó lépésként szimplán beírjuk az A1 cellába az eredményt.

A bejegyzés trackback címe:

https://officeguru.blog.hu/api/trackback/id/tr713187214

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

2017.11.07. 21:55:22

hogy a kisbetű benne (és egy kicsit szebb is) legyen:
Sub randomizer()

Dim random, egykar As String
Dim i As Integer
Randomize
For i = 1 To 8

Select Case Int((3 * Rnd) + 1)
Case 1
egykar = Chr(Int(26 * Rnd + 65))
Case 2
egykar = Chr(Int(26 * Rnd + 97))
Case 3
egykar = Int(10 * Rnd)
End Select

random = random + egykar

Next i
ActiveSheet.Range("A1").Formula = random
End Sub

/nem nehéz észrevenni, hogy egy kis aritmetikai zsonglőrködéssel a kis/nagy-betű rész könnyen optimalizálható lenne, de egyrészt nem ér annyit, másrészt így lehetőséget ad egyszerűen alakítani a kódot pld. olyanná, hogy a betű/BETŰ/szám valószínűség ne 1/3-ad legyen/
süti beállítások módosítása