@veltra/sheet 2.3.3 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/report/binding-badge.js +23 -5
- package/dist/components/report/designer/drill-dialog.js +258 -0
- package/dist/components/report/designer/float-panel.js +26 -14
- package/dist/components/report/print.js +39 -0
- package/dist/components/report/report-designer.js +56 -21
- package/dist/components/report/report-viewer.js +173 -44
- package/dist/components/report/style2.css +91 -0
- package/dist/components/report/use-report-designer.js +2 -1
- package/dist/components/report/use-report-viewer.js +88 -3
- package/dist/components/sheet/insert-image.js +1 -1
- package/dist/components/sheet/popups/import.worker.js +2 -3
- package/dist/components/sheet/use-sheet-state.js +2 -2
- package/dist/index.d.ts +5 -3
- package/dist/index.js +4 -2
- package/dist/report/drill.d.ts +48 -0
- package/dist/report/drill.js +78 -0
- package/dist/report/export-xlsx.d.ts +3 -7
- package/dist/report/export-xlsx.js +6 -85
- package/dist/report/index.d.ts +5 -3
- package/dist/report/print.d.ts +23 -0
- package/dist/report/print.js +197 -0
- package/dist/report/render/aggregate.js +25 -1
- package/dist/report/types.d.ts +19 -1
- package/dist/tools/download.js +2 -2
- package/dist/types/report-designer.d.ts +13 -0
- package/dist/types/report-viewer.d.ts +19 -0
- package/package.json +6 -9
- package/src/components/report/__test__/binding-badge.test.ts +92 -0
- package/src/components/report/__test__/report-designer.test.ts +98 -3
- package/src/components/report/__test__/report-drill.test.ts +692 -0
- package/src/components/report/__test__/report-viewer.test.ts +43 -0
- package/src/components/report/__test__/use-report-designer.test.ts +108 -1
- package/src/components/report/binding-badge.ts +35 -5
- package/src/components/report/designer/drill-dialog.vue +245 -0
- package/src/components/report/designer/float-panel.vue +12 -0
- package/src/components/report/print.ts +44 -0
- package/src/components/report/report-designer.vue +35 -2
- package/src/components/report/report-viewer.vue +171 -18
- package/src/components/report/style-designer.scss +66 -0
- package/src/components/report/style-viewer.scss +40 -0
- package/src/components/report/use-report-designer.ts +8 -1
- package/src/components/report/use-report-viewer.ts +150 -11
- package/src/components/sheet/insert-image.ts +1 -1
- package/src/components/sheet/popups/export-popup.vue +1 -1
- package/src/components/sheet/popups/import.worker.ts +7 -10
- package/src/components/sheet/use-sheet-state.ts +2 -2
- package/src/report/__test__/drill.test.ts +194 -0
- package/src/report/__test__/export-xlsx.test.ts +3 -25
- package/src/report/__test__/print.test.ts +170 -0
- package/src/report/__test__/render.test.ts +26 -0
- package/src/report/drill.ts +112 -0
- package/src/report/export-xlsx.ts +5 -103
- package/src/report/index.ts +4 -1
- package/src/report/print.ts +234 -0
- package/src/report/render/aggregate.ts +28 -0
- package/src/report/types.ts +20 -0
- package/src/tools/__test__/builtin.test.ts +1 -1
- package/src/tools/download.ts +2 -2
- package/src/tools/export.worker.ts +2 -2
- package/src/types/report-designer.ts +18 -1
- package/src/types/report-viewer.ts +18 -1
|
@@ -1,22 +1,34 @@
|
|
|
1
|
+
import { buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams } from "../../report/drill.js";
|
|
1
2
|
import { renderReport, resolveFilledColWidths } from "../../report/render/index.js";
|
|
2
3
|
import { fetchTemplateRecords, resolveParamDefaults, resolveTemplateParams } from "../../report/template.js";
|
|
3
4
|
import { computed, ref, shallowRef, watch } from "vue";
|
|
5
|
+
import { cellKey } from "@veltra/sheet-core";
|
|
4
6
|
//#region src/components/report/use-report-viewer.ts
|
|
5
7
|
/**
|
|
6
8
|
* UReportViewer 的 headless 编排:参数提取 → 取数 → renderReport 展开。
|
|
7
9
|
* 不持有 DOM / 网格引用;填充快照经 `filledSnapshot` 交给组件壳应用。
|
|
10
|
+
* 下钻:openMode 'switch' 栈式切换当前层;'dialog' 由组件壳解析目标后嵌套独立查看器。
|
|
11
|
+
* 导出 / 打印始终作用于当前可见层。
|
|
8
12
|
*/
|
|
9
13
|
function useReportViewer(props) {
|
|
10
14
|
const loading = ref(false);
|
|
11
15
|
const error = shallowRef(null);
|
|
12
16
|
const filledSnapshot = shallowRef(null);
|
|
13
17
|
const filledColWidths = shallowRef(void 0);
|
|
14
|
-
const
|
|
18
|
+
const drillStack = shallowRef(null);
|
|
19
|
+
const drillHits = shallowRef(/* @__PURE__ */ new Map());
|
|
20
|
+
const currentTemplate = computed(() => {
|
|
21
|
+
const stack = drillStack.value;
|
|
22
|
+
return stack ? currentDrillLayer(stack).template : props.template;
|
|
23
|
+
});
|
|
24
|
+
const drillDepth = computed(() => (drillStack.value?.length ?? 1) - 1);
|
|
25
|
+
const canDrillBack = computed(() => drillDepth.value > 0);
|
|
26
|
+
const params = computed(() => resolveTemplateParams(currentTemplate.value));
|
|
15
27
|
const values = shallowRef({});
|
|
16
28
|
let fetchSeq = 0;
|
|
17
29
|
async function refresh() {
|
|
18
30
|
const current = ++fetchSeq;
|
|
19
|
-
const template =
|
|
31
|
+
const template = currentTemplate.value;
|
|
20
32
|
loading.value = true;
|
|
21
33
|
error.value = null;
|
|
22
34
|
const result = await fetchTemplateRecords(props.connector, template, values.value);
|
|
@@ -29,15 +41,81 @@ function useReportViewer(props) {
|
|
|
29
41
|
}
|
|
30
42
|
filledSnapshot.value = renderReport(template, result.data);
|
|
31
43
|
filledColWidths.value = template.colWidths?.length ? resolveFilledColWidths(template, result.data, template.colWidths) : void 0;
|
|
44
|
+
drillHits.value = props.resolveTemplate ? buildDrillHitMap(template, result.data) : /* @__PURE__ */ new Map();
|
|
45
|
+
}
|
|
46
|
+
/** 切层共有收尾:清填充结果与命中索引,写入新层参数并重新取数 */
|
|
47
|
+
function transitionTo(layerParams) {
|
|
48
|
+
filledSnapshot.value = null;
|
|
49
|
+
filledColWidths.value = void 0;
|
|
50
|
+
drillHits.value = /* @__PURE__ */ new Map();
|
|
51
|
+
values.value = layerParams;
|
|
52
|
+
return refresh();
|
|
53
|
+
}
|
|
54
|
+
async function resolveDrillTarget(config, record) {
|
|
55
|
+
const resolve = props.resolveTemplate;
|
|
56
|
+
if (!resolve) return null;
|
|
57
|
+
let target;
|
|
58
|
+
try {
|
|
59
|
+
target = await resolve(config.target);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
error.value = {
|
|
62
|
+
code: "DRILL_RESOLVE_FAILED",
|
|
63
|
+
message: err instanceof Error ? err.message : String(err)
|
|
64
|
+
};
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
if (!target) {
|
|
68
|
+
error.value = {
|
|
69
|
+
code: "DRILL_RESOLVE_FAILED",
|
|
70
|
+
message: `下钻目标模板解析失败:${config.target}`
|
|
71
|
+
};
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
error.value = null;
|
|
75
|
+
return {
|
|
76
|
+
template: target,
|
|
77
|
+
params: {
|
|
78
|
+
...resolveParamDefaults(resolveTemplateParams(target)),
|
|
79
|
+
...resolveDrillParams(config, record)
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
async function drillInto(config, record) {
|
|
84
|
+
const next = await resolveDrillTarget(config, record);
|
|
85
|
+
if (!next) return;
|
|
86
|
+
const base = drillStack.value ?? createDrillStack({
|
|
87
|
+
template: props.template,
|
|
88
|
+
params: values.value
|
|
89
|
+
});
|
|
90
|
+
drillStack.value = pushDrillLayer(base, {
|
|
91
|
+
template: next.template,
|
|
92
|
+
params: next.params
|
|
93
|
+
}, values.value);
|
|
94
|
+
await transitionTo(next.params);
|
|
95
|
+
}
|
|
96
|
+
async function drillBack() {
|
|
97
|
+
const stack = drillStack.value;
|
|
98
|
+
if (!stack || stack.length <= 1) return;
|
|
99
|
+
const next = popDrillLayer(stack);
|
|
100
|
+
drillStack.value = next;
|
|
101
|
+
await transitionTo({ ...currentDrillLayer(next).params });
|
|
102
|
+
}
|
|
103
|
+
function resolveDrillHit(addr) {
|
|
104
|
+
return drillHits.value.get(cellKey(addr)) ?? null;
|
|
32
105
|
}
|
|
33
106
|
function setValues(next) {
|
|
34
107
|
values.value = next;
|
|
35
108
|
refresh();
|
|
36
109
|
}
|
|
37
110
|
watch(() => props.template, () => {
|
|
111
|
+
drillStack.value = null;
|
|
112
|
+
drillHits.value = /* @__PURE__ */ new Map();
|
|
38
113
|
filledSnapshot.value = null;
|
|
39
114
|
filledColWidths.value = void 0;
|
|
40
|
-
values.value =
|
|
115
|
+
values.value = {
|
|
116
|
+
...resolveParamDefaults(params.value),
|
|
117
|
+
...props.initialValues
|
|
118
|
+
};
|
|
41
119
|
refresh();
|
|
42
120
|
}, { immediate: true });
|
|
43
121
|
return {
|
|
@@ -47,6 +125,13 @@ function useReportViewer(props) {
|
|
|
47
125
|
error,
|
|
48
126
|
filledSnapshot,
|
|
49
127
|
filledColWidths,
|
|
128
|
+
currentTemplate,
|
|
129
|
+
drillDepth,
|
|
130
|
+
canDrillBack,
|
|
131
|
+
resolveDrillHit,
|
|
132
|
+
resolveDrillTarget,
|
|
133
|
+
drillInto,
|
|
134
|
+
drillBack,
|
|
50
135
|
refresh,
|
|
51
136
|
setValues
|
|
52
137
|
};
|
|
@@ -18,7 +18,7 @@ const EXT_TO_TYPE = {
|
|
|
18
18
|
svg: "svg",
|
|
19
19
|
webp: "webp"
|
|
20
20
|
};
|
|
21
|
-
/** MIME →
|
|
21
|
+
/** MIME → sheet-core 图片类型(core/image 的 SheetImageType);MIME 为空时回落扩展名 */
|
|
22
22
|
function resolveImageType(file) {
|
|
23
23
|
const mime = file.type.trim().toLowerCase();
|
|
24
24
|
if (mime && MIME_TO_TYPE[mime]) return MIME_TO_TYPE[mime];
|
|
@@ -3,10 +3,9 @@ self.onmessage = (e) => {
|
|
|
3
3
|
const { buffer } = e.data;
|
|
4
4
|
(async () => {
|
|
5
5
|
try {
|
|
6
|
-
const
|
|
7
|
-
const hucreWb = await readXlsx(new Uint8Array(buffer), XLSX_READ_OPTIONS);
|
|
6
|
+
const { importXlsx } = await import("@veltra/sheet-core/core/io/import");
|
|
8
7
|
let lastPercent = -1;
|
|
9
|
-
const wb =
|
|
8
|
+
const wb = await importXlsx(new Uint8Array(buffer), (done, total) => {
|
|
10
9
|
const percent = total > 0 ? Math.floor(done / total * 10) : 10;
|
|
11
10
|
if (percent !== lastPercent || done === total) {
|
|
12
11
|
lastPercent = percent;
|
|
@@ -78,8 +78,8 @@ function useSheetState(props, emit, hooks) {
|
|
|
78
78
|
];
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
* 工作簿内容被结构性替换后同步(如导入 xlsx 的
|
|
82
|
-
*
|
|
81
|
+
* 工作簿内容被结构性替换后同步(如导入 xlsx 的 replaceWorkbookWithSnapshots):
|
|
82
|
+
* 整簿替换未必触发 active-sheet-change(同 index),需显式同步 tabs、
|
|
83
83
|
* 重绑 sheet 事件并重建网格。
|
|
84
84
|
*/
|
|
85
85
|
function syncFromWorkbook() {
|
package/dist/index.d.ts
CHANGED
|
@@ -4,18 +4,20 @@ import _sfc_main from "./components/report/report-designer.js";
|
|
|
4
4
|
import { SheetContext, createSheetContext } from "./tools/context.js";
|
|
5
5
|
import { SheetTool, SheetToolGroup, SheetToolPopupType, defaultToolRegistry, registerTool, unregisterTool } from "./tools/registry.js";
|
|
6
6
|
import { SheetEmits, SheetExposed, SheetProps, _SheetExposed } from "./types/sheet.js";
|
|
7
|
-
import { ConditionalOperator, ConditionalRule, DatasetCatalogItem, DatasetField, DatasetRecords, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, ReportAggregate, ReportBinding, ReportExpand, ReportPreset, ReportSort } from "./report/types.js";
|
|
7
|
+
import { ConditionalOperator, ConditionalRule, DatasetCatalogItem, DatasetField, DatasetRecords, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, ReportAggregate, ReportBinding, ReportDrillConfig, ReportExpand, ReportPreset, ReportSort, ReportTemplateListItem } from "./report/types.js";
|
|
8
8
|
import { InferParentOptions, ListParentCandidateOptions, REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, prefersGroupParent, presetBindingPatch, presetStillApplies, setBindingCatalog } from "./report/binding.js";
|
|
9
9
|
import { ConditionalEvalContext, evaluateCondition, evaluateConditionalStyle, resolveRuleCompareValue, toComparableNumber } from "./report/rules/evaluate.js";
|
|
10
10
|
import { buildParamDefs, extractParamIds, resolveBoundDatasetParams } from "./report/params.js";
|
|
11
|
-
import { ReportColWidthEntry,
|
|
11
|
+
import { ReportColWidthEntry, exportFilledReportXlsx } from "./report/export-xlsx.js";
|
|
12
12
|
import { mapFilledColWidths } from "./report/render/builder.js";
|
|
13
13
|
import { renderReport, resolveFilledColWidths } from "./report/render/index.js";
|
|
14
14
|
import { ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, QueryResult, Result, createHttpConnector, resolvePortOnTypeChange } from "./report/connector.js";
|
|
15
15
|
import { IncompatibleTemplateVersionError, REPORT_TEMPLATE_VERSION, ReportDatasetDef, ReportTemplate, assertCompatibleTemplateVersion, createReportTemplate, fetchTemplateRecords, getBoundDatasetIds, getTemplateDatasets, resolveParamDefaults, resolveTemplateParams } from "./report/template.js";
|
|
16
16
|
import { parseDateRangeValue, patchParamValues, resolveNumberParamValue } from "./report/filter-bar.js";
|
|
17
|
+
import { DrillHit, DrillStack, DrillStackLayer, ResolveReportTemplate, buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams } from "./report/drill.js";
|
|
18
|
+
import { ReportPrintOptions, buildFilledReportPrintHtml } from "./report/print.js";
|
|
17
19
|
import "./report/index.js";
|
|
18
20
|
import { ReportViewerExposed, ReportViewerProps, _ReportViewerExposed } from "./types/report-viewer.js";
|
|
19
21
|
import { ReportDesignerEmits, ReportDesignerExposed, ReportDesignerProps, _ReportDesignerExposed } from "./types/report-designer.js";
|
|
20
22
|
import "./types/index.js";
|
|
21
|
-
export { type ConditionalEvalContext, ConditionalOperator, ConditionalRule, ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, DatasetCatalogItem, DatasetField, DatasetRecords, IncompatibleTemplateVersionError, InferParentOptions, ListParentCandidateOptions, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, QueryResult, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, ReportAggregate, ReportBinding, ReportColWidthEntry, ReportDatasetDef, type ReportDesignerEmits, type ReportDesignerExposed, type ReportDesignerProps, ReportExpand, ReportPreset, ReportSort, ReportTemplate, type ReportViewerExposed, type ReportViewerProps, Result, type SheetContext, type SheetEmits, type SheetExposed, type SheetProps, type SheetTool, type SheetToolGroup, type SheetToolPopupType, _sfc_main as UReportDesigner, _sfc_main$1 as UReportViewer, _sfc_main$2 as USheet, type _ReportDesignerExposed, type _ReportViewerExposed, type _SheetExposed, applyReportPreset, assertCompatibleTemplateVersion,
|
|
23
|
+
export { type ConditionalEvalContext, ConditionalOperator, ConditionalRule, ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, DatasetCatalogItem, DatasetField, DatasetRecords, DrillHit, DrillStack, DrillStackLayer, IncompatibleTemplateVersionError, InferParentOptions, ListParentCandidateOptions, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, QueryResult, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, ReportAggregate, ReportBinding, ReportColWidthEntry, ReportDatasetDef, type ReportDesignerEmits, type ReportDesignerExposed, type ReportDesignerProps, ReportDrillConfig, ReportExpand, ReportPreset, ReportPrintOptions, ReportSort, ReportTemplate, ReportTemplateListItem, type ReportViewerExposed, type ReportViewerProps, ResolveReportTemplate, Result, type SheetContext, type SheetEmits, type SheetExposed, type SheetProps, type SheetTool, type SheetToolGroup, type SheetToolPopupType, _sfc_main as UReportDesigner, _sfc_main$1 as UReportViewer, _sfc_main$2 as USheet, type _ReportDesignerExposed, type _ReportViewerExposed, type _SheetExposed, applyReportPreset, assertCompatibleTemplateVersion, buildDrillHitMap, buildFilledReportPrintHtml, buildParamDefs, createDrillStack, createHttpConnector, createReportBinding, createReportTemplate, createSheetContext, currentDrillLayer, defaultToolRegistry, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, popDrillLayer, prefersGroupParent, presetBindingPatch, presetStillApplies, pushDrillLayer, registerTool, renderReport, resolveBoundDatasetParams, resolveDrillParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber, unregisterTool };
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,11 @@ import { defaultToolRegistry, registerTool, unregisterTool } from "./tools/regis
|
|
|
2
2
|
import "./tools/builtin.js";
|
|
3
3
|
import { createSheetContext } from "./tools/context.js";
|
|
4
4
|
import _sfc_main$2 from "./components/sheet/sheet.js";
|
|
5
|
-
import {
|
|
5
|
+
import { exportFilledReportXlsx } from "./report/export-xlsx.js";
|
|
6
|
+
import { buildFilledReportPrintHtml } from "./report/print.js";
|
|
6
7
|
import { parseDateRangeValue, patchParamValues, resolveNumberParamValue } from "./report/filter-bar.js";
|
|
7
8
|
import { REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, prefersGroupParent, presetBindingPatch, presetStillApplies, setBindingCatalog } from "./report/binding.js";
|
|
9
|
+
import { buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams } from "./report/drill.js";
|
|
8
10
|
import { evaluateCondition, evaluateConditionalStyle, resolveRuleCompareValue, toComparableNumber } from "./report/rules/evaluate.js";
|
|
9
11
|
import { mapFilledColWidths } from "./report/render/builder.js";
|
|
10
12
|
import { renderReport, resolveFilledColWidths } from "./report/render/index.js";
|
|
@@ -13,4 +15,4 @@ import { IncompatibleTemplateVersionError, REPORT_TEMPLATE_VERSION, assertCompat
|
|
|
13
15
|
import _sfc_main$1 from "./components/report/report-viewer.js";
|
|
14
16
|
import { DEFAULT_CONNECTION_PORTS, createHttpConnector, resolvePortOnTypeChange } from "./report/connector.js";
|
|
15
17
|
import _sfc_main from "./components/report/report-designer.js";
|
|
16
|
-
export { DEFAULT_CONNECTION_PORTS, IncompatibleTemplateVersionError, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, _sfc_main as UReportDesigner, _sfc_main$1 as UReportViewer, _sfc_main$2 as USheet, applyReportPreset, assertCompatibleTemplateVersion,
|
|
18
|
+
export { DEFAULT_CONNECTION_PORTS, IncompatibleTemplateVersionError, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, _sfc_main as UReportDesigner, _sfc_main$1 as UReportViewer, _sfc_main$2 as USheet, applyReportPreset, assertCompatibleTemplateVersion, buildDrillHitMap, buildFilledReportPrintHtml, buildParamDefs, createDrillStack, createHttpConnector, createReportBinding, createReportTemplate, createSheetContext, currentDrillLayer, defaultToolRegistry, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, popDrillLayer, prefersGroupParent, presetBindingPatch, presetStillApplies, pushDrillLayer, registerTool, renderReport, resolveBoundDatasetParams, resolveDrillParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber, unregisterTool };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DatasetRecords, ParamValues, ReportDrillConfig } from "./types.js";
|
|
2
|
+
import { ReportTemplate } from "./template.js";
|
|
3
|
+
import { SheetSnapshot } from "@veltra/sheet-core";
|
|
4
|
+
//#region src/report/drill.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* 宿主模板解析契约:按下钻 target 引用取回目标模板(允许同步/异步)。
|
|
7
|
+
* 失败抛错——查看器提示可读错误并停留当前报;设计器配置对话框据此解析目标模板查询参数。
|
|
8
|
+
*/
|
|
9
|
+
type ResolveReportTemplate = (ref: string) => ReportTemplate | Promise<ReportTemplate>;
|
|
10
|
+
/**
|
|
11
|
+
* 按下钻映射从该格对应记录取值,生成详情报 Filter Bar 参数值。
|
|
12
|
+
* 记录缺字段(值为 `undefined`)时跳过对应参数,由详情报回退默认值;空映射返回空参数。
|
|
13
|
+
*/
|
|
14
|
+
declare function resolveDrillParams(config: ReportDrillConfig, record: Record<string, unknown>): ParamValues;
|
|
15
|
+
/** 下钻栈层:一张报表模板 + 当时 Filter Bar 参数值(回退时据此恢复并重新取数) */
|
|
16
|
+
interface DrillStackLayer {
|
|
17
|
+
template: ReportTemplate;
|
|
18
|
+
params: ParamValues;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 下钻栈:自根(初始报表)到顶的层序列,至少一层。
|
|
22
|
+
* 只经下方纯函数做不可变更新(返回新栈),便于组件层直接挂响应式。
|
|
23
|
+
*/
|
|
24
|
+
type DrillStack = DrillStackLayer[];
|
|
25
|
+
/** 以初始报表为根层创建下钻栈 */
|
|
26
|
+
declare function createDrillStack(root: DrillStackLayer): DrillStack;
|
|
27
|
+
/**
|
|
28
|
+
* 压入详情报新层并使其成为当前层;`currentParams` 把当前层参数定格为离开时的值
|
|
29
|
+
* (缺省保留原值)。指向自身或成环不做检测,照常压栈,靠 pop 逐级退出。
|
|
30
|
+
*/
|
|
31
|
+
declare function pushDrillLayer(stack: DrillStack, next: DrillStackLayer, currentParams?: ParamValues): DrillStack;
|
|
32
|
+
/** 弹出当前层返回上一层;仅剩根层时原样返回(查看器始终保留一张报表) */
|
|
33
|
+
declare function popDrillLayer(stack: DrillStack): DrillStack;
|
|
34
|
+
/** 当前层(栈顶) */
|
|
35
|
+
declare function currentDrillLayer(stack: DrillStack): DrillStackLayer;
|
|
36
|
+
/** 下钻命中:物理格对应的下钻配置与该格记录 */
|
|
37
|
+
interface DrillHit {
|
|
38
|
+
config: ReportDrillConfig;
|
|
39
|
+
record: Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 构建填充报表的物理格 → 下钻命中索引(每次成功取数后重建)。
|
|
43
|
+
* 仅含配了下钻的绑定格落点(含分组/汇总格与展开后的实例格,合并跨度内每格都命中);
|
|
44
|
+
* 记录由 `resolvePlacementContext` 解析:list 明细取源数据行,分组/汇总取分组上下文。
|
|
45
|
+
*/
|
|
46
|
+
declare function buildDrillHitMap(template: SheetSnapshot, data: DatasetRecords): Map<number, DrillHit>;
|
|
47
|
+
//#endregion
|
|
48
|
+
export { DrillHit, DrillStack, DrillStackLayer, ResolveReportTemplate, buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { buildTemplateIndex } from "./render/template-index.js";
|
|
2
|
+
import { computeExpansionLayout } from "./render/coordinate.js";
|
|
3
|
+
import { AggregateIndex, resolvePlacementContext } from "./render/aggregate.js";
|
|
4
|
+
import { cellKey } from "@veltra/sheet-core";
|
|
5
|
+
//#region src/report/drill.ts
|
|
6
|
+
/**
|
|
7
|
+
* 按下钻映射从该格对应记录取值,生成详情报 Filter Bar 参数值。
|
|
8
|
+
* 记录缺字段(值为 `undefined`)时跳过对应参数,由详情报回退默认值;空映射返回空参数。
|
|
9
|
+
*/
|
|
10
|
+
function resolveDrillParams(config, record) {
|
|
11
|
+
const values = {};
|
|
12
|
+
for (const [field, paramId] of Object.entries(config.mapping)) {
|
|
13
|
+
const value = record[field];
|
|
14
|
+
if (value === void 0) continue;
|
|
15
|
+
values[paramId] = value;
|
|
16
|
+
}
|
|
17
|
+
return values;
|
|
18
|
+
}
|
|
19
|
+
/** 以初始报表为根层创建下钻栈 */
|
|
20
|
+
function createDrillStack(root) {
|
|
21
|
+
return [{
|
|
22
|
+
template: root.template,
|
|
23
|
+
params: { ...root.params }
|
|
24
|
+
}];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 压入详情报新层并使其成为当前层;`currentParams` 把当前层参数定格为离开时的值
|
|
28
|
+
* (缺省保留原值)。指向自身或成环不做检测,照常压栈,靠 pop 逐级退出。
|
|
29
|
+
*/
|
|
30
|
+
function pushDrillLayer(stack, next, currentParams) {
|
|
31
|
+
const top = stack[stack.length - 1];
|
|
32
|
+
const layers = currentParams ? [...stack.slice(0, -1), {
|
|
33
|
+
template: top.template,
|
|
34
|
+
params: { ...currentParams }
|
|
35
|
+
}] : [...stack];
|
|
36
|
+
layers.push({
|
|
37
|
+
template: next.template,
|
|
38
|
+
params: { ...next.params }
|
|
39
|
+
});
|
|
40
|
+
return layers;
|
|
41
|
+
}
|
|
42
|
+
/** 弹出当前层返回上一层;仅剩根层时原样返回(查看器始终保留一张报表) */
|
|
43
|
+
function popDrillLayer(stack) {
|
|
44
|
+
if (stack.length <= 1) return stack;
|
|
45
|
+
return stack.slice(0, -1);
|
|
46
|
+
}
|
|
47
|
+
/** 当前层(栈顶) */
|
|
48
|
+
function currentDrillLayer(stack) {
|
|
49
|
+
return stack[stack.length - 1];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 构建填充报表的物理格 → 下钻命中索引(每次成功取数后重建)。
|
|
53
|
+
* 仅含配了下钻的绑定格落点(含分组/汇总格与展开后的实例格,合并跨度内每格都命中);
|
|
54
|
+
* 记录由 `resolvePlacementContext` 解析:list 明细取源数据行,分组/汇总取分组上下文。
|
|
55
|
+
*/
|
|
56
|
+
function buildDrillHitMap(template, data) {
|
|
57
|
+
const hits = /* @__PURE__ */ new Map();
|
|
58
|
+
const index = buildTemplateIndex(template);
|
|
59
|
+
const layout = computeExpansionLayout(index, data);
|
|
60
|
+
const aggregateIndex = new AggregateIndex(data);
|
|
61
|
+
for (const placement of layout.placements) {
|
|
62
|
+
const config = placement.binding?.drill;
|
|
63
|
+
if (!config) continue;
|
|
64
|
+
const record = resolvePlacementContext(placement, index, data, aggregateIndex);
|
|
65
|
+
if (!record) continue;
|
|
66
|
+
const hit = {
|
|
67
|
+
config,
|
|
68
|
+
record
|
|
69
|
+
};
|
|
70
|
+
for (let row = placement.physical.start.row; row <= placement.physical.end.row; row++) for (let col = placement.physical.start.col; col <= placement.physical.end.col; col++) hits.set(cellKey({
|
|
71
|
+
row,
|
|
72
|
+
col
|
|
73
|
+
}), hit);
|
|
74
|
+
}
|
|
75
|
+
return hits;
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
export { buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams };
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { Sheet } from "@veltra/sheet-core";
|
|
2
|
-
import { ColumnDef } from "hucre";
|
|
3
2
|
//#region src/report/export-xlsx.d.ts
|
|
4
3
|
/** 列宽条目:模型列索引 → 像素宽(与 SheetSnapshot.colWidths 同构) */
|
|
5
4
|
type ReportColWidthEntry = readonly [number, number];
|
|
6
|
-
/** VTable 像素列宽 → Excel 字符宽度(近似换算) */
|
|
7
|
-
declare function pxToExcelColWidth(px: number): number;
|
|
8
|
-
/** 从列宽条目构建 hucre ColumnDef */
|
|
9
|
-
declare function buildColumnDefs(colWidths: ReadonlyArray<ReportColWidthEntry>): ColumnDef[];
|
|
10
5
|
/**
|
|
11
|
-
* 将已填充的 Sheet(Filled Report)导出为保真 XLSX(合并 / 样式 / 行高 /
|
|
6
|
+
* 将已填充的 Sheet(Filled Report)导出为保真 XLSX(合并 / 样式 / 行高 / 列宽 / 浮动图)。
|
|
7
|
+
* 组装与序列化委托 sheet-core `exportSheetXlsx`(与 `exportWorkbookXlsx` 同一套单表逻辑);
|
|
12
8
|
* 条件样式颜色已在 renderReport 展开阶段打平进 StylePool(ADR-0001 决策 2)。
|
|
13
9
|
* 列宽取自 sheet 模型(`getColWidths`)。
|
|
14
10
|
*/
|
|
15
11
|
declare function exportFilledReportXlsx(sheet: Sheet): Promise<Uint8Array>;
|
|
16
12
|
//#endregion
|
|
17
|
-
export { ReportColWidthEntry,
|
|
13
|
+
export { ReportColWidthEntry, exportFilledReportXlsx };
|
|
@@ -1,92 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { writeXlsx } from "hucre/xlsx";
|
|
1
|
+
import { exportSheetXlsx } from "@veltra/sheet-core/core/io/export";
|
|
3
2
|
//#region src/report/export-xlsx.ts
|
|
4
|
-
/** 像素 → Excel points */
|
|
5
|
-
function pxToPt(px) {
|
|
6
|
-
return px * .75;
|
|
7
|
-
}
|
|
8
|
-
/** VTable 像素列宽 → Excel 字符宽度(近似换算) */
|
|
9
|
-
function pxToExcelColWidth(px) {
|
|
10
|
-
return Math.max(1, Math.round((px - 5) / 7));
|
|
11
|
-
}
|
|
12
|
-
/** 从列宽条目构建 hucre ColumnDef */
|
|
13
|
-
function buildColumnDefs(colWidths) {
|
|
14
|
-
if (colWidths.length === 0) return [];
|
|
15
|
-
const maxCol = Math.max(...colWidths.map(([col]) => col));
|
|
16
|
-
const columns = Array.from({ length: maxCol + 1 }, () => ({}));
|
|
17
|
-
for (const [col, width] of colWidths) columns[col] = { width: pxToExcelColWidth(width) };
|
|
18
|
-
return columns;
|
|
19
|
-
}
|
|
20
3
|
/**
|
|
21
|
-
* 将已填充的 Sheet(Filled Report)导出为保真 XLSX(合并 / 样式 / 行高 /
|
|
4
|
+
* 将已填充的 Sheet(Filled Report)导出为保真 XLSX(合并 / 样式 / 行高 / 列宽 / 浮动图)。
|
|
5
|
+
* 组装与序列化委托 sheet-core `exportSheetXlsx`(与 `exportWorkbookXlsx` 同一套单表逻辑);
|
|
22
6
|
* 条件样式颜色已在 renderReport 展开阶段打平进 StylePool(ADR-0001 决策 2)。
|
|
23
7
|
* 列宽取自 sheet 模型(`getColWidths`)。
|
|
24
8
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
let maxRow = -1;
|
|
28
|
-
let maxCol = -1;
|
|
29
|
-
for (const [addr] of sheet.store.entries()) {
|
|
30
|
-
if (addr.row > maxRow) maxRow = addr.row;
|
|
31
|
-
if (addr.col > maxCol) maxCol = addr.col;
|
|
32
|
-
}
|
|
33
|
-
for (const [row] of sheet.getRowHeights()) if (row > maxRow) maxRow = row;
|
|
34
|
-
for (const [col] of widths) if (col > maxCol) maxCol = col;
|
|
35
|
-
const rows = maxRow < 0 ? [] : Array.from({ length: maxRow + 1 }, () => Array.from({ length: maxCol + 1 }, () => null));
|
|
36
|
-
const cells = /* @__PURE__ */ new Map();
|
|
37
|
-
for (const [addr, data] of sheet.store.entries()) {
|
|
38
|
-
const row = rows[addr.row];
|
|
39
|
-
const key = `${addr.row},${addr.col}`;
|
|
40
|
-
const cell = {};
|
|
41
|
-
const style = sheet.getEffectiveStyle(addr);
|
|
42
|
-
if (style) cell.style = styleToHucre(style);
|
|
43
|
-
if (data.f != null && data.f !== "") {
|
|
44
|
-
cell.formula = data.f;
|
|
45
|
-
if (data.v != null) cell.formulaResult = data.v;
|
|
46
|
-
row[addr.col] = data.v ?? null;
|
|
47
|
-
cells.set(key, cell);
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
if (data.t === "e") {
|
|
51
|
-
cell.value = data.v;
|
|
52
|
-
cell.type = "error";
|
|
53
|
-
row[addr.col] = null;
|
|
54
|
-
cells.set(key, cell);
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
if (data.t === "d") {
|
|
58
|
-
cell.value = data.v;
|
|
59
|
-
cell.type = "number";
|
|
60
|
-
cell.style = {
|
|
61
|
-
...cell.style,
|
|
62
|
-
numFmt: "yyyy-mm-dd"
|
|
63
|
-
};
|
|
64
|
-
row[addr.col] = null;
|
|
65
|
-
cells.set(key, cell);
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
row[addr.col] = data.v ?? null;
|
|
69
|
-
if (Object.keys(cell).length > 0) cells.set(key, cell);
|
|
70
|
-
}
|
|
71
|
-
const writeSheet = {
|
|
72
|
-
name: sheet.name || "报表",
|
|
73
|
-
rows,
|
|
74
|
-
...cells.size > 0 ? { cells } : {},
|
|
75
|
-
...sheet.merges.size > 0 ? { merges: sheet.merges.getMerges().map((range) => rangeToHucre(range)) } : {},
|
|
76
|
-
...widths.length > 0 ? { columns: buildColumnDefs(widths) } : {}
|
|
77
|
-
};
|
|
78
|
-
const frozen = sheet.frozen;
|
|
79
|
-
if (frozen.rows > 0 || frozen.cols > 0) writeSheet.freezePane = {
|
|
80
|
-
rows: frozen.rows,
|
|
81
|
-
columns: frozen.cols
|
|
82
|
-
};
|
|
83
|
-
const rowDefs = /* @__PURE__ */ new Map();
|
|
84
|
-
for (const [row, height] of sheet.getRowHeights()) rowDefs.set(row, { height: pxToPt(height) });
|
|
85
|
-
if (rowDefs.size > 0) writeSheet.rowDefs = rowDefs;
|
|
86
|
-
return writeXlsx({
|
|
87
|
-
sheets: [writeSheet],
|
|
88
|
-
activeSheet: 0
|
|
89
|
-
});
|
|
9
|
+
function exportFilledReportXlsx(sheet) {
|
|
10
|
+
return exportSheetXlsx(sheet, { fallbackName: "报表" });
|
|
90
11
|
}
|
|
91
12
|
//#endregion
|
|
92
|
-
export {
|
|
13
|
+
export { exportFilledReportXlsx };
|
package/dist/report/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { ConditionalOperator, ConditionalRule, DatasetCatalogItem, DatasetField, DatasetRecords, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, ReportAggregate, ReportBinding, ReportExpand, ReportPreset, ReportSort } from "./types.js";
|
|
1
|
+
import { ConditionalOperator, ConditionalRule, DatasetCatalogItem, DatasetField, DatasetRecords, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, ReportAggregate, ReportBinding, ReportDrillConfig, ReportExpand, ReportPreset, ReportSort, ReportTemplateListItem } from "./types.js";
|
|
2
2
|
import { InferParentOptions, ListParentCandidateOptions, REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, prefersGroupParent, presetBindingPatch, presetStillApplies, setBindingCatalog } from "./binding.js";
|
|
3
3
|
import { ConditionalEvalContext, evaluateCondition, evaluateConditionalStyle, resolveRuleCompareValue, toComparableNumber } from "./rules/evaluate.js";
|
|
4
4
|
import "./rules/index.js";
|
|
5
5
|
import { buildParamDefs, extractParamIds, resolveBoundDatasetParams } from "./params.js";
|
|
6
|
-
import { ReportColWidthEntry,
|
|
6
|
+
import { ReportColWidthEntry, exportFilledReportXlsx } from "./export-xlsx.js";
|
|
7
7
|
import { mapFilledColWidths } from "./render/builder.js";
|
|
8
8
|
import { renderReport, resolveFilledColWidths } from "./render/index.js";
|
|
9
9
|
import { ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, QueryResult, Result, createHttpConnector, resolvePortOnTypeChange } from "./connector.js";
|
|
10
10
|
import { IncompatibleTemplateVersionError, REPORT_TEMPLATE_VERSION, ReportDatasetDef, ReportTemplate, assertCompatibleTemplateVersion, createReportTemplate, fetchTemplateRecords, getBoundDatasetIds, getTemplateDatasets, resolveParamDefaults, resolveTemplateParams } from "./template.js";
|
|
11
11
|
import { parseDateRangeValue, patchParamValues, resolveNumberParamValue } from "./filter-bar.js";
|
|
12
|
-
|
|
12
|
+
import { DrillHit, DrillStack, DrillStackLayer, ResolveReportTemplate, buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams } from "./drill.js";
|
|
13
|
+
import { ReportPrintOptions, buildFilledReportPrintHtml } from "./print.js";
|
|
14
|
+
export { type ConditionalEvalContext, ConditionalOperator, ConditionalRule, ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, DatasetCatalogItem, DatasetField, DatasetRecords, DrillHit, DrillStack, DrillStackLayer, IncompatibleTemplateVersionError, InferParentOptions, ListParentCandidateOptions, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, QueryResult, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, ReportAggregate, ReportBinding, ReportColWidthEntry, ReportDatasetDef, ReportDrillConfig, ReportExpand, ReportPreset, ReportPrintOptions, ReportSort, ReportTemplate, ReportTemplateListItem, ResolveReportTemplate, Result, applyReportPreset, assertCompatibleTemplateVersion, buildDrillHitMap, buildFilledReportPrintHtml, buildParamDefs, createDrillStack, createHttpConnector, createReportBinding, createReportTemplate, currentDrillLayer, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, popDrillLayer, prefersGroupParent, presetBindingPatch, presetStillApplies, pushDrillLayer, renderReport, resolveBoundDatasetParams, resolveDrillParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Sheet } from "@veltra/sheet-core";
|
|
2
|
+
//#region src/report/print.d.ts
|
|
3
|
+
/** 报表打印选项 */
|
|
4
|
+
interface ReportPrintOptions {
|
|
5
|
+
/** 打印文档标题(打印对话框标题 / 另存 PDF 文件名);缺省取 sheet 名,再回落「报表」 */
|
|
6
|
+
title?: string;
|
|
7
|
+
/** 纸张方向(@page size),默认 portrait */
|
|
8
|
+
orientation?: 'portrait' | 'landscape';
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 将已填充的 Sheet(Filled Report)构建为打印专用 HTML 文档(纯 TS、headless、无 DOM)。
|
|
12
|
+
*
|
|
13
|
+
* 路线说明:网格渲染层是 canvas + 虚拟滚动(视口外不绘制),无法直接 window.print;
|
|
14
|
+
* 这里从模型单一事实源(与 exportFilledReportXlsx 同一读取路径)重建 `<table>`——
|
|
15
|
+
* 矢量文字清晰、浏览器原生分页、合并格天然映射 rowspan/colspan。
|
|
16
|
+
*
|
|
17
|
+
* 保真范围:值 / 合并 / 有效样式(fill + border + font + align/wrap,条件样式已在
|
|
18
|
+
* 展开阶段打平进 StylePool)/ 行高 / 列宽 / 浮动图(data URL 内嵌,跨页被裁剪属预期)。
|
|
19
|
+
* 与 Excel 默认一致:不打印屏幕网格线(仅模型显式边框)。
|
|
20
|
+
*/
|
|
21
|
+
declare function buildFilledReportPrintHtml(sheet: Sheet, options?: ReportPrintOptions): string;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { ReportPrintOptions, buildFilledReportPrintHtml };
|