ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 21979|回复: 42

[求助] 如何用Excel VBA解析JSON数据(这个对我真的好难!)

[复制链接]

TA的精华主题

TA的得分主题

发表于 2015-9-6 14:15 | 显示全部楼层 |阅读模式
本帖最后由 zhangjimfu 于 2015-9-6 14:16 编辑

一、问题描述:

如何把JSON数据转换成EXCEL格式的文档,便于财务人员做统计用,我自已尝试了几种方法,都无功而返,请各位过走路过的大侠们助我一臂之力,万分感谢!
(注:公司现在在用的收银系统没有办法提供统计报表,故不得不从后台导数据自己统计,导出来后发现都是JSON数据,还是不能统计。)
JSON数据格式如下:
{"1":{"id":1,"pid":"3600","cid":"1376","name":"\u8702\u871c\u67da\u5b50\u8336 Honey Citron Tea","price":"30","mprice":"0","ctype":"0","is_discount":"1","second_discount":"1","is_free":0,"cost":"0","num":"1","type":"","practice_id":"6"},"2":{"id":2,"pid":"3536","cid":"1370","name":"\u62ff\u94c1 Caffe Latte","price":"32","mprice":"0","ctype":"0","is_discount":"1","second_discount":"1","is_free":0,"cost":"0","num":"1","type":""}}

附件: JSON数据.rar (11.25 KB, 下载次数: 212)

二、我尝试的两种解决方法:

方法一,不知道哪里出错,每次都执行不下去。(注:我对正则表达式完全看不懂,我保证我百度看过正则表达式。)
Sub testJson()      '方法一
    Dim a, ind
    Dim re As Object
    Dim mc As Object, mc2 As Object, m As Object
    Set re = CreateObject("VBSCRIPT.REGEXP")
    json = Sheets("Sheet1").Range("A1").Value

    With re
        .Pattern = """pid"":\d+.\d+,""name"":\d+.\d+"
        .Global = True
        Set mc = .Execute(json)
    End With

    If mc.Count > 0 Then
        ReDim a(0 To mc.Count - 1, 0 To 1)
        'ind = 1
        For ind = 0 To mc.Count - 1
            Set m = mc(ind)
            With re
                .Pattern = "\d+.\d+"
                .Global = True
                Set mc2 = .Execute(m.Value)
                a(ind, 0) = mc2(0)
                a(ind, 1) = mc2(1)
            End With
        Next ind
    End If

    For ind = 0 To UBound(a, 1)
        Debug.Print a(ind, 0), a(ind, 1)
    Next ind

End Sub


=============================================================================================》

方法二,代码能执行下去,但是有两个问题不知道怎么回事:
1.代码MsgBox y.t1.pid,如果改成MsgBox y.1.pid,或MsgBox y.t1.name就会出错,没办法执行;
2.因为JSON数据的长短会根据客人点的饮料多少而变化,通过这个方法怎样才能把所有数据取出来。


Sub bluejson()    '方法二
    Dim aa, y As Object
    Set x = CreateObject("ScriptControl"): x.Language = "JScript"

    aa = Sheets("Sheet1").Range("A5").Value
    Set y = x.eval("eval(" & aa & ")")
    MsgBox y.t1.pid

End Sub


三、数据详见附件(注:如果有其他简单快捷的方法解析JSON数据也请大侠们指教)



TA的精华主题

TA的得分主题

发表于 2015-9-6 14:32 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
能不能明确下目标格式是怎样的,希望在附件中体现出来,以方便别人对着这个目标编写代码

TA的精华主题

TA的得分主题

发表于 2015-9-6 14:41 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助

Sub bluejson()    '方法二
    Dim aa, y As Object
    Set x = CreateObject("ScriptControl"): x.Language = "JScript"
    aa = Sheets("Sheet1").Range("A5").Value
    Set y = x.eval("eval(" & aa & ")")
    MsgBox y.t1.pid

End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-9-6 14:49 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
LIUZHU 发表于 2015-9-6 14:32
能不能明确下目标格式是怎样的,希望在附件中体现出来,以方便别人对着这个目标编写代码

兄弟,多谢提醒,有劳了!下图是我想要的效果:
QQ图片20150906144345.png

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-9-6 14:53 | 显示全部楼层
onlycxb 发表于 2015-9-6 14:41
Sub bluejson()    '方法二
    Dim aa, y As Object
    Set x = CreateObject("ScriptControl"): x.L ...

兄弟,真正的数据源是A1单元格里面的数据,因为A1单元格数据源没有办法用这个代码所以我把数据源改成了A5单元格的格式。

TA的精华主题

TA的得分主题

发表于 2015-9-6 15:00 | 显示全部楼层
  • Sub bluejson()    '方法二
  •     Dim aa, y As Object, x As Object
  •     Dim name, id   ' 这里重新定义 json 中的 key,避免vba自动改大小写而失败。
  •     Set x = CreateObject("ScriptControl")
  •     x.Language = "JScript"
  •     aa = Sheets("Sheet1").Range("A5").Value
  •     Set y = x.eval("eval(" & aa & ")")
  •     With CallByName(y, "1", VbGet)
  •         Debug.Print .id, .pid, .name
  •     End With
  • End Sub


TA的精华主题

TA的得分主题

发表于 2015-9-6 15:02 | 显示全部楼层
本帖最后由 onlycxb 于 2015-9-6 15:04 编辑
zhangjimfu 发表于 2015-9-6 14:53
兄弟,真正的数据源是A1单元格里面的数据,因为A1单元格数据源没有办法用这个代码所以我把数据源改成了A5 ...

  1. Sub bluejson()                                             '方法二
  2.     Dim aa, y As Object
  3.     Set x = CreateObject("ScriptControl"): x.Language = "JScript"
  4.     aa = Sheets("Sheet1").Range("A1").Value
  5.     MsgBox x.eval("var a=" & aa & ";s='';for(x in a){ for(y in a[x]){s+=a[x][y]+'\t';}s+='\r'}")
  6. End Sub

复制代码

TA的精华主题

TA的得分主题

发表于 2015-9-6 16:37 | 显示全部楼层
zhangjimfu 发表于 2015-9-6 14:53
兄弟,真正的数据源是A1单元格里面的数据,因为A1单元格数据源没有办法用这个代码所以我把数据源改成了A5 ...

方法三:

  1. Option Explicit
  2. Sub Crazy0qwer()
  3.     Dim Ar, Br
  4.     Dim I As Long, J As Long, X As Long, X1 As Long
  5.     Dim N As Long, C As Long, R As Long, L As Long
  6.     Dim S As String, S1 As String, SS As String
  7.     Dim D As Object
  8.     Set D = CreateObject("SCRIPTING.DICTIONARY")
  9.     Ar = Sheets("SHEET1").Range("A1:A" & Sheets("SHEET1").[A65536].End(xlUp).Row)
  10.     ReDim Br(1 To 1000, 1 To 100)
  11.     D("AAA") = 1
  12.     For I = 1 To UBound(Ar)
  13.         If Ar(I, 1) <> "" Then
  14.             L = InStr(Ar(I, 1), """")
  15.             R = InStr(L + 1, Ar(I, 1), """")
  16.             SS = Mid(Ar(I, 1), L + 1, R - L - 1)
  17.             L = 2: C = 1
  18.             Do
  19.                 L = InStr(L + 1, Ar(I, 1), "{")
  20.                 If L = 0 Then Exit Do
  21.                 R = InStr(L, Ar(I, 1), "}")
  22.                 X = L
  23.                 N = N + 1
  24.                 Br(N, 1) = SS
  25.                 Do
  26.                     X = InStr(X + 1, Ar(I, 1), ":")
  27.                     If X = 0 Or X > R Then Exit Do
  28.                     X1 = InStrRev(Ar(I, 1), """", X - 2)
  29.                     S = Mid(Ar(I, 1), X1 + 1, X - X1 - 2)
  30.                     If D.EXISTS(S) = False Then D(S) = C + 1: C = C + 1
  31.                     X1 = InStr(X, Ar(I, 1), ",")
  32.                     If X1 > R Or X1 = 0 Then X1 = R
  33.                     S1 = Replace(Mid(Ar(I, 1), X + 1, X1 - X - 1), """", "")
  34.                     X1 = D(S)
  35.                     If InStr(S1, "\u") Then
  36.                         Br(N, X1) = Right(S1, Len(S1) - InStr(S1, " ") + 1)
  37.                         S1 = Left(S1, InStr(S1, " ") - 1)
  38.                         S1 = Replace(S1, "\u", "&H")
  39.                         For J = Len(S1) - 5 To 1 Step -6
  40.                             Br(N, X1) = ChrW(Mid(S1, J, 6)) & Br(N, X1)
  41.                         Next
  42.                     Else
  43.                         Br(N, X1) = S1
  44.                     End If
  45.                 Loop
  46.             Loop Until L = 0
  47.         End If
  48.     Next
  49.     C = D.Count
  50.     With Sheets("SHEET2")
  51.         .Cells.Clear
  52.         .[A1].Resize(1, C) = D.KEYS
  53.         .[A2].Resize(N, C) = Br
  54.     End With
  55. End Sub
复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-9-6 16:47 | 显示全部楼层

兄弟,我真的有点感动了,你我非亲非故,写这么长的代码一定花了你不少时间和精力,不管能不能解决问题,先感谢了!

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-9-6 16:55 | 显示全部楼层

大侠,你的代码我测试过了,这就是我想要的,非常感谢!
另外,有两个不情之请:
1、转换过的数据能否像我发的图片一样放到EXCEL工作表里面的每个单元格。
2、能否解释一样代码的原理(因为还有其他的数据,不好总是麻烦大家了)。
x.eval("var a=" & aa & ";s='';for(x in a){ for(y in a[x]){s+=a[x][y]+'\t';}s+='\r'}")
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-18 23:47 , Processed in 0.047935 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表