Excel Test Length of 1 field and divide if len>200 - excel

I have column B that I need to test the length to see if it is longer than 200 characters. If it is longer than 200 characters, I need it to go from right to left and find the occurrence of the semicolon ";" and split the field from the right of the semicolon into column C. Can this be done? Before I was having to do this with 4 columns and have reduced it to one column. Please advise to the best formula to do this.

=IF(LEN(B1)>200,MID(B1,SEARCH("#",SUBSTITUTE(B1,";","#",LEN(B1)-LEN(SUBSTITUTE(B1,";",""))))+1,LEN(B1)),"")
Explanation:
Remove all instances of the delimiter: SUBSTITUTE(B1,";","")
Subtract the length of (1) from the length of the entire string to get the number of occurrences of the delimiter: LEN(B1)-LEN([1])
Substitute the last occurrence of the delimiter with an #: SUBSTITUTE(B1,";","#",[2])
Find the location of the #: SEARCH("#",[3])
Get the substring of everything to the right of the # location: MID(B1, [4] +1,LEN(B1))
Add if condition to only process strings of length > 200: =IF(LEN(B1)>200,[5],"")

I searched the web for formulas for this and concluded that you either need a lot of nesting and a difficult to follow formula or a VBA function. I would suggest using a VBA function such as the one I have written below (FindLast) within a simple formula. Let me know if you need instructions on how to create this VBA formula:
Function FindLast(find_text As String, within_text As Range) As Double
Dim i As Integer
i = Len(within_text.Value) ' start at last character and work back
Do While Mid(within_text.Value, i, 1) <> find_text
i = i - 1
Loop
FindLast = i
End Function
You will then be able to use FindLast within a formula such as the below in C1:
=IF(LEN(B1)>200,MID(B1,FindLast(";",B1)+1,500),"")
UPDATE
The 500 in the above is just a long number I picked to mean the rest of the cell. If there may be more than 500 characters after the final ; then use a larger number. Unfortunately I don't think the MID function allows you to specify that you want to return the rest of the cell. I have put to return nothing if B1 is not >200 characters, let me know if this is not the requirement.

Related

Get Digits at the end of a String

The strings are mixed alphas and digits, but there is always a set of digits at the end of the string.
Any leading digits or digits in the middle of the string should be ignored. I came up with:
Public Function trailing(S As String) As Long
Dim r As String
Dim i As Long
For i = Len(S) To 1 Step -1
If IsNumeric(Mid(S, i, 1)) Then
r = Mid(S, i, 1) & r
Else
Exit For
End If
Next i
trailing = CLng(r)
End Function
It seems to work:
However the user is working on a .xlsx and can't use UDFs. Is there a formula that gets the same results ??Thanks in advance
In cell B1 and copied down:
=--RIGHT(A1,LOOKUP(2,1/(ISNUMBER(--RIGHT(A1,ROW($1:$15)))),ROW($1:$15)))
Simply make sure that the 15 in $1:$15 is going to be larger than the maximum possible number of ending digits for any given string. No array formula entry necessary, and no helper columns necessary.
Alternate version so you don't have to repeat ROW($1:$15):
=--RIGHT(A1,MATCH(TRUE,INDEX(ISERROR(--RIGHT(A1,ROW($1:$15))),),0)-1)
Alright, so bear with me...this is ugly and there could be some opportunity to clean this up (or a better approach altogether utilizing the same concepts) and since you already know that this is a much better candidate for RegEx/VBA, we are in agreement of a better approach, yet under the criteria/restrictions of your question, here we go...
Since you said the length varies between 2 and 12, we can make a set of array formulas in 12 columns, B-M which extracts the RIGHT() of 1, 2, ..., 12 characters accordingly. We wrap this with a VALUE to return an error #VALUE! for non-numerics -- NOTE: This formula is entered by first selecting cells B2:M2, typing the formula, =VALUE(RIGHT(A2, {1,2,3,4,5,6,7,8,9,10,11,12})) and then the obligatory CTRL + SHIFT + ENTER
We then find the position of the first error in COLUMN O with a MATCH() formula looking for the first TRUE of another array formula utilizing ISERROR().
We get the solution by doing an index of the position 1-12 columns returning the column next to the first error it finds. This is because you know that column A will always end in a number.
N.B. Since you specified that it is only a 4-digit numeric string at the end, you can probably get away with reducing this method to the first 4 columns; that is, rather than utilizing 12 columns, just use columns B:E and continue as above.
We end by begging the client/customer to consider a .xlsm workbook/VBA/RegEx or other solution...
Another possible solution:
=AGGREGATE(14,6,--RIGHT(A1,ROW(INDIRECT("1:"&LEN(A1)))),1)
In some cases it could give wrong results:
aaa12.1
bc1E+13
As a workaround you can use SUBSTITUTE to replace E, e and . (maybe also , and space) in input string with another letter.

Why are cells containing formula's counting as having string in them?

I've got a fairly simple question and I'm sure that I'm missing something obvious.
I've got say 40 cells and all of them contain a formula in them. Only 38 of those cells actually have string or text in them the remaining two do NOT. They're blank with the exception of the formula.
However when I do a COUNTIF or a COUNTA to try and not count the cells that are filled automatically it is giving me the result of 40.
Ways I've tried this and all go the result of 40:
=COUNTIF(B60:B99,"*")
=COUNTIF(B60:B99)
=(COUNTA(B60-B99)
Does anyone know what I'm doing wrong?
Example of the formula in a blank cell that is being counted:
=IF(ISBLANK('Dodgeball'!B48),"",'Dodgeball'!B48)
Use:
=SUMPRODUCT(--(B60:B99<>""))
as this ignores null strings.
You are attempting to count the cells that are not "" but considering them as blank. Try using
=countif(B60:B99,"<>""""")
To explain that final string of quotes, the first one is an escape character so that the second one is read as quotes within the string, similarly the third and fourth are an escape character and a quote for within the string, and finally we end the string with a quote.
One option would be to insert an additional column and simply use the istext() function. Then you can sum that column to get your text count, because false counts and 0 and true counts as 1.

excel functions find pattern of a string in a cell

I have personal ID's in reports I have to find in one cell. Too bad the string in the cell which hides this ID can be anything, the ID can be at the beginning, the end, anywhere, but it is there.
The only thing I know is the pattern "space,letter,letter,number,number,number,number,number,number,space". Jike DB544345
I was looking for the correct word for this "mask", but couldn't find an answer. Thank you for your help.
As the comments are numerous I have created a minimal example that might represent what the OP is dealing with:
A1: 123456789 DB544345 asdfg asdfghjk
A2: creating dummy data is a DB544345 pain
A3: DB5443456 and soething else
parsed a copy of that in ColumnB with Text To Columns (with space as the delimiter) then applied:
=IFERROR(IF(AND(LEN(B1)=8,CODE(LEFT(B1))>64,CODE(LEFT(B1))<91,CODE(MID(B1,2,1))>64,CODE(MID(B1,2,1))<91,ISNUMBER(RIGHT(B1,6)*1),RIGHT(B1,6)*1>99999),B1,""),"")
to K1, copied this across to P1 and then K1:P1 down.
A concise "built-in function only" solution to a problem such as this requires a bit of tinkering as many attempts will dead-end or need workarounds due to deficiencies and quirks in the built-in Excel formulas. I much prefer single cell formulas because they minimally affect the general spreadsheet structure. However, due to the limitations listed above, complex single cell solutions often come at the cost of being rather long and cumbersome (this answer is somehow still only two lines on my formula bar in Excel). I came back to your question and cobbled together a formula that can (as far as I have tested) extract the first occurrence of this pattern with a single cell formula. This is an array formula (Ctrl+Shift+Enter instead of Enter) that assumes your data is in A2. This rough formula returns the first 8 characters if no match is found and throws #REF if the string is shorter than 10 characters.
=MID(A2,MIN(IF(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9))),1)=" ",IF(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+9,1)=" ",IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+1,1))>64,IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+1,1))<91,IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+2,1))>64,IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+2,1))<91,IF(IFERROR(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+3,6)*1>99999,FALSE),ROW(INDIRECT("A1:A"&(LEN(A2)-9)))))))))))+1,8)
Let me try to break this down at least on a high level. We are splitting the main text into every possible ten character chunk so that we can test each one using the suggestion of #pnuts to verify the Unicode values of the first two characters and run an ISNUMBER check on the rest of the string. This first block recurs throughout my formula. It generates a list of numbers from 1 to n-9 where n is the length of our main text string.
ROW(INDIRECT("A1:A"&(LEN(A2)-9)))
Let's assume our string is 40 characters long and replace the above formula with {1...31}. Using this number sequence generation we can check if characters 1 to 31 are spaces:
IF(MID(A2,{1...31},1)=" "
Then we can check if characters 10 to 40 are spaces:
IF(MID(A2,{1...31}+9,1)=" "
Then we can check if characters 2 to 32 are capital letters:
IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+1,1))>64,
IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+1,1))<91
Then we can check if characters 3 to 33 are capital letters:
IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+2,1))>64,
IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+2,1))<91
Then we can check if the strings of characters 4 to 9, 5 to 10, ..., 33 to 38, 34 to 39 are six-digit numbers:
IF(IFERROR(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+3,6)*1>99999,FALSE)
If all conditions are TRUE, that 10 digit chunk test will return the index of its first character in the string via another instance of the original array {1...31}. Otherwise it returns nothing. We take the Min of all return indexes and then use the Mid function to grab the 8 digit string determined by the aforementioned minimum index:
=MID(A2,MIN(matching index list)+1,8)
I think this will work, if we assume that the SPACE at the beginning and end are merely to differentiate the ID from the rest of the string; hence would not be present if the ID were at the beginning or end of the string. This formula is case insensitive. If case sensitivity is required, we could do character code comparisons.
=LOOKUP(2,1/((LEFT(myArr,2)>="AA")*(LEFT(myArr,2)<="ZZ")*(LEN(myArr)=8)*ISNUMBER(-RIGHT(myArr,6))),myArr)
Where myArr refers to:
=TRIM(MID(SUBSTITUTE(TRIM(Sheet2!A1)," ",REPT(" ",99)),(ROW(INDIRECT("1:10"))-1)*99+1,99))
If myArr is initially defined with the cursor in B1, referring to A1 as shown, it will adjust to refer to the cell one column to the left of the cell in which the Name appears.
The 10 in 1:10 is the maximum number of words in the string -- can be adjusted if required.

MS Excel: remove number of characters after a specific character in a string

I have a column with values like
WI60P-14E64F5167E6-01138
or
WI60-34D03E185267-01051
etc....
i need to find the first occurrence of - till the second occurrence of - and remove the resulting character.
I am using this function =MID(A1,FIND("-",A1),13) which returns me -34D03E185267 or -14E64F5167E6 from the above strings.
But I want the output like WI60P-01138 or WI60-01051
Can anyone help me?
Assuming that the length of text between the two hyphens never varies, you can use your existing function, along with SUBSTITUTE to get the desired string, like so:
=SUBSTITUTE(A1,MID(A1,FIND("-",A1),13),"")
Alternately, you can use FIND to get the hyphen positions and again use SUBSTITUTE to get the replaced string, like so:
=SUBSTITUTE(A1,MID(A1,FIND("-",A1),FIND("-",A1,FIND("-",A1)+1)-FIND("-",A1)),"")
Notice that one of the FIND expressions takes 3 parameters - by passing FIND("-",A1) + 1 as the third parameter, we get the second occurence of '-' within the cell.
This will work for any position of the two hyphens:
=CONCATENATE(MID(A1;FIND("-";A1)+1;FIND("-";A1;FIND("-";A1)+1)-FIND("-";A1)-1))
Solution using multiple cells as support (with dynamic length of the string):
Put this in cell B1 to obtain the first part of the code:
=MID(A1,1,FIND("-",A1)-1)
Put this in cell C1 to obtain the last part of the code:
=MID(A1,FIND("-",A1)+1,LEN(A1))
Put this in cell D1 to concatenate both and get your result:
=concat(B1,C1)
Solution in a single cell (with dynamic length of the string)
Put this in cell B1 to get the same result as above :
=concat(MID(A1,1,FIND("-",A1)-1),MID(MID(A1,FIND("-",A1)+1,LEN(A1)),FIND("-",MID(A1,FIND("-",A1)+1,LEN(A1))),LEN(MID(A1,FIND("-",A1)+1,LEN(A1)))))

How to convert a word to a Unique Code in Excel using Formula without using VBA?

Say, I got 2 words A1:ddC, A2:DDC
I want to convert these 2 words into a unique code so that so that i can do the Case Sensitive Vlookup.
So i tried, =Code(A1) & it returned 100, but if i tried =Code("dady") then it also returns 100. It is cos =Code() only pic the first char of the word.
I want to convert a word to a Unique Code (could be ASCII code or any form of unique code).
So how to do that without using VBA?
As this is a hash, it would be possible for some strings to end up with the same value, but it would be unlikely.
Note that the row function uses 1:255 to generate a list of numbers from 1 to 255 - change this number if your strings end up longer.
=A1&SUMPRODUCT(IF(IFERROR(CODE(MID(A1,ROW($1:$255),1)),0)>96,1,0),POWER(2,ROW($1:$255)))
This has to be entered as an array formula using CTRL+SHIFT+ENTER - you will see {} around the formula if you have successfully done that.
This will produce a decimal representation of the upper and lower case letters, and this is then appended to the word itself - this will guarantee uniqueness, as the only way to have a word and number match is to have the same word and case, which means it was a duplicate in the first place.
With this, ddC = ddC & 1*2 + 1*4 + 0*8 = ddC6
DDC = DDC & 0*2 + 0*4 + 0*6 = DDC0
ddC (ddC with a space after it) = ddc & 1*2 + 1*4 + 1*8 + 0*16 = ddC 6
*WARNING: * This is not a solution to the titled question
"How to convert a word to a Unique Code in Excel using Formula without using VBA?" but instead is a solution to what I believe is the underling problem as the original question states "so that i can do the Case Sensitive Vlookup." this is a solution acomplishing a Case Sensitive Vlookup, without the need to convert the values before doing so.
An alternative to converting all the values then doing a look up on the converted values, you could use the INDEX and MATCH functions in an array entered formula and directly look up the values:
=INDEX(A1:A14,MATCH(TRUE,EXACT(A1:A14,"ddC"),0))
This will return the value in A1:A14, at the same index of an exact (case-sensitive) match in A1:A14 to ddC you can VERY easily modify this into a look up of other columns.
Explanation:
Start with getting an array of all exact matches in your look up list to your look up value:
So if I enter this formula:
=EXACT(A1:A14,"ddC")
Then go into the formula bar and press F9 it will show me an array of true false values, relating to each cell in the range A1:A14 that are an Exact match to my expression "ddC":
now if we take this Boolean Array, and use the Match function to return the relative position of True in the array.
=MATCH(TRUE,EXACT(A1:A14,"ddC"),0)
But remember we need to enter this by pressing Ctrl + Shift + Enter because we need the EXACT(A1:A14,"ddC") portion of the formula to be returned as an array.
Now that we have the position of the True in the array, in this case 6 we can use that to retrieve the corresponding value in any column, as long as it is relational and that same size. So if we want to return the value of the exact match (although relatively useless in this situation, but will continue for demonstration) in the original look up column we just wrap the last formula up in an Index function:
=INDEX(A1:A14,MATCH(TRUE,EXACT(A1:A14,"ddC"),0))
But remember we need to enter this by pressing Ctrl + Shift + Enter because we need the EXACT(A1:A14,"ddC") portion of the formula to be returned as an array.
Now we can apply that same concept to a larger range for more useful look up function:
But remember we need to enter this by pressing Ctrl + Shift + Enter because we need the EXACT(A1:A14,"ddC") portion of the formula to be returned as an array.
Now notice in this last step I offered 2 formulas:
=INDEX(A1:B14,MATCH(TRUE,EXACT(A1:A14,D2),0),2)
And
=INDEX(B1:B14,MATCH(TRUE,EXACT(A1:A14,D2),0))
The first returns the value in the range A1:B14 in the Second column at the position of the exact match in A1:A14 to the value in D2 (in this case "dady")
The second returns the value in the range B1:B14 at the position of the exact match in A1:A14 to the value in D2 (in this case "dady")
Hopefully someone else can add more input but as far as I know the second might be better performing, as it has a smaller index range, and doesn't require going to the specified column, it is also shorter.
While the first to me is much easier to read, to some (more of a preference I think) because you know that your looking at a look up table that spans 2 columns and that you are returning the value in the second column.
*Notes: * I am note sure if this solution will be better in practice then converting the original values in the first place, seeing as how converting all the values once, then hard coding the converted values will require no additional formula or calculation (if formulas are afterwards replaced with values) once finished, while this method will recalculate, and also is array entered. But I feel in the case the asker is doing a single look up against a changing look up list (one that constantly requires all values are converted at all times using array formula) this option does allow you to remove the formula per word, with one single formula
all in all I hope this solves your original problem,
Cheers!!
if all your strings like the one you pointed above try something like this:
= CONCATENATE(Code(A1) , Code(Mid(A1,2,1)) , Code(Mid(A1,3,1)))
In order to account for capital letters you're going to end up with a VERY long formula, especially if you have long word entries. Without VBA I would approach it this way and set up the formula once to allow for the biggest word you anticipate, and then copy it around as needed.
Formula (to expand):
=CONCATENATE(IF(EXACT(A1,UPPER(A1))=TRUE,"b","s")&CODE(A1),IF(EXACT(A1,UPPER(A1))=TRUE,"b","s")&CODE(MID(A1,2,1)),IF(EXACT(A1,UPPER(A1))=TRUE,"b","s")&CODE(MID(A1,3,1)), . . . )
You can substitue the "b" and "s" with whatever you like. I was just using those for a case check for capital versus lowercase letters (b=big, s=small) and building that into your unique code.
In order to expand this, add additional cases to account for the length of the words you are using by adding this snippet JUST inside the last parenthesis and modifying the "3" in the MID() function to account for a word length of "4", "5", "6", etc.:
IF(EXACT(A1,UPPER(A1))=TRUE,"b","s")&CODE(MID(A1,3,1))
Painful, yes, but it should work.
Cheers.

Resources