How to generate a random alphanumeric string with a formula in Excel (or Google Sheets or LibreOffice) - excel

I'm trying to generate a random 8 character alphanumeric string in Excel (or Google Sheets or Libreoffice, which both have the same challenge) using a formula. I'd like to get something like this:
6n1a3pax
I've tried various formulae including ones like this which generate the ASCII characters for individual random numbers between an upper and lower number:
=CHAR(RANDBETWEEN(65,90)) & CHAR(RANDBETWEEN(65,90)) & CHAR(RANDBETWEEN(65,90)) &CHAR(RANDBETWEEN(65,90))& CHAR(RANDBETWEEN(65,90)) & CHAR(RANDBETWEEN(65,90)) & CHAR(RANDBETWEEN(65,90)) & CHAR(RANDBETWEEN(65,90))
However, they're lengthy, you have to repeat the RANDBETWEEN() function multiple times inside a formula, and you can't choose both "alpha" and "numeric" in the same RANDBETWEEN().
Is there any easy way to do this in Excel, Google Sheets or LibreOffice Calc? If a solution works in one and not in the others then great if you can mention which one(s).
(N.B. This is not a duplicate of questions about how to stop recalculation of randomisation functions in Excel)

in GS try:
=LAMBDA(x, x)(DEC2HEX(RANDBETWEEN(0, HEX2DEC("FFFFFFFF")), 8))
if that's not enough and you need
A-Z char 65-90
a-z char 97-122
0-9 char 48-58
=JOIN(, BYROW(SEQUENCE(8), LAMBDA(x, IF(COINFLIP(), IF(COINFLIP(),
CHAR(RANDBETWEEN(65, 90)), CHAR(RANDBETWEEN(97, 122))), RANDBETWEEN(0, 9)))))
frozen:
=LAMBDA(x, x)(JOIN(, BYROW(SEQUENCE(8), LAMBDA(x, IF(COINFLIP(), IF(COINFLIP(),
CHAR(RANDBETWEEN(65, 90)), CHAR(RANDBETWEEN(97, 122))), RANDBETWEEN(0, 9))))))
alternative (with better distribution):
=JOIN(, BYROW(SEQUENCE(8), LAMBDA(x, SINGLE(SORT(CHAR({
SEQUENCE(10, 1, 48);
SEQUENCE(26, 1, 65);
SEQUENCE(26, 1, 97)}),
RANDARRAY(62, 1), )))))
or frozen:
=LAMBDA(x, x)(JOIN(, BYROW(SEQUENCE(8), LAMBDA(x, SINGLE(SORT(CHAR({
SEQUENCE(10, 1, 48);
SEQUENCE(26, 1, 65);
SEQUENCE(26, 1, 97)}),
RANDARRAY(62, 1), ))))))
for more see: stackoverflow.com/questions/66201364

LibreOffice Calc 7.x:
A non-volatile option for LibreOffice Calc 7.x is the use of the RANDBETWEEN.NV() function:
Formula in A1:
=CONCAT(IF({1,2,3,4,5,6,7,8},MID("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",RANDBETWEEN.NV(1,62),1),))
Note that using ROW(1:8) would still force recalculation when any value in rows 1-8 have been made (thus volatile):
=CONCAT(IF(ROW(1:8),MID("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",RANDBETWEEN.NV(1,62),1),))
Excel ms365:
Unfortunately there is, AFAIK, not a non-volatile Excel equivalent to this function. If volatility is not a problem, then try:
=CONCAT(MID("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",RANDARRAY(8,,1,62,1),1))

Here's my take, for Google Sheets:
=lambda(_,
_
)(
lambda(
numWords, wordLength, charRegex, ascii,
lambda(
alphabet,
map(
sequence(numWords),
lambda(_,
concatenate(
map(
sequence(wordLength),
lambda(_,
mid(alphabet, randbetween(1, len(alphabet)), 1)
)
)
)
)
)
)(concatenate(filter(ascii, regexmatch(ascii, charRegex))))
)(10, 8, "[0-9a-zA-Z]", arrayformula(char(sequence(127))))
)
The formula will generate 10 passwords of 8 characters each from an alphabet that includes lower and upper case letters, and digits.
To choose which characters to include in the alphabet, replace [0-9a-zA-Z] with another regex like [0-9a-z!#$%&/] or [-!#$%&/\w]. Note that you may need to \escape any regex special characters there.
The pattern avoids the non-uniform distribution issues that plague some of the solutions presented in this thread. The ones that use coinflip() or isodd(rand()*N) will give results that overrepresent smaller sub alphabets like 0-9. The ones that use sort() will not repeat any chars in the result, which is not optimal.

It's possible to do this in Excel using a combination of the following functions:
SEQUENCE() VSTACK() RANDARRAY() CHAR() INDEX() TEXTJOIN()
Unfortunately this doesn't work in LibreOffice (at the moment) as it does not have the SEQUENCE() function. It does not work in Google Sheets as the RANDARRAY() function only takes 2 parameters and the VSTACK() function does not exist, although you can use braces and a semicolon, e.g. {SEQUENCE(26,1,97,1);SEQUENCE(10,1,48,1)}.
Here's the formula you need:
Upper-case e.g "413BK5S0": =TEXTJOIN("",1,INDEX(CHAR(VSTACK(SEQUENCE(26,1,65,1),SEQUENCE(10,1,48,1))),RANDARRAY(8,1,1,36,TRUE)))
Lower-case e.g. "b8etbno8": =TEXTJOIN("",1,INDEX(CHAR(VSTACK(SEQUENCE(26,1,97,1),SEQUENCE(10,1,48,1))),RANDARRAY(8,1,1,36,TRUE)))
The following explanation for each function:
SEQUENCE() - a sequence of e.g. 26 numbers, in 1 column, starting at number 65, increasing by 1 each time (with the second incidence of the function being 10 numbers starting at 48)
VSTACK() - combine the 2 SEQUENCE() formulae into 1 array (sequence) of numbers
CHAR() - the ASCII character associated with a decimal ASCII number (where the decimal number is generated by the SEQUENCE() function) - see https://www.asciitable.com/
RANDARRAY() - an array of 8 random numbers, 1 column wide, minimum number 1, maximum 36
INDEX() - the value from each element within the sequence of characters, where each of 8 element numbers is provided by RANDARRAY()
TEXTJOIN() - join the values in an array together into one cell, with no separator and ignoring empty values

What do you think of something like this?
=CONCATENATE(BYROW(SEQUENCE(8),LAMBDA(e,IF(ISODD(ROUNDUP(RAND()*10)),CHAR(RANDBETWEEN(65,90)),ROUNDDOWN(RAND()*10)))))
If you want to include lower case, you can do a similar logic:
=CONCATENATE(BYROW(SEQUENCE(8),LAMBDA(e,IF(ISODD(ROUNDUP(RAND()*10)),IF(ISODD(ROUNDUP(RAND()*10)),CHAR(RANDBETWEEN(65,90)),CHAR(RANDBETWEEN(97,122))),ROUNDDOWN(RAND()*10)))))
The logic is the next one: what I'm doing is with ISODD(ROUNDUP(RAND()*10) generating a random number between 1 and 10 and checking if it's odd. If it is, it generates a letter or else it generates a number. With CONCATENATE(BYROW(SEQUENCE(8)... I'm doing this 8 times and concatenating them. What I just added was a second "random and odd" time when it's time to generate a letter so you can have upper and lower case

Related

How do I find the last number in a string with excel formulas

I'm parsing strings in excel, and I need to return everything through the last number. For example:
Input: A00XX
Output: A00
In my case, I know the last number will be between index 3 and 5, so I'm brute-forcing it with:
=LEFT([#Point],
IF(SUM((MID([#Point],5,1)={"0","1","2","3","4","5","6","7","8","9"})+0),5,
IF(SUM((MID([#Point],4,1)={"0","1","2","3","4","5","6","7","8","9"})+0),4,
IF(SUM((MID([#Point],3,1)={"0","1","2","3","4","5","6","7","8","9"})+0),3,
))))
Unfortunately, I've run into some edge cases where the numbers extended beyond index 5. Is there a generic way to find the last number in a string using excel formulas?
Note:
I've tried =MAX(SEARCH(... but it returns the index of the first number, not the last.
As a starting point: if we know the position of the last number, we can use LEFT to get the string to that point. Suppose that the position is 5:
=LEFT(A1, 5)
But, we don't know the position of the last number. Now, what if the only valid number was 0, and it only appeared once: then we could use FIND to locate the position of the number:
=LEFT(A1, FIND(0, A1))
But, we have more than one valid number. Suppose that we had all the numbers from 0 through 9, but each number could only appear once — then we could use MAX on a FIND array, to tell us which of the numbers is the last one:
=LEFT(A1, MAX(FIND({0,1,2,3,4,5,6,7,8,9}, A1)))
Unfortunately, FIND will throw a #VALUE! error any number doesn't appear, which will then make MAX return the same error. So, we need to fix that with IFERROR:
=LEFT(A1, MAX(IFERROR(FIND({0,1,2,3,4,5,6,7,8,9}, A1), 0)))
However, numbers can appear more than once. As such, we need a method to find the last occurrence of a value in a string (since FIND and SEARCH will, by default, return the first occurrence).
The SUBSTITUTE function has 3 mandatory arguments — Initial String, Value to be Replaced, Value to Replace with — and one Optional argument — the occurrence to replace. Normally, this is omitted, so that all occurrences are replaced. But, if we know how many times a character appears in a string, then we can replace just the last instance with a special/uncommon sub-string to search for.
To count how many times a character appears in a String, just start with the length of the String, then subtract the length when you SUBSTITUTE all copies of that character for Nothing:
=LEN(A1) - LEN(SUBSTITUTE(A1, 0, ""))
This means we can now replace the last occurrence of the character with, for example, ">¦<", and then FIND that:
=FIND(">¦<", SUBSTITUTE(A1, 0, ">¦<", LEN(A1) - LEN(SUBSTITUTE(A1, 0, ""))))
Of course, we want to do this for all the numbers from 0 to 9, and take the MAX value (remembering our IFERROR), so we need to put the Array of values back in:
=MAX(IFERROR(FIND(">¦<", SUBSTITUTE(A1, {0,1,2,3,4,5,6,7,8,9}, ">¦<", LEN(A1) - LEN(SUBSTITUTE(A1, {0,1,2,3,4,5,6,7,8,9}, "")))), 0))
Then, we plug that all back into our initial LEFT function:
=LEFT(A1, MAX(IFERROR(FIND(">¦<", SUBSTITUTE(A1, {0,1,2,3,4,5,6,7,8,9}, ">¦<", LEN(A1) - LEN(SUBSTITUTE(A1, {0,1,2,3,4,5,6,7,8,9}, "")))), 0)))
An alternative, assuming that the length of the string in question will never be more than 9 characters (which seems a safe assumption based on your description):
=LEFT(A1,MATCH(0,0+ISERR(0+MID(A1,{1;2;3;4;5;6;7;8;9},1))))
This, depending on your version of Excel, may or may not require committing with CTRL+SHIFT+ENTER.
Note also that the separator within the array constant {1;2;3;4;5;6;7;8;9} is the semicolon, which, for English-language versions of Excel, represents the row-separator. This may require amending if you are using a non-English-language version.
Of course, we can replace this static constant with a dynamic construction. However, since we are already making the assumption that 9 is an upper limit on the number of characters for the string in question, this would not seem to be necessary.
If you have the newest version of Excel, you can try something like:
=LEFT(D1,
LET(x, SEQUENCE(LEN(D1)),
MAX(IF(ISNUMBER(NUMBERVALUE(MID(D1, SEQUENCE(LEN(D1)), 1))), x))))
For example:

Excel formula to extract a number preceding an x not working

I'm using the following formula to extract the number preceding an "x" from a string (e.g. ##x## where # equals a number 0-9) but with I have other words in the string that have an "x" in them, the formula doesn't work.
Here's the formula:
=IF(ISBLANK(A154),"",IFERROR(IF(VALUE(MID(A154,MIN(FIND({"1","2","3","4","5","6","7","8","9","0"},A154 & "(1,2,3,4,5,6,7,8,9,0")),FIND(INDEX(SET_TERMS,MATCH(1,COUNTIF(A154,"*"&$R$2:$R$5&"*"),0)),A154,1)-MIN(FIND({"1","2","3","4","5","6","7","8","9","0"},A154 & "(1,2,3,4,5,6,7,8,9,0"))))<=1,"",TRIM(MID(A154,MIN(FIND({"1","2","3","4","5","6","7","8","9","0"},A154 & "(1,2,3,4,5,6,7,8,9,0")),FIND(INDEX(SET_TERMS,MATCH(1,COUNTIF(A154,"*"&$R$2:$R$5&"*"),0)),A154,1)-MIN(FIND({"1","2","3","4","5","6","7","8","9","0"},A154 & "(1,2,3,4,5,6,7,8,9,0")))&" sets")),""))
Notes: SET_TERMS ($R$2:$R$5) is a list: rounds, set, sets, x.
Here are examples where the formula works fine:
Skater jumps 3x5 each side RESULT 3 sets
Russian Twist 3x30 seconds RESULT 3 sets
Push-ups 3x max RESULT 3 sets
Y holds 3x30 seconds RESULT 3 sets
Now, here are two examples of the strings that return a blank because Flexion and Extension have "x" in them:
Neck Flexion 3x20 seconds RESULT Blank
Neck Extension 3x20 seconds Result Blank
Any ideas on how to fix this?
Thanks
You just need to be more specific in what you are looking for.
For example, the following will return the digit prior to the x:
=MID(A1,MIN(FIND({0;1;2;3;4;5;6;7;8;9}&"x",A1&"0x1x2x3x4x5x6x7x8x9x")),1)
If you have Windows Excel 2013+ or O365, and you need to deal with multiple digit numbers, the following will extract space-separated "nodes" that have the pattern of ddx, where dd can be any number (including decimals). You can then use string functions to extract just the number.
=FILTERXML("<t><s>" & SUBSTITUTE(A1," ","</s><s>") & "</s></t>","//s[boolean(number(substring-before(.,'x')))]")

EXCEL: Unique alphanumeric code with certain characters excluded (without VBA / duplicates)

I am trying to create a list =5 alphanumeric characters.
They cannot contain 1, and i and there cannot be duplicates when dragging / copying the code down.
The characters that are allowed are:
023456789ABCDEFGHJKLMNOPQRSTUWVXYZ (Capital)
I have tried numerous of options but I can't seem to figure this one out.
Cheers
If your allowable character string is in cell A1 then the following formula will result in random codes that are each five characters in length:
=MID(A1,RANDBETWEEN(1,34),1) & MID(A1,RANDBETWEEN(1,34),1) & MID(A1,RANDBETWEEN(1,34),1) & MID(A1,RANDBETWEEN(1,34),1) & MID(A1,RANDBETWEEN(1,34),1)
But note that there is no guarantee that the codes will be unique.
As #ScottCraner pointed out... if you should happen to have Office 365, you can use this much shorter formula that takes advantage of two new functions only available in Excel 365:
=CONCAT(MID(A1,RANDARRAY(5,,1,34,TRUE),1))
But again, there is no guarantee that the resulting codes will be unique.
This formula will generate the codes in order
=SUBSTITUTE(SUBSTITUTE(BASE(K, 34,5),"1","Z"),"I","Y")
Here K can be 0, 1, 2, .... One way to generate the first ~1,048,576 K's is to use ROW()-1. You could get higher values of K by using something like K = 1048576*(COLUMN()-1) + ROW()-1.
The formula works by
(a) calling BASE(K, 34, 5) to get a 5-char long base-34 representation of K
(b) substituting Z for 1 since 1 is not a valid char
(c) substituting Y for I since I is not a valid char

Excel get substring from nth position up to the end of string

So How to get substring from nth position up to the end of string?
Input at cell A1 Name: Thomas B.
Expected output: Thomas B.
I know some way to do it but I wonder if there are other elegant ways than them? (some kind of =RIGHT(A1, -6)....)
=MID(A1, 6, 999999) //999999 looks not so good
=MID(A1, 6, LEN(A1) - 5) //must calculate 2 times, first get len, then get substring, seems too much works?
REPLACE
As Dominique already wrote:
'Why don't you just replace the first six characters by an empty string?'
=REPLACE(A1,1,6,"")
I've done some time measuring, but the difference is less than a second at 50000 records (for LEFT, MID, REPLACE & SUSTITUTE). So I'm afraid ELEGANCE is all you're going to get.
A Small Study
I created this study due to the fact that when you say from the n-th character, your n-th character is 7 (your MID-s are wrong), but you want to remove the first n-1 (6) characters. So depending on how you formulate your question, you might have a different approach in RIGHT or MID, and you will remember REPLACE and SUBSTITUTE or you may not.
Small Study Formulas for A1 (*) and B1 (#, ?, *)
Get String From N-th Character to the End, e.g. 7
=RIGHT(A1,LEN(A1)-(B1-1))
=RIGHT(A1,LEN(A1)-B1+1)
=RIGHT(A1,LEN(A1)-6)
=MID(A1,B1,LEN(A1)-(B1-1))
=MID(A1,B1,LEN(A1)-B1+1)
=MID(A1,B1,LEN(A1))
=MID(A1,7,LEN(A1)-6)
=MID(A1,7,LEN(A1))
Remove N First Characters of a String, e.g. 6
=RIGHT(A1,LEN(A1)-B1)
=RIGHT(A1,LEN(A1)-6)
=MID(A1,B1+1,LEN(A1)-B1)
=MID(A1,B1+1,LEN(A1))
=MID(A1,7,LEN(A1)-6)
=MID(A1,7,LEN(A1))
Get String After a Character e.g. " "
=RIGHT(A1,LEN(A1)-(FIND(B1,A1)))
=RIGHT(A1,LEN(A1)-(FIND(" ",A1)))
=MID(A1,FIND(B1,A1)+1,LEN(A1)-FIND(B1,A1))
=MID(A1,FIND(B1,A1)+1,LEN(A1))
=MID(A1,FIND(" ",A1)+1,LEN(A1)-FIND(" ",A1))
=MID(A1,FIND(" ",A1)+1,LEN(A1))
Get String After a String e.g. ": "
=RIGHT(A1,LEN(A1)-(FIND(B1,A1)+LEN(B1))+1)
=RIGHT(A1,LEN(A1)-FIND(B1,A1)-LEN(B1)+1)
=RIGHT(A1,LEN(A1)-FIND(": ",A1)-LEN(": ")+1)
=MID(A1,FIND(B1,A1)+LEN(B1),LEN(A1)-(FIND(B1,A1)+LEN(B1))+1)
=MID(A1,FIND(B1,A1)+LEN(B1),LEN(A1)-FIND(B1,A1)-LEN(B1)+1)
=MID(A1,FIND(B1,A1)+LEN(B1),LEN(A1))
=MID(A1,FIND(": ",A1)+LEN(": "),LEN(A1)-FIND(": ",A1)-LEN(": ")+1)
=MID(A1,FIND(": ",A1)+LEN(": "),LEN(A1))
Back to Remove N First Characters of a String, e.g. 6
=SUBSTITUTE(A1,LEFT(A1,6),"",1)
=REPLACE(A1,1,6,"")
Well, both of your methods already work, but you could also use this one:
=RIGHT(A1,LEN(A1)-6)
(you nearly had this one in your own question)
or this one:
=TRIM(MID(A1,FIND(":",A1)+1,100))
(the FIND() function returns the numeric position of a search string, so is great for doing dynamic substrings)
Why don't you just replace the first six characters by an empty string?
=SUBSTITUTE(A1;LEFT(A1;6);"";1)
Another possibility is that you create a constant with the value 2^31-1 (=2147483647), which is the maximum signed integer value on 32-bit systems, and you give it a nice name, like MaxInt, then your first formula will be efficient and nice looking, too:
=MID(A1, 6, MaxInt)
You can add the Name with Ctrl+F3. If you are interested in fast calculations, giving it as 2147483647 rather than 2^31-1 may have some (very little) advantage.

How to build complex value from three variables?

I have an Excel spreadsheet with over 2000 entries:
Field B1: CustomerID as 000012345
Field B2: CustomerID as 0000432
Field C1: CustomerCountry as DE
Field C2: CustomerCountry as IT
I need to build codes 13 digits long including "CustomerCountry" + "CustomerID" without leading 0 + random number (can be 6 digits, more or less, depends in length of CustomerID).
The results should be like this: D1 Code as DE12345967895 or D2 Code as IT43274837401
How to do it with Excel functions?
UPDATED:
I tried this one. My big problem is to say that random number should be long enough to get 13 characters in all. Sometimes CustomerID is just 3 or 4 digits long, and concatenation of three variables can be just 10 or 9 characters. But codes have to be always 13 characters long.
Use & to concatenate strings.
Use VALUE(CustomerID) to trim the leading zeroes from the ID
Use RAND() to add a random number between 0 and 1 or RANDBETWEEN(x,y) to create one between x and y.
Combine the above and there you are!
If you always want 13 digits you can use LEFT(INT(RAND()*10^13);(13-LEN(CustomerCountry)-LEN(VALUE(CustomerID)))) for the random number to ALWAYS be the right length.
total formula
= CustomerCountry
& VALUE(CustomerID)
& LEFT(INT(RAND()*10^13);(13-LEN(CustomerCountry)-LEN(VALUE(CustomerID))))
=C1 & TEXT(B1,"0") & RIGHT(TEXT(RANDBETWEEN(0,99999999999),"00000000000"),11 - LEN(TEXT(B1,"0")))
that should do it
I don’t understand what is where and OP has accepted answer so have not bothered testing:
=LEFT(RIGHT(C1,2)&VALUE(MID(B1,15,13))&RANDBETWEEN(10^9,10^10),13)
(but I might revert to this if no one else picks the flaws in it first!)

Resources