replace multiple cell value from a group of strings - excel

Hi I want to replace multiple values in one for example :
sunny 91878656 rere
vicky 91864567 gfgf
honey 91941561 ytyt
monika 98887888 hjhj
NOw if I want to replace the following two values together with space:
91941561
98887888
How can I do it ?
I dont want to do simple find and replace as this is just an exmaple I have a list of over 12000 records and the numbers which needs to be replaced are more than 900
the reason i want to replace is they are not valid anymore.
also is it possible to remove whole record like if 91941561 is found whole of the record should be deleted or replaced with space like:
honey 91941561 ytyt
monika 98887888 hjhj
thanks

You may use the Regular expression. Below is a sample code
Sub test()
Dim str_demo As String
str_demo = "monika 98887888 hjhj"
MsgBox getString(str_demo)
End Sub
Function getString(ByVal str As String) As String
Dim objRegEx As Object
Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.IgnoreCase = True
objRegEx.Global = True
objRegEx.Pattern = "[a-zA-Z]"
Set allMatches = objRegEx.Execute(str)
For i = 0 To allMatches.Count - 1
result = result & allMatches.Item(i)
Next
getString = result
End Function

Related

What's the best way to keep regex matches in Excel?

I'm working off of the excellent information provided in "How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops", however I'm running into a wall trying to keep the matched expression, rather than the un-matched portion:
"2022-02-14T13:30:00.000Z" converts to "T13:30:00.000Z" instead of "2022-02-14", when the function is used in a spreadsheet. Listed below is the code which was taken from "How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops". I though a negation of the strPattern2 would work, however I'm still having issues. Any help is greatly appreciated.
Function simpleCellRegex(Myrange As Range) As String
Dim regEx As New RegExp
Dim strPattern As String
Dim strPattern2 As String
Dim strInput As String
Dim strReplace As String
Dim strOutput As String
strPattern = "^T{0-9][0-9][:]{0-9][0-9][:]{0-9][0-9][0-9][Z]"
strPattern2 = "^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])"
If strPattern2 <> "" Then
strInput = Myrange.Value
strReplace = ""
With regEx
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = strPattern2
End With
If regEx.test(strInput) Then
simpleCellRegex = regEx.Replace(strInput, strReplace)
Else
simpleCellRegex = "Not matched"
End If
End If
End Function
Replace is very powerful, but you need to do two things:
Specify all the characters you want to drop, if your regexp is <myregexp>, then change it to ^.*?(<myregexp>).*$ assuming you only have one date occurrence in your string. The parentheses are called a 'capturing group' and you can refer to them later as part of your replacement pattern. The ^ at the beginning and the $ at the end ensure that you will only match one occurrence of your pattern even if Global=True. I noticed you were already using a capturing group as a back-reference - you need to add one to the back-reference number because we added a capturing group. Setting up the pattern this way, the entire string will participate in the match and we will use the capturing groups to preserve what we want to keep.
Change your strReplace="" to strReplace="$1", indicating you want to replace whatever was matched with the contents of capturing group #1.
Here is a screenprint from Excel using my RegexpReplace User Defined Function to process your example with my suggestions:
I had to fix up your time portion regexp because you used curly brackets three times where you meant square, and you left out the seconds part completely. Notice by adjusting where you start and end your capturing group parentheses you can keep or drop the T & Z at either end of the time string.
Also, if your program is being passed system timestamps from a reliable source then they are already well-formed and you don't need those long, long regular expressions to reject March 32. You can code both parts in one as
([-0-9/.]{10,10})T([0-9:.]{12,12})Z and when you want the date part use $1 and when you want the time part use $2.

How to loop through XML-nodes and validate if values exists?

I have through an API fetched my data as an XML, and I wish to cycle through nodes (there are several of the same type) and add them to certain fields/a table.
Example from the XML-file:
<HistRating
xmlns="">
<EndrAr>2020</EndrAr>
<EndrMnd>7</EndrMnd>
<Rating>A</Rating>
</HistRating>
<HistRating
xmlns="">
<EndrAr>2019</EndrAr>
<EndrMnd>6</EndrMnd>
<Rating>A</Rating>
</HistRating>
I have tried the following format (at this point the XML I need is in a string in xmlDoc xmlDoc = CreateObject("MSXML2.DOMDocument.6.0"). Fully aware that this is not a really "sexy" way to write it, but I'm new at this game:
Set nodeXML = xmlDoc.getElementsByTagName("EndrAr")
Range("G1").Value = nodeXML(1).Text
Range("H1").Value = nodeXML(2).Text
Range("I1").Value = nodeXML(3).Text
Set nodeXML = xmlDoc.getElementsByTagName("EndrMnd")
Range("G2").Value = nodeXML(1).Text
Range("H2").Value = nodeXML(2).Text
Range("I2").Value = nodeXML(3).Text
Set nodeXML = xmlDoc.getElementsByTagName("Rating")
Range("G3").Value = nodeXML(1).Text
Range("H3").Value = nodeXML(2).Text
Range("I3").Value = nodeXML(3).Text
This works great as long as all three items are there. Unfortunately that is not given. If it is a new company i.e. (3) wont exist (there is one line per year above), and I would like to either set the cell to Blank or No value or something.
The result from when I run the above code:
But if I try to add a line 4 to test what happens if value does not exists I get the following (for obvious reasons)
What I would love some help with is:
Can I by some "magic" add a ifmissing (tried it, but could not get it to work)?
Other ways to add a if variable is not found, input following into cell
Or are there a complete different way I should have solved this?
This is to add accounting data from last X available years (where X is ie 4, or less if not 4 is available) from 30 nodes.
You could use an Error trapping Function. Note in the code below we choose not to use the returned boolean.
Dim myTest as String
.
.
TryReadingXmlNode nodeXML,1, myText
Range("G1").Value = myText
.
.
Public Function TryReadingXmlNode(ByVal ipNode as object, ByVal ipIndex as Long, ByRef opText as string) as boolean
On Error Resume Next
opText=ipNode.Item(ipIndex).Text
TryReadingXmlNode=Len(opText)>0
If err.number>0 then opText="NoValue"
on Error Goto 0
End Function
Start by querying all of the HistRating elements, then loop over that collection:
Const MAX_YEARS As Long = 4
Dim ratings, rating, c As Range, i as Long
Set c= Range("A1")
Set ratings = xmlDoc.getElementsByTagName("HistRating")
For Each rating in ratings
c.offset(0, i) = rating.getElementsByTagName("EndrAr")(0).Text
c.offset(1, i) = rating.getElementsByTagName("EndrMnd")(0).Text
c.offset(2, i) = rating.getElementsByTagName("Rating")(0).Text
i = i + 1
If i >= MAX_YEARS Then Exit For 'exit if processed enough nodes
Next rating

VB.net Trim function

I have an issue with trim the string method NOT working completely I have reviewed MS Docs and looked of forums but with no luck... It's probably something simple or some other parameter is missing. This is just a sample,
Please note I need to pick up text before and after #, hence than I was planning to use # as a separator. Trim start # #, Trim End # #. I can't use The last Index or Replace per my understanding they have no direction. But perhaps I am misunderstood MS docs regards to trim Start and End as well...
thanks!
Dim str As String = "this is a #string"
Dim ext As String = str.TrimEnd("#")
MsgBox(ext)
ANSWER:
I found a solution for my problem, if you experience similar please see below:
1st: Trim end will NOT scan for the "character" from the Right as I originally thought it will just remove it from the right.... A weak function I would say:). IndexOf direction ID would be a very simple and helpful. Regards My answer was answered by Andrew, thanks!
Now there is another way around it if you try to split a SINGLE String INTO - QTY based on CHARACTER separation and populate fields accordingly.
Answer is ArrayList. Array List will ID each String so you can avoid repeated populations and etc. After you can use CASE or IF to populate accordingly.
Dim arrList As New ArrayList("this is a # string".Split("#"c)) ' Will build the list of your strings
Dim index As Integer = 1 ' this will help us index the strings 1st, 2nd and etc.
For Each part In arrList 'here we are going thru the list
Select Case index ' Here we are identifying which field we are populating
Case 1 '1st string(split)
MsgBox("1 " & arrList(0) & index) '1st string value left to SPLIT arrList(0).
Case 2 '2nd string(split)
MsgBox("2 " & arrList(1) & index) '2nd string value left to SPLIT arrList(1).
End Select
index += 1 'Here we adding one shift thru strings as we go
Next
Rather than:
Dim str As String = "this is a #string"
Dim ext As String = str.TrimEnd("#")
Try:
Dim str As String = "this is a #string"
Dim ext As String = str.Replace("#", "")
Dim str As String = "this is a #string"
Dim parts = str.Split("#"c)
For Each part in parts
Console.WriteLine($"|{part}|")
Next
Output:
|this is a |
|string|
Maybe there is a better way as we know there are multiple things to do the same thing.
The solution I used is below:
Dim arrList As New ArrayList("this is a # string".Split("#"c)) ' Will build the list of your strings
Dim index As Integer = 1 ' this will help us index the strings 1st, 2nd and etc.
For Each part In arrList 'here we are going thru the list
Select Case index ' Here we are identifying which field we are populating
Case 1 '1st string(split)
MsgBox("1 " & arrList(0) & index) '1st string value left to SPLIT arrList(0).
Case 2 '2nd string(split)
MsgBox("2 " & arrList(1) & index) '2nd string value left to SPLIT arrList(1).
End Select
index += 1 'Here we adding one shift thru strings as we go
Next

how to format many emails with regex using vba

With vba, i want to validate many emails between then with semicolon,every mail must end with #customercurrency.com and user can put 2 or 3 or 4 or many emails as he want.
Example : aung#customercurrency.com;thet#customercurrency.com;htoo#customercurrency.com
My code is here.But it might be something wrong.
Public Function ValidateEmailAddressWithSemi(ByRef strEmailAddress As String) As Boolean
'Create Regular expression object
Dim objRegExp As New RegExp
'Set Case insensitive
objRegExp.IgnoreCase = True
objRegExp.pattern = "^\s?([_a-z0-9-]+(.[a-z0-9-]+)#customconcurrency.com)+([;.]([_a-z0-9-]+(.[a-z0-9-]+)#customconcurrency.com)*$"
ValidateEmailAddress = objRegExp.Test(strEmailAddress)
End Function
try this pattern :
"^\s?([_a-z0-9-]+(.[a-z0-9-]+)#customercurrency.com)+([;.]([_a-z0-9-]+(.[a-z0-9-]+)#customercurrency.com))*$"
(mistake in the domain name and a paranthesis is missing)

Excel: Extract text from cell where text is always #.#

I have a bunch of text in cells but many of the cells contain some text in the format of #.# (where # is actually a number from 0-9).
I'm using this formula which works okay, but sometimes there is junk in the cell that causes the formula to return the wrong information.
=MID(B7,(FIND({"."},B7,1)-1),3)
For instance, sometimes a cell contains: "abc (1st. list) testing 8.7 yay". Thus I end up with t. instead of the desired 8.7.
Any ideas?
Thank you!
Here is a User Defined Function that will return a numeric pattern in the string if and only if it matches the pattern you describe. If the pattern you describe is not exactly representative, you'll need to provide a better example:
Option Explicit
Function reValue(S As String)
Dim RE As Object, MC As Object
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.Pattern = "\b\d\.\d\b"
If .test(S) = True Then
Set MC = .Execute(S)
reValue = CDbl(MC(0))
Else
reValue = ""
End If
End With
End Function

Resources