Consider this example:
Option Explicit
Sub JsonPopulateCellsTest()
Dim strJsonString As String
Dim varJson As Variant
Dim strState As String
Dim i As Long
Dim y As Long
' parse JSON string
strJsonString = "[{""name"":""ryan"",""age"":1,""roll"":2,""address"":""aaa""},{""name"":""ryna"",""age"":2,""roll"":3,""address"":""bbb""},{""name"":""yran"",""age"":5,""roll"":3,""address"":""ccc""},{""name"":""yrna"",""age"":20,""roll"":4,""address"":""ddd""}]"
ParseJson strJsonString, varJson, strState
If strState = "Error" Then
MsgBox "Error"
Exit Sub
End If
' show the full structure starting from root element
MsgBox BeautifyJson(varJson)
y = 1 ' begin row
' output
For i = 0 To UBound(varJson)
Cells(y + i, 1).Value = varJson(i)("name")
Cells(y + i, 2).Value = varJson(i)("age")
Cells(y + i, 3).Value = varJson(i)("roll")
Cells(y + i, 4).Value = varJson(i)("address")
Next
End Sub
Sub ParseJson(ByVal strContent As String, varJson As Variant, strState As String)
' strContent - source JSON string
' varJson - created object or array to be returned as result
' strState - Object|Array|Error depending on processing to be returned as state
Dim objTokens As Object
Dim lngTokenId As Long
Dim objRegEx As Object
Dim bMatched As Boolean
Set objTokens = CreateObject("Scripting.Dictionary")
lngTokenId = 0
Set objRegEx = CreateObject("VBScript.RegExp")
With objRegEx
' specification http://www.json.org/
.Global = True
.MultiLine = True
.IgnoreCase = True
.Pattern = """(?:\""|[^""])*""(?=s*(?:,|:|]|}))"
Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "str"
.Pattern = "(?:[+-])?(?:d+.d*|.d+|d+)e(?:[+-])?d+(?=s*(?:,|]|}))"
Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "num"
.Pattern = "(?:[+-])?(?:d+.d*|.d+|d+)(?=s*(?:,|]|}))"
Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "num"
.Pattern = "b(?:true|false|null)(?=s*(?:,|]|}))"
Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "cst"
.Pattern = "b[A-Za-z_]w*(?=s*:)" ' unspecified name without quotes
Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "nam"
.Pattern = "s"
strContent = .Replace(strContent, "")
.MultiLine = False
Do
bMatched = False
.Pattern = "<d+(?:str|nam)>:<d+(?:str|num|obj|arr|cst)>"
Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "prp"
.Pattern = "{(?:<d+prp>(?:,<d+prp>)*)?}"
Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "obj"
.Pattern = "[(?:<d+(?:str|num|obj|arr|cst)>(?:,<d+(?:str|num|obj|arr|cst)>)*)?]"
Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "arr"
Loop While bMatched
.Pattern = "^<d+(?:obj|arr)>$" ' unspecified top level array
If Not (.test(strContent) And objTokens.Exists(strContent)) Then
varJson = Null
strState = "Error"
Else
Retrieve objTokens, objRegEx, strContent, varJson
strState = IIf(IsObject(varJson), "Object", "Array")
End If
End With
End Sub
Sub Tokenize(objTokens, objRegEx, strContent, lngTokenId, bMatched, strType)
Dim strKey As String
Dim strRes As String
Dim lngCopyIndex As Long
Dim objMatch As Object
strRes = ""
lngCopyIndex = 1
With objRegEx
For Each objMatch In .Execute(strContent)
strKey = "<" & lngTokenId & strType & ">"
bMatched = True
With objMatch
objTokens(strKey) = .Value
strRes = strRes & Mid(strContent, lngCopyIndex, .FirstIndex - lngCopyIndex + 1) & strKey
lngCopyIndex = .FirstIndex + .Length + 1
End With
lngTokenId = lngTokenId + 1
Next
strContent = strRes & Mid(strContent, lngCopyIndex, Len(strContent) - lngCopyIndex + 1)
End With
End Sub
Sub Retrieve(objTokens, objRegEx, strTokenKey, varTransfer)
Dim strContent As String
Dim strType As String
Dim objMatches As Object
Dim objMatch As Object
Dim strName As String
Dim varValue As Variant
Dim objArrayElts As Object
strType = Left(Right(strTokenKey, 4), 3)
strContent = objTokens(strTokenKey)
With objRegEx
.Global = True
Select Case strType
Case "obj"
.Pattern = "<d+w{3}>"
Set objMatches = .Execute(strContent)
Set varTransfer = CreateObject("Scripting.Dictionary")
For Each objMatch In objMatches
Retrieve objTokens, objRegEx, objMatch.Value, varTransfer
Next
Case "prp"
.Pattern = "<d+w{3}>"
Set objMatches = .Execute(strContent)
Retrieve objTokens, objRegEx, objMatches(0).Value, strName
Retrieve objTokens, objRegEx, objMatches(1).Value, varValue
If IsObject(varValue) Then
Set varTransfer(strName) = varValue
Else
varTransfer(strName) = varValue
End If
Case "arr"
.Pattern = "<d+w{3}>"
Set objMatches = .Execute(strContent)
Set objArrayElts = CreateObject("Scripting.Dictionary")
For Each objMatch In objMatches
Retrieve objTokens, objRegEx, objMatch.Value, varValue
If IsObject(varValue) Then
Set objArrayElts(objArrayElts.Count) = varValue
Else
objArrayElts(objArrayElts.Count) = varValue
End If
varTransfer = objArrayElts.Items
Next
Case "nam"
varTransfer = strContent
Case "str"
varTransfer = Mid(strContent, 2, Len(strContent) - 2)
varTransfer = Replace(varTransfer, """", """")
varTransfer = Replace(varTransfer, "\", "")
varTransfer = Replace(varTransfer, "/", "/")
varTransfer = Replace(varTransfer, "b", Chr(8))
varTransfer = Replace(varTransfer, "f", Chr(12))
varTransfer = Replace(varTransfer, "n", vbLf)
varTransfer = Replace(varTransfer, "r", vbCr)
varTransfer = Replace(varTransfer, "t", vbTab)
.Global = False
.Pattern = "\u[0-9a-fA-F]{4}"
Do While .test(varTransfer)
varTransfer = .Replace(varTransfer, ChrW(("&H" & Right(.Execute(varTransfer)(0).Value, 4)) * 1))
Loop
Case "num"
varTransfer = Evaluate(strContent)
Case "cst"
Select Case LCase(strContent)
Case "true"
varTransfer = True
Case "false"
varTransfer = False
Case "null"
varTransfer = Null
End Select
End Select
End With
End Sub
Function BeautifyJson(varJson As Variant) As String
Dim strResult As String
Dim lngIndent As Long
BeautifyJson = ""
lngIndent = 0
BeautyTraverse BeautifyJson, lngIndent, varJson, vbTab, 1
End Function
Sub BeautyTraverse(strResult As String, lngIndent As Long, varElement As Variant, strIndent As String, lngStep As Long)
Dim arrKeys() As Variant
Dim lngIndex As Long
Dim strTemp As String
Select Case VarType(varElement)
Case vbObject
If varElement.Count = 0 Then
strResult = strResult & "{}"
Else
strResult = strResult & "{" & vbCrLf
lngIndent = lngIndent + lngStep
arrKeys = varElement.Keys
For lngIndex = 0 To UBound(arrKeys)
strResult = strResult & String(lngIndent, strIndent) & """" & arrKeys(lngIndex) & """" & ": "
BeautyTraverse strResult, lngIndent, varElement(arrKeys(lngIndex)), strIndent, lngStep
If Not (lngIndex = UBound(arrKeys)) Then strResult = strResult & ","
strResult = strResult & vbCrLf
Next
lngIndent = lngIndent - lngStep
strResult = strResult & String(lngIndent, strIndent) & "}"
End If
Case Is >= vbArray
If UBound(varElement) = -1 Then
strResult = strResult & "[]"
Else
strResult = strResult & "[" & vbCrLf
lngIndent = lngIndent + lngStep
For lngIndex = 0 To UBound(varElement)
strResult = strResult & String(lngIndent, strIndent)
BeautyTraverse strResult, lngIndent, varElement(lngIndex), strIndent, lngStep
If Not (lngIndex = UBound(varElement)) Then strResult = strResult & ","
strResult = strResult & vbCrLf
Next
lngIndent = lngIndent - lngStep
strResult = strResult & String(lngIndent, strIndent) & "]"
End If
Case vbInteger, vbLong, vbSingle, vbDouble
strResult = strResult & varElement
Case vbNull
strResult = strResult & "Null"
Case vbBoolean
strResult = strResult & IIf(varElement, "True", "False")
Case Else
strTemp = Replace(varElement, """", """")
strTemp = Replace(strTemp, "", "\")
strTemp = Replace(strTemp, "/", "/")
strTemp = Replace(strTemp, Chr(8), "b")
strTemp = Replace(strTemp, Chr(12), "f")
strTemp = Replace(strTemp, vbLf, "n")
strTemp = Replace(strTemp, vbCr, "r")
strTemp = Replace(strTemp, vbTab, "t")
strResult = strResult & """" & strTemp & """"
End Select
End Sub
Bookmark this app
Press Ctrl + D to add this page to your favorites or Esc to cancel the action.
Send the download link to
Send us your feedback
Oops! An error has occurred.
Invalid file, please ensure that uploading correct file
Error has been reported successfully.
You have successfully reported the error, You will get the notification email when error is fixed.
Click this link to visit the forums.
Immediately delete the uploaded & processed files.
Are you sure to delete the files?
Enter Url
Есть ли какие-нибудь инструменты для работы с JSON d Excel? |
|
JeyCi Пользователь Сообщений: 3357 |
Изменено: JeyCi — 28.09.2015 10:45:19 чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах) |
Doober Пользователь Сообщений: 2201 |
Для работы в VBA использую найденный на просторах класс Jsonbad. Прикрепленные файлы
Изменено: Doober — 28.09.2015 12:24:41 |
А куда все это подкладывать? |
|
Doober Пользователь Сообщений: 2201 |
Под квочку |
Закопировал в модуль, там столько красного, жесть просто((( |
|
Doober Пользователь Сообщений: 2201 |
#7 28.09.2015 14:08:53 Красного нет.Пример для авторизации
Кратенькое видео в формате ехе как надо использовать ресурсы инета. Изменено: Doober — 28.09.2015 14:09:31 <#0> |
||
Николай Бородин Пользователь Сообщений: 347 |
#8 28.09.2015 16:19:20
Ммм… чую подвох я в этой штуке |
||
Doober Пользователь Сообщений: 2201 |
|
Игорь Пользователь Сообщений: 3631 |
#10 28.09.2015 19:38:58 А я использую конвертацию JSON в XML (на просторах инета нашел модуль парсинга JSON в объект, состоящий из коллекций и словарей, и добавил туда конвертацию в XML) PS: Может, кто подскажет, что это за синтаксис такой, с восклицательными знаками?
это как-то касается NewEnum?
Изменено: Игорь — 28.09.2015 19:44:07 |
||||||
Vitallic Пользователь Сообщений: 239 |
Николай Бородин, на этом форуме встречал такую тему , судя по отзывам неплохая библиотека, Второе найденое решение . |
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#12 29.09.2015 06:01:34 Доброе время суток
Это обращение к свойству по умолчанию с учётом того, что у свойства есть параметр (если значение параметра без пробелов, то можно опустить и символы [] вокруг него).(Интересно бы было знать — как в таком ключе использовать, если параметров у свойства больше одного)?
А это похоже настройка итератора, чтобы можно было использовать For Each |
||||||
Игорь Пользователь Сообщений: 3631 |
Андрей, большое спасибо за ответ. |
JeyCi Пользователь Сообщений: 3357 |
#14 29.09.2015 08:56:57
я не совсем могу представить — это как?.. прямой линк )… т.е. если у свойства есть несколько параметров, то они в рамках общего свойства тоже имеют свои свойства-идентифицирующие их… мне кажется, такова структура json — и никак иначе… имхо… и тогда просто в рамках свойства выделяется объект, состоящий из нескольких параметров и их свойств… я это однозначно видела , когда адаптировала тот код (из примера1 с использованием ScriptControl — на stackoverflow) и не поставила set value=…
P.S. как в др кодах-обработки json — не знаю… Изменено: JeyCi — 29.09.2015 09:10:50 чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах) |
||||
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#15 29.09.2015 09:34:28
Да не за что. Когда то кодил на VB6, там это всё явно выставлялось…
Давайте по порядку.
Сохраните этот класс в файл и допишите в нём атрибут свойства по-умолчанию
То вы получите возможность обращаться к этому свойству в такой манере
Но, допустим мы определили свойство с двумя параметрами
И указали его как свойство по умолчанию, варианты
понятны, а как будет выглядеть это же в «хитрой» нотации с ![] Изменено: Андрей VG — 30.09.2015 00:53:38 |
||||||||||||||
JeyCi Пользователь Сообщений: 3357 |
#16 29.09.2015 10:02:08
вот, теперь я поняла вопрос…
… и более «хитрых» вариантов тем более не видела… поэтому мой ответ оказался о другом… чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах) |
||||
Vitallic,Скачал второй вариант, но запустить его в работу не могу. Там в коде есть такая тема, как создание объекта Dictionary, но его описания я нигде не нашел. Я так понимаю он должен быть в классах описан? |
|
Игорь Пользователь Сообщений: 3631 |
Николай Бородин
, нажмите Tools — References, и поставьте галочку напротив Microsoft Scripting Runtime |
Чувствую прям немного осталось |
|
В общем что то я не пойму какие процедуры и функции мне нужно применять для преобразования строки json в объект! Ткните пальцем пожалуйста |
|
Николай Бородин, «Справка» не пробовали нажать? Как объявлены JSONTEXT, parse? |
|
Прикрепленные файлы
|
|
Udik Пользователь Сообщений: 372 excel 2016х64 Контакты в профиле |
#26 02.01.2017 18:06:23 Обычно, чтобы не гадать на какой системе будет работать макрос, по такому принципу делают
Арфы — нет, возьмите бубен. |
||
sv_ispu Пользователь Сообщений: 17 |
#27 03.01.2021 15:44:20 Помогите решить задачу. Необходимо в VBA сделать пользовательскую функцию, чтобы с помощью формул вытаскивать из JSON нужные теги…
Результат: PBF Energy Inc. В параметрах функции задаем источник JSON и Xpath (тег) который нужно извлечь. В инете самое близкое нашел вот это ( https://medium.com/swlh/excel-vba-parse-json-easily-c2213f4d8e7a ), но там не для вставки в формулы. Я подозреваю, что можно как-то этот код с работой в формулах связать, но мозгов не хватает… Изменено: sv_ispu — 03.01.2021 15:44:50 |
||
sv_ispu Пользователь Сообщений: 17 |
Александр Моторин, вот спасибо, добрый человек! я сток промучался, а тут неск минут делов…. Для моей задачи пока хватит..Еще б разобраться с массивами, но это попозже напишу…. |
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#30 04.01.2021 10:07:59 Вариант на Power Query
Откуда информация, что в JSON есть теги и каким-то боком можно использовать XPath? Прикрепленные файлы
|
||
You can parse (or deconstruct) the contents of a column with text strings that contain JSON or XML. To help illustrate how to use the Parse command, the following sample data starts with JSON and XML data entered as text fields.
For more information on importing JSON and XML, see Import data from external data sources.
JavaScript Object Notation (JSON) is a common data format, and you can import it into Excel.
To transform the SalesPerson column from text strings to a structured Record column:
-
Select the SalesPerson column.
-
Select Transform > Parse > JSON.
-
Select Record to see the values.
-
Select the Expand icon next to the SalesPerson column header. From the Expand columns dialog box, select only the FirstName and LastName fields.
Result
Extensible Markup Language (XML) is a common markup and data format, and you can import it into Excel.
To transform the Country column from text strings to Table values.
-
Select the Country column.
-
Select Transform > Parse > XML.
-
Select Table to see the values.
-
Select the Expand icon next to the Country column header. From the Expand columns dialog box, select only the Country and Division fields.
Result
Tip With a Table, you can also select Aggregate to aggregate data in different ways, such as Sum or Count. For more information, see Aggregate data from a column.
See Also
Power Query for Excel Help
Work with a List, Record, or Table structured column
Parse text as JSON or XML (docs.com)
Need more help?
Параметры действия: отсутствуют
Предназначение действия:
Переводит текст из формата JSON в формат XML (для облегчения последующего парсинга)
После выполнения такого преобразования, парсер легко получит из XML любые данные при помощи действия Поиск тегов или действия Выборка из XML
Для ключей массива JSON, начинающихся с цифры, в тегу XML добавляется текст qq_ (т.к. название элемента XML не может начинаться с цифры)
Для элементов неассоциативного массива, к тегам добавляется атрибут index
Возвращаемое значение: XML (HTML) код
Примеры использования:
Действие | Параметр | Значение |
---|---|---|
Преобразование JSON в XML |
Исходное значение | Результат | |
---|---|---|
{"total":2156,"start":2100,"count":100, "good":[{"sort":715, "uuid":"175698b4-60c3-11e7-7a6c-d2a90046a815", "name":"u0418u0440u0438u0441", "productCode":"AX163","type": "u041au0430u0440u0442u0438u043du044b u043fu043e u043du043eu043cu0435u0440u0430u043c", "isPremium":false, "properties": {"Размер": "10x15","Основная категория": "Для начинающих", "Тип": "На холсте", "Кол-во цветов" :7, "Спецразметка": "Новинки", "Премиум": false}, "salePrice":8500,"internetPrice":15000, "retailPrice":15000}]} |
<?xml version="1.0"?> <root><total>2156</total><start>2100</start><count>100</count><good index="1"><sort>715</sort><uuid>175698b4-60c3-11e7-7a6c-d2a90046a815</uuid><name>Ирис</name><productCode>AX163</productCode><type>Картины по номерам</type><isPremium>False</isPremium><properties><Размер>10x15</Размер><Основнаякатегория>Для начинающих</Основнаякатегория><Тип>На холсте</Тип><Кол-воцветов>7</Кол-воцветов><Спецразметка>Новинки</Спецразметка><Премиум>False</Премиум></properties><salePrice>8500</salePrice><internetPrice>15000</internetPrice><retailPrice>15000</retailPrice></good></root> |
Если нажать в окне тестирования действий ссылку XML, то результат преобразования можно посмотреть в браузере в более наглядном виде: