Since you only provided data for the 1st set of JSON format (the 2nd set of format looks weird anyway, are you sure that's correct?), below code only cater for the 1st set of JSON format:
Public Function ToJSON(rng As Range) As String ' Make sure there are two columns in the range If rng.Columns.Count < 2 Then ToJSON = CVErr(xlErrNA) Exit Function End If Const rootKey As String = "sections" Const surveyKey As String = "surveyQuestions" Dim rngArr As Variant rngArr = rng.Value2 Dim JSONStr As String Dim JSONSurvey As String Dim i As Long ' Skip the first row as it's been used as a header For i = 2 To UBound(rngArr, 1) If rngArr(i, 1) <> vbNullString Or rngArr(i, 2) <> vbNullString Then If rngArr(i, 1) <> vbNullString Then Dim currentName As String If rngArr(i, 1) <> currentName Then If currentName <> vbNullString Then currentName = rngArr(i, 1) JSONStr = JSONStr & JSONSurvey & "]},{" & KeyValue(rngArr(1, 1), rngArr(i, 1)) & "," & Chr(34) & surveyKey & Chr(34) & ": [" JSONSurvey = vbNullString Else currentName = rngArr(i, 1) JSONStr = JSONStr & "{" & KeyValue(rngArr(1, 1), rngArr(i, 1)) & "," & Chr(34) & surveyKey & Chr(34) & ": [" End If Else End If Else JSONSurvey = JSONSurvey & "," End If Dim n As Long For n = 2 To UBound(rngArr, 2) If n = 2 Then JSONSurvey = JSONSurvey & "{" Select Case n Case 4, 5: JSONSurvey = JSONSurvey & KeyValue(rngArr(1, n), rngArr(i, n), False) Case Else: JSONSurvey = JSONSurvey & KeyValue(rngArr(1, n), rngArr(i, n)) End Select If n <> UBound(rngArr, 2) Then JSONSurvey = JSONSurvey & "," Else JSONSurvey = JSONSurvey & "}" End If Next n End If Next JSONStr = JSONStr & JSONSurvey & "]}" ' Strip out the last comma JSONStr = Left(JSONStr, Len(JSONStr) - 1) ToJSON = "{" & Chr(34) & rootKey & Chr(34) & ": [" & _ JSONStr & _ "}]}" End Function Private Function KeyValue(argKey As Variant, argValue As Variant, Optional ValueAsText As Boolean = True) As String If ValueAsText Then KeyValue = Chr(34) & argKey & Chr(34) & ":" & Chr(34) & argValue & Chr(34) Else KeyValue = Chr(34) & argKey & Chr(34) & ":" & LCase(argValue) End If End Function
Running this to Range("A1:G23") which is your entire data will produce this:
{"sections": [{"name":"About the inspection","surveyQuestions": [{"questionText":"report name","questionHelp":"some help 1","sortOrder":1,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"surveyor","questionHelp":"some help 2","sortOrder":2,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"asssigned to","questionHelp":"some help 3","sortOrder":3,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"client firstname","questionHelp":"some help 4","sortOrder":4,"isActive":true,"questionType":"NUMBER","options":""},{"questionText":"client lastname","questionHelp":"some help 5","sortOrder":5,"isActive":true,"questionType":"STARS","options":""},{"questionText":"report reference","questionHelp":"some help 6","sortOrder":6,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"date of inspection","questionHelp":"some help 7","sortOrder":7,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"house / building number","questionHelp":"some help 8","sortOrder":8,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"address line 1","questionHelp":"some help 9","sortOrder":9,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"address line 2","questionHelp":"some help 10","sortOrder":10,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"postcode","questionHelp":"some help 11","sortOrder":11,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"weather conditions","questionHelp":"some help 12","sortOrder":12,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"property status","questionHelp":"some help 13","sortOrder":13,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"property type","questionHelp":"property help","sortOrder":14,"isActive":true,"questionType":"LIST","options":"Bungalow;Semi-detatched, Detached, Terraced, Flat"}]},{"name":"Overall opinion","surveyQuestions": [{"questionText":"our overall opinion of the property","questionHelp":"some help 15","sortOrder":1,"isActive":true,"questionType":"TEXT","options":""}]},{"name":"About the property","surveyQuestions": [{"questionText":"type of property","questionHelp":"some help 17","sortOrder":1,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"approximate year property was built","questionHelp":"some help 18","sortOrder":2,"isActive":true,"questionType":"NUMBER","options":""},{"questionText":"approximate year the property was extended","questionHelp":"some help 19","sortOrder":3,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"approximate year the property was converted","questionHelp":"some help 20","sortOrder":4,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"information relevant to flats and maisonettes","questionHelp":"some help 21","sortOrder":5,"isActive":true,"questionType":"TEXT","options":""}]}]}
And the pretty print version:
{ "sections": [ { "name": "About the inspection", "surveyQuestions": [ { "questionText": "report name", "questionHelp": "some help 1", "sortOrder": 1, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "surveyor", "questionHelp": "some help 2", "sortOrder": 2, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "asssigned to", "questionHelp": "some help 3", "sortOrder": 3, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "client firstname", "questionHelp": "some help 4", "sortOrder": 4, "isActive": true, "questionType": "NUMBER", "options": "" }, { "questionText": "client lastname", "questionHelp": "some help 5", "sortOrder": 5, "isActive": true, "questionType": "STARS", "options": "" }, { "questionText": "report reference", "questionHelp": "some help 6", "sortOrder": 6, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "date of inspection", "questionHelp": "some help 7", "sortOrder": 7, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "house / building number", "questionHelp": "some help 8", "sortOrder": 8, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "address line 1", "questionHelp": "some help 9", "sortOrder": 9, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "address line 2", "questionHelp": "some help 10", "sortOrder": 10, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "postcode", "questionHelp": "some help 11", "sortOrder": 11, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "weather conditions", "questionHelp": "some help 12", "sortOrder": 12, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "property status", "questionHelp": "some help 13", "sortOrder": 13, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "property type", "questionHelp": "property help", "sortOrder": 14, "isActive": true, "questionType": "LIST", "options": "Bungalow;Semi-detatched, Detached, Terraced, Flat" } ] }, { "name": "Overall opinion", "surveyQuestions": [ { "questionText": "our overall opinion of the property", "questionHelp": "some help 15", "sortOrder": 1, "isActive": true, "questionType": "TEXT", "options": "" } ] }, { "name": "About the property", "surveyQuestions": [ { "questionText": "type of property", "questionHelp": "some help 17", "sortOrder": 1, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "approximate year property was built", "questionHelp": "some help 18", "sortOrder": 2, "isActive": true, "questionType": "NUMBER", "options": "" }, { "questionText": "approximate year the property was extended", "questionHelp": "some help 19", "sortOrder": 3, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "approximate year the property was converted", "questionHelp": "some help 20", "sortOrder": 4, "isActive": true, "questionType": "TEXT", "options": "" }, { "questionText": "information relevant to flats and maisonettes", "questionHelp": "some help 21", "sortOrder": 5, "isActive": true, "questionType": "TEXT", "options": "" } ] } ] }
Disclaimer: the code looks messy but it's late and it works!
Forloop toFor dataLoop = 2 To rng.Rows.Countthen removeIf dataLoop > 1 Thenstatement if you are going to always skip the 1st row.