VBA dynamic dates inside an API URL - vba

I have an API that I want to update dynamically so that the user can enter a start date and an end date on a spreadsheet and my macro will pull back data for that particular date range.
The issue I'm having is that within the API URL the StartDate and EndDate parameters must be in the format yyyy-mm-dd as a string.
I've tried URL = "https:// ...&StartDate = Format(Date(),"yyyy-mm-dd") & EndDate=Format(Date(),"yyyy-mm-dd")&..." (the ... is for the things before and after the URL).
An example of the type of URL I'm looking at is:
https://www.googleapis.com/analytics/v3/data/ga?ids=ga:12345&startdate=2008-10-01&end-date=2008-10-31&metrics=ga:sessions,ga:bounces
I've also played around with adding in extra quotes within the URL string but I can't seem to get it to work.
I keep getting told that the dates aren't being recognised and therefore I can only get the code to run if I hardcode dates.
Any suggestions?

I noticed a few issues in the code posted. The & is the concatenation operator in VBA. You need to enclose that in "" to make sure you are returning the ampersand as a string, and not joining strings together.
I've added some sample code which hopefully illustrates the idea and get's you back up and running. The code should print out True if the createdURL and testURL are equal, or False if not.
Code
Option Explicit
Public Sub FormatExample()
'This is the example provided
Dim testURL As String
testURL = "https://www.googleapis.com/analytics/v3/data/ga?ids=ga:12345&" & _
"startdate=2008-10-01&end-date=2008-10-31&metrics=ga:sessions,ga:bounces"
'This is a built string example
Dim createdURL As String
createdURL = "https://www.googleapis.com/analytics/v3/data/ga?ids=ga:12345" & _
"&startdate=" & Format(#10/1/2008#, "yyyy-mm-dd") & _
"&end-date=" & Format(#10/31/2008#, "yyyy-mm-dd") & _
"&metrics=ga:sessions,ga:bounces"
'Print out if they are equal
Debug.Print createdURL = testURL
End Sub

Related

String Variable inside Single Quotes in Another String Variable Not Expanding - VBA

I'm trying to build quite a complicated URL String in VBA and I'm having troule escaping everything correctly. I managed to get the URL to work, but now I'm trying to "variablize" the importart parts and can't understand the issue (VBA doesn't exactly give detailed errors either).
Here is a working and non-working example URL:
Dim URL As STring, Client As String
Client = "AClientName"
URL = "http://URL?filter={'mode':'cli','client':'AClientName'}" ' This Works
URL = "http://URL?filter={'mode':'cli','client':' & CLIENT & '}" ' This Fails to Open
You're just missing the a close and open quote around the variable.
If you debug.print, you can see that it's interpreting your & and Client as just another part of the string instead of concatenating it as a variable.
In:
Debug.Print "http://URL?filter={'mode':'cli','client':'AClientName'}"
Out:
http://URL?filter={'mode':'cli','client':'AClientName'}
This works because there's no escaping the string or concatenation needed.
You can see here that & CLIENT & are part of the string.
In:
Debug.Print "http://URL?filter={'mode':'cli','client':' & CLIENT & '}"
Out:
http://URL?filter={'mode':'cli','client':' & CLIENT & '}
To get the proper string with the variable use this.
In:
Debug.Print "http://URL?filter={'mode':'cli','client':'" & Client & "'}"
Out:
http://URL?filter={'mode':'cli','client':'AClientName'}

vb.net app converts dates correctly on one machine but not on another - GB/US formats

I've written an app which brings in a CSV export from our HR system, loops through all the records and applies the values from the HR system to active directory.
It works a treat, and when running on my machine i get no errors whatsoever.
When running it on one of our servers, where it is ultimately going to live and will be executed by a service account, I get date conversion errors...
System.InvalidCastException: Conversion from string "21/08/2020" to type 'Date' is not valid.
Right at the start of my code I'm defining the region...
Dim ukCulture = New Globalization.CultureInfo("en-GB")
System.Threading.Thread.CurrentThread.CurrentCulture = ukCulture
And if I query current culture at runtime, it shows 'en-GB', so that seems right.
If i write out the date strings, they all look right, and the compare operation is working fine.
The error seems to occur in this section of code...
Dim converted_hr_accountexpiry_timestamp= hr_row(0).Item("Termination Date") & ""
Dim hr_termdate_var() As String = converted_hr_accountexpiry_timestamp.split("/")
updatescript = updatescript.Replace("$x", "'" & hr_termdate_var(0) & "'") _
.Replace("$y", "'" & hr_termdate_var(1) & "'") _
.Replace("$z", "'" & hr_termdate_var(2) & "'")
So for context, this code is building up a powershell script which is executed to make the necessary changes in AD.
The section of that powershell code that we're looking at here is this...
$server = "MyPrimaryDNSServer.FQDN"
$exp = get-date -Day $x -Month $y -Year $z -Hour 00 -Minute 00 -Second 00
$expirydate = $exp.ToUniversalTime().AddDays(1)
It seems clear that its trying to use a US date format, because if the date provided would match an acceptable US date, ie 3/5/2020, then it will accept it and the wrong date will be applied. The error is only thrown when the day (dd) portion of the date would not be accepted as MM on an american format date, ie 31/07/2020.
And to re-iterate; this issue doesnt happen on my machine, only on the server that will eventually execute the application. I've been through all the region settings on that device itself and everything is set to united kingdom, with the correct dd/MM/yyyy formats for dates.
I'm at a total loss on this one and pulling out what little hair i have left.
Any suggestions/help appriciated!
EDIT 1:
This is the full exception, minus the users name obvs...
Error with account : Joe Bloggs (1010245)
System.InvalidCastException: Conversion from string "24/07/2020" to type 'Date' is not valid.
at Microsoft.VisualBasic.CompilerServices.Conversions.ToDate(String Value)
at Microsoft.VisualBasic.CompilerServices.Operators.CompareObject2(Object Left, Object Right, Boolean TextCompare)
at Microsoft.VisualBasic.CompilerServices.Operators.CompareObjectEqual(Object Left, Object Right, Boolean TextCompare)
at Atlas.Main.GetAccountsWithUpdates()
EDIT 2:
So it looks like there are two errors occuring, which is why I couldnt find it by commenting each related line out in turn.
This is definately one of the erroring lines...
converted_ad_expiry_timestamp = converted_ad_expiry_timestamp.ToString("dd/MM/yyyy").Split(" ")(0)
The value returned is a datetime not a date, so i use tostring and split it on the space to grab just the date portion.
The second error seems to occur in here...
If Not (converted_hr_expiry_timestamp = converted_ad_expiry_timestamp) Then updateme = True : If (hr_row(0).Item("Termination Date")) = "" Then account_expiration_date = "$null" Else account_expiration_date = converted_hr_expiry_timestamp
It looks like the problem revolves around converted_ad_expiry_timestamp which seems to be a Date (the VB type is an alias for a .NET DateTime). You put it into a specific localized format via converted_ad_expiry_timestamp.ToString("dd/MM/yyyy") and then rely on automated conversion to turn it back into a Date. The way to avoid the problem you see here (where the automated conversion uses the system locale to decide the format) is to use one of the Parse or ParseExact family to control the conversion yourself. With Parse, you can specify the locale to use, or with ParseExact you can specify the format.
Similarly, when you attempt to compare them in If Not (converted_hr_expiry_timestamp = converted_ad_expiry_timestamp) Then ..., the first item in the comparison is a string; if you want to do this comparison, you need to either use ToString on the ad_expiry or parse the hr_expiry into a Date.
I would also recommend using Option Strict if you can to turn these implicit conversions into errors, or if that would introduce to many issues, at least turn on the warning for implicit conversions.
I know this is just working around the problem, and will stop it working locally for you (or rather move the problem to your machine), but if it's only ever going to be run on that server can you not just swap X and Y values?
Dim converted_hr_accountexpiry_timestamp= hr_row(0).Item("Termination Date") & ""
Dim hr_termdate_var() As String = converted_hr_accountexpiry_timestamp.split("/")
updatescript = updatescript.Replace("$x", "'" & hr_termdate_var(1) & "'") _
.Replace("$y", "'" & hr_termdate_var(0) & "'") _
.Replace("$z", "'" & hr_termdate_var(2) & "'")
Alternatively, if you want it to work on both systems then maybe a check before running the offending code is in order, something like this has worked for me in the past:
Try
Dim TempTimeString As String = "31/01/2020 01:00 AM"
Dim ConvertedTime As Date
ConvertedTime = DateTime.Parse(TempTimeString)
'''Don't swap X and Y as it was able to convert
Catch ex As Exception
'''swap X and Y as it was unable to convert
End Try

DLookup When Trying Use Form Field as Criteria

I am new to Access and also to VB. I have a report that displays information on transformers, the report displays data from a query that queries data from two different tables. I would like to use a button to open a PDF document saved in one of the tables.
The code I have so far is this:
Private Sub Command70_Click()
Dim hypa As String
hypa = DLookup("[TestReport]", "TransformerPics", "TxID = " & [Reports]![TransformerInfoSheet]!TXID)
Application.FollowHyperlink [hypa]
End Sub
The error i get is Run-time error '2471' The expression you have entered as a parameter produced this error: 'TP00686'
TP00686 is the transformer number that is displayed on the report.
You need to have some quotes in there:
hypa = DLookup("[TestReport]", "TransformerPics", "TxID = '" & [Reports]![TransformerInfoSheet]!TXID & "'")
Please also see:
DLookup Usage Samples
Dlookup using a string variable as criteria parameter

Excel VBA Macro No Longer Works (Possible issue with http.Send)

I have a little Excel VBA macro that retrieves the stock value for a given company on a given day. The company is specified by passing in their stock symbol ("AZO" for AutoZone, "WMT" for Wal-Mart, etc.), and the date is an actual date value retrieved from an adjacent cell.
It has been working beautifully for 2.5 years, but this week it just stopped working, even though I didn't change anything whatsoever. Where the macro should be returning a value, now it's just returning #VALUE!. When I step through the code, everything is working fine until I get to the .Send(), where it just stops (no error messages or hints as to what went wrong; it just completely stops as if execution were finished). I tried adding an On Error clause but it doesn't get hit. Note: I'm thinking it doesn't make a difference, but originally I had http.Send with no parentheses, but I saw a lot of examples with ("") so I added that but it appears to not have an effect.
My VBA experience is very limited, so I was hoping someone would be able to point me in the right direction.
CODE:
Function StockQuote(strTicker As String, Optional dtDate As Variant)
' Date is optional - if omitted, use today. If value is not a date, throw error.
If IsMissing(dtDate) Then
dtDate = Date
Else
If Not (IsDate(dtDate)) Then
StockQuote = CVErr(xlErrNum)
End If
End If
Dim dtPrevDate As Date
Dim strURL As String, strCSV As String, strRows() As String, strColumns() As String
Dim dbClose As Double
dtPrevDate = dtDate - 7
' Compile the request URL with start date and end date
strURL = "http://ichart.finance.yahoo.com/table.csv?s=" & strTicker & _
"&a=" & Month(dtPrevDate) - 1 & _
"&b=" & Day(dtPrevDate) & _
"&c=" & Year(dtPrevDate) & _
"&d=" & Month(dtDate) - 1 & _
"&e=" & Day(dtDate) & _
"&f=" & Year(dtDate) & _
"&g=d&ignore=.csv"
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", strURL, False
http.Send ("")
strCSV = http.responseText
' The most recent information is in row 2, just below the table headings.
' The price close is the 5th entry
strRows() = Split(strCSV, Chr(10)) ' split the CSV into rows
strColumns = Split(strRows(1), ",") ' split the relevant row into columns. 1 means 2nd row, starting at index 0
dbClose = strColumns(4) ' 4 means: 5th position, starting at index 0
StockQuote = dbClose
Set http = Nothing
End Function
Ran into this same issue today with VBA code that has been working fine for many years. Thanks to this post, not only was I able to get it working again by using https. But I may know the underlying cause as well.
Believe the underlying cause may be perhaps finance.yahoo.com has enabled HSTS. This would mean that once the site is visited using https. The use of https will be enforced for all future requests.
HTTP Strict Transport Security
https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security

Decimal Confusion in VBA

I run different scripts using VBA on my German computer with an English Excel 2013 version installed on it. My local decimal settings are set to be international, e.g. 123123 is displayed as 123,123.00.
However, when I program with VBA, the decimal changes.
For example:
sub decimal_problem()
dim sDecSep as string
dim sThSep as string
sDecSep = Application.International(xlDecimalSeparator) ' sDecSep = "."
sThSep = Application.International(xlThousandsSeparator) ' sThSep = ","
Fmt= "#" & sThSep & "##0" & sDecSep & "00"
'Fmt looks like "#,##0.00" which is what I want
Msgbox(Format(123123,Fmt)) 'Fmt="#,##0.00"
end sub
The number in the Msgbox is 123.123,00 which is the German number format and definitely not the format I specified before.
When I change the format in a Spreadsheet I get the correct separators (e.g. "#,##0.00" returns 123,123.00).
Do you have a solution for that issue?
As I need to calculate with the formatted number, I try to avoid to change the number to a string and use the replace function.
Thanks for the help!
The code you mentioned above is showing the output you wanted that is 123,123.00 and not 123.123,00.
Also as soon as you will assign this value to a range in a sheet this Text value will get converted to numeric automatically. for ex - thisworkbook.sheets(1).range("a1").value = Format(123123, Fmt)--This will assign cell a1 walue as 123,123.00 which will be in numeric
please let me know if I have not understood your scenario.