VBA实战 - 一个简单的 httplib

概要

VBA 的应用场景基本都还是在单机应用, 随着 Web 应用的风靡, 以及浏览器越来越强大, 单机类的应用逐渐没落.

虽然 Web 应用越来越多, 功能和体验也越来越好, 但是 Excel 依然有很强的生命力, 毕竟 Web 页面上的表格再强大, 也没有 Excel 那么方便易用.

Excel 经过这么多年的积累, 不仅有很大的用户基础, 对表格类数据的处理几乎已经到极致.
如果能够以 Excel 本身作为 UI, 通过 VBA 来连接 Excel 和后端服务, 使它成为 Web 页面的辅助, 而不是强行在 Web 页面实现 Excel 表格的各种功能, 应该能有事半功倍的效果.

前后端分离已经是目前的主流, 只要能够通过 VBA 访问后端的 API, 并解析后端返回的数据(一般是 JSON 格式), 就能让 Excel 成为 Web 页面的辅助, 高效的处理表格类数据.

VBA httplib 库的简单实现

为了能和后端 API 交互, 需要实现一个简单的 httplib 库, 便于在各个 VBA 工程中复用.

根据目前自己的需求, 这个简单的 httplib 库暂时完成以下几个功能:

  1. 能够发送 GET 请求
  2. 能够发送 POST 请求
  3. 能够解析请求返回的 JSON 数据
  4. POST 请求中可以带 JSON 格式的参数
  5. 请求的 header 中可以加入 jwt token 信息

环境准备

为了测试 httplib, 用 golang 的 gin 框架简单实现了一个 http API 服务. 代码参见文后的 附录一

httplib 主要实现了 get/post 访问 API, 参数和返回值都是 json 格式字符串. 代码参见文后的 附录二

下面的测试主要演示如何使用 httplib :

发送 GET 请求

 1  Function testGet()
 2      Dim hlib As New HttpLib
 3      Dim ret As Boolean
 4  
 5      hlib.SetUrl = "http://localhost:8000/get-test"
 6      ret = hlib.HttpGetJSON("")
 7      Debug.Print ret
 8      If ret = True Then
 9          Debug.Print hlib.GetJSONResp
10      End If
11  End Function

SetUrl 之后, 调用 HttpGetJSON 即可
运行结果如下:

True
{"message":"get success"}

发送 POST 请求

 1  Function testPost()
 2      Dim hlib As New HttpLib
 3      Dim ret As Boolean
 4  
 5      hlib.SetUrl = "http://localhost:8000/post-test"
 6      ret = hlib.HttpPostJSON("")
 7      Debug.Print ret
 8      If ret = True Then
 9          Debug.Print hlib.GetJSONResp
10      End If
11  End Function

SetUrl 之后, 调用 HttpPostJSON 即可
运行结果如下:

True
{"message":"post success"}

解析请求返回的 JSON 数据

要解析返回的 JSON 数据, 这里借助另外一个 VBA 模块: VBA-JSON

 1  Function testPostWithReturn()
 2  
 3      Dim hlib As New HttpLib
 4      Dim ret As Boolean
 5  
 6      hlib.SetUrl = "http://localhost:8000/post-test-return"
 7      ret = hlib.HttpPostJSON("")
 8      Debug.Print ret
 9      If ret = True Then
10          Dim resp As Object
11          Set resp = JsonConverter.ParseJson(hlib.GetJSONResp)
12          Debug.Print "response json: " & hlib.GetJSONResp
13          Debug.Print "username: " & resp("username")
14          Debug.Print "data -> list 1: " & resp("data")("list")(1)
15          Debug.Print "data -> list 2: " & resp("data")("list")(2)
16          Debug.Print "data -> list 3: " & resp("data")("list")(3)
17      End If
18  End Function

在使用 VBA-JSON 库的时候, 需要添加引用 Microsoft Scripting Runtime

添加的方法, 在 VBA 编辑器中 选择 "工具" -> "引用" -> 添加 "Microsoft Scripting Runtime"

运行结果如下:

True
response json: {"data":{"list":["a","b","c"]},"username":"string"}
username: string
data -> list 1: a
data -> list 2: b
data -> list 3: c

POST 请求中带 JSON 格式的参数

 1  Function testPostWithParam()
 2  
 3      Dim hlib As New HttpLib
 4      Dim ret As Boolean
 5      Dim p As Dictionary
 6      Set p = New Dictionary
 7  
 8      hlib.SetUrl = "http://localhost:8000/post-test-param"
 9      p("name") = "name"
10      p("data") = Array("a", "b", "c")
11  
12      ret = hlib.HttpPostJSON(JsonConverter.ConvertToJson(p))
13      Debug.Print ret
14      If ret = True Then
15          Debug.Print "response json: " & hlib.GetJSONResp
16      End If
17  End Function

在服务端的 log 中, 可以看到, 执行后获取到了传递的参数

2019/10/09 12:14:38 param: struct { Name string "json:\"name\""; Data []string "json:\"data\"" }{Name:"name", Data:[]string{"a", "b", "c"}}

请求的 header 中加入 jwt token 信息

请求中 header 加入信息很简单, 在 httplib 库中的 HttpGetJSONHttpPostJSON 方法中都有:

1  http.setRequestHeader "Content-Type", "text/json"
2  http.setRequestHeader "If-Modified-Since", "0"  ' 清除缓存
3  If jwtToken <> "" Then
4      http.setRequestHeader "Authorization", "Bearer " & jwtToken
5  End If

附录

附录一 测试用服务端(by golang)

 1  package main
 2  
 3  import (
 4   "log"
 5   "net/http"
 6  
 7   "github.com/gin-contrib/cors"
 8   "github.com/gin-gonic/gin"
 9  )
10  
11  func StartGinServ() {
12   r := gin.Default()
13   r.Use(cors.Default())
14  
15   r.GET("/get-test", func(c *gin.Context) {
16     c.JSON(http.StatusOK, gin.H{
17       "message": "get success",
18     })
19   })
20  
21   r.POST("/post-test", func(c *gin.Context) {
22     c.JSON(http.StatusOK, gin.H{
23       "message": "post success",
24     })
25   })
26  
27   var list = []string{"a", "b", "c"}
28   r.POST("/post-test-return", func(c *gin.Context) {
29     c.JSON(http.StatusOK, gin.H{
30       "username": "string",
31       "data": gin.H{
32         "list": list,
33       },
34     })
35   })
36  
37   r.POST("/post-test-param", func(c *gin.Context) {
38     var param struct {
39       Name string   `json:"name"`
40       Data []string `json:"data"`
41     }
42  
43     if err := c.BindJSON(&param); err != nil {
44       log.Fatal("param error")
45     }
46  
47     log.Printf("param: %#v\n", param)
48  
49     c.JSON(http.StatusOK, gin.H{
50       "message": "post with param",
51     })
52   })
53  
54   if err := r.Run(":8000"); err != nil {
55     log.Fatal(err)
56   }
57  
58  }

附录二 完整的 httplib 库

 1  Option Explicit
 2  
 3  Const ClsName = "lib for http request"
 4  
 5  ' 请求的URL
 6  Dim url As String
 7  ' API认证用的 jwt token
 8  Dim jwtToken As String
 9  ' API返回的json格式结果
10  Dim jsonResp As String
11  
12  ' 设置 URL 属性
13  Public Property Let SetUrl(p As String)
14      url = p
15  End Property
16  
17  ' 获取 URL 属性
18  Public Property Get GetUrl() As String
19      GetUrl = url
20  End Property
21  
22  ' 设置 jwt token 属性
23  Public Property Let SetJwtToken(p As String)
24      jwtToken = p
25  End Property
26  
27  ' 获取 jwt token 属性
28  Public Property Get GetJwtToken() As String
29      GetJwtToken = jwtToken
30  End Property
31  
32  ' 获取 json response 属性
33  Public Property Get GetJSONResp() As String
34      GetJSONResp = jsonResp
35  End Property
36  
37  ' TODO 登录操作, 登录成功后, 设置 jwt token
38  Function Login(user As String, pwd As String) As Boolean
39      ' TODO 这里可以根据具体的登录实现方式来实现
40      '      登录成功后, 设置 jwtToken 属性
41      Login = False
42  End Function
43  
44  ' GET 方式访问 API
45  Function HttpGetJSON(jsonStr As String) As Boolean
46      HttpGetJSON = False
47      jsonResp = ""
48  
49      Dim http
50      Set http = CreateObject("Msxml2.XMLHTTP")
51      http.Open "GET", url, False
52  
53      ' 设置headers
54      http.setRequestHeader "Content-Type", "text/json"
55      http.setRequestHeader "If-Modified-Since", "0"  ' 清除缓存
56      If jwtToken <> "" Then
57          http.setRequestHeader "Authorization", "Bearer " & jwtToken
58      End If
59  
60      http.send jsonStr
61  
62      If http.Status = 200 Then
63          jsonResp = http.responseText
64          HttpGetJSON = True
65      End If
66  
67  End Function
68  
69  ' POST 方式访问 API
70  Function HttpPostJSON(jsonStr As String) As Boolean
71      HttpPostJSON = False
72      jsonResp = ""
73  
74      Dim http
75      Set http = CreateObject("Msxml2.XMLHTTP")
76      http.Open "POST", url, False
77  
78      http.setRequestHeader "Content-Type", "text/json"
79      http.setRequestHeader "If-Modified-Since", "0"  ' 清除缓存
80      If jwtToken <> "" Then
81          http.setRequestHeader "Authorization", "Bearer " & jwtToken
82      End If
83  
84      http.send jsonStr
85  
86      If http.Status = 200 Then
87          jsonResp = http.responseText
88          HttpPostJSON = True
89      End If
90  End Function

猜你喜欢

转载自www.cnblogs.com/wang_yb/p/11641020.html