项目场景:
需要读取飞书云文档的电子表格,但是表格有公式计算的值,以及合并单元格。
问题显示:调用api可以读取表格。1.公式不自动计算,直接返回公式。2.读取合并的单元格,只有第一行有数据,其余合并的无数据。
直接看读取表格的代码:
java
public SpreadsheetData getSheet(String token, String sheetId) {
// 发起请求
try {
String url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/" + token + "/values_batch_get?ranges=" + sheetId;
RawResponse resp = client.get(url, null, AccessTokenType.Tenant);
if (resp.getStatusCode() == 200) {
//LarkResult<SpreadsheetData>用来封装api响应体
Type type = new TypeToken<LarkResult<SpreadsheetData>>() {}.getType();
LarkResult<SpreadsheetData> result = Jsons.DEFAULT.fromJson(new String(resp.getBody()), type);
return result.getData();
}
throw new AIGCBusinessExceptions(ResultCodeEnum.HTTP_REQUEST_FAILED.getCode(), Arrays.toString(resp.getBody()));
} catch (Exception e) {
throw new AIGCBusinessExceptions(Result.HTTP_REQUEST_FAILED.getCode(), "读取电子表格报错" + e.getMessage());
}
}
打断点看一下api返回的东西:
重点对比一下第三行和四五行的数据,因为从第三行开始合并的单元格以及公式计算
现在需要解决这两个问题:
1.显示数据,不显示公式。
2.合并的单元格也要显示数据
问题1:公式计算
飞书api官方文档
读取多个范围 - 服务端 API - 开发文档 - 飞书开放平台 (feishu.cn) 根据项目需求,我调用的是这个api。这个问题好解决,加一个查询参数valueRenderOption=FormattedValue 计算并格式化单元格;
java
String url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/" + token + "/values_batch_get?ranges=" + sheetId+"&valueRenderOption=FormattedValue";
okk, 公式计算的问题解决了,现在显示结果了。下次要认真阅读api文档,官方文档写了.....查询参数那列valueRenderOption
问题2:读取合并单元格
这个问题官方文档好像是没写,翻阅了官方文档没找到。需求在那也只能硬着头皮写了。 以下是我自己的方法,感觉不是很好用,有大佬知道这个问题请多多指教。
1.调用api查询出表合并单元格的相关信息
查询工作表 - 服务端 API - 开发文档 - 飞书开放平台 (feishu.cn) 响应体中的merges会返回表合并单元格的相关信息。
java
public List<Merges> getSheetDetail(String token, String sheetId){
try {
String substring = sheetId.substring(0, sheetId.indexOf('!'));
String url="https://open.feishu.cn/open-apis/sheets/v3/spreadsheets/"+ token +"/sheets/"+substring;
RawResponse resp = client.get(url, null, AccessTokenType.Tenant);
if (resp.getStatusCode() == 200) {
Type type = new TypeToken<LarkResult<Spreadsheet>>() {}.getType();
LarkResult<Spreadsheet> result = Jsons.DEFAULT.fromJson(new String(resp.getBody()), type);
Spreadsheet spreadsheet = result.getData();
List<Merges> merges = spreadsheet.getSheet().getMerges();
return merges;
}
throw new AIGCBusinessExceptions(ResultCodeEnum.HTTP_REQUEST_FAILED.getCode(), Arrays.toString(resp.getBody()));
} catch (Exception e) {
throw new AIGCBusinessExceptions(Result.HTTP_REQUEST_FAILED.getCode(), "读取电子表格报错" + e.getMessage());
}
}
注意:这里返回的行列index都是,第n行列-1。start_row_index=2实际上是第三行
2.给合并单元格赋值
现在只取游戏图那一列合并单元格的数据
java
/**
* spreadsheetData 表数据
* mergesList 合并单元格的信息
*/
public void mergeCell(SpreadsheetData spreadsheetData,List<Merges> mergesList){
//获取游戏图所在的列,get(0)是表头
SpreadsheetData.ValueRange head = spreadsheetData.getValueRanges().get(0);
List<List<Object>> headValues = head.getValues();
List<Object> headObjects = headValues.get(0);
Integer index=0;
for (int i = 0; i < headObjects.size(); i++) {
if (headObjects.get(i).equals("游戏图")){
index=i;
break;
}
}
//取合并单元格的行号
List<Integer> indexList=new ArrayList<>();
for (Merges merges : mergesList) {
if (merges.getStart_column_index().equals(index) && merges.getEnd_column_index().equals(index)){
Integer startRowIndex = merges.getStart_row_index();
Integer endRowIndex = merges.getEnd_row_index();
for (int i=startRowIndex;i<=endRowIndex;i++){
indexList.add(i);
}
}
}
//get(1)取表内的数据
SpreadsheetData.ValueRange valueRange = spreadsheetData.getValueRanges().get(1);
String range = valueRange.getRange();
//取开始行号 ,计算每行数据在表格内的行号,与indexList进行对比
int startRow = Integer.parseInt(range.substring(range.indexOf('!') + 2, range.indexOf(':')));
List<List<Object>> values = valueRange.getValues();
Object temp=null;
for (int i = 0; i < values.size(); i++) {
Object o = values.get(i).get(index);
if (o!=null){
temp= o;
}
if (o ==null && indexList.contains(i+startRow-1) ){
values.get(i).set(index,temp);
}
}
}
3.最后
java
public SpreadsheetData getSheet(String token, String sheetId) {
// 发起请求
try {
String url = "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/" + token + "/values_batch_get?ranges=" + sheetId+"&valueRenderOption=FormattedValue";
RawResponse resp = client.get(url, null, AccessTokenType.Tenant);
if (resp.getStatusCode() == 200) {
Type type = new TypeToken<LarkResult<SpreadsheetData>>() {}.getType();
LarkResult<SpreadsheetData> result = Jsons.DEFAULT.fromJson(new String(resp.getBody()), type);
SpreadsheetData spreadsheetData = result.getData();
//获取合并的单元格,下标从0开始
List<Merges> mergesList = getSheetDetail(token, sheetId);
mergeCell(spreadsheetData,mergesList);
return result.getData();
}
throw new AIGCBusinessExceptions(ResultCodeEnum.HTTP_REQUEST_FAILED.getCode(), Arrays.toString(resp.getBody()));
} catch (Exception e) {
throw new AIGCBusinessExceptions(Result.HTTP_REQUEST_FAILED.getCode(), "读取电子表格报错" + e.getMessage());
}
}
结果:"游戏图"那列的合并单元格,不止第三行,第四五行都有了数据。
最后:如果有大佬有更好的方法,请多多指教