I would like a formula in excel that does what Text To Columns does.
For example the following string in A1
" text with a comma, stays in one column",," keep starting blank text",1,2,3,"123"
Would be split into multiple cells like this...
The following LET Function allows you to split the text into columns based on the splitter character (in this instance a comma).
It ignores commas that are between quotes (the Delim argument - which has double quotes in it).
It does this by ensuring there is an even number of quotes before the splitter character.
=LET(
NOTES,"Splits a string but also checks to see if the splitter is inside a delimiter. So will ignore a comma inside quotes.",
RawString,$A1,
Splitter,",",Note2,"This is the character to split the string by",
Delim,"""",Note4,"This is the text delimiter it looks odd but it's just a double quote - change to "" if you don't want text delimitation",
IgnoreBlanks,FALSE,
CleanTextDelims,TRUE,
TrimBlanks,FALSE,
SplitString,Splitter&RawString&Splitter,Note3,"Add the splitter to the start and the end to help create the array of split positions",
StringLength,LEN(SplitString),
Seq,SEQUENCE(1,StringLength),Note5,"Get a sequence from 1 to the length of the split string",
Note6,"The below does the bulk of the work. It works out if we are at an odd or even point in terms of count of text delimiters up to the point in the sequence we are processing.",
Note7,"if we are at an even point and we have a delimiter then make a note of the sequence otherwise put a blank.",
PosArray,IF(Seq=StringLength,Seq,IF(MOD(LEN(LEFT(SplitString,Seq))-LEN(SUBSTITUTE(LEFT(SplitString,Seq),Delim,"")),2)=0,IF(MID(SplitString,Seq,1)=Splitter,Seq,""),"")),
PosArrayClean,FILTER(PosArray,PosArray<>""),Note8,"Clean blanks",
StartArray,FILTER(PosArrayClean,PosArrayClean<>StringLength),
EndArray,FILTER(PosArrayClean,PosArrayClean<>1),
StringArray,MID(SplitString,StartArray+1,EndArray-StartArray-1),
StringArrayB,IF(IgnoreBlanks,FILTER(StringArray,StringArray<>""),StringArray),
StringArrayC,IF(CleanTextDelims,IF(LEFT(StringArrayB,1)=Delim,MID(StringArrayB,2,IF(RIGHT(StringArrayB,1)=Delim,LEN(StringArrayB)-2,LEN(StringArrayB))),StringArrayB),StringArrayB),
IFERROR(IF(TrimBlanks,TRIM(StringArrayC),StringArrayC),"")
)
Breaking down each step in the LET formula:
Supply the raw string (from cell A1 in this case)
Set the splitter character - in this case a comma
Set the text delimiter - in this case double quotes (looks odd because it has to be as double double quotes - Delim,"""" )
IgnoreBlanks is an option to exclude blank cells in the output
CleanTextDelims will clean the TextDelimiter (Double quotes) from the start and end of the resultant string
Create a SplitString variable with the split character at the front and back.
Get the length of the string for ease of use
Get a sequence from 1 to the length of the string.
Get an array of the position of characters that are splitters with an even number of Text Delimiters to the left of that position in the string the posArray (splitter position array).
Clean the blanks to get the posArrayClean
Create a start and end array (start array ignores the last and end array ignores the first item in the PosArrayClean)
Get the array of strings/cells to output.
If the IgnoreBlanks is used then igore blank cells
If the CleanTextDelims option is set then strip off the Text Delim (double quotes) from the start and end of the resultant string.
If the TrimBlanks option is set then trim blank spaces off the start and end of the resulting strings.
Hopefully the notes explain clearly how this works and make it easy to modify.
If you want create a named Lambda to use you can use the following code to paste into the formula of a named range called SplitStringDelim (you can name it what you like of course). NB You can't have the line separators in this and I stripped the notes out of it.
=LAMBDA(StringRaw,SplitChar,DelimChar,IgnoreBlank,CleanTextDelim,TrimBlank, LET( RawString,StringRaw, Splitter,SplitChar, Delim,DelimChar, IgnoreBlanks,IgnoreBlank, CleanTextDelims,CleanTextDelim, TrimBlanks,TrimBlank, SplitString,Splitter&RawString&Splitter, StringLength,LEN(SplitString), Seq,SEQUENCE(1,StringLength), PosArray,IF(Seq=StringLength,Seq,IF(MOD(LEN(LEFT(SplitString,Seq))-LEN(SUBSTITUTE(LEFT(SplitString,Seq),Delim,"")),2)=0,IF(MID(SplitString,Seq,1)=Splitter,Seq,""),"")), PosArrayClean,FILTER(PosArray,PosArray<>""),Note8,"Clean blanks", StartArray,FILTER(PosArrayClean,PosArrayClean<>StringLength), EndArray,FILTER(PosArrayClean,PosArrayClean<>1), StringArray,MID(SplitString,StartArray+1,EndArray-StartArray-1), StringArrayB,IF(IgnoreBlanks,FILTER(StringArray,StringArray<>""),StringArray), StringArrayC,IF(CleanTextDelims,IF(LEFT(StringArrayB,1)=Delim,MID(StringArrayB,2,IF(RIGHT(StringArrayB,1)=Delim,LEN(StringArrayB)-2,LEN(StringArrayB))),StringArrayB),StringArrayB), IFERROR(IF(TrimBlanks,TRIM(StringArrayC),StringArrayC),"")))
Here is what I put in the cell
="A "&'2018-2019'!C34&" B"
and this is what I got
A 1256838 B
But I want it to display like this
A 1,256,838 B
Use TEXT to format the number.
="A "&TEXT('2018-2019'!C34, "#,##0")&" B"
In fact, if the prefix and suffix characters are static, they can be wrapped into the format mask.
=TEXT('2018-2019'!C34, "\A #,##0 \B")
The \ is an escape character. I'm pretty sure that A is not a reserved character in a format mask but B is used for the Buddhist calendar.
I have a string variable with short text strings. I want to replace all the text strings with numbers based on key words contained inside the individual cells.
Example: Some cells states "I like cats", while others "I dont like the smell of wet dog".
I want to assign the value 1 to all cells containing the word cat, and the number 2 to all cells containing the word dog.
How do I do this?
This will put 1 in NewVar when "cat" appears in OldVar, 2 for "dog", 3 for "mouse":
do repeat wrd="cat" "dog" "mouse"/val= 1 2 3.
if index(OldVar, wrd)>0 NewVar=val.
end repeat.
This is only good if there will never be a cat AND a dog in the same sentence. If you do have such cases you should go this way:
do repeat wrd="cat" "dog" "mouse"/NewVar=cat dog mouse.
compute NewVar=char.index(OldVar, wrd)>0.
end repeat.
This will create a new variable for each of the possible words, putting 1 in cases where the word appears in OldVar, 0 when it doesn't.
Apparently you have to open a syntax window and enter this command:
COMPUTE newvar=CHAR.INDEX(UPCASE(VAR1),"ABCD")>0
newvar is the name of the new variable.
VAR1 is the name of the variable to be searched.
ABCD is the text to be searched for. NOTE: This must be in CAPITAL letters.
newvar will recieve a value of 1 if the text is found.
I'm writing a macro in Excel that is reading some text from a single cell.
ProductID = rw.Cells(1, 1).Text
However the cell may contain some buffer characters, specifically 5 consecutive space characters. I am trying to remove all the characters (length and actual text may vary) after the 5 spaces (including the spaces).
So if the string was:
MyProduct123 removethis
The desired string would be
MyProduct123
It seems I can remove the 5 spaces with
Replace(MyProductStr, " ", "")
but how can I get the position of the right side string or the text to remove that?
You can do this using InStr to find the starting position of the five spaces, and then Left to take just the part of the string before that:
Dim pos As Integer
pos = InStr(ProductID, " ")
If pos > 0 Then
ProductID = Left(ProductID, pos - 1)
End If
How do I concatenate together two strings, of unknown length, in COBOL? So for example:
WORKING-STORAGE.
FIRST-NAME PIC X(15) VALUE SPACES.
LAST-NAME PIC X(15) VALUE SPACES.
FULL-NAME PIC X(31) VALUE SPACES.
If FIRST-NAME = 'JOHN ' and LAST-NAME = 'DOE ', how can I get:
FULL-NAME = 'JOHN DOE '
as opposed to:
FULL-NAME = 'JOHN DOE '
I believe the following will give you what you desire.
STRING
FIRST-NAME DELIMITED BY " ",
" ",
LAST-NAME DELIMITED BY SIZE
INTO FULL-NAME.
At first glance, the solution is to use reference modification to STRING together the two strings, including the space. The problem is that you must know how many trailing spaces are present in FIRST-NAME, otherwise you'll produce something like 'JOHNbbbbbbbbbbbbDOE', where b is a space.
There's no intrinsic COBOL function to determine the number of trailing spaces in a string, but there is one to determine the number of leading spaces in a string. Therefore, the fastest way, as far as I can tell, is to reverse the first name, find the number of leading spaces, and use reference modification to string together the first and last names.
You'll have to add these fields to working storage:
WORK-FIELD PIC X(15) VALUE SPACES.
TRAILING-SPACES PIC 9(3) VALUE ZERO.
FIELD-LENGTH PIC 9(3) VALUE ZERO.
Reverse the FIRST-NAME
MOVE FUNCTION REVERSE (FIRST-NAME) TO WORK-FIELD.
WORK-FIELD now contains leading spaces, instead of trailing spaces.
Find the number of trailing spaces in FIRST-NAME
INSPECT WORK-FIELD TALLYING TRAILING-SPACES FOR LEADING SPACES.
TRAILING-SPACE now contains the number of trailing spaces in FIRST-NAME.
Find the length of the FIRST-NAME field
COMPUTE FIELD-LENGTH = FUNCTION LENGTH (FIRST-NAME).
Concatenate the two strings together.
STRING FIRST-NAME (1:FIELD-LENGTH – TRAILING-SPACES) “ “ LAST-NAME DELIMITED BY SIZE, INTO FULL-NAME.
You could try making a loop for to get the real length.