You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

求助:如何通过VBA将Excel数据写入指定Google Sheets

嘿,我完全懂你现在的麻烦——用IE自动化操控Google Sheets真的太不靠谱了,网页元素定位容易失效不说,还经常因为加载延迟、页面结构更新出问题。换成Google Sheets API才是正确的打开方式,不仅稳定,还能精准实现你要的「清空全表+粘贴三列数据到A1」需求。下面我一步步给你讲怎么操作:

一、先搞定Google Cloud平台的API配置

这一步是基础,得先让你的VBA有权限访问Google Sheets:

  • 打开Google Cloud控制台,创建一个新项目(或者用现有项目)
  • 在项目里搜索并启用「Google Sheets API」
  • 进入「凭据」页面,创建「服务账号」,随便给它起个名字后点击创建
  • 给服务账号添加「编辑器」权限(或者更细的权限,只要能读写目标Sheets就行)
  • 生成并下载服务账号的密钥文件(JSON格式),保存到本地一个安全的路径,比如C:\gcp-key.json
  • 打开你要写入的目标Google Sheets,点击右上角「共享」,把服务账号的邮箱(就是JSON文件里的client_email字段)添加为编辑器,确保权限生效
二、VBA环境准备

打开你的Excel文件,按Alt+F11进入VBA编辑器:

  • 点击「工具」→「引用」,勾选「Microsoft XML, v6.0」(用来发送HTTP请求)
  • 因为Google API用JSON格式交互,VBA本身没有内置JSON解析功能,推荐你导入「VBA-JSON」模块(直接把模块代码复制粘贴到VBA里就行,不用额外安装)
  • 另外,JWT认证需要RSA签名和Base64URL编码,你得找现成的VBA实现(比如搜索「VBA RSA SHA256签名」和「VBA Base64URL编码」),把对应的模块也导入到项目里
三、完整VBA代码实现

下面的代码包含了清空目标Sheets全表写入Excel三列数据的功能,你可以直接套用,记得替换里面的参数:

Sub WriteToGoogleSheets()
    ' 配置参数,根据你的情况修改
    Dim serviceAccountKeyPath As String
    Dim targetSheetId As String
    Dim excelDataRange As Range
    
    serviceAccountKeyPath = "C:\gcp-key.json" ' 你的服务账号密钥路径
    targetSheetId = "your-google-sheet-id-here" ' 目标Google Sheets的ID(从URL里取,d/后面的部分)
    Set excelDataRange = ThisWorkbook.ActiveSheet.Range("A:C") ' 你要复制的三列数据范围
    
    ' 1. 获取访问令牌(用服务账号密钥申请)
    Dim accessToken As String
    accessToken = GetGoogleAccessToken(serviceAccountKeyPath)
    If accessToken = "" Then
        MsgBox "获取访问令牌失败,请检查密钥文件或RSA模块"
        Exit Sub
    End If
    
    ' 2. 清空目标Google Sheets的所有数据
    ClearGoogleSheet targetSheetId, accessToken
    
    ' 3. 将Excel数据写入Google Sheets的A1位置
    WriteDataToGoogleSheet targetSheetId, excelDataRange, accessToken
    
    MsgBox "数据同步完成!"
End Sub

' 函数:获取Google API的访问令牌
Private Function GetGoogleAccessToken(keyPath As String) As String
    Dim jsonKey As String
    Dim http As MSXML2.XMLHTTP60
    Dim response As String
    Dim jsonObj As Object
    
    ' 读取密钥文件内容
    Open keyPath For Input As #1
    jsonKey = Input$(LOF(1), 1)
    Close #1
    
    ' 发送请求获取令牌
    Set http = New MSXML2.XMLHTTP60
    With http
        .Open "POST", "https://oauth2.googleapis.com/token", False
        .SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
        .Send "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=" & CreateJWT(jsonKey)
        response = .responseText
    End With
    
    ' 解析JSON获取令牌
    Set jsonObj = JsonConverter.ParseJson(response)
    If jsonObj.Exists("access_token") Then
        GetGoogleAccessToken = jsonObj("access_token")
    End If
End Function

' 函数:创建JWT令牌(用于服务账号认证)
Private Function CreateJWT(jsonKey As String) As String
    Dim jsonObj As Object
    Dim header As String, payload As String
    Dim currentTime As Long, expireTime As Long
    Dim signature As String
    
    Set jsonObj = JsonConverter.ParseJson(jsonKey)
    
    ' JWT头部
    header = JsonConverter.ConvertToJson(CreateObject("Scripting.Dictionary") _
        .Add("alg", "RS256") _
        .Add("typ", "JWT"))
    
    ' JWT载荷
    currentTime = DateDiff("s", "1970-01-01", Now())
    expireTime = currentTime + 3600 ' 令牌有效期1小时
    payload = JsonConverter.ConvertToJson(CreateObject("Scripting.Dictionary") _
        .Add("iss", jsonObj("client_email")) _
        .Add("scope", "https://www.googleapis.com/auth/spreadsheets") _
        .Add("aud", "https://oauth2.googleapis.com/token") _
        .Add("exp", expireTime) _
        .Add("iat", currentTime))
    
    ' 编码头部和载荷(用Base64URL编码)
    Dim encodedHeader As String, encodedPayload As String
    encodedHeader = Base64UrlEncode(header)
    encodedPayload = Base64UrlEncode(payload)
    
    ' 用服务账号的私钥签名(需要你实现SignRSA函数)
    signature = SignRSA(encodedHeader & "." & encodedPayload, jsonObj("private_key"))
    
    ' 拼接成完整的JWT
    CreateJWT = encodedHeader & "." & encodedPayload & "." & Base64UrlEncode(signature)
End Function

' 子过程:清空Google Sheets全表
Private Sub ClearGoogleSheet(sheetId As String, token As String)
    Dim http As MSXML2.XMLHTTP60
    Dim requestBody As String
    
    ' 构造清空数据的请求体(清空默认工作表的所有单元格)
    requestBody = JsonConverter.ConvertToJson(CreateObject("Scripting.Dictionary") _
        .Add("requests", Array( _
            CreateObject("Scripting.Dictionary") _
                .Add("deleteRange", CreateObject("Scripting.Dictionary") _
                    .Add("range", CreateObject("Scripting.Dictionary") _
                        .Add("sheetId", 0) ' 默认第一个工作表,改这里的数字可以操作其他表
                        .Add("startRowIndex", 0) _
                        .Add("startColumnIndex", 0)) _
                    .Add("shiftDimension", "ROWS")))))
    
    ' 发送请求
    Set http = New MSXML2.XMLHTTP60
    With http
        .Open "POST", "https://sheets.googleapis.com/v4/spreadsheets/" & sheetId & ":batchUpdate", False
        .SetRequestHeader "Authorization", "Bearer " & token
        .SetRequestHeader "Content-Type", "application/json"
        .Send requestBody
    End With
End Sub

' 子过程:将Excel数据写入Google Sheets的A1位置
Private Sub WriteDataToGoogleSheet(sheetId As String, dataRange As Range, token As String)
    Dim http As MSXML2.XMLHTTP60
    Dim dataArray As Variant
    Dim requestBody As String
    
    ' 将Excel范围转换成二维数组
    dataArray = dataRange.Value
    
    ' 构造写入数据的请求体
    requestBody = JsonConverter.ConvertToJson(CreateObject("Scripting.Dictionary") _
        .Add("values", dataArray))
    
    ' 发送请求,写入到Sheet1的A1位置(要改工作表名就替换这里的"Sheet1")
    Set http = New MSXML2.XMLHTTP60
    With http
        .Open "PUT", "https://sheets.googleapis.com/v4/spreadsheets/" & sheetId & "/values/Sheet1!A1?valueInputOption=USER_ENTERED", False
        .SetRequestHeader "Authorization", "Bearer " & token
        .SetRequestHeader "Content-Type", "application/json"
        .Send requestBody
    End With
End Sub
几个必须注意的细节
  • JWT签名和Base64URL编码:这两个是服务账号认证的核心,VBA本身没有内置这些功能,你必须找到对应的VBA实现代码导入到项目里。比如搜索「VBA Base64URL编码」就能找到现成的函数,RSA签名可以用「VBA-RSA」模块来实现。
  • 工作表ID和名称:如果目标Sheets里有多个工作表,ClearGoogleSheet里的sheetId是工作表的数字ID(在Google Sheets编辑URL里的gid=后面),而WriteDataToGoogleSheet里的Sheet1是工作表的名称,根据你的实际情况修改。
  • 数据解析选项valueInputOption=USER_ENTERED会让Google Sheets自动识别数据格式(比如日期、数字),如果要纯文本写入,改成RAW就行。

这样一套流程下来,就能稳定实现你要的功能,而且比IE自动化可靠多了,再也不用担心页面结构变化导致代码失效。

内容的提问来源于stack exchange,提问作者Eugeny Filippov

火山引擎 最新活动