This commit is contained in:
2025-11-06 11:33:52 +08:00
parent 0b6ba14f2f
commit 2428295542
2 changed files with 550 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
package com.ruoyi.jarvis.util;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -365,20 +366,114 @@ public class TencentDocApiUtil {
* @return 写入结果
*/
public static JSONObject writeSheetData(String accessToken, String appId, String openId, String fileId, String sheetId, String range, Object values, String apiBaseUrl) {
// V3版本API路径格式/openapi/spreadsheet/v3/files/{fileId}/{sheetId}/{range}
String apiUrl = String.format("%s/files/%s/%s/%s", apiBaseUrl, fileId, sheetId, range);
// 腾讯文档 V3 API 没有直接的 PUT 写入接口
// 必须使用 batchUpdate 接口https://docs.qq.com/open/document/app/openapi/v3/sheet/batchupdate/update.html
// 构建V3 API规范的请求体
// 根据腾讯文档V3 API文档https://docs.qq.com/open/document/app/openapi/v3/sheet/model/spreadsheet.html
// 对于简单的文本数据写入可以直接使用values二维数组
// 对于复杂的单元格数据包含格式、类型等需要使用完整的CellData结构
// 解析 A1 表示法,转换为行列索引
// 例如:"M3" -> row=2 (索引从0开始), col=12
int[] position = parseA1Notation(range);
int rowIndex = position[0];
int colIndex = position[1];
// 构建 updateCells 请求
JSONObject updateCells = new JSONObject();
// 设置范围
JSONObject rangeObj = new JSONObject();
rangeObj.put("sheetId", sheetId);
rangeObj.put("startRowIndex", rowIndex);
rangeObj.put("endRowIndex", rowIndex + 1); // 不包含
rangeObj.put("startColumnIndex", colIndex);
rangeObj.put("endColumnIndex", colIndex + 1); // 不包含
updateCells.put("range", rangeObj);
// 构建单元格数据
JSONArray rows = new JSONArray();
JSONObject rowData = new JSONObject();
JSONArray cellValues = new JSONArray();
// 如果 values 是二维数组
if (values instanceof JSONArray) {
JSONArray valuesArray = (JSONArray) values;
if (!valuesArray.isEmpty() && valuesArray.get(0) instanceof JSONArray) {
JSONArray firstRow = valuesArray.getJSONArray(0);
if (!firstRow.isEmpty()) {
String text = firstRow.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);
updateCells.put("rows", rows);
// 构建 requests
JSONArray requests = new JSONArray();
JSONObject request = new JSONObject();
request.put("updateCells", updateCells);
requests.add(request);
// 构建完整请求体
JSONObject requestBody = new JSONObject();
requestBody.put("values", values);
requestBody.put("requests", requests);
log.info("写入表格数据 - fileId: {}, sheetId: {}, range: {}, apiUrl: {}", fileId, sheetId, range, apiUrl);
// 调用 batchUpdate API
String apiUrl = String.format("%s/files/%s/batchUpdate", apiBaseUrl, fileId);
log.info("写入表格数据batchUpdate- fileId: {}, sheetId: {}, range: {}, rowIndex: {}, colIndex: {}",
fileId, sheetId, range, rowIndex, colIndex);
log.debug("写入表格数据 - 请求体: {}", requestBody.toJSONString());
return callApi(accessToken, appId, openId, apiUrl, "PUT", requestBody.toJSONString());
return callApi(accessToken, appId, openId, apiUrl, "POST", requestBody.toJSONString());
}
/**
* 解析 A1 表示法为行列索引
* 例如:
* A1 -> [0, 0]
* M3 -> [2, 12]
* Z100 -> [99, 25]
*
* @param a1Notation A1 表示法字符串
* @return [rowIndex, colIndex]从0开始
*/
private static int[] parseA1Notation(String a1Notation) {
if (a1Notation == null || a1Notation.isEmpty()) {
throw new IllegalArgumentException("A1 表示法不能为空");
}
// 提取列字母和行号
StringBuilder colLetters = new StringBuilder();
StringBuilder rowNumber = new StringBuilder();
for (char c : a1Notation.toCharArray()) {
if (Character.isLetter(c)) {
colLetters.append(Character.toUpperCase(c));
} else if (Character.isDigit(c)) {
rowNumber.append(c);
}
}
if (colLetters.length() == 0 || rowNumber.length() == 0) {
throw new IllegalArgumentException("无效的 A1 表示法: " + a1Notation);
}
// 列字母转索引A=0, B=1, ..., Z=25, AA=26, ...
int colIndex = 0;
for (int i = 0; i < colLetters.length(); i++) {
colIndex = colIndex * 26 + (colLetters.charAt(i) - 'A' + 1);
}
colIndex -= 1; // 转为从0开始的索引
// 行号转索引1->0, 2->1, ...
int rowIndex = Integer.parseInt(rowNumber.toString()) - 1;
return new int[]{rowIndex, colIndex};
}
/**