refactor(core):优化飞书表格写入逻辑并提取常量

- 重构 writeTableHeaders 方法以支持分批写入表头数据
- 添加对空表头列表的校验处理
- 实现按最大列数限制分片处理表头写入-重构 addRowColumns 方法支持批量添加行列操作
- 添加对添加长度为零情况的处理
- 引入 FsUtil 类统一管理飞书相关常量配置
- 提取 FS_MAX_COLUMNS_PER_REQUEST 和 FS_MAX_DIMENSION_LENGTH 常量
- 统一使用 FsUtil.ROWS 常量替代硬编码字符串"ROWS"
- 新增 getSheetTokenByFsLink 工具方法用于解析表格链接获取token
This commit is contained in:
liushuang 2025-11-13 11:23:18 +08:00
parent 02e4552972
commit 58251de5a0
5 changed files with 86 additions and 28 deletions

@ -350,7 +350,7 @@ public class FsHelper {
int rowTotal = sheet.getGridProperties().getRowCount(); int rowTotal = sheet.getGridProperties().getRowCount();
int rowNum = rowCount.get(); int rowNum = rowCount.get();
if (rowNum >= rowTotal) { if (rowNum >= rowTotal) {
FsApiUtil.addRowColumns(sheetId, spreadsheetToken, "ROWS", Math.abs(rowTotal - rowNum), client); FsApiUtil.addRowColumns(sheetId, spreadsheetToken, FsUtil.ROWS, Math.abs(rowTotal - rowNum), client);
} }
Object resp = FsApiUtil.batchPutValues(sheetId, spreadsheetToken, resultValuesBuilder.build(), client); Object resp = FsApiUtil.batchPutValues(sheetId, spreadsheetToken, resultValuesBuilder.build(), client);

@ -559,7 +559,7 @@ public class MapWriteBuilder {
private void ensureSufficientRows(Sheet sheet, int requiredRows, FeishuClient client) { private void ensureSufficientRows(Sheet sheet, int requiredRows, FeishuClient client) {
int rowTotal = sheet.getGridProperties().getRowCount(); int rowTotal = sheet.getGridProperties().getRowCount();
if (requiredRows >= rowTotal) { if (requiredRows >= rowTotal) {
FsApiUtil.addRowColumns(sheetId, spreadsheetToken, "ROWS", Math.abs(requiredRows - rowTotal), client); FsApiUtil.addRowColumns(sheetId, spreadsheetToken, FsUtil.ROWS, Math.abs(requiredRows - rowTotal), client);
} }
} }

@ -298,7 +298,7 @@ public class WriteBuilder<T> {
int rowTotal = sheet.getGridProperties().getRowCount(); int rowTotal = sheet.getGridProperties().getRowCount();
int rowNum = rowCount.get(); int rowNum = rowCount.get();
if (rowNum >= rowTotal) { if (rowNum >= rowTotal) {
FsApiUtil.addRowColumns(sheetId, spreadsheetToken, "ROWS", Math.abs(rowTotal - rowNum), client); FsApiUtil.addRowColumns(sheetId, spreadsheetToken, FsUtil.ROWS, Math.abs(rowTotal - rowNum), client);
} }
fileDataList.forEach(fileData -> { fileDataList.forEach(fileData -> {

@ -435,15 +435,33 @@ public class FsApiUtil {
/** /**
* 写入表头 * 写入表头
*/ */
public static Object writeTableHeaders(String sheetId, String spreadsheetToken, List<String> headers, int titleRow, FeishuClient client) { public static Object writeTableHeaders(String sheetId, String spreadsheetToken, List<String> headers,
CustomValueService.ValueRequest.BatchPutValuesBuilder batchPutValuesBuilder = CustomValueService.ValueRequest.batchPutValues(); int titleRow, FeishuClient client) {
if (headers == null || headers.isEmpty()) {
return null;
}
CustomValueService.ValueRequest.BatchPutValuesBuilder builder =
CustomValueService.ValueRequest.batchPutValues();
int fromColumnIndex = 1;
int index = 0;
while (index < headers.size()) {
int end = Math.min(index + FsUtil.FS_MAX_COLUMNS_PER_REQUEST, headers.size());
List<String> slice = headers.subList(index, end);
String startColumn = FsTableUtil.getColumnNameByNuNumber(fromColumnIndex);
String endColumn = FsTableUtil.getColumnNameByNuNumber(fromColumnIndex + slice.size() - 1);
builder.addRange(sheetId + "!" + startColumn + "1:" + endColumn + "1");
builder.addRow(slice.toArray());
index = end;
fromColumnIndex += slice.size();
}
Object putValues = FsApiUtil.putValues(spreadsheetToken, builder.build(), client);
String position = FsTableUtil.getColumnNameByNuNumber(headers.size()); String position = FsTableUtil.getColumnNameByNuNumber(headers.size());
batchPutValuesBuilder.addRange(sheetId + "!A" + titleRow + ":" + position + titleRow);
batchPutValuesBuilder.addRow(headers.toArray());
Object putValues = FsApiUtil.putValues(spreadsheetToken, batchPutValuesBuilder.build(), client);
String[] positionArr = {"A" + titleRow, position + titleRow}; String[] positionArr = {"A" + titleRow, position + titleRow};
MapSheetConfig config = MapSheetConfig.createDefault(); MapSheetConfig config = MapSheetConfig.createDefault();
@ -509,25 +527,40 @@ public class FsApiUtil {
public static Object addRowColumns(String sheetId, String spreadsheetToken, String type, int length,FeishuClient client) { public static Object addRowColumns(String sheetId, String spreadsheetToken, String type, int length,FeishuClient client) {
CustomDimensionService.DimensionBatchUpdateRequest batchRequest = CustomDimensionService.DimensionBatchUpdateRequest.newBuilder() if (length <= 0) {
return null;
}
Object lastRespData = null;
int remaining = length;
while (remaining > 0) {
int batchLength = Math.min(remaining, FsUtil.FS_MAX_DIMENSION_LENGTH);
CustomDimensionService.DimensionBatchUpdateRequest batchRequest =
CustomDimensionService.DimensionBatchUpdateRequest.newBuilder()
.addRequest(CustomDimensionService.DimensionRequest.addDimension() .addRequest(CustomDimensionService.DimensionRequest.addDimension()
.sheetId(sheetId) .sheetId(sheetId)
.majorDimension(type) .majorDimension(type)
.length(length).build()) .length(batchLength).build())
.build(); .build();
try { try {
ApiResponse batchResp = client.customDimensions().dimensionsBatchUpdate(spreadsheetToken, batchRequest); ApiResponse batchResp = client.customDimensions().dimensionsBatchUpdate(spreadsheetToken, batchRequest);
if (batchResp.success()) { if (batchResp.success()) {
return batchResp.getData(); lastRespData = batchResp.getData();
} else { } else {
FsLogger.warn("【飞书表格】 添加行列失败!参数:{}错误信息:{}", sheetId, gson.toJson(batchResp)); FsLogger.warn("【飞书表格】 添加行列失败!参数:{}长度:{}错误信息:{}", sheetId, batchLength, gson.toJson(batchResp));
throw new FsHelperException("【飞书表格】 添加行列失败!"); throw new FsHelperException("【飞书表格】 添加行列失败!");
} }
} catch (IOException e) { } catch (IOException e) {
FsLogger.warn("【飞书表格】 添加行列异常!参数:{}错误信息:{}", sheetId, e.getMessage()); FsLogger.warn("【飞书表格】 添加行列异常!参数:{}长度:{}错误信息:{}", sheetId, batchLength, e.getMessage());
throw new FsHelperException("【飞书表格】 添加行列异常!"); throw new FsHelperException("【飞书表格】 添加行列异常!");
} }
remaining -= batchLength;
}
return lastRespData;
} }
public static Object getTableInfo(String sheetId, String spreadsheetToken, FeishuClient client) { public static Object getTableInfo(String sheetId, String spreadsheetToken, FeishuClient client) {

@ -0,0 +1,25 @@
package cn.isliu.core.utils;
import java.net.MalformedURLException;
import java.net.URL;
public class FsUtil {
public static final int FS_MAX_COLUMNS_PER_REQUEST = 100;
public static final int FS_MAX_DIMENSION_LENGTH = 5000;
public static final String ROWS = "ROWS";
public static String getSheetTokenByFsLink(String fsLink) {
if (fsLink == null) {
return null;
}
// 获取url 最后一个斜杆后的数据不包含url参数
String path;
try {
path = new URL(fsLink).getPath();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
return path.substring(path.lastIndexOf('/') + 1);
}
}