Excel Macro- remove a word that starts with certain characters - excel

In a VB macro for Excel, how do I remove all occurances of a word that starts with a certain string?
Eg:
The string reads: xxxx $AUD543.43 yyyy
I want to search for anything in a string that starts with $AUD and remove the whole word before the next space
So the example above should result in:
xxxx yyyy

use Regex. Add a reference to Microsoft VBScript Regular Expressions in VBA >> Tools >> Options.
Dim txt As String
txt = "$Audthisfew is$Aud $Auda test $Aud"
Set regEx = New RegExp
With regEx
.Global = True
.Pattern = "((^, )\$Aud)"
Debug.Print .Replace(txt, "")
End With

It would be remiss of me not to remind you of the expectation that you show "what you (have) tried". (Which I do to avoid me being yelled at for answering the question.) My duty thus having been done, I now move on to it.
You actually don't necessarily need VBA code to do this; you could do it with the Find() function albeit more clumsily and I wouldn't recommend it for a really large sheet. Still, VBA code you have specified, and that you shall have. Change the range to match the one that you'll be searching. ALSO, you should note that you have only one space between the x's and y's in your example but that varies from your request that it be the word starting with $AUD and ending BEFORE the next space. If you want only one space, please adjust the formulas accordingly.
Sub ReplaceText()
Dim rng As Excel.Range
Dim s_Contents As String
Dim l_FindAUD As Long, l_FindSpace As Long
For Each rng In ActiveSheet.UsedRange
s_Contents = rng.Value
'Does the $AUD expression exist in this cell?
l_FindAUD = InStr(1, s_Contents, "$AUD", vbTextCompare)
If l_FindAUD > 0 Then
'If so, is it followed by a space?
l_FindSpace = InStr(l_FindAUD, s_Contents, " ")
If l_FindSpace > 0 Then
'If so, take all of the content up to but not including the $
'and all of the contents from the space onwards, merge them
'together and write to the cell.
s_Contents = Left$(s_Contents, l_FindAUD - 1) & Mid$(s_Contents, l_FindSpace)
rng.Value = s_Contents
End If
End If
Next
End Sub

Although not exactly what you ask for, but you could also use an Excel formula to achieve this. Assuming your text is in A1, the formula would be:
=TRIM(LEFT(A1,FIND("$AUD",A1)-1))&RIGHT(A1,LEN(A1)-FIND(" ",A1,FIND("$AUD",A1))+1)

My example is used for delete the last few words of a cell
For example:
in cell A1: ABCDE[Acct:12345]
in cell A2: FGHIJ[Acct:67890]
in cell A3: KLMNO
Wanna delete all the words begin with "[Acct:", note not every cell includes "[Acct:"
Now in column B, insert the below function, this will return with the words on the left on "[Acct:"
=LEFT(A1,FIND("[Acct:",A1)-1)
Result: A B
ABCDE[Acct:12345] ABCDE
FGHIJ[Acct:67890] FGHIJ
KLMNO #VALUE!
Now in column C, insert below function, this will check whether column B is #VALUE! and then return with what we want
=IF(ISERROR(C1)=TRUE,A1,B1))
Result:
A B C
ABCDE[Acct:12345] ABCDE ABCDE
FGHIJ[Acct:67890] FGHIJ FGHIJ
KLMNO #VALUE! KLMNO
Then you can copy the three columns and paste with value, and delete column A and B , column C will be the final result you want.

Related

Use a Text Based Formula from one cell as the actual formula in another [duplicate]

I have 0,4*A1 in a cell (as a string). How can convert this "string formula" into a real formula and calculate its value, in another cell?
Evaluate might suit:
http://www.mrexcel.com/forum/showthread.php?t=62067
Function Eval(Ref As String)
Application.Volatile
Eval = Evaluate(Ref)
End Function
I concatenated my formula as normal, but at the start I had '= instead of =.
Then I copy and paste as text to where I need it. Then I highlight the section saved as text and press ctrl + H to find and replace.
I replace '= with = and all of my functions are active.
It's a few steps, but it avoids VBA.
UPDATE This used to work (in 2007, I believe), but does not in Excel 2013.
EXCEL 2013:
This isn't quite the same, but if it's possible to put 0.4 in one cell (B1, say), and the text value A1 in another cell (C1, say), in cell D1, you can use =B1*INDIRECT(C1), which results in the calculation of 0.4 * A1's value.
So, if A1 = 10, you'd get 0.4*10 = 4 in cell D1. I'll update again if I can find a better 2013 solution, and sorry the Microsoft destroyed the original functionality of INDIRECT!
EXCEL 2007 version:
For a non-VBA solution, use the INDIRECT formula. It takes a string as an argument and converts it to a cell reference.
For example, =0.4*INDIRECT("A1") will return the value of 0.4 * the value that's in cell A1 of that worksheet.
If cell A1 was, say, 10, then =0.4*INDIRECT("A1") would return 4.
Just for fun, I found an interesting article here, to use a somehow hidden evaluate function that does exist in Excel. The trick is to assign it to a name, and use the name in your cells, because EVALUATE() would give you an error msg if used directly in a cell. I tried and it works! You can use it with a relative name, if you want to copy accross rows if a sheet.
I prefer the VBA-solution for professional solutions.
With the replace-procedure part in the question
search and replace WHOLE WORDS ONLY, I use the following VBA-procedure:
''
' Evaluate Formula-Text in Excel
'
Function wm_Eval(myFormula As String, ParamArray variablesAndValues() As Variant) As Variant
Dim i As Long
'
' replace strings by values
'
For i = LBound(variablesAndValues) To UBound(variablesAndValues) Step 2
myFormula = RegExpReplaceWord(myFormula, variablesAndValues(i), variablesAndValues(i + 1))
Next
'
' internationalisation
'
myFormula = Replace(myFormula, Application.ThousandsSeparator, "")
myFormula = Replace(myFormula, Application.DecimalSeparator, ".")
myFormula = Replace(myFormula, Application.International(xlListSeparator), ",")
'
' return value
'
wm_Eval = Application.Evaluate(myFormula)
End Function
''
' Replace Whole Word
'
' Purpose : replace [strFind] with [strReplace] in [strSource]
' Comment : [strFind] can be plain text or a regexp pattern;
' all occurences of [strFind] are replaced
Public Function RegExpReplaceWord(ByVal strSource As String, _
ByVal strFind As String, _
ByVal strReplace As String) As String
' early binding requires reference to Microsoft VBScript
' Regular Expressions:
' with late binding, no reference needed:
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
re.Global = True
're.IgnoreCase = True ' <-- case insensitve
re.Pattern = "\b" & strFind & "\b"
RegExpReplaceWord = re.Replace(strSource, strReplace)
Set re = Nothing
End Function
Usage of the procedure in an excel sheet looks like:
In my opinion the best solutions is in this link:
http://www.myonlinetraininghub.com/excel-factor-12-secret-evaluate-function
Here is a summary:
In cell A1 enter 1,
In cell A2 enter 2,
In cell A3 enter +,
Create a named range, with =Evaluate(A1 & A3 & A2) in the refers to field while creating the named range. Let's call this named range "testEval",
In cell A4 enter =testEval,
Cell A4 should have the value 3 in it.
Notes:
a) Requires no programming/VBA.
b) I did this in Excel 2013 and it works.
Say, let we have column E filled by formulas that returns string, like:
= " = " & D7
where D7 cell consist more complicated formula, that composes final desired result, say:
= 3.02 * 1024 * 1024 * 1024
And so in all huge qty of rows that are.
When rows are a little - it just enough to copy desired cells as values (by RMB)
to nearest column, say G, and press F2 with following Enter in each of rows.
However, in case of huge qty of rows it's impossible ...
So, No VBA. No extra formulas. No F&R
No mistakes, no typo, but stupid mechanical actions instead only,
Like on a Ford conveyor. And in just a few seconds only:
[Assume, all of involved columns are in "General" format.]
Open Notepad++
Select entire column D
Ctrl+C
Ctrl+V in NPP
Ctrl+A in NPP
Select cell in the first row of desired column G1
Ctrl+V
Enjoy :)
.
Excel 2019 here. EVALUATE isn't valid.
It would work if we created a Named Range out of it:
But in this case we provide an absolute reference, which is not nice:
We would have to modify the formula every time we want to reuse it.
When the value in A1 changes, the evaluated result would not change.
Solution:
=EVALUATE(GET.CELL(5,OFFSET(INDIRECT("RC",FALSE),0,-1)))
The best, non-VBA, way to do this is using the TEXT formula. It takes a string as an argument and converts it to a value.
For example, =TEXT ("0.4*A1",'##') will return the value of 0.4 * the value that's in cell A1 of that worksheet.

display inside a column the number from a string

I have one column (B) ( over 3k cells ):
TestUrl
__________________________________
http://www.testing.eu/test123.html
http://www.testing.eu/test154.html
http://www.testing.eu/test983.html
.. and so on ...
I want in column C, to get only the numbers:
Numbers
__________
123
154
983
..and so on..
How can I achieve this?
using an array formula..
assuming your data starts at B2.
type this in the formula bar on C2.
Then instead of pressing ENTER, press CTRL+SHIFT+ENTER.
Then just drag down to copy to other cells below.
=SUMPRODUCT(MID(0&B2,LARGE(INDEX(ISNUMBER(--MID(B2,ROW($1:$50),1))* ROW($1:$50),0),ROW($1:$50))+1,1)*10^ROW($1:$50)/10)
change the B2 in the formula if your data starts somwhere else. Just make sure to press CTRL+SHIFT+ENTER instead of ENTER after changing.
got this from:
http://www.extendoffice.com/documents/excel/1622-excel-extract-number-from-string.html
Using formula in column B:
=MID(A1,LEN("http://www.testing.eu/test") + 1, LEN(A1) - LEN(".html") - LEN("http://www.testing.eu/test"))
Using VBA and Regex:
Sub GetNumberFromURL()
Dim regEx As Object, matches As Object, cl As Range
Set regEx = CreateObject("vbscript.regexp")
regEx.Pattern = "([0-9]+)"
For Each cl In Range("A1:A10") //Update to suit your needs
Set matches = regEx.Execute(cl)
cl.Offset(0, 1) = matches.Item(0)
Next
End Sub
Copy the B column data in notepad and replace http://www.testing.eu/test by empty string and then do same thing with .html. After replacing/removing these string paste the notepad content in column C

Excel: Formula to extract a string of text delimited by markers from cells

I'm messing with a spreadsheet containing postal addresses that have been inserted in the cells' comments
Each comment contain an address composed of a variable number of lines (damn UK addresses, they can have up to 7 lines!) in the following format:
Line1,
Line2,
Line3,
[...],
State
With my poor skills, I've managed to extract the comment with a VBA script, obtaining the following string on a single cell:
Line1,Line2,Line3,[...],State
At this point each string between commas must be extracted to its own cell.
I've managed to extract the 1st 3 lines with the following formulas:
For Line1:
=LEFT(A8;(SEARCH(",";A8))-1)
For Line2:
=MID(A8; SEARCH(",";A8)+1; SEARCH(","; A8; SEARCH(","; A8)+1)-SEARCH(",";A8)-1)
For Line3:
=MID(A8; SEARCH(",";A8;SEARCH(",";A8;SEARCH(",";A8;SEARCH(",";A8)))+1)+1;SEARCH(","; A8; SEARCH(","; A8;SEARCH(",";A8)+1)+1)-SEARCH(",";A8;SEARCH(",";A8)+1)-1)
From this point I start to get overflow errors from my brain... I probably need some days of sleep.
Can anybody help me to get to "line6", and finally suggest me how to pull out the "State line" which ends without comma?
I thought I could pull out the "State" line with =RIGHT(",";SEARCH(",";A8)-1) but I'm obviously doing something wrong because that pulls out a comma instead of a string.
I guess I could do everything with a VBA script, but I'm not that skilled yet :(
With comma separated data in A1, in B1 enter:
=TRIM(MID(SUBSTITUTE($A1,",",REPT(" ",999)),COLUMNS($A:A)*999-998,999))
and copy across. For example:
Note:
Why not use TextToColumns ?
The row of formulas re-calculates automatically if A1 changes.
The row of formulas will work even if A1, itself, contains a formula.
If you are wanting to do this programmatically instead of using a built-in, check out the split function for chopping up your comma separated string. It will split up your input string into an array. Then you can do whatever you like with the array.
Dim Names() As String
Names() = Split(inputValue, ",")
For i = 0 To UBound(Names)
' do what you want with each piece
Next
Gary's Student's answer is great for using the built-in functions.
If you want a VBA solution:
Sub spitString()
Dim sourceRange As Range
Dim stringArr() As String
Dim i As Integer
Set sourceRange = ActiveSheet.Range("A1")
stringArr = Split(sourceRange.Value, ",")
For i = LBound(stringArr) To UBound(stringArr)
sourceRange.Offset(0, i + 1).Value = stringArr(i)
Next i
End Sub
You could avoid adding comments: Are you aware that users can add line breaks inside a cell by pressing ALT+RETURN?
If having high rows d is a problem and you don't like that formatting, an alternative approach might be to write a simple bit of code that changes the height of the current row when a user clicks in a certain range. It would , make other rows less high. Perhaps.
Just a thought. It has benefits keeping it simple.
Harvey.

How can I pull hashtags out of a text column?

I have an Excel sheet in which there is a "description" column. The values in this column often contain anywhere from 0-3 tags, all starting with the # symbol. Is there a way to pull all of these tags out in to columns?
Perhaps just have 3 blank columns called hashtag 1, 2, 3 and pull them in to each column.
It isn't even important that it remove them from the description column while pulling them out.
Example of descriptions:
"#0034 #lost client lost file" - pull out 0034 and lost
"worker has bad quality #SusanB #quality" - pull out SusanB and quality
"#0840 client complaint" - pull out 0840
"lots of ipsum" - pull out nothing
Lets say Column A is Description column, and in A2 you have the first cell with hashtags
In B2 enter:
=MID(A2;(FIND("#";A2))+1;(FIND(" ";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))-(FIND("#";A2))-1)
In C2 enter:
=MID(A2;(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))+1;(FIND(" ";MID(A2;(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))+1;LEN(A2)-(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))))+(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2))))-(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))-1)
In D2 enter:
=MID(A2;(FIND("#";MID(A2;(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))+1;LEN(A2)-(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))))+(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2))))+1;(FIND(" ";MID(A2;(FIND("#";MID(A2;(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))+1;LEN(A2)-(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))))+(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2))))+1;LEN(A2)-(FIND("#";MID(A2;(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))+1;LEN(A2)-(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))))+(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2))))))+(FIND("#";MID(A2;(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))+1;LEN(A2)-(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))))+(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))))-(FIND("#";MID(A2;(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))+1;LEN(A2)-(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2)))))+(FIND("#";MID(A2;(FIND("#";A2))+1;LEN(A2)-(FIND("#";A2))))+(FIND("#";A2))))-1)
I'm fond of an extension that can let you use REGEX in Excel ...
Without this :
1) find the position of the separator character (# ?) in your string with FIND()
2) then use LEFT(), MID() and RIGHT() to explode your string into 3 columns
3) you can delete the # using MID() instead of LEFT() and RIGHT()
--
It would be something like this for the first tag with the # :
=LEFT(A1,FIND("#",A1)-1)
--
Hope this will help !
This can always be done using regular expression.
In VBE, write following function in a module:
Function getHashTags(rng As Range) As Variant
Dim regEx As RegExp
Set regEx = New RegExp
regEx.Pattern = "#\w*\b"
regEx.IgnoreCase = True
regEx.Global = True
Set myMatches = regEx.Execute(rng.Value)
Dim arr(1 To 1, 1 To 3) As Variant
For i = 1 To 3
If i > myMatches.Count Then
arr(1, i) = ""
Else
arr(1, i) = Replace(myMatches(i - 1), "#", "")
End If
Next i
getHashTags = arr
End Function
Now, let's suppose Column A is the Description column, and in cell A2 you have the first cell with hash tags.
In cell B2 enter this:
=getHashTags(B$2)
Now select the cells B2, C2, D2, Press F2 and then ctrl+shift+enter. This will populate the variant return from the function getHashTags to the selected cells.
I hope this helps.
PS: And, yes for this to work you also need to give reference to Microsoft VBScript Regular Expressions 5.5 library.

Extract the last substring from a cell

I have names in a column. I need to split just the last names from that column into another column.
The last name is delimited by a space from the right side.
The contents in cell A2 = Alistair Stevens and I entered the formula in cell B2 (I need 'Stevens' in cell B2)
I tried using the following formulas:
=RIGHT(A2,FIND(" ",A2,1)-1)
=RIGHT(A2,FIND(" ",A2))
Both these formulas work for this cell but when I fill it down / copy and paste it for the cells below it doesn't work. I get the wrong values!!
A3 -> David Mckenzie
B3 -> Mckenzie
This works, even when there are middle names:
=MID(A2,FIND(CHAR(1),SUBSTITUTE(A2," ",CHAR(1),LEN(A2)-LEN(SUBSTITUTE(A2," ",""))))+1,LEN(A2))
If you want everything BUT the last name, check out this answer.
If there are trailing spaces in your names, then you may want to remove them by replacing all instances of A2 by TRIM(A2) in the above formula.
Note that it is only by pure chance that your first formula =RIGHT(A2,FIND(" ",A2,1)-1) kind of works for Alistair Stevens. This is because "Alistair" and " Stevens" happen to contain the same number of characters (if you count the leading space in " Stevens").
The answer provided by #Jean provides a working but obscure solution (although it doesn't handle trailing spaces)
As an alternative consider a vba user defined function (UDF)
Function RightWord(r As Range) As Variant
Dim s As String
s = Trim(r.Value)
RightWord = Mid(s, InStrRev(s, " ") + 1)
End Function
Use in sheet as
=RightWord(A2)
Try this function in Excel:
Public Shared Function SPLITTEXT(Text As String, SplitAt As String, ReturnZeroBasedIndex As Integer) As String
Dim s() As String = Split(Text, SplitAt)
If ReturnZeroBasedIndex <= s.Count - 1 Then
Return s(ReturnZeroBasedIndex)
Else
Return ""
End If
End Function
You use it like this:
First Name (A1) | Last Name (A2)
Value in cell A1 = Michael Zomparelli
I want the last name in column A2.
=SPLITTEXT(A1, " ", 1)
The last param is the zero-based index you want to return. So if you split on the space char then index 0 = Michael and index 1 = Zomparelli
The above function is a .Net function, but can easily be converted to VBA.
If you want to get the second to last word in a text, you can use this macro as a function in your spreadsheet:
Public Function Get2ndText(S As String) As String
Dim sArr() As String
Dim i As Integer
sArr = Split(S, " ")
'get the next to the last string
i = UBound(sArr) - 1
Get2ndText = sArr(i)
End Function
Then in your spreadsheet B1 as the text:
CURRENT OWNER 915 BROADWAY ST HOUSTON TX 77012-2126
in B2 your formula would be:
=Get2ndText(B1)
The result would be
TX
Simpler would be:
=TRIM(RIGHT(SUBSTITUTE(TRIM(A2)," ",REPT(" ",99)),99))
You can use A2 in place of TRIM(A2) if you are sure that your data doesn't contain any unwanted spaces.
Based on concept explained by Rick Rothstein:
http://www.excelfox.com/forum/showthread.php/333-Get-Field-from-Delimited-Text-String
Sorry for being necroposter!
Right(A1, Len(A1)-Find("(asterisk)",Substitute(A1, "(space)","(asterisk)",Len(A1)-Len(Substitute(A1,"(space)", "(no space)")))))
Try this. Hope it works.
Try this:
=RIGHT(TRIM(A2),LEN(TRIM(A2))-FIND(" ",TRIM(A2)))
I was able to copy/paste the formula and it worked fine.
Here is a list of Excel text functions (which worked in May 2011, and but is subject to being broken the next time Microsoft changes their website). :-(
You can use a multiple-stage-nested IF() functions to handle middle names or initials, titles, etc. if you expect them. Excel formulas do not support looping, so there are some limits to what you can do.
RIGHT return whatever number of characters in the second parameter from the right of the first parameter. So, you want the total length of your column A - subtract the index. which is therefore:
=RIGHT(A2, LEN(A2)-FIND(" ", A2, 1))
And you should consider using TRIM(A2) everywhere it appears...
Try this:
Right(RC[-1],Len(RC[-1])-InStrRev(RC[-1]," "))

Resources