如何实现 开放平台OpenApi2.0导出Excel表格的功能原创
金蝶云社区-吴锐雄
吴锐雄
11人赞赏了该文章 1968次浏览 未经作者许可,禁止转载编辑于2023年11月23日 15:35:38

关键词:OpenApi2.0案例,开放平台,导出


一、需求

通过调用苍穹api的方式,获取到一个excel文件,excel里面存放了单据数据。


二、思路与方案

思路:

构建出excel表格,需要有数据源,我们可以使用QueryServiceHelper,将多个DataSet使用Algo合并为一个数据源。

构建出excel表格,可以使用POI框架(苍穹的jar包带了POI框架,无需二次引入构造XSSFWorkbook对象来生成excel。

有了excel表格之后,将它转为文件流,上传到我们的文件服务器上。上传时可以指定文件路径。有了文件路径之后,我们就可以拼接为一个下载路径。

以上业务逻辑,可以使用openapi2.0,在自定义服务插件中实现。当用户调用api时,将下载路径响应给用户。


方案:

1.进入开放平台,创建第三方app

2.编写自定义服务插件:

    2.1在插件中获取单据数据,生成excel文件对象

    2.2调用文件服务,生成下载链接

3.创建api2.0的自定义服务

4.使用http工具,调用自定义服务,测试api接口:

    4.1调用第三方app服务,获取apptoken

    4.2调用/login.do,获取accesstoken

    4.3调用自定义服务,获取文件下载链接


三、实现过程


准备数据源

这一步是本案例的准备工作,我们接下来将要把以下单据列表数据导出到excel表格中。

如果各位读者已有需要导出的数据源,当前步骤可以跳过。


创建 基础资料“化肥”,单据“水果”,添加预置数据,为即将导出的数据准备数据源。

页面结构请参考我的上一篇文章:

如何通过二开的方式将数据导出到Excel,并调整Excel样式

添加预置数据如下:

 image.png

 image.png



创建第三方app

开发服务云,进入开放平台,进入第三方应用列表,新增一个第三方应用。

image.png    image.png


认证方式选择最基本的accessToken;

api授权勾选“全部api授权”(这里仅作为演示,实际场景建议配置授权api)。

image.png


编写自定义服务插件

(1)创建自定义服务类FruitApi2Plugin,添加@ApiController @ApiMapping注解;

(2)添加exportFruitPro方法,添加@ApiPostMapping注解;

(3)方法入参numberFilter,添加@ApiParam注解;

(4)响应模型FruitModel类,添加@ApiResponseBody注解。

@ApiController(value = "kdec_wrx_col_app", desc = "导出水果生产数据")
@ApiMapping("/fp")
public class FruitApi2Plugin {

    @Validated
    @ApiPostMapping("/export")
    public CustomApiResult<@ApiResponseBody("响应") FruitModel> exportFruitPro(@Valid @NotNull @ApiParam(value = "过滤") String numberFilter) {
            String title = "水果生产以及产地";
            DataSet dataSet = queryData(numberFilter);
            List<List<String>> excelList = getExcelList(dataSet);
            // 创建excel工作簿
            XSSFWorkbook workbook = MyExportUtil.excel(excelList, title);
            // 上传
            String path = MyExportUtil.upload(title, workbook);
            String downloadUrl = RequestContext.get().getClientFullContextPath() + "/attachment/download.do?path=" + path;
            
            FruitModel fruitModel = new FruitModel();
            fruitModel.setUrl(downloadUrl);
            return CustomApiResult.success(fruitModel);
    }
    
}

(5)创建FruitModel类,添加@ApiModel注解,实例化Serializable接口;

内部变量url,添加@ApiParam注解,之后会把这个变量存储excel文件的下载链接。

@ApiModel
public class FruitModel implements java.io.Serializable{
    @ApiParam(value = "下载链接", position = 1)
    String url;
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
}

(6)查询数据

public DataSet queryData() {
    DataSet dataSetFruits = QueryServiceHelper.queryDataSet("FruitPro", "kdec_fruit_bill",
            "id, billno as kdec_fnumber, kdec_entryentity.kdec_fruits as kdec_fname, kdec_fruit_pro.id as proid, kdec_fruit_pro.name as kdec_pro", null, "");

    DataSet dataSet2 = dataSetFruits.copy();
    Iterator<Row> iterator = dataSet2.iterator();
    List proList = new ArrayList<>();
    while (iterator.hasNext()) {
        Row row = iterator.next();
        proList.add(row.get("proid"));
    }
    QFilter qFilter = new QFilter("kdec_region", QCP.in, proList);
    DataSet dataSetFertilizer = QueryServiceHelper.queryDataSet("FruitPro", "kdec_fertilizer_bill",
            "id, billno as kdec_fernumber, kdec_name as kdec_fername, kdec_region", qFilter.toArray(), "");

    DataSet result = dataSetFruits.rightJoin(dataSetFertilizer)
            .select(new String[]{"kdec_fnumber", "kdec_fname", "kdec_pro"}, new String[]{"kdec_fernumber", "kdec_fername"})
            .on("proid", "kdec_region").finish();
    return result;
}

(7)构造准备导出的excel数据源

public List<List<String>> getExcelList (DataSet dataSet) {
    // excelList用于提供数据源给 excel工作簿,外层的list是行,里面的List<String>是列,存储value
    List<List<String>> excelList = new ArrayList<>();

    List<String> titles = new ArrayList<>();
    titles.add("水果编码");
    titles.add("水果名称");
    titles.add("产地");
    titles.add("化肥编码");
    titles.add("化肥名称");
    excelList.add(titles);

    while (dataSet.hasNext()) {
        Row row = dataSet.next();
        List<String> strings = new ArrayList<>();
        for ( int j = 0; j < row.size(); j++) {
            String value = row.getString(j);
            strings.add(value);
        }
        excelList.add(strings);
    }
    return excelList;
}

(8)构造XSSFWorkbook对象,此处省略了部分风格样式设置的代码,如果有需要,请查看源码

public static XSSFWorkbook excel(List<List<String>> excelList, String title) {
    //创建excel工作簿
    XSSFWorkbook workbook = new XSSFWorkbook();
    //创建工作表sheet
    XSSFSheet sheet = workbook.createSheet();

    //写入单据列表数据
    for (int i = 0; i < excelList.size(); i++) {
        // i+1是因为前面第1行加了一个标题,单据列表数据是从Excel的第2行开始的,所以要+1
        XSSFRow nrow = sheet.createRow(i+1);
        for (int u=0;u<excelList.get(i).size();u++){
            XSSFCell ncell = nrow.createCell(u);
            if (i == 0) {
                ncell.setCellStyle(firstRowStyle);
            } else if (u == 0) {
                ncell.setCellStyle(firstColumnStyle);
            } else {
                ncell.setCellStyle(billStyle);
            }
            ncell.setCellValue(excelList.get(i).get(u));
        }
    }
    return workbook;
}

(9)将XSSFWorkbook转为文件流,并调用FileService上传

public static String upload (String entityName, XSSFWorkbook workbook) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
    String fileName = entityName + sdf.format(new Date()) + ".xlsx";
    String pathName = "/offices/" + fileName;
    try {
        OutputStream outputStream = new ByteArrayOutputStream();
        workbook.write(outputStream);
        InputStream inputStream = parse(outputStream);

        FileService fs = FileServiceFactory.getAttachmentFileService();
        String path = fs.upload(new FileItem(fileName, pathName, inputStream));

        return path;
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
    return "";
}



创建api

进入api管理列表,选择一个业务云,选择云下面的应用(业务云和应用在开发平台中创建)。

image.png


如上图点击新增之后,选择“自定义API”

image.png


把上一步写好的api2.0的类和路径输入,点击“同步”按钮,会按照注解信息,把FruitApi2Plugin的信息加载到当前页面上

image.png

点击同步之后的效果

image.png



调用api服务

我使用postman工具,调用刚刚创建好的自定义api服务。

(1)调用第三方应用/api/getAppToken.do,获取app token

image.png


(2)使用app token,调用/api/login.do获取access token

image.png

(3)使用access token,调用自定义api服务。

注意access token是放在请求头里面的。image.png

在请求体中,设置编码过滤。

最终响应体如图所示,返回了excel文件下载链接:

image.png


四、效果图

excel文件下载链接,放到浏览器中访问:

image.png

最终下载文件如下:

image.png


五、开发环境版本

image.png


六、注意事项

开放平台的api2.0是比较新的苍穹版本中才能使用的,例如我的苍穹版本是5.0.008(参考上图)。


七、参考文章

自定义API(脚本开发)

https://vip.kingdee.com/link/s/MDlc2


金蝶云苍穹开放平台API调用流程

https://vip.kingdee.com/link/s/MDl7p


如何通过二开的方式将数据导出到Excel,并调整Excel样式

https://vip.kingdee.com/link/s/MIttZ









赞 11