How can I RegEx this string into a list?
My String is like this:
google (2.0.3) - Python bindings to the Google search engine.
bits-google (1.12.17) - BITS Google
oauthkit-google (0.1.2) - OAuthKit for Google
google-reauth (0.1.0) - Google Reauth Library
google-common (0.0.1) - Google namespace package
google-colab (1.0.0) - Google Colaboratory tools
google-auth (1.11.2) - Google Authentication Library
INSTALLED: 1.7.0
LATEST: 1.11.2
google-endpoints (4.8.0) - Google Cloud Endpoints
google-oauth (1.0.1) - OAuth2 for Google APIs
google-gax (0.16.0) - Google API Extensions
google-finance (0.1.0) - Google Finance API ikmgitj oijhotrjtrhj
kjhghjihotrhjtri9h
I want to get the name, the version, the description, and eventually if its installed.
I know how to separate a string with only one space, but how do I do that when the string has multiple spaces which vary and also have a dash in it?
EDIT:
I integrated the code now like this (For the people who are interested. Credit):
Dim patt = "(.*?.)(\(\d+.\d+.\d+\)|\d+.\d+.\d+)(=?.*?-.)?(.*)"
Dim matches = Regex.Matches(sOutput, patt, RegexOptions.IgnoreCase)
Dim found_packages As New Dictionary(Of String, List(Of String))
For Each m As Match In matches
Dim key = m.Groups(1).Value.Trim({" "c, ":"c})
If key = "INSTALLED" Then
found_packages(found_packages.Last().Key).Add(m.Groups(2).Value.Trim({" "c, ":"c}))
Continue For
ElseIf key = "LATEST" Then
Continue For
End If
found_packages.Add(key, New List(Of String))
found_packages(key).Add(m.Groups(2).Value.Trim({" "c, ":"c}).Replace("(", "").Replace(")", ""))
If Not String.IsNullOrWhiteSpace(m.Groups(4).Value) Then
found_packages(key).Add(m.Groups(4).Value.Trim({" "c, ":"c}))
End If
Next
For Each package In found_packages
Dim item As New ListViewItem
item.Text = package.Key
item.SubItems.Add(package.Value(0))
item.SubItems.Add(package.Value(1))
If package.Value.Count > 2 Then
item.SubItems.Add(package.Value(2))
End If
lvPackages.Items.Add(item)
Next
You can use RegEx to parse this input and create a Dictionary(Of String, List(Of String)) where each key-value entry is a property (the name) with several values (the version and the description):
Dim patt = "(.*?.)(\(\d+.\d+.\d+\)|\d+.\d+.\d+)(=?.*?-.)?(.*)"
Dim matches = Regex.Matches(txtIn.Text, patt)
Dim dict As New Dictionary(Of String, List(Of String))
For Each m As Match In matches
Dim key = m.Groups(1).Value.Trim({" "c, ":"c})
dict.Add(key, New List(Of String))
dict(key).Add(m.Groups(2).Value.Trim({" "c, ":"c}))
If Not String.IsNullOrWhiteSpace(m.Groups(4).Value) Then
dict(key).Add(m.Groups(4).Value.Trim({" "c, ":"c}))
End If
Next
The dict contains the following:
google
(2.0.3)
Python bindings to the Google search engine.
bits-google
(1.12.17)
BITS Google
oauthkit-google
(0.1.2)
OAuthKit for Google
google-reauth
(0.1.0)
Google Reauth Library
google-common
(0.0.1)
Google namespace package
google-colab
(1.0.0)
Google Colaboratory tools
google-auth
(1.11.2)
Google Authentication Library
INSTALLED
1.7.0
LATEST
1.11.2
google-endpoints
(4.8.0)
Google Cloud Endpoints
google-oauth
(1.0.1)
OAuth2 for Google APIs
google-gax
(0.16.0)
Google API Extensions
google-finance
(0.1.0)
Google Finance API ikmgitj oijhotrjtrhj kjhghjihotrhjtri9h
You can get the values (version and description) of the google key (name) for example as follows:
Dim version = dict("google")(0)
Dim descrip = dict("google")(1)
Note that, both INSTALLED and LATEST keys have no description value, so the Dim descrip = dict("LATEST")(1) will throw an exception. So you have to check first. Now you have the dict dictionary where the dict.Keys are the name-s and the dict.Values are the version-s and description-s for each key.
If you just want to create a List(Of String):
Dim patt = "(.*?.)(\(\d+.\d+.\d+\)|\d+.\d+.\d+)(=?.*?-.)?(.*)"
Dim matches = Regex.Matches(txtIn.Text, patt)
Dim lst As New List(Of String)
For Each m As Match In matches
lst.Add(m.Groups(1).Value.Trim({" "c, ":"c}))
lst.Add(m.Groups(2).Value.Trim({" "c, ":"c}))
If Not String.IsNullOrWhiteSpace(m.Groups(4).Value) Then
lst.Add(m.Groups(4).Value.Trim({" "c, ":"c}))
End If
Next
Here's the regex101 test for the preceding RegEx pattern.
Edit: Suggested Improvements
According to your last edit which clarifies what you are trying to achieve, I'd like to suggest the following:
You can get rid of the Dictionary(Of String, List(Of String)) and work directly with the ListViewItemCollection of the ListView control. This way, just one ForEach loop will do the job.
Dim patt = "(.*?.)(\(\d+.\d+.\d+\)|\d+.\d+.\d+)(=?.*?-.)?(.*)"
Dim matches = Regex.Matches(sOutput.Text, patt)
lvPackages.BeginUpdate()
lvPackages.Items.Clear()
For Each m As Match In matches
Dim key = m.Groups(1).Value.Trim({" "c, ":"c})
If key.IndexOf("latest", StringComparison.InvariantCultureIgnoreCase) >= 0 Then
Continue For
End If
Dim lvi As ListViewItem
If key.IndexOf("installed", StringComparison.InvariantCultureIgnoreCase) >= 0 Then
lvi = lvPackages.Items.OfType(Of ListViewItem).LastOrDefault
'Just in case
If lvi IsNot Nothing Then
lvi.SubItems.Add(m.Groups(2).Value.Trim({" "c, ":"c}))
End If
Continue For
End If
lvi = New ListViewItem(key)
'Add the version..
lvi.SubItems.Add(Regex.Match(m.Groups(2).Value, "\d+.\d+.\d+").Value)
If Not String.IsNullOrWhiteSpace(m.Groups(4).Value) Then
'Add the description..
lvi.SubItems.Add(m.Groups(4).Value.Trim({" "c, ":"c}))
End If
lvPackages.Items.Add(lvi)
Next
'Optional: Auto size each column to fit the longest item.
lvPackages.Columns.Cast(Of ColumnHeader).
ToList().ForEach(Sub(x) x.Width = -1)
lvPackages.EndUpdate()
Check it out.
This is a job for regular expressions. You can parse the string using a variable number of whitespace characters. I'm not sure about vb, but in python I would do something like this (but iterating over each line by splitting based on the \r):
Related
Here is what I need to do (for clarity)
Take a PDF file (link on the bottom)
Then parse only the information under each header into a DataFridView.
I couldn't think of a way to do this (seeing as there is no native way to handle PDFs)
So my only thought was to convert it to a txt document then (somehow) take the txt from the text document and put it into the datagridview.
So, using Itextsharp I first convert the PDF to a text file; Which keeps "most" of its formatting (see link below)
This is the source for that
Dim mPDF As String = "C:\Users\Innovators World Wid\Documents\test.pdf"
Dim mTXT As String = "C:\Users\Innovators World Wid\Documents\test.txt"
Dim mPDFreader As New iTextSharp.text.pdf.PdfReader(mPDF)
Dim mPageCount As Integer = mPDFreader.NumberOfPages()
Dim parser As PdfReaderContentParser = New PdfReaderContentParser(mPDFreader)
'Create the text file.
Dim fs As FileStream = File.Create(mTXT)
Dim strategy As iTextSharp.text.pdf.parser.SimpleTextExtractionStrategy
For i As Integer = 1 To mPageCount
strategy = parser.ProcessContent(i, New iTextSharp.text.pdf.parser.SimpleTextExtractionStrategy())
Dim info As Byte() = New UTF8Encoding(True).GetBytes(strategy.GetResultantText())
fs.Write(info, 0, info.Length)
Next
fs.Close()
however I only need the "lines" of information. So everything should look like this
63 FMPC0847535411 OD119523523152105000 Aug 28, 2020 02:18 PM EXPRESS
64 FMPP0532201112 OD119523544975573000 Aug 28, 2020 02:18 PM EXPRESS
65 FMPP0532243104 OD119523557412412000 Aug 28, 2020 02:18 PM EXPRESS
66 FMPC0847516962 OD119523576945605000 Aug 28, 2020 02:18 PM EXPRESS
67 FMPC0847520947 OD119523760191783000 Aug 28, 2020 02:19 PM EXPRESS
In order to do that now I needed to use RegEx to remove everything I didn't want
here is the RegEx I Used
The RegEx is
(\d{2}\s.{14}\s.{20}\s.{3}\s\d{1,2},\s\d{4}\s\d{2}:\d{2}\s.{2}\sEXPRESS,*\s*R*e*p*l*a*c*e*m*e*n*t*\s*o*r*d*e*r*)";
Here is the code I used.
Private Sub Fixtext()
Dim regex As Regex = New Regex("\d{2}\s.{14}\s.{20}\s.{3}\s\d{1,2},\s\d{4}\s\d{2}:\d{2}\s.{2}\sEXPRESS,*\s*R*e*p*l*a*c*e*m*e*n*t*\s*o*r*d*e*r*")
Using reader As StreamReader = New StreamReader("C:\Users\Innovators World Wid\Documents\test.txt")
While (True)
Dim line As String = reader.ReadLine()
If line = Nothing Then
Return
End If
Dim match As Match = regex.Match(line)
If match.Success Then
Dim value As String = match.Groups(1).Value
Console.WriteLine(line)
End If
End While
End Using
End Sub
The results are "close" but not exactly the way I need it. In some cases they are "crammed" together and there are still parts left behind. An example would be
90 FMPC0847531898 OD119522758218348000 Aug 28, 2020 03:20 PM EXPRESS
491 FMPP0532220915 OD119522825195489000 Aug 28, 2020 03:21 PM EXPRESS
Tracking Id Forms Required Order Id RTS done on Notes492 FMPP0532194482 OD119522868525176000 Aug 28, 2020 03:21 PM EXPRESS
493 FMPP0532195684 OD119522871090000000 Aug 28, 2020 03:21 PM EXPRESS494 FMPP0532224318 OD119522895172342000 Aug 28, 2020 03:21 PM EXPRESS
the format I actually need is (again) a format I can use to import the data later into a datagridview
so for each line it needs to be
[number][ID][ID2][Date][Notes]
[number][ID][ID2][Date][Notes]
[number][ID][ID2][Date][Notes]
[number][ID][ID2][Date][Notes]
using this "Concept" This is an example of what I need (though i know this doesn't work, but something along these lines that will work)
Dim regex As Regex = New Regex("\d{2}\s.{14}\s.{20}\s.{3}\s\d{1,2},\s\d{4}\s\d{2}:\d{2}\s.{2}\sEXPRESS,*\s*R*e*p*l*a*c*e*m*e*n*t*\s*o*r*d*e*r*")
Using reader As StreamReader = New StreamReader("C:\Users\Innovators World Wid\Documents\test.txt")
While (True)
Dim line As String = reader.ReadLine()
If line = Nothing Then
Return
End If
Dim match As Match = regex.Match(line)
If match.Success Then
Dim value As String = match.Groups(1).Value
Dim s As String = value
s = s.Replace(" Tracking Id Forms Required Order Id RTS done on Notes", Nothing)
s = s.Replace("EXPRESS ", "EXPRESS")
s = s.Replace("EXPRESS", "EXPRESS" & vbCrLf)
Console.WriteLine(line)
End If
End While
End Using
Here is a "brief" explanation with files included.
Copy of the original PDF (This is the PDF being converted to .txt using itext)
I am only doing this because I can't think of a way (outside of paying for a 3rd party tool to convert a pdf to XLS)
https://drive.google.com/file/d/1iHMM_G4UBUlKaa44-Wb00F_9ZdG-vYpM/view?usp=sharing
using the above "itext method" I mentioned this is the outputted converted file
https://drive.google.com/file/d/10dgJDFW5XlhsB0_0QAWQvtimsDoMllx-/view?usp=sharing
I then use the above Regex (mentioned above) to parse out what I don't need.
however it isn't working.
So my Questions are (for "clarity")
Is this the only or best method to do what I need done? (Convert PDF to text, Remove what I don't need then input that information into a DataGridView; Or is there another , Cleaner , Better method?
(if not 1) How can I make this work? Is something wrong with my RegEx or My Logic? Am I missing something better/cleaner that someone can help me see.
(if 2 ^ Not 1) What is the best way to take the results and place them in the proper DataGridView Column.
Final Statement: It doesn't have to be this method. I will take "ANY" method that will allow me to do what I need to be done, the cleaner the better however I have to do this avoiding 3rd party libraries that are free with limitations; Paid 3rd party libraries. That leaves me with limitations. IE: PDFBox, itext,itextsharp) And this has to be able to lead me from a PDF (like the above sample) to that table information in a Datagridview or even a listview.
I will take any help and I am more then appreciative. Also I did re-Ask this question because a mod closed my original question "Stating it wasn't clear what I needed" I did try in both cases to make the question as "thorough" as possible but I do hope this is "Clearer" so it doesn't get closed abruptly.
I cheated a bit by correcting the text file. It goes a little wonky at page breaks and misses starting a new line. Perhaps you can correct that with Itextsharp or the hard to maintain regex.
I made a class to hold the data. The property names become the column headers in the DataGridView.
I read all the lines in the text file into an array. I checked the first character of the line to see if it was a digit then split the line into another array based on the space. Next I created a new Tracking object, fleshing it out with all its properties with the parameterized constructor.
Finally, I checked it the line contained a comma and added that bit of text to the notes parameter. The completed object is added to the list.
After the loop the lst is bound to the grid.
Public Class Tracking
Public Property Number As Integer
Public Property ID As String
Public Property ID2 As String
Public Property TrackDate As Date
Public Property Notes As String
Public Sub New(TNumber As Integer, TID As String, TID2 As String, TDate As DateTime, TNotes As String)
Number = TNumber
ID = TID
ID2 = TID2
TrackDate = TDate
Notes = TNotes
End Sub
End Class
Private Sub OPCode()
Dim lst As New List(Of Tracking)
Dim lines = File.ReadAllLines("C:\Users\maryo\Desktop\test.txt")
For Each line In lines
If Char.IsDigit(line(0)) Then
Dim parts = line.Split(" "c)
Dim T As New Tracking(CInt(parts(0)), parts(1), parts(2), Date.ParseExact($"{parts(3)} {parts(4)} {parts(5)} {parts(6)} {parts(7)}", "MMM d, yyyy hh:mm tt", CultureInfo.CurrentCulture), parts(8))
If line.Contains(",") Then
T.Notes &= line.Substring(line.IndexOf(","))
End If
lst.Add(T)
End If
Next
DataGridView1.DataSource = lst
End Sub
EDIT
To pinpoint the error let's try...
Private Sub OPCode()
Dim lst As New List(Of Tracking)
Dim lines = File.ReadAllLines("C:\Users\maryo\Desktop\test.txt")
For Each line In lines
If Char.IsDigit(line(0)) Then
Dim parts = line.Split(" "c)
If parts.Length < 9 Then
Debug.Print(line)
MessageBox.Show($"We have a line that does not include all fields.")
Exit Sub
End If
Dim T As New Tracking(CInt(parts(0)), parts(1), parts(2), Date.ParseExact($"{parts(3)} {parts(4)} {parts(5)} {parts(6)} {parts(7)}", "MMM d, yyyy hh:mm tt", CultureInfo.CurrentCulture), parts(8))
If line.Contains(",") Then
T.Notes &= line.Substring(line.IndexOf(","))
End If
lst.Add(T)
End If
Next
DataGridView1.DataSource = lst
End Sub
Try this regex and see if this works according to your requirement:
\b[0-9].*(FMPC|OD).*(EXPRESS|Replacement\sOrder)\b
I would like to list up devices and put their prices next to them.
My goal is to check different sites every week and notice trends.
This is a hobby project, I know there are sites that already do this.
For instance:
Device | URL Site 1 | Site 1 | URL Site 2 | Site 2
Device a | http://... | €40,00 | http://... | €45,00
Device b | http://... | €28,00 | http://... | €30,50
Manually, this is a lot of work (checking every week), so I thought a Macro in Excel would help. The thing is, I would like to put the data in a single cell and excel only recognises tables. Solution: view source code, read price, export price to specific cell.
I think this is all possible within Excel, but I can't quiet figure out how to read the price or other given data and how to put it in one specific cell. Can I specify coordinates in the source code, or is there a more effective way of thinking?
First of all you have to find out how does the website works. For the page you asked I have done the following:
Opened http://www.mediamarkt.de page in Chrome.
Typed BOSCH WTW 85230 in the search box, suggestion list appeared.
Pressed F12 to open developer tools and clicked Network tab.
Each time I was typing, the new request appeared (see yellow areas):
Clicked the request to examine general info:
You can see that it uses GET method and some parameters including url-encoded product name.
Clicked the Response tab to examine the data returning from the server:
You can see it is a regular JSON, full content is as follows:
{"suggestions":[{"attributes":{"energyefficiencyclass":"A++","modelnumber":"2004975","availabilityindicator":"10","customerrating":"0.00000","ImageUrl":"http://pics.redblue.de/artikelid/DE/2004975/CHECK","collection":"shop","id":"MediaDEdece2358813","currentprice":"444.00","availabilitytext":"Lieferung in 11-12 Werktagen"},"hitCount":0,"image":"http://pics.redblue.de/artikelid/DE/2004975/CHECK","name":"BOSCH WTW 85230 Kondensationstrockner mit Warmepumpentechnologie (8 kg, A++)","priority":9775,"searchParams":"/Search.ff?query=BOSCH+WTW+85230+Kondensationstrockner+mit+W%C3%A4rmepumpentechnologie+%288+kg%2C+A+%2B+%2B+%29\u0026channel=mmdede","type":"productName"}]}
Here you can find "currentprice":"444.00" property with the price.
Simplified the request by throwing out some optional parameters, it turned out that the same JSON response can be received by the URL http://www.mediamarkt.de/FACT-Finder/Suggest.ff?channel=mmdede&query=BOSCH+WTW+85230
That data was enough to built some code, assuming that first column intended for products:
Option Explicit
Sub TestMediaMarkt()
Dim oRange As Range
Dim aResult() As String
Dim i As Long
Dim sURL As String
Dim sRespText As String
' set source range with product names from column A
Set oRange = ThisWorkbook.Worksheets(1).Range("A1:A3")
' create one column array the same size
ReDim aResult(1 To oRange.Rows.Count, 1 To 1)
' loop rows one by one, make XHR for each product
For i = 1 To oRange.Rows.Count
' build up URL
sURL = "http://www.mediamarkt.de/FACT-Finder/Suggest.ff?channel=mmdede&query=" & EncodeUriComponent(oRange.Cells(i, 1).Value)
' retrieve HTML content
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", sURL, False
.Send
sRespText = .responseText
End With
' regular expression for price property
With CreateObject("VBScript.RegExp")
.Global = True
.MultiLine = True
.IgnoreCase = True
.Pattern = """currentprice""\:""([\d.]+)""" ' capture digits after 'currentprice' in submatch
With .Execute(sRespText)
If .Count = 0 Then ' no matches, something going wrong
aResult(i, 1) = "N/A"
Else ' store the price to the array from the submatch
aResult(i, 1) = .Item(0).Submatches(0)
End If
End With
End With
Next
' output resultion array to column B
Output Sheets(1).Range("B1"), aResult
End Sub
Function EncodeUriComponent(strText)
Static objHtmlfile As Object
If objHtmlfile Is Nothing Then
Set objHtmlfile = CreateObject("htmlfile")
objHtmlfile.parentWindow.execScript "function encode(s) {return encodeURIComponent(s)}", "jscript"
End If
EncodeUriComponent = objHtmlfile.parentWindow.encode(strText)
End Function
Sub Output(oDstRng As Range, aCells As Variant)
With oDstRng
.Parent.Select
With .Resize( _
UBound(aCells, 1) - LBound(aCells, 1) + 1, _
UBound(aCells, 2) - LBound(aCells, 2) + 1 _
)
.NumberFormat = "#"
.Value = aCells
.Columns.AutoFit
End With
End With
End Sub
Filled worksheet with some product names:
Launched the sub and got the result:
It is just the example how to retrieve a data from the website via XHR and parse a response with RegExp, I hope it helps.
I would like to grab the cost shown below as a number:
478150 or 478150.00
Net Cost Budget Amount: $478,150.00 - Current Baselined Version Number - 1 - Version Name - Net
The text is found in an outlook email body and I am trying to use VBA to grab this item.
With BDGT
.Pattern = "(Net Cost Budget Amount[:] \d{1,3}(,\d{3})*(\.\d+))\n"
.Global = False
End With
Try this instead:
.Pattern = "Net Cost Budget Amount\: \$((?:\d{1,3}\,\d{3}|\d{1,3})\.\d+)"
It will match any number between (and including) 0.00 and 999,999.99, with mandatory separators.
I assume you already know how to extract matches/submatches with the vbscript.regex engine in VBA. If you don't, let me know.
I have data in Excel like follows (one row here - one cell in Excel):
07 July 2015 12:02 – 14 July 2015 17:02
12 August 2015 22:02 – 01 September 2015 11:02
I want to write a macro that will delete all time info (e.g. "12:02") within a user's selection (multiple cells) to look like this:
07 July 2015 – 14 July 2015
12 August 2015 – 01 September 2015
When all "times" where similar ("00:00") this macro worked perfectly:
Sub delete_time()
Selection.Replace What:="00:00", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End Sub
But then time-info stopped being uniform, so I decided to use RegEx. The problem is I can't find a proper way to do this on VBA. I tried this macro:
Sub delete_time()
Dim RegEx As Object
Set RegEx = CreateObject("VBScript.RegExp")
On Error Resume Next
RegEx.Global = True
RegEx.Pattern = "\d\d\:\d\d"
ActiveDocument.Range = _
RegEx.Replace(ActiveDocument.Range, "")
End Sub
But it didn't work. Also tried "[0-9]{2}:[0-9]{2}" and "[0-9][0-9]:[0-9][0-9]" patterns but nothing changed. So the problem must be in my misunderstanding of VBA (I'm new to it).
Can anyone help?
The problem is with your selection.
ActiveDocument.Range = _
RegEx.Replace(ActiveDocument.Range, "")
ActiveDocument doesn't exist in the Excel namespace. We have ActiveWorkbook or ThisWorkbook, but what you need now is the Selection.
Use a for each loop to iterate all the cells in the current selection like this:
Dim myCell As Range
For Each myCell In Selection.Cells
myCell.Value = RegEx.Replace(myCell.Value, "")
Next
A faster approach would be to combine your RegExp with a variant array:
'Press Alt + F11 to open the Visual Basic Editor (VBE)
'From the Menu, choose Insert-Module.
'Paste the code into the right-hand code window.
'Press Alt + F11 to close the VBE
'In Xl2003 Goto Tools … Macro … Macros and double-click KillDate
Sub KillDate()
Dim rng1 As Range
Dim rngArea As Range
Dim lngRow As Long
Dim lngCol As Long
Dim lngCalc As Long
Dim objReg As Object
Dim X()
On Error Resume Next
Set rng1 = Application.InputBox("Select range for the replacement", "User select", Selection.Address, , , , , 8)
If rng1 Is Nothing Then Exit Sub
On Error GoTo 0
'See Patrick Matthews excellent article on using Regular Expressions with VBA
Set objReg = CreateObject("vbscript.regexp")
objReg.Pattern = "\d\d\:\d\d"
objReg.Global = True
'Speed up the code by turning off screenupdating and setting calculation to manual
'Disable any code events that may occur when writing to cells
With Application
lngCalc = .Calculation
.ScreenUpdating = False
.Calculation = xlCalculationManual
.EnableEvents = False
End With
'Test each area in the user selected range
'Non contiguous range areas are common when using SpecialCells to define specific cell types to work on
For Each rngArea In rng1.Areas
'The most common outcome is used for the True outcome to optimise code speed
If rngArea.Cells.Count > 1 Then
'If there is more than once cell then set the variant array to the dimensions of the range area
'Using Value2 provides a useful speed improvement over Value. On my testing it was 2% on blank cells, up to 10% on non-blanks
X = rngArea.Value2
For lngRow = 1 To rngArea.Rows.Count
For lngCol = 1 To rngArea.Columns.Count
'replace the leading zeroes
X(lngRow, lngCol) = objReg.Replace(X(lngRow, lngCol), vbNullString)
Next lngCol
Next lngRow
'Dump the updated array sans leading zeroes back over the initial range
rngArea.Value2 = X
Else
'caters for a single cell range area. No variant array required
rngArea.Value = objReg.Replace(rngArea.Value, vbNullString)
End If
Next rngArea
'cleanup the Application settings
With Application
.ScreenUpdating = True
.Calculation = lngCalc
.EnableEvents = True
End With
Set objReg = Nothing
End Sub
The easiest approach to me seems to be to use LEFT and RIGHT functions to extract the two separate timestamps, then to convert these timestamps to dates using TEXT function. Probably easiest in excel directly, but if you want to go down VBA route then example solution below:
' Taking a random date from Cell A1
DateRange = Range("A1")
' Extracting the first timestamp
FirstTimeStamp = Left(DateRange, Application.Find(" – ", DateRange))
' Converting to required date format
FirstDate = Application.Text(FirstTimeStamp, "dd-mmm-yyyy")
LastTimeStamp = Right(DateRange, Application.Find(" – ", DateRange))
LastDate = Application.Text(LastTimeStamp, "dd-mmm-yyyy")
Function ReplaceRegEx(str As String, pattern As String, newChar As String) As String 'recherche et remplace une expression reguliere par une chaine de char
Dim regEx As Object, found As Object, counter As Integer, F As Object
Set regEx = CreateObject("VBscript.RegExp")
regEx.Global = True
regEx.ignorecase = False
regEx.pattern = pattern
Set found = regEx.Execute(str)
counter = found.Count
If counter <> 0 Then
For Each F In found
str = Replace(str, F, newChar)
Next F
End If
ReplaceRegEx = str
End Function
In a VBA module in excel 2007, is it possible to call a web service? If so, any code snippets? How would I add the web reference?
Yes You Can!
I worked on a project that did that (see comment). Unfortunately no code samples from that one, but googling revealed these:
How you can integrate data from several Web services using Excel and VBA
STEP BY STEP: Consuming Web Services through VBA (Excel or Word)
VBA: Consume Soap Web Services
Here's an overview from MS:
Consuming Web Services in Excel 2007
For an updated answer see this SO question:
calling web service using VBA code in excel 2010
Both threads should be merged though.
In Microsoft Excel Office 2007 try installing "Web Service Reference Tool" plugin. And use the WSDL and add the web-services. And use following code in module to fetch the necessary data from the web-service.
Sub Demo()
Dim XDoc As MSXML2.DOMDocument
Dim xEmpDetails As MSXML2.IXMLDOMNode
Dim xParent As MSXML2.IXMLDOMNode
Dim xChild As MSXML2.IXMLDOMNode
Dim query As String
Dim Col, Row As Integer
Dim objWS As New clsws_GlobalWeather
Set XDoc = New MSXML2.DOMDocument
XDoc.async = False
XDoc.validateOnParse = False
query = objWS.wsm_GetCitiesByCountry("india")
If Not XDoc.LoadXML(query) Then 'strXML is the string with XML'
Err.Raise XDoc.parseError.ErrorCode, , XDoc.parseError.reason
End If
XDoc.LoadXML (query)
Set xEmpDetails = XDoc.DocumentElement
Set xParent = xEmpDetails.FirstChild
Worksheets("Sheet3").Cells(1, 1).Value = "Country"
Worksheets("Sheet3").Cells(1, 1).Interior.Color = RGB(65, 105, 225)
Worksheets("Sheet3").Cells(1, 2).Value = "City"
Worksheets("Sheet3").Cells(1, 2).Interior.Color = RGB(65, 105, 225)
Row = 2
Col = 1
For Each xParent In xEmpDetails.ChildNodes
For Each xChild In xParent.ChildNodes
Worksheets("Sheet3").Cells(Row, Col).Value = xChild.Text
Col = Col + 1
Next xChild
Row = Row + 1
Col = 1
Next xParent
End Sub
Excel 2013 Read Data from a web service and bash the JSON till you can get what you want out of it (given the JSON will always be in the same format).
This code should just work without the need for any plugins.
You will need your own free API key from the currency converter website though.
I used it to load the USD to GBP value into a cell on my sheet.
Option Explicit
Sub Test_LateBinding()
Dim objRequest As Object
Dim strUrl As String
Dim blnAsync As Boolean
Dim strResponse As String
Set objRequest = CreateObject("MSXML2.XMLHTTP")
strUrl = "https://free.currconv.com/api/v7/convert?q=USD_GBP&compact=ultra&apiKey=[MY_API_KEY]"
blnAsync = True
With objRequest
.Open "GET", strUrl, blnAsync
.SetRequestHeader "Content-Type", "application/json"
.Send
While objRequest.readyState <> 4
DoEvents
Wend
strResponse = .responsetext
End With
Dim responseArray() As String
responseArray = Split(strResponse, ":", -1)
Dim value As String
value = responseArray(1)
Dim valueArray() As String
valueArray = Split(value, "}", -1)
Dim finalValue As String
finalValue = valueArray(0)
Sheet2.Cells(22, "C") = finalValue
End Sub