导入导出二开常见问题

栏目:云苍穹知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:1

导入导出二开常见问题

**1.二开时,如何将继承导入插件BatchImportPlugin中的部分数据或标识,传递至表单插件中,以供类似beforeImport的方法获取?** 答:可在BatchImportPlugin的插件中,调用导入上下文对象ImportContext(ctx)中插入数据,后续通过方法入参中的option对象即可获取。 **2.当需要同时导入多个业务对象时,如何二开实现?** 答:可按如下方案实现: 方案一:上传多个Excel模板,每个模板均符合对应业务对象的导入模板要求。 优点:代码开发量小,可复用现有的导入相关的二开逻辑; 缺点:该方式实际是将多次导入过程在二开代码中整合成一次,可调整的逻辑较小。 步骤: ①构建一个文件上传入口,可上传一个或多个Excel文件。 ②监听步骤①的上传事件(表单插件中监听upload事件),收集上传完成的Excel文件。 ③可参考标准产品kd.bos.form.plugin.impt.ImportService#startImport的写法,启动导入相关的两个线程(入参url即为Excel的文件服务器地址,调用一次启动一个单据的导入任务,多个单据启动多次,BatchImportPlugin可为业务单据的导入插件(即BatchImportPlugin子类)) ```java /** * 设置导入页面显示 * * @param rc rc * @param ctx ctx * @param startArgs startArgs * @return BatchImportPlugin */ @Override public BatchImportPlugin setContext(RequestContext rc, ImportContext ctx, List<String> startArgs) { try { Field view = ctx.getClass().getDeclaredField("view"); ReflectionUtils.makeAccessible(view); try { IFormView formView = (FormView) view.get(ctx); formView.setVisible(false, "radiofield", "radiofield1"); } catch (IllegalAccessException e) { LOGGER.error(e.getMessage()); } } catch (NoSuchFieldException e) { LOGGER.error(e.getMessage()); } return super.setContext(rc, ctx, startArgs); } ``` 方案二:构建一个包含多个业务对象字段的整合型单据(假设多个单据间存在一对一,一对多关系,则可按照分录等格式构建),配置标准导入操作。 优点:相较于方案一更加灵活 缺点:不执行各单据原有的导入相关逻辑; 步骤: ①配置多个业务对象的整合型单据实体 ②该单据配置标准导入操作 ③该单据配置导入插件(BatchImportPlugin),并重写其save方法,在save方法中,完成对数据的分离及各实际库表的持久化。 **3.当业务需要导入非标准模板的数据时,如何二开实现?** 参照问题5中方案一的实现,并且重写其导入插件的“resolveExcel”方法,构造与标准产品一致的JSON格式数据。 代码可以参考: ```java //伪代码,仅供参考,请勿复制 public void statlmport(String ogld,String sevicehppld, String checkRightApid,String billFornd,String listlame, String url,String importpiugin){ RequestContext rc = RequestContext.qet(); string readoriginalNumstring = System.getProperty( "import.readoriginalNum", Boolean.tostring(false)); Boslean readOriginalNum = Boolean.parseBoolean(readoriginaNumString); Importcontext ctx =(new Imortontext(this.getView(), logId, seviceAppId, checkrightappId, listMame,billFomld,"save",url,"", false ,"", null,null, "", null, read0riginalNum)) .addOption("importtype","new") .addOption("KeyFields", null) .addOption("ForUpdateMultiLangFields",false) .addOption("OverrideEntry",false) .addOption("SetNuLL",true) .addOption("splitSubEntries", false); IImportDataPlugin plugin = (IImportDataPlugin)TypesContainer.createInstance(importPlugin); BatchImportplugin batchPlugin = ((BatchImportpludin)pluin).setContext(rc, ctx,Arnays.aslist("resolveExcel", "importData"); thregdPool.submit(batchplugin); threadPool.submit(batchplugin); ``` **4.当业务需要将引出的Excel文件做一些格式的调整时,如何二开实现?** 答:可以重写列表导出插件中的afterExportFile方法,该方法中,二开可以获取即将下载的文件流,拿到文件流后,可以使用POI提供的相关类进行文件格式、数据的修改调整。可参考如下代码: ```java /**@author rd_agbyte_yang * * 示例代码实现功能: * 1.修改按列表导出的文件名为【实体名称】+列表.xlsx * 2.修改前三行的第一列为红色字体 * */ public class TestExportListPlugin extends AbstractListPlugin { @Override public void beforeExportFile(BeforeExportFileEvent e) { // 示例:将引出文件名重置为主实体名称+“引出列表” e.setFileName(e.getMainEntityType().getDisplayName() + "引出列表.xlsx"); } @Override public void afterExportFile(ExportFileEvent e) { File file = e.getFile(); if (file != null) { // 示例:修改前三行的第一列为红色字体 try (FileInputStream fis = new FileInputStream(file);) { Workbook wb = new XSSFWorkbook(fis); Sheet sheet = wb.getSheetAt(0); // 修改背景颜色(示例写死,自行修改) for (int i = 0; i < 3; i++) { CellStyle cs = wb.createCellStyle(); cs.setFillForegroundColor(IndexedColors.RED.getIndex()); cs.setFillPattern(FillPatternType.SOLID_FOREGROUND); sheet.getRow(i).getCell(1).setCellStyle(cs); } // 保存 FileOutputStream out = new FileOutputStream(file); wb.write(out); wb.close(); out.close(); } catch (Throwable ex) { ex.printStackTrace(); } } } } ``` **5.当业务需要将导出的Excel文件做一些格式的调整时,且数据量较大时(问题7方式可能在大数据量下导致OOM),如何二开实现?** 问题7的解决方案较为简单,可以适用于大部分数据量小的导出场景,当数据量较大时,POI的方法 ```java Workbook wb = new XSSFWorkbook(fis); ``` 可能存在性能问题,占用较大内存空间,产生OOM问题,此时需要另外的方式进行处理,建议参考如下伪代码进行处理 ```java //伪代码 MySheetHandler更多细节可参考 kd.bos.form.plugin.impt.BatchImportFailedSheetHandler#handleRow //伪代码,请勿复制 public void afterExportFile(ExportFileEvent e) { File file = e.getFile(); if (file != null) { new ExcelReader().read(in, new SheetHandler() { @Override public void handleRow(ParsedRow row) { /** *入参为Excel的每行数据,根据业务场景处理,也可参考 *kd.bos.form.plugin.impt.BatchImportFailedSheetHandler#handleRow */ dealWithRowData(row); } }, true); } } ``` **6.导入模板中的基础资料,需要手动输入编码,可能存在错误输入(如空格)或客户认为输入编码较为繁琐,如何二开实现基础资料如下拉选项字段一样,可以下拉选择基础资料值?** 可参考链接:https://vip.kingdee.com/knowledge/specialDetail/228886918686445824?category=449142108704634112&id=327109527931751680&productLineId=29 **7.客户现场不想使用苍穹标准的导入模板,二开如何实现导入客户的模板?** 可参考如下demo,自行处理解析数据的逻辑: ```java public class TestBatchImportPlugin extends BatchImportPlugin { @Override protected void resolveExcel() { FileService service = FileServiceFactory.getAttachmentFileService(); ExcelReader reader = new ExcelReader(); //此为历史设计,当前导入文件路径集合中有且仅有一条数据 Set<String> allUrls = ctx.getAllUrls(); List<String> urlList = new ArrayList<>(allUrls); String importExcelFileUrl = urlList.get(0); try (InputStream in = service.getInputStream(importExcelFileUrl)) { MainEntityType mainEntityType = buildMainEntityType(null); if (mainEntityType instanceof QueryEntityType) { mainEntityType = ((QueryEntityType) mainEntityType).getMainEntityType(); } // MySheetHandler为用户自定义的excel解析器 reader.read(in, new MySheetHandler(ctx, mainEntityType, importExcelFileUrl)); } catch (Exception e) { throw new RuntimeException(e); } finally { ctx.setResolveComplete(importExcelFileUrl); } } /** * 可以自定义保存,比如直接入库等,还可以在保存后做额外的逻辑 */ @Override protected ApiResult save(List<ImportBillData> rowdatas, ImportLogger logger) { ApiResult result = super.save(rowdatas, logger); if (result.getSuccess()) { // TODO 额外的逻辑,比如级联更新别的实体的数据,触发另外的操作等等 } return result; } } class MySheetHandler extends SheetHandler { private int startRowNum = 0; private int currRowNum = 0; private ImportEntityMapping entityMapping; private Map<Integer, String> nameRow; private ImportContext ctx; private MainEntityType mainEntityType; private String importExcelFileUrl; private LinkedBlockingQueue<ImportBillData> dataQueue; public MySheetHandler(ImportContext ctx, MainEntityType mainEntityType, String importExcelFileUrl) { this.ctx = ctx; this.mainEntityType = mainEntityType; this.importExcelFileUrl = importExcelFileUrl; this.dataQueue = ctx.getDataQueue(importExcelFileUrl); this.importExcelFileUrl = importExcelFileUrl; } @Override public void handleRow(ParsedRow currentRow) { JSONObject jsonData = new JSONObject(); currRowNum = currentRow.getRowNum(); //假设字段标识行在第三行 if (currRowNum == 2) { nameRow = currentRow.getData(); } if (currRowNum == 3) { //注意 此处会根据标识构建一个映射对象,如不适用该对象,请自行构建 //包含的主要信息为Map<String, ColInfo> cols;列数据格式 entityMapping = ImportEntityMapping.create(mainEntityType, nameRow, currentRow.getData()); } //假设数据行从Excel第五行开始 if (currRowNum >= 4) { Map<Integer, String> rowData = currentRow.getData(); for (Map.Entry<Integer, String> integerStringEntry : rowData.entrySet()) { /** * 示例代码,根据实际数据解析构建成JSON格式 */ jsonData.put("keyField1",integerStringEntry.getValue()); } } addBillData(new ImportBillData(jsonData, startRowNum, currRowNum,entityMapping)); } private void addBillData(ImportBillData billData) { try { if (!dataQueue.offer(billData, 10, TimeUnit.MINUTES)) { throw new KDBizException("解析超时"); } } catch (Throwable e) { throw new KDBizException("解析存在未知异常"); } } } } ```

导入导出二开常见问题

**1.二开时,如何将继承导入插件BatchImportPlugin中的部分数据或标识,传递至表单插件中,以供类似beforeImport的方法获取?**答:可在Bat...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息