diff --git a/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt b/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt index 771c91cc8..ade864706 100644 --- a/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt +++ b/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt @@ -572,6 +572,7 @@ /nop/report/demo/base/12-动态Sheet和动态列.xpt.xlsx /nop/report/demo/base/13-复杂结构列展开.xpt.xlsx /nop/report/demo/base/14-复杂结构行展开.xpt.xlsx +/nop/report/demo/base/15-兄弟节点同时展开.xpt.xlsx /nop/report/demo/ext/report-with-params.xpt.xlsx /nop/report/demo/pages/demo.page.yaml /nop/report/demo/pages/report-with-params.page.yaml @@ -618,7 +619,6 @@ /nop/report/xlib/xpt-rt.xlib /nop/report/xlib/xpt.xlib /nop/rpc/imp/api.imp.xml -/nop/rpc/imp/api.imp.xml.rej /nop/rpc/imp/template.api.xlsx /nop/rule/_module /nop/rule/auth/_nop-rule-api.action-auth.xml @@ -1051,7 +1051,6 @@ /nop/web/xlib/view-gen.xlib /nop/web/xlib/view-gen/impl_GenFromMeta.xpl /nop/web/xlib/web.xlib -/nop/web/xlib/web.xlib.rej /nop/web/xlib/web/grid_crud.xpl /nop/web/xlib/web/impl_GenForm.xpl /nop/web/xlib/web/impl_GenGrid.xpl diff --git a/nop-excel/src/main/java/io/nop/excel/ExcelConstants.java b/nop-excel/src/main/java/io/nop/excel/ExcelConstants.java index 4bf6cbbb7..95bf39da0 100644 --- a/nop-excel/src/main/java/io/nop/excel/ExcelConstants.java +++ b/nop-excel/src/main/java/io/nop/excel/ExcelConstants.java @@ -29,6 +29,8 @@ public interface ExcelConstants { String VAR_FIELD_LABEL = "fieldLabel"; + String VAR_SHEET_NAME_MAPPING = "sheetNameMapping"; + /** * By default, Microsoft Office Excel 2007 uses the Calibry font in font size 11 */ diff --git a/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/ExcelSheetWriter.java b/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/ExcelSheetWriter.java index 0f07d9927..b144e0d04 100644 --- a/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/ExcelSheetWriter.java +++ b/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/ExcelSheetWriter.java @@ -81,7 +81,7 @@ public void generateXml(IXNodeHandler out, IEvalContext context) { genRows(out, sheet); genMergeCells(out, sheet); - genLinks(out, sheet); + genLinks(out, sheet, context); genPageMargins(out, sheet); @@ -273,7 +273,7 @@ void genPageMargins(IXNodeHandler out, IExcelSheet sheet) { * * */ - void genLinks(IXNodeHandler out, IExcelSheet sheet) { + void genLinks(IXNodeHandler out, IExcelSheet sheet, IEvalContext context) { List links = new ArrayList<>(); sheet.getTable().forEachRealCell((cell, rowIndex, colIndex) -> { String linkUrl = cell.getLinkUrl(); @@ -298,7 +298,8 @@ void genLinks(IXNodeHandler out, IExcelSheet sheet) { links.forEach(link -> { Map attrs = new LinkedHashMap<>(); attrs.put("ref", ValueWithLocation.of(null, CellPosition.toABString(link.rowIndex, link.colIndex))); - attrs.put("location", ValueWithLocation.of(null, normalizeLocation(link.location))); + attrs.put("location", ValueWithLocation.of(null, normalizeLocation(link.location, + (Map) context.getEvalScope().getValue(ExcelConstants.VAR_SHEET_NAME_MAPPING)))); attrs.put("display", ValueWithLocation.of(null, link.text)); attrs.put("xr:id", ValueWithLocation.of(null, intToUUID(link.index))); out.simpleNode(null, "hyperlink", attrs); @@ -307,13 +308,16 @@ void genLinks(IXNodeHandler out, IExcelSheet sheet) { } } - private String normalizeLocation(String location) { + private String normalizeLocation(String location, Map sheetNameMap) { int pos = location.indexOf('!'); if (pos > 0) { String abPos = location.substring(pos + 1); try { CellPosition.fromABString(abPos); String sheetName = location.substring(0, pos); + String mappedName = sheetNameMap == null ? null : sheetNameMap.get(sheetName); + if (mappedName != null) + return mappedName + '!' + abPos; return normalizeSheetName(sheetName, sheetIndex, workbook) + '!' + abPos; } catch (Exception e) { return location; diff --git a/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/ExcelTemplate.java b/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/ExcelTemplate.java index 24f62dd60..9b5addb41 100644 --- a/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/ExcelTemplate.java +++ b/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/ExcelTemplate.java @@ -13,6 +13,7 @@ import io.nop.core.resource.IResource; import io.nop.core.resource.impl.ByteArrayResource; import io.nop.core.resource.impl.FileResource; +import io.nop.excel.ExcelConstants; import io.nop.excel.model.ExcelImage; import io.nop.excel.model.ExcelSheet; import io.nop.excel.model.ExcelWorkbook; @@ -35,7 +36,6 @@ import java.util.Map; import static io.nop.ooxml.common.model.PackagingURIHelper.createPartName; -import static io.nop.ooxml.xlsx.output.XlsxGenHelper.normalizeSheetName; public class ExcelTemplate extends AbstractOfficeTemplate { @@ -79,9 +79,9 @@ public void generateToDir(File dir, IEvalContext context) { GenState genState = new GenState(); if (sheetGenerator != null) { - sheetGenerator.generate(context, sheet -> { + sheetGenerator.generate(context,(sheet,ctx) -> { int index = genState.nextSheetIndex++; - generateSheet(pkg, dir, index, sheet, context, genState); + generateSheet(pkg, dir, index, sheet, ctx, genState); }); } else if (workbook != null) { for (ExcelSheet sheet : workbook.getSheets()) { @@ -110,7 +110,7 @@ private void generateSheet(ExcelOfficePackage pkg, File dir, int index, IExcelSh OfficeRelsPart rels = pkg.makeRelsForPart(workbook); String relPath = "worksheets/sheet" + sheetId + ".xml"; String relId = rels.addRelationship(XSSFRelation.WORKSHEET.getRelation(), relPath, null); - workbook.addSheet(relId, sheetId, normalizeSheetName(sheet.getName(), index, this.workbook)); + workbook.addSheet(relId, sheetId, normalizeSheetName(sheet.getName(), index, context)); IResource resource = new FileResource(new File(dir, sheetPath)); ExcelSheetWriter writer = new ExcelSheetWriter(sheet, index == 0, index, this.workbook); @@ -129,6 +129,16 @@ private void generateSheet(ExcelOfficePackage pkg, File dir, int index, IExcelSh sheetRels.addRelationship(XSSFRelation.SHEET_COMMENTS.getRelation(), relCommentsPath, null); } + private String normalizeSheetName(String sheetName, int index, IEvalContext context) { + Map mapping = (Map) context.getEvalScope().getValue(ExcelConstants.VAR_SHEET_NAME_MAPPING); + if (mapping != null) { + String mappedName = mapping.get(sheetName); + if (mappedName != null) + return mappedName; + } + return XlsxGenHelper.normalizeSheetName(sheetName, index, workbook); + } + private void generateDrawings(ExcelOfficePackage pkg, IExcelSheet sheet, String drawingRelId, IOfficePackagePart sheetPart, GenState genState) { if (sheet.getImages() == null || sheet.getImages().isEmpty()) return; diff --git a/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/IExcelSheetGenerator.java b/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/IExcelSheetGenerator.java index 3b5bdb169..d9e7bae62 100644 --- a/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/IExcelSheetGenerator.java +++ b/nop-ooxml/nop-ooxml-xlsx/src/main/java/io/nop/ooxml/xlsx/output/IExcelSheetGenerator.java @@ -10,8 +10,8 @@ import io.nop.core.context.IEvalContext; import io.nop.excel.model.IExcelSheet; -import java.util.function.Consumer; +import java.util.function.BiConsumer; public interface IExcelSheetGenerator { - void generate(IEvalContext context, Consumer consumer); + void generate(IEvalContext context, BiConsumer consumer); } diff --git a/nop-report/nop-report-core/src/main/java/io/nop/report/core/build/XptConfigParseHelper.java b/nop-report/nop-report-core/src/main/java/io/nop/report/core/build/XptConfigParseHelper.java index bb11eb126..34e91ecab 100644 --- a/nop-report/nop-report-core/src/main/java/io/nop/report/core/build/XptConfigParseHelper.java +++ b/nop-report/nop-report-core/src/main/java/io/nop/report/core/build/XptConfigParseHelper.java @@ -23,12 +23,12 @@ public class XptConfigParseHelper { - public static void parseWorkbookModel(ExcelWorkbook workbook) { + public static XptWorkbookModel parseWorkbookModel(ExcelWorkbook workbook) { ImportModel importModel = ImportModelHelper.getImportModel(XptConstants.XPT_IMP_MODEL_PATH); - parseWorkbookModel(workbook, importModel); + return parseWorkbookModel(workbook, importModel); } - public static void parseWorkbookModel(ExcelWorkbook workbook, ImportModel importModel) { + public static XptWorkbookModel parseWorkbookModel(ExcelWorkbook workbook, ImportModel importModel) { IEvalScope scope = XLang.newEvalScope(); scope.setLocalValue(ExcelConstants.VAR_WORKBOOK, workbook); @@ -42,7 +42,7 @@ public static void parseWorkbookModel(ExcelWorkbook workbook, ImportModel import if (namedStyles != null) { workbookModel.prop_remove(XptConstants.PROP_NAMED_STYLES); for (DynamicObject namedStyle : namedStyles) { - ExcelStyle style = getStyle(workbook,(String)namedStyle.prop_get(XptConstants.PROP_STYLE)); + ExcelStyle style = getStyle(workbook, (String) namedStyle.prop_get(XptConstants.PROP_STYLE)); if (style != null) { String id = (String) namedStyle.prop_get(XptConstants.PROP_ID); if (!StringHelper.isEmpty(id)) { @@ -53,8 +53,11 @@ public static void parseWorkbookModel(ExcelWorkbook workbook, ImportModel import } } } - workbook.setModel(workbookModel); + }else { + workbookModel = new XptWorkbookModel(); } + workbook.setModel(workbookModel); + return workbookModel; } static ExcelStyle getStyle(ExcelWorkbook wk, String styleId){ diff --git a/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/ExpandedSheetGenerator.java b/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/ExpandedSheetGenerator.java index f7e1ad270..97bda4a66 100644 --- a/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/ExpandedSheetGenerator.java +++ b/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/ExpandedSheetGenerator.java @@ -42,6 +42,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.function.BiConsumer; import java.util.function.Consumer; public class ExpandedSheetGenerator implements IExcelSheetGenerator { @@ -54,7 +55,7 @@ public ExpandedSheetGenerator(ExcelWorkbook workbook) { } @Override - public void generate(IEvalContext ctx, Consumer consumer) { + public void generate(IEvalContext ctx, BiConsumer consumer) { XptRuntime xptRt = new XptRuntime(ctx.getEvalScope()); xptRt.setWorkbook(workbook); @@ -79,7 +80,7 @@ public void generate(IEvalContext ctx, Consumer consumer) { }); } - void generateSheetLoop(ExcelSheet sheet, ExcelWorkbook workbook, IXptRuntime xptRt, Consumer consumer) { + void generateSheetLoop(ExcelSheet sheet, ExcelWorkbook workbook, IXptRuntime xptRt, BiConsumer consumer) { XptSheetModel sheetModel = sheet.getModel(); xptRt.getEvalScope().setLocalValue(null, XptConstants.VAR_SHEET_TPL, sheet); @@ -106,7 +107,7 @@ void generateSheetLoop(ExcelSheet sheet, ExcelWorkbook workbook, IXptRuntime xpt if (sheetModel != null) runXpl(sheetModel.getAfterExpand(), xptRt); - consumer.accept(expandedSheet); + consumer.accept(expandedSheet,xptRt); } finally { xptRt.runSheetCleanup(); } diff --git a/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/ReportEngine.java b/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/ReportEngine.java index a8afb8eee..154a093b5 100644 --- a/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/ReportEngine.java +++ b/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/ReportEngine.java @@ -64,7 +64,7 @@ public ITemplateOutput getRendererForExcel(ExcelWorkbook model, String renderTyp throw new NopException(ERR_XPT_UNSUPPORTED_RENDER_TYPE) .param(ARG_RENDER_TYPE, renderType); - return rendererFactory.buildRenderer(model, (ctx, action) -> model.getSheets().forEach(action)); + return rendererFactory.buildRenderer(model, (ctx, action) -> model.getSheets().forEach(sheet-> action.accept(sheet,ctx))); } diff --git a/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/renderer/HtmlRenderHelper.java b/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/renderer/HtmlRenderHelper.java index 80f94c1ff..436f5726d 100644 --- a/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/renderer/HtmlRenderHelper.java +++ b/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/renderer/HtmlRenderHelper.java @@ -17,7 +17,7 @@ public class HtmlRenderHelper { public static String getHtml(ExcelWorkbook workbook, IExcelSheet sheet) { return new HtmlReportRendererFactory.HtmlTemplate(workbook, - (ctx, action) -> action.accept(sheet)).generateText(DisabledEvalScope.INSTANCE); + (ctx, action) -> action.accept(sheet,ctx)).generateText(DisabledEvalScope.INSTANCE); } public static void dumpHtml(ExcelWorkbook workbook, IExcelSheet sheet, String fileName) { diff --git a/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/renderer/HtmlReportRendererFactory.java b/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/renderer/HtmlReportRendererFactory.java index 3f556a32e..7e84252ce 100644 --- a/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/renderer/HtmlReportRendererFactory.java +++ b/nop-report/nop-report-core/src/main/java/io/nop/report/core/engine/renderer/HtmlReportRendererFactory.java @@ -65,10 +65,10 @@ public void generateToWriter(Writer out, IEvalContext context) throws IOExceptio MutableInt index = new MutableInt(); if (sheetGenerator != null) { - sheetGenerator.generate(context, sheet -> { + sheetGenerator.generate(context, (sheet,ctx) -> { index.incrementAndGet(); String sheetId = reportId + "-sheet-" + index; - renderSheet(sheet, sheetId, scopeCssPrefix, out, context); + renderSheet(sheet, sheetId, scopeCssPrefix, out, ctx); }); } else { model.getSheets().forEach(sheet -> { diff --git a/nop-report/nop-report-core/src/main/java/io/nop/report/core/imp/ExcelTemplateToXptModelTransformer.java b/nop-report/nop-report-core/src/main/java/io/nop/report/core/imp/ExcelTemplateToXptModelTransformer.java index 3fe8db165..b1978513b 100644 --- a/nop-report/nop-report-core/src/main/java/io/nop/report/core/imp/ExcelTemplateToXptModelTransformer.java +++ b/nop-report/nop-report-core/src/main/java/io/nop/report/core/imp/ExcelTemplateToXptModelTransformer.java @@ -33,6 +33,7 @@ import io.nop.excel.model.ExcelWorkbook; import io.nop.excel.model.XptCellModel; import io.nop.excel.model.XptSheetModel; +import io.nop.excel.model.XptWorkbookModel; import io.nop.excel.model.constants.XptExpandType; import io.nop.report.core.XptConstants; import io.nop.report.core.build.XptConfigParseHelper; @@ -53,13 +54,26 @@ */ public class ExcelTemplateToXptModelTransformer { private final IEvalScope scope; + private final XLangCompileTool compileTool = XLang.newCompileTool().allowUnregisteredScopeVar(true); public ExcelTemplateToXptModelTransformer(IEvalScope scope) { this.scope = scope; } public void transform(ExcelWorkbook template, ImportModel model) { - XptConfigParseHelper.parseWorkbookModel(template); + XptWorkbookModel xptModel = XptConfigParseHelper.parseWorkbookModel(template); + + XNode beforeExpandNode = XNode.fromValue(model.prop_get(XptConstants.EXT_PROP_XPT_BEFORE_EXPAND)); + if (beforeExpandNode != null) { + IEvalAction action = compileTool.compileTagBodyWithSource(beforeExpandNode, XLangOutputMode.none); + xptModel.setBeforeExpand(action); + } + + XNode afterExpandNode = XNode.fromValue(model.prop_get(XptConstants.EXT_PROP_XPT_AFTER_EXPAND)); + if (afterExpandNode != null) { + IEvalAction action = compileTool.compileTagBodyWithSource(afterExpandNode, XLangOutputMode.none); + xptModel.setAfterExpand(action); + } for (ExcelSheet sheet : template.getSheets()) { ImportSheetModel sheetModel = getSheetModel(model, sheet); @@ -76,7 +90,7 @@ public void transform(ExcelWorkbook template, ImportModel model) { private void transformSheet(ExcelSheet sheet, ImportSheetModel sheetModel) { new TreeTableDataParser(scope).parse(sheet.getName(), sheet.getTable(), sheetModel, - new BuildXptModelListener(sheet)); + new BuildXptModelListener(sheet, compileTool)); } private ImportSheetModel getSheetModel(ImportModel model, ExcelSheet sheet) { @@ -104,7 +118,7 @@ static class BuildXptModelListener implements ITableDataEventListener { private final List labelCells = new ArrayList<>(); - private final XLangCompileTool compileTool = XLang.newCompileTool().allowUnregisteredScopeVar(true); + private final XLangCompileTool compileTool; static class FieldRange { int rowIndex; @@ -131,8 +145,9 @@ public FieldRange(int rowIndex, int colIndex, int maxRowIndex, } } - public BuildXptModelListener(ExcelSheet sheet) { + public BuildXptModelListener(ExcelSheet sheet, XLangCompileTool compileTool) { this.sheet = sheet; + this.compileTool = compileTool; } public ExcelTable getTable() { diff --git a/nop-report/nop-report-pdf/src/main/java/io/nop/report/pdf/renderer/PdfReportRenderer.java b/nop-report/nop-report-pdf/src/main/java/io/nop/report/pdf/renderer/PdfReportRenderer.java index b7057cf62..cee55c8bb 100644 --- a/nop-report/nop-report-pdf/src/main/java/io/nop/report/pdf/renderer/PdfReportRenderer.java +++ b/nop-report/nop-report-pdf/src/main/java/io/nop/report/pdf/renderer/PdfReportRenderer.java @@ -69,9 +69,7 @@ public void generateToStream(OutputStream os, IEvalContext context) throws IOExc if (sheetGenerator != null) { - sheetGenerator.generate(context, sheet -> { - renderSheet(sheet, context); - }); + sheetGenerator.generate(context, this::renderSheet); } else { model.getSheets().forEach(sheet -> { renderSheet(sheet, context); diff --git a/nop-rpc/nop-rpc-model/src/main/resources/_vfs/nop/rpc/imp/api.imp.xml b/nop-rpc/nop-rpc-model/src/main/resources/_vfs/nop/rpc/imp/api.imp.xml index e167b11f1..d1dae0e6f 100644 --- a/nop-rpc/nop-rpc-model/src/main/resources/_vfs/nop/rpc/imp/api.imp.xml +++ b/nop-rpc/nop-rpc-model/src/main/resources/_vfs/nop/rpc/imp/api.imp.xml @@ -4,6 +4,18 @@ templatePath="template.api.xlsx" xmlns:c="c" xmlns:xpt="xpt" xdef="/nop/schema/api.xdef"> + + diff --git a/nop-xlang/src/main/java/io/nop/xlang/api/EvalActionWithCode.java b/nop-xlang/src/main/java/io/nop/xlang/api/EvalActionWithCode.java index b57483c75..1511178bd 100644 --- a/nop-xlang/src/main/java/io/nop/xlang/api/EvalActionWithCode.java +++ b/nop-xlang/src/main/java/io/nop/xlang/api/EvalActionWithCode.java @@ -21,6 +21,10 @@ public String getSource() { return code; } + public String toString() { + return code == null ? "" : code; + } + @Override public Object invoke(IEvalContext ctx) { return action.invoke(ctx);