1

I have the following

  • Column A == FEdEX AWB #s
  • Column B == Delivery date (Empty)

I would like to write a function where it reads the tracking number on Column A and extracts the delivery date from the website - all AWB # are delivered - 100% sure

The code I have writes all the info found in the website into the sheet - not sure how to extract only the delivered date.

Sub Macro1()
    With ActiveSheet.QueryTables.Add(Connection:= _
    "URL;https://www.bing.com/packagetrackingv2? 
    packNum=727517426234&carrier=Fedex&FORM=PCKTR1" _
    , Destination:=Range("$A$1"))
    .Name = _
    "https://www.bing.com/packagetrackingv2? 
     packNum=727517426234&carrier=Fedex&FORM=PCKTR1"
    .FieldNames = True
    .RowNumbers = False
    .FillAdjacentFormulas = False
    .PreserveFormatting = True
    .RefreshOnFileOpen = False
    .BackgroundQuery = True
   .RefreshStyle = xlInsertDeleteCells
   .SavePassword = False
   .SaveData = True
   .AdjustColumnWidth = True
   .RefreshPeriod = 0
   .WebSelectionType = xlEntirePage
   .WebFormatting = xlWebFormattingNone
   .WebPreFormattedTextToColumns = True
   .WebConsecutiveDelimitersAsOne = True
   .WebSingleBlockTextImport = False
   .WebDisableDateRecognition = False
   .WebDisableRedirections = False
   .Refresh BackgroundQuery:=False
    End With

End Sub
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Fab
  • 49
  • 4

2 Answers2

1

A function, getting passing the airway bill number and returning the date would be quite enough:

Function GetDateFromAwb(awbNumber As String) As String

    Dim objIE As New InternetExplorer   'Microsoft Internet Controls library added
    objIE.Visible = False               'Or put True, if you want to see the IE

    objIE.navigate "https://www.fedex.com/apps/fedextrack/?tracknumbers=" & awbNumber

    Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
    Application.Wait (Now + TimeValue("0:00:05"))

    GetDateFromAwb = objIE.Document.getElementsByClassName("redesignSnapshotTVC snapshotController_date dest").Item.InnerText
    objIE.Quit

End Function

The idea of the function is to append the airbill string number to the URL and to open the corresponding site. Then, using the class "redesignSnapshotTVC snapshotController_date dest", the corresponding date is taken.

This is a possible way to call the function, displaying the date in a MsgBox:

Sub Main()

    Dim awbNumber As String
    awbNumber = 727517426234#
    Dim awbDate As String

    awbDate = GetDateFromAwb(awbNumber)
    MsgBox awbDate

End Sub

Make sure that the library "Microsoft Internet Controls" is added from the VBE menu>Extras>References:

enter image description here

Vityata
  • 42,633
  • 8
  • 55
  • 100
1

Rather than using a browser you could use xmlhttp request which is quicker.

The page does a form XHR POST request which returns json you can parse (lots of info returned including a delivery date field). You can use this as a function in the sheet. I also show a test call. The id (tracking number) is passed as an argument to the function GetDeliveryDate.

Here is the request made when you submit your tracking number on the site:

As you can see from the above, and further detailed in code, the tracking number is part of the body sent in the request (data param); it is also part of one of the request headers.

I use jsonconverter.bas to parse the json response. After adding the code from there to your project you need go VBE > Tools > References and add a reference to Microsoft Scripting Runtime.

View the json response here

As you say all requests will return a delivery date, if you don't want to load this external library you could use split to isolate the date.


Relevant json:

You can see relevant part of json here:

I use the field actDeliveryDt for version of code using split as I can separate an unambiguous date yyyy-mm-dd from the datetime string. I use displayActDeliveryDt for json parsing though you could use either (removing time part with split if usnig the former as shown in examples below)

Caveat: I have had only one delivery id to use for testing.


TODO:

  1. You could add in a test for whether a valid request was made as the json response includes a field for this.
  2. If performing this for multiple requests I would recommend, for efficiency, to re-write using a sub which loops an array of the tracking numbers, stores results in an array and writes that array out in go at end.

VBA:

JSON parsing:

Option Explicit 'example test call from VBE
Public Sub test()    
    Debug.Print GetDeliveryDate(727517426234#)
End Sub

 Public Function GetDeliveryDate(ByVal id As Double) As Date
    Dim json As Object, body As String  '<  VBE > Tools > References > Microsoft Scripting Runtime
    body = "data={""TrackPackagesRequest"":{""appType"":""WTRK"",""appDeviceType"":""DESKTOP"",""supportHTML"":true,""supportCurrentLocation"":true,""uniqueKey"":"""",""processingParameters"":{},""trackingInfoList"":[{""trackNumberInfo"":{""trackingNumber"":" & Chr$(34) & CStr(id) & Chr$(34) & ",""trackingQualifier"":"""",""trackingCarrier"":""""}}]}}"
    body = body & "&action=trackpackages&locale=en_US&version=1&format=json"

    With CreateObject("MSXML2.XMLHTTP")
        .Open "POST", "https://www.fedex.com/trackingCal/track", False
        .setRequestHeader "Referer", "https://www.fedex.com/apps/fedextrack/?tracknumbers=" & CStr(id)
        .setRequestHeader "User-Agent", "Mozilla/5.0"
        .setRequestHeader "X-Requested-With", "XMLHttpRequest"
        .setRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"
        .send body
        Set json = JsonConverter.ParseJson(.responseText)
    End With
    GetDeliveryDate = json("TrackPackagesResponse")("packageList")(1)("displayActDeliveryDt")
End Function

Using split:

Option Explicit
Public Sub test()
   Debug.Print GetDeliveryDate(727517426234#)
End Sub


Public Function GetDeliveryDate(ByVal id As Double) As Date
    Dim s As String, body As String
    body = "data={""TrackPackagesRequest"":{""appType"":""WTRK"",""appDeviceType"":""DESKTOP"",""supportHTML"":true,""supportCurrentLocation"":true,""uniqueKey"":"""",""processingParameters"":{},""trackingInfoList"":[{""trackNumberInfo"":{""trackingNumber"":" & Chr$(34) & CStr(id) & Chr$(34) & ",""trackingQualifier"":"""",""trackingCarrier"":""""}}]}}"
    body = body & "&action=trackpackages&locale=en_US&version=1&format=json"

    With CreateObject("MSXML2.XMLHTTP")
        .Open "POST", "https://www.fedex.com/trackingCal/track", False
        .setRequestHeader "Referer", "https://www.fedex.com/apps/fedextrack/?tracknumbers=" & CStr(id)
        .setRequestHeader "User-Agent", "Mozilla/5.0"
        .setRequestHeader "X-Requested-With", "XMLHttpRequest"
        .setRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"
        .send body
        s = .responseText
    End With
    GetDeliveryDate = Split(Replace$(Split(Split(s, """actDeliveryDt"":""")(1), Chr$(34))(0), "\u002d", "-"), "T")(0)
End Function

Example usage in sheet:

Note: I have UK format dd/mm/yyyy in sheet

enter image description here

QHarr
  • 83,427
  • 12
  • 54
  • 101
  • I would liek to use this but it is not working - where do i copy paste this Json code found on the link provided ? do i copy everything ? i did copy it on mymodule in VBA and it gives me errors ??? i have never used this Json before, any step by step instruction would be appreciated - Thanks – Fab May 17 '19 at 14:11
  • go to https://github.com/VBA-tools/VBA-JSON/blob/master/JsonConverter.bas > click raw > copy all the code > in your vba project right click insert standard module > press F4 rename as JSONConverter, paste the code inside that module. Then VBE > Tools > References > Add reference to Microsoft Scripting Runtime. – QHarr May 17 '19 at 18:53
  • i did what you suggested - copy the code - and add the function 'using JASON Parsin' in to the VBA under the ThisWorkbook page in VBA. It gave me the following error - under the JSON converter code - it did not recognize the first line "Attribute VB_Name = "JsonConverter"" - giving me a Compile error Syntax error so i cancel out that line and when i run it again (the public sub test()) it gave me this error "Run-Time Error '5' invalid procedure call or argument............. – Fab May 22 '19 at 18:54
  • Then i moved the code - function into the same module wherei put the JSON Converter - when i run the test function it gives me a runtime error "The parameter is incorrect" when i hit on debug it highlights the line " .send body" under the GetDeliveryDate function - within the Create Object("MSXML2.XMLHTTP") – Fab May 22 '19 at 18:54
  • Sorry, i left home yesterday, i just saw your comment and the link does not longer contain the file- i will be in front of my computer for th enext 8 hrs.... – Fab May 23 '19 at 11:44
  • One moment then, – QHarr May 23 '19 at 11:44
  • Got the file, and still does not work, when i open VBA and run teh Public Sub Test function from VBA it gives me this error " Run time error '-2147024809(80070057) The parameter is incorrect" - i am running Windows 7 Enterprise service pack 1 64 bit - Microsoft Excel 2013 – Fab May 23 '19 at 12:16
  • and when i hit debug on the error - VBA highlits the line ".send body" within the getDeliveryDate function – Fab May 23 '19 at 12:22
  • also , i see in your code that you are colling Mozilla/5.0 - i do not have mozilla installed only chrome and IE, could this be the reason ? – Fab May 23 '19 at 12:23
  • i also found this post (it seems to have exactly the same issue as i am having)- however i do not fully understand the solution --- https://stackoverflow.com/questions/28565971/vba-http-post-parameter-incorrect – Fab May 23 '19 at 12:26
  • Not sure but shouldn’t be user agent as that could be pretty much any value. I’ll have to have a look later – QHarr May 23 '19 at 12:26
  • You can always pull your user-agent from dev tools network tab or using online what’s my user agent tool. – QHarr May 23 '19 at 12:36