Skip to content

Commit ddec974

Browse files
feat(datagrid-web): add type and format to ds export request
1 parent dc9763d commit ddec974

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

packages/pluggableWidgets/datagrid-web/src/Datagrid.xml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,22 +121,24 @@
121121
<enumerationValue key="boolean">Boolean</enumerationValue>
122122
</enumerationValues>
123123
</property>
124-
<property key="exportNumberFormat" type="textTemplate" required="false">
124+
<property key="exportNumberFormat" type="expression" required="false">
125125
<caption>Export number format</caption>
126126
<description>
127127
Optional Excel number format string to apply when exporting numeric values.
128128
You can use any valid SheetJS number format, including currency, percentage, or custom patterns
129129
(e.g. "#,##0.00", "$0.00", "0.00%").
130130
See full syntax reference here: https://docs.sheetjs.com/docs/csf/features/nf/
131131
</description>
132+
<returnType type="String" />
132133
</property>
133-
<property key="exportDateFormat" type="textTemplate" required="false">
134+
<property key="exportDateFormat" type="expression" required="false">
134135
<caption>Export date format</caption>
135136
<description>
136137
Optional Excel date format string to apply when exporting Date or DateTime values.
137138
Follows JavaScript date format conventions supported by SheetJS
138139
(e.g. "yyyy-mm-dd", "dd/mm/yyyy hh:mm", "mmm d, yyyy").
139140
</description>
141+
<returnType type="String" />
140142
</property>
141143
<property key="header" type="textTemplate" required="false">
142144
<caption>Caption</caption>

packages/pluggableWidgets/datagrid-web/src/features/data-export/DSExportRequest.ts

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { isAvailable } from "@mendix/widget-plugin-platform/framework/is-available";
22
import Big from "big.js";
3-
import { ListValue, ObjectItem, ValueStatus } from "mendix";
3+
import { DynamicValue, ListValue, ObjectItem, ValueStatus } from "mendix";
44
import { createNanoEvents, Emitter, Unsubscribe } from "nanoevents";
55
import { ColumnsType, ShowContentAsEnum } from "../../../typings/DatagridProps";
66

7-
/** Represents a single Excel cell (SheetJS compatible, simplified) */
7+
/** Represents a single Excel cell (SheetJS compatible) */
88
interface ExcelCell {
99
/** Cell type: 's' = string, 'n' = number, 'b' = boolean, 'd' = date */
1010
t: "s" | "n" | "b" | "d";
@@ -275,13 +275,17 @@ const readers: ReadersByType = {
275275
}
276276

277277
const value = data.value;
278+
const format = getCellFormat({
279+
exportType: props.exportType,
280+
exportDateFormat: props.exportDateFormat,
281+
exportNumberFormat: props.exportNumberFormat
282+
});
278283

279284
if (value instanceof Date) {
280285
return {
281-
t: "d", // date cell
286+
t: "d",
282287
v: value,
283-
z: "dd/mm/yyyy hh:mm", // Excel date format
284-
w: value.toISOString().split("T")[0] // human-readable fallback
288+
z: format
285289
};
286290
}
287291

@@ -293,22 +297,18 @@ const readers: ReadersByType = {
293297
};
294298
}
295299

296-
// Number (Big or JS number)
297300
if (value instanceof Big || typeof value === "number") {
298301
const num = value instanceof Big ? value.toNumber() : value;
299302
return {
300303
t: "n",
301304
v: num,
302-
z: '"$"#,##0.00_);\\("$"#,##0.00\\)',
303-
w: num.toLocaleString(undefined, { minimumFractionDigits: 2 })
305+
z: format
304306
};
305307
}
306308

307-
// Default: string (ensure fallback is a string)
308309
return {
309310
t: "s",
310-
v: data.displayValue ?? "",
311-
w: data.displayValue ?? ""
311+
v: data.displayValue ?? ""
312312
};
313313
},
314314

@@ -321,23 +321,49 @@ const readers: ReadersByType = {
321321

322322
switch (data.status) {
323323
case "available":
324-
return { t: "s", v: data.value ?? "", w: data.value ?? "" };
324+
const format = getCellFormat({
325+
exportType: props.exportType,
326+
exportDateFormat: props.exportDateFormat,
327+
exportNumberFormat: props.exportNumberFormat
328+
});
329+
return { t: "s", v: data.value ?? "", z: format };
325330
case "unavailable":
326-
return { t: "s", v: "n/a", w: "n/a" };
331+
return { t: "s", v: "n/a" };
327332
default:
328333
return makeEmptyCell();
329334
}
330335
},
331336

332337
customContent(item, props) {
333338
const value = props.exportValue?.get(item).value ?? "";
334-
return { t: "s", v: value, w: value };
339+
const format = getCellFormat({
340+
exportType: props.exportType,
341+
exportDateFormat: props.exportDateFormat,
342+
exportNumberFormat: props.exportNumberFormat
343+
});
344+
return { t: "s", v: value, z: format };
335345
}
336346
};
337347

338-
// Helper for empty cells
339348
function makeEmptyCell(): ExcelCell {
340-
return { t: "s", v: "", w: "" };
349+
return { t: "s", v: "" };
350+
}
351+
352+
interface DataExportProps {
353+
exportType: "text" | "number" | "date" | "boolean";
354+
exportDateFormat?: DynamicValue<string>;
355+
exportNumberFormat?: DynamicValue<string>;
356+
}
357+
358+
function getCellFormat({ exportType, exportDateFormat, exportNumberFormat }: DataExportProps): string | undefined {
359+
switch (exportType) {
360+
case "date":
361+
return exportDateFormat?.status === "available" ? exportDateFormat.value : "mm/dd/yyyy";
362+
case "number":
363+
return exportNumberFormat?.status === "available" ? exportNumberFormat.value : undefined;
364+
default:
365+
return undefined;
366+
}
341367
}
342368

343369
function createRowReader(columns: ColumnsType[]): RowReader {

0 commit comments

Comments
 (0)