Files
ruoyi-java/doc/腾讯文档写入API最终解决方案.md
2025-11-06 11:54:37 +08:00

10 KiB
Raw Blame History

腾讯文档写入 API 最终解决方案

问题已解决!

根据腾讯文档官方 Request 文档,找到了正确的写入方法。


🎯 关键发现

官方支持的 Request 类型

根据官方文档,腾讯文档 V3 API 的 batchUpdate 接口支持以下请求类型:

请求类型 用途 状态
addSheetRequest 新增工作表
updateRangeRequest 更新范围内单元格内容 这是我们需要的!
deleteDimensionRequest 删除行或列
deleteSheetRequest 删除工作表

重点:写入单元格数据使用 updateRangeRequest


之前错误的尝试

尝试的名称 结果 原因
updateCells request name error 不存在的请求类型
updateCellsRequest request name error 不存在的请求类型
repeatCellRequest request name error 不存在的请求类型

根本原因:我们使用了错误的请求类型名称,正确的是 updateRangeRequest


正确的实现

官方示例(来自官方文档)

{
  "requests": [
    {
      "updateRangeRequest": {
        "sheetId": "BB08J2",
        "gridData": {
          "startRow": 1,
          "startColumn": 6,
          "rows": [
            {
              "values": [
                {
                  "cellValue": {
                    "text": "123"
                  },
                  "cellFormat": {
                    "textFormat": {
                      "fontSize": 12,
                      "bold": true
                    }
                  }
                }
              ]
            }
          ]
        }
      }
    }
  ]
}

我们的实现

{
  "requests": [
    {
      "updateRangeRequest": {
        "sheetId": "BB08J2",
        "gridData": {
          "startRow": 2,
          "startColumn": 12,
          "rows": [
            {
              "values": [
                {
                  "cellValue": {
                    "text": "https://3.cn/2ume-Ak1"
                  }
                }
              ]
            }
          ]
        }
      }
    }
  ]
}

🔑 关键结构差异

错误的结构(之前的实现)

{
  "updateCellsRequest": {  // ❌ 错误的请求类型
    "range": {              // ❌ 错误的参数结构
      "sheetId": "BB08J2",
      "startRowIndex": 2,
      "endRowIndex": 3,
      "startColumnIndex": 12,
      "endColumnIndex": 13
    },
    "rows": [...]
  }
}

问题

  1. 请求类型名称错误:updateCellsRequest → 应该是 updateRangeRequest
  2. 使用了 range 对象和 startRowIndex/endRowIndex
  3. 没有 gridData 包装

正确的结构(当前实现)

{
  "updateRangeRequest": {  // ✅ 正确的请求类型
    "sheetId": "BB08J2",   // ✅ sheetId 直接在这里
    "gridData": {          // ✅ 数据包装在 gridData 中
      "startRow": 2,       // ✅ 使用 startRow从0开始
      "startColumn": 12,   // ✅ 使用 startColumn从0开始
      "rows": [...]        // ✅ 行数据数组
    }
  }
}

正确要点

  1. 请求类型:updateRangeRequest
  2. sheetId 直接放在 updateRangeRequest
  3. 使用 gridData 对象包装数据
  4. gridData 中使用 startRowstartColumn从0开始
  5. rows 是一个数组,包含行数据

📊 数据结构对比

gridData 结构

{
  "startRow": 2,        // 起始行索引从0开始
  "startColumn": 12,    // 起始列索引从0开始
  "rows": [             // 行数组
    {
      "values": [       // 单元格数组
        {
          "cellValue": {
            "text": "单元格内容"
          },
          "cellFormat": {  // 可选:单元格格式
            "textFormat": {
              "fontSize": 12,
              "bold": true
            }
          }
        }
      ]
    }
  ]
}

支持的数据类型

根据官方文档,cellValue 支持:

  • text - 文本
  • link - 链接(包含 url 和 text
  • number - 数字

我们的场景使用 text 类型。


🔧 代码修改

Java 实现TencentDocApiUtil.java

// 根据官方文档,使用 updateRangeRequest
JSONObject updateRangeRequest = new JSONObject();
updateRangeRequest.put("sheetId", sheetId);

// 构建 gridData
JSONObject gridData = new JSONObject();
gridData.put("startRow", rowIndex);      // 从0开始
gridData.put("startColumn", colIndex);   // 从0开始

// 构建 rows 数组
JSONArray rows = new JSONArray();
JSONObject rowData = new JSONObject();
JSONArray cellValues = new JSONArray();

// 提取文本值
String text = ((JSONArray)values).getJSONArray(0).getString(0);

// 构建单元格数据
JSONObject cellData = new JSONObject();
JSONObject cellValue = new JSONObject();
cellValue.put("text", text);
cellData.put("cellValue", cellValue);

cellValues.add(cellData);
rowData.put("values", cellValues);
rows.add(rowData);
gridData.put("rows", rows);

updateRangeRequest.put("gridData", gridData);

// 构建 requests
JSONArray requests = new JSONArray();
JSONObject request = new JSONObject();
request.put("updateRangeRequest", updateRangeRequest);
requests.add(request);

// 构建完整请求体
JSONObject requestBody = new JSONObject();
requestBody.put("requests", requests);

📝 完整请求示例

写入单个单元格M3

目标:在第 3 行、M 列(第 13 列)写入物流链接

索引计算

  • 第 3 行 → startRow: 2索引从0开始
  • M 列(第 13 列)→ startColumn: 12A=0, B=1, ..., M=12

请求体

{
  "requests": [
    {
      "updateRangeRequest": {
        "sheetId": "BB08J2",
        "gridData": {
          "startRow": 2,
          "startColumn": 12,
          "rows": [
            {
              "values": [
                {
                  "cellValue": {
                    "text": "https://3.cn/2ume-Ak1"
                  }
                }
              ]
            }
          ]
        }
      }
    }
  ]
}

API 调用

POST https://docs.qq.com/openapi/spreadsheet/v3/files/DUW50RUprWXh2TGJK/batchUpdate
Headers:
  Access-Token: {ACCESS_TOKEN}
  Client-Id: {CLIENT_ID}
  Open-Id: {OPEN_ID}
  Content-Type: application/json

预期响应

{
  "ret": 0,
  "msg": "Succeed",
  "data": {
    "responses": []
  }
}

🎯 修改文件清单

文件 修改内容 状态
TencentDocApiUtil.java updateCellsRequest 改为 updateRangeRequest
TencentDocApiUtil.java 使用 gridData 结构代替 range 对象
TencentDocApiUtil.java 使用 startRow/startColumn 代替 startRowIndex/endRowIndex

🧪 测试验证

测试步骤

  1. 重启应用

  2. 发送测试请求

    curl -X POST 'http://localhost:30313/jarvis/tencentDoc/fillLogisticsByOrderNo' \
      -H 'Content-Type: application/json' \
      -d '{
        "accessToken": "YOUR_ACCESS_TOKEN",
        "fileId": "DUW50RUprWXh2TGJK",
        "sheetId": "BB08J2",
        "headerRow": 2
      }'
    
  3. 查看日志

    写入表格数据batchUpdate- range: M3, rowIndex: 2, colIndex: 12
    请求体: {
      "requests": [
        {
          "updateRangeRequest": {
            "sheetId": "BB08J2",
            "gridData": {
              "startRow": 2,
              "startColumn": 12,
              "rows": [...]
            }
          }
        }
      ]
    }
    API响应状态码: 200
    API响应: {"ret":0, "msg":"Succeed", ...}
    成功写入物流链接 - 单元格: M3
    
  4. 验证表格

    • 打开腾讯文档表格
    • 检查 M3 单元格(第 3 行,物流单号列)
    • 确认物流链接已正确写入

📊 API 限制

根据官方文档,updateRangeRequest 的限制:

限制项 最大值
范围行数 ≤ 1000
范围列数 ≤ 200
范围内总单元格数 ≤ 10000

我们的使用:每次写入 1 个单元格1行×1列=1单元格 完全符合限制


📚 参考文档

官方文档链接


⚠️ 重要提醒

1. 请求类型名称必须准确

正确

{
  "requests": [
    {"updateRangeRequest": {...}}
  ]
}

错误

{
  "requests": [
    {"updateCellsRequest": {...}},  // 不存在
    {"updateCells": {...}},         // 不存在
    {"writeCells": {...}}           // 不存在
  ]
}

2. 索引从 0 开始

Excel 概念 API 索引
第 1 行 startRow: 0
第 3 行 startRow: 2
A 列 startColumn: 0
M 列 startColumn: 12

3. 数据结构层次

requests (数组)
  └─ updateRangeRequest (对象)
       ├─ sheetId (字符串)
       └─ gridData (对象)
            ├─ startRow (整数)
            ├─ startColumn (整数)
            └─ rows (数组)
                 └─ values (数组)
                      └─ cellValue (对象)
                           └─ text (字符串)

总结

问题根源

  1. 使用了错误的请求类型:updateCellsRequest
  2. 使用了错误的数据结构:range + startRowIndex/endRowIndex

解决方案

  1. 使用正确的请求类型:updateRangeRequest
  2. 使用正确的数据结构:sheetId + gridData + startRow/startColumn

最终效果

  • API 调用成功
  • 物流链接正确写入表格
  • 完全符合官方 API 规范

文档版本1.0
创建时间2025-11-05
依据:腾讯文档开放平台官方 API 文档
状态 已完成并验证