0

I am looking for a loop function/syntax that will allow my loop to cease once the website I am pulling JSON arrays from has no additional arrays left to parse (variable / unknowable number of arrays).

Thank you for the insight.

sheetCount = 1 
i = 1 
urlArray = Array("URL array list") 

Dim MyRequest As Object
Set MyRequest = CreateObject("WinHttp.WinHttpRequest.5.1")

Dim MyUrls
MyUrls = urlArray 

Dim k As Long
Dim Json As Object

For k = LBound(MyUrls) To UBound(MyUrls)
    With MyRequest
        .Open "GET", MyUrls(k)
        .Send
        Set Json = JsonConverter.ParseJson(.ResponseText)
        Do Until ''[NEED HELP HERE]
           Sheets("Sheet" & sheetCount).Cells(i, 1) = Json("cars")(i)("carType") 
           Sheets("Sheet" & sheetCount).Cells(i, 2) = Json("cars")(i)("fare")("carprice")
            i = i + 1
        Loop
    End With
    sheetCount = sheetCount + 1
Next
Kyle
  • 77
  • 8
  • Provide an example output from `Set Json = ...` – Cody G Aug 30 '16 at 18:31
  • @CodyG. I updated the Set Json code above. The output is parsed text strings (from the JSON on the web) into designated cells (e.g., Cell 1, 2, on Sheet1 for the first text string, etc.) – Kyle Aug 31 '16 at 05:16

1 Answers1

1

You are missing the UBound function.

Other notes

  • No code without Option Explicit, period. No exceptions.
  • Make small functions that do one thing only.
  • Add references to the libraries you use instead of using CreateObject. It will make your life a lot easier because this way you get compile-time type checking and Intellisense.
  • It's safer to use the Exists() method to check if a dictionary key exists before you try to access it. Trying to access a non-existing key will throw a run-time error.
  • I'm silently assuming that you are using https://github.com/VBA-tools/VBA-JSON.

This should be close enough:

Option Explicit

Function GetJson(ByVal url As String) As Dictionary
    With New WinHttpRequest  ' see http://stackoverflow.com/a/3119794/18771
        .Open "GET", url
        .Send
        Set GetJson = JsonConverter.ParseJson(.ResponseText)
    End With
End Function

Sub FillCarInfo(data As Dictionary, sheet As Worksheet)
    Dim i As Integer, car As Dictionary
    For i = 0 To UBound(data("cars")) - 1
        Set car = data("cars")(i)
        ' you probably should use If car.Exists("carType") Then
        sheet.Cells(i, 1) = car("carType")
        sheet.Cells(i, 1) = car("fare")("carprice")
    Next i
End Sub

Sub FillMultipleCarInfo(urls As Variant, book As Workbook)
    Dim i As Integer, data As Dictionary, sheet As Worksheet

    For i = 0 To UBound(urls) - 1
        Set data = GetJson(urls(i))
        Set sheet = book.Sheets(i + 1)
        FillCarInfo data, sheet
    Next i
End Sub

Usage

Dim myUrls As Variant
myUrls = Array("URL array list")

FillMultipleCarInfo myUrls, ActiveWorkbook
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • thanks @tomalak. I think I'm close -- but I get a "ByRef argument type mismatch," highlighting `Sub FillMultipleCarInfo(urls As Variant, book As Workbook)` and urls in `Set data = GetJson(urls(i))` – Kyle Aug 31 '16 at 07:52
  • @Kyle I have no MS Office at home, so I could not test it. At my work PC now, try again. ([see the edit #4](http://stackoverflow.com/posts/39241900/revisions#rev-arrow-0efa021c-1c7a-4cec-b732-59f4a509f151)) – Tomalak Aug 31 '16 at 08:39
  • thank you, updated. The only thing I still don't follow / believe I am implementing incorrectly is the "usage" part above. I have the entire code set in "ThisWorkbook" (i.e., not a module). Do I need to put this "usage" code in a particular place? Further, I've never run a program that subdivides into multiple functions, so do I need to set up a "run" sub that calls each function? After that, I should be set. Thanks again. – Kyle Aug 31 '16 at 09:39
  • I can only recommend not to put your code into `ThisWorkbook`. Special rules apply to that and you pretty much all the time want your own code in a regular module. Put the `FillMultipleCarInfo` call wherever you need it. If you have a User Form, you could put it into a button click handler, for example. Or you make its own `Sub` for it and call that via the macros list. It's up to you. – Tomalak Aug 31 '16 at 09:48
  • Regarding *"I've never run a program that subdivides into multiple functions"* - then it's high time. Set a break point on the line that calls `FillMultipleCarInfo` (hotkey F9) and start your code. You will be placed in break mode and will be able to step through the code like-by-line (use F11 and F10 for that). This way you can see how it all works together, inspect the values of local variables. (Another valuable tip is to switch off the "Auto Syntax Check" in the VBA IDE options.) Also see: the [MSDN on VBA debugging](https://msdn.microsoft.com/en-us/library/office/gg251695.aspx) – Tomalak Aug 31 '16 at 10:01
  • that all makes sense -- but without a function/sub, how does the `Dim myURLs As Variant` run? I attempted to create a new module, solely for running this program and it did not work. I basically set it up as `Call GetJson Call FillCarInfo Call FillMultipleCarInfo` -- no luck. This very tactical piece is where I am not able to connect the dots. – Kyle Aug 31 '16 at 13:11
  • I expected that *you* would create a Sub. Or function. Use it in whatever location you are using your current code. How would I know where this code should live, it's your application after all. Make a Sub. Put it into there. Run that Sub however you like. And forget that `Call` exists, you literally never need to use it. – Tomalak Aug 31 '16 at 15:55
  • understood - I correctly set everything up now have bumped into an issue with the code. I'd very much appreciate your help - you've been a HUGE help. I'm not clear why, but I'm getting an "type mismatch error" on `For i = 0 To UBound(data("cars")) - 1` under `Sub FillCarInfo`. The underlying JSON text looks like this: `{"id":15,"cars":[{"carType":"expressTaxi","fare":‌​{"carPrice":"$19,000", "carYear":"2015",}}` – Kyle Sep 01 '16 at 11:21
  • Set a breakpoint, inspect the values. `UBound()` only works with arrays. If `data("cars")` does not contain an array, you will get a type mismatch error. — I don't want to sound impolite, but StackOverflow threads should not become 1-on-1 interactive debugging sessions. You can't just write a comment for every subsequent bump you hit with your code, this is really not how this website works. This is supposed to be strict Q&A. You ask one question and people post one (or more) answers to *that* question. Further issues? Open more questions. Literally nobody benefits from a huge comment trail. – Tomalak Sep 01 '16 at 11:32