xlvane 1.2.3 → 1.3.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.
@@ -1,4 +1,4 @@
1
- import { $t as drawingParts, A as limitExceeded, At as nameScopeKey, Bt as checkKeyText, C as Bytes, Ct as relationshipsPartName, D as TAIL_BYTES, Dt as normalizeTable, E as NotLoaded, Et as TABLE_CONTENT_TYPE, F as validateLocalHeaders, Gt as printXml, Ht as resolveLimits, I as WarningCollector, It as normalizeStyle, K as SheetRels, Kt as sheetProtectionXml, L as sheetNotFound, N as readCentralDirectory, O as checkSource$1, Ot as checkDefinedName, P as unsupported, Q as createSharedStrings, Qt as MediaParts, R as createWorksheetParser, S as workbookPartsToLoad, St as openPackage, T as HEAD_BYTES, Tn as clip, Tt as zipNameToPartName, Vt as checkOutputPositions, Wt as printNames, X as cellXml, Xt as DRAWING_CONTENT_TYPE, Y as buildStyles, Z as contentTypesXml, Zt as IMAGE_CONTENT_TYPES, _ as isoDate, _n as corePropertiesXml, _t as FormulaGroups, a as DATE_FORMAT, an as classifyRelationship, cn as MAX_ROWS, ct as sheetHead, d as convertCellInput, dt as sheetTail, f as createWorkbook, gn as appPropertiesXml, gt as workbookXml, h as detectHeader, hn as CORE_PROPERTIES_PART, ht as workbookRelsXml, i as readOptions, it as noteParts, j as locateCentralDirectory, jn as XlvError, k as corrupt, kt as checkUniqueName, ln as columnLetters, lt as sheetRelsPartName, mn as APP_PROPERTIES_PART, n as oneOfOption, nn as resolveImage, nt as hyperlinksXml, o as DATE_TIME_FORMAT, ot as rootRelsXml, p as sortedNotes, pt as tableParts, rt as nameTitles, sn as MAX_COLUMNS, st as rowStart, tn as metricsOf, u as checkBookViews, un as formatCellRef, ut as sheetRulesXml, v as analyzeWorkbook, w as CORRUPT_HINT, wt as partKey, xn as createXmlByteStreamParser, y as readNotes, yt as crc32, zt as DEFAULT_READ_LIMITS } from "./options-Cw7OraxE.js";
1
+ import { $t as metricsOf, A as checkSource$1, B as createWorksheetParser, Bt as resolveLimits, Cn as CORE_PROPERTIES_PART, Ct as relationshipsPartName, D as HEAD_BYTES, Dt as checkUniqueName, E as CORRUPT_HINT, Et as checkDefinedName, F as readCentralDirectory, Ht as printNames, I as unsupported, Jt as DRAWING_CONTENT_TYPE, K as SheetRels, L as validateLocalHeaders, Lt as DEFAULT_READ_LIMITS, M as limitExceeded, N as locateCentralDirectory, Nn as clip, O as NotLoaded, Ot as nameScopeKey, Pt as normalizeStyle, Q as createSharedStrings, R as WarningCollector, Rt as checkKeyText, Sn as APP_PROPERTIES_PART, St as openPackage, T as Bytes, Tn as corePropertiesXml, Tt as normalizeTable, Ut as printXml, Wt as sheetProtectionXml, X as cellXml, Xt as MediaParts, Y as buildStyles, Yt as IMAGE_CONTENT_TYPES, Z as contentTypesXml, Zt as drawingParts, _t as FormulaGroups, a as DATE_FORMAT, b as readNotes, bn as partKey, cn as chartPartXml, ct as sheetHead, d as convertCellInput, dt as sheetTail, en as resolveAnchor, f as createWorkbook, g as detectHeader, gn as formatCellRef, gt as workbookXml, hn as columnLetters, ht as workbookRelsXml, i as readOptions, in as classifyRelationship, it as noteParts, j as corrupt, k as TAIL_BYTES, kn as createXmlByteStreamParser, ln as chartSheetNames, lt as sheetRelsPartName, mn as MAX_ROWS, n as oneOfOption, nt as hyperlinksXml, o as DATE_TIME_FORMAT, on as CHART_CONTENT_TYPE, ot as rootRelsXml, p as sortedNotes, pn as MAX_COLUMNS, pt as tableParts, rt as nameTitles, sn as chartPartName, st as rowStart, tn as resolveImage, u as checkBookViews, un as resolveChartSheets, ut as sheetRulesXml, v as isoDate, w as workbookPartsToLoad, wn as appPropertiesXml, wt as TABLE_CONTENT_TYPE, xn as zipNameToPartName, y as analyzeWorkbook, yt as crc32, z as sheetNotFound, zn as XlvError, zt as checkOutputPositions } from "./options-Cxt-LJE4.js";
2
2
  import { Deflate, Inflate } from "fflate";
3
3
  // src/zip/stream.ts
4
4
  /**
@@ -952,6 +952,7 @@ function writeWorkbookStream(options) {
952
952
  "tables",
953
953
  "images",
954
954
  "background",
955
+ "charts",
955
956
  "rows"
956
957
  ], `sheets[${String(i)}]`);
957
958
  const state = s.get("state");
@@ -1058,6 +1059,7 @@ function writeWorkbookStream(options) {
1058
1059
  sheet.addImage(image, anchor, options);
1059
1060
  }
1060
1061
  if (s.has("background")) sheet.background(s.get("background"));
1062
+ for (const v of listOf("charts", "{ type: \"column\", anchor: \"E2:L18\", series: [{ values: \"Data!B2:B13\" }] }")) sheet.addChart(v);
1061
1063
  return {
1062
1064
  spec: raw,
1063
1065
  sheet,
@@ -1074,6 +1076,12 @@ function writeWorkbookStream(options) {
1074
1076
  const prepared = dynamic ? [] : specs.map(prepare);
1075
1077
  if (!dynamic && !prepared.some((p) => p.sheet.state === "visible")) throw noVisibleSheet();
1076
1078
  if (!dynamic) addNames();
1079
+ if (!dynamic) {
1080
+ const lookup = chartSheetNames(prepared.map((q) => q.sheet.name));
1081
+ for (const p of prepared) for (const c of p.sheet.chartList) resolveChartSheets(c.chart, lookup, p.sheet.name);
1082
+ }
1083
+ /** Charts in workbook order (CH-01); their parts are written once every sheet name is known. */
1084
+ const chartQueue = [];
1077
1085
  const strings = shared ? createSharedStrings() : null;
1078
1086
  const styleCache = /* @__PURE__ */ new WeakMap();
1079
1087
  const dateStyle = /* @__PURE__ */ new Map();
@@ -1228,7 +1236,19 @@ function writeWorkbookStream(options) {
1228
1236
  conditionalFormats: p.sheet.conditionalList,
1229
1237
  dataValidations: p.sheet.validationList
1230
1238
  }, n);
1231
- const drawing = drawingParts(p.sheet.imageList.map((i) => resolveImage(i, metricsOf(p.sheet.columnMap, p.sheet.rowMap))), p.sheet.backgroundImage, media, ++drawingCount, p.rels);
1239
+ const frames = p.sheet.chartList.map((c) => {
1240
+ chartQueue.push({
1241
+ chart: c.chart,
1242
+ sheet: p.sheet.name
1243
+ });
1244
+ return {
1245
+ ...resolveAnchor(c.anchor, metricsOf(p.sheet.columnMap, p.sheet.rowMap)),
1246
+ name: c.chart.name,
1247
+ description: c.chart.description,
1248
+ target: `../charts/chart${String(chartQueue.length)}.xml`
1249
+ };
1250
+ });
1251
+ const drawing = drawingParts(p.sheet.imageList.map((i) => resolveImage(i, metricsOf(p.sheet.columnMap, p.sheet.rowMap))), p.sheet.backgroundImage, media, ++drawingCount, p.rels, frames);
1232
1252
  if (drawing.part === null) drawingCount--;
1233
1253
  p.drawing = drawing.part;
1234
1254
  const sheetTables = tableParts(p.sheet.tableList, tableCount + 1, p.rels);
@@ -1345,10 +1365,16 @@ function writeWorkbookStream(options) {
1345
1365
  if (prepared.length === 0) throw new XlvError("XLV_E_INVALID_INPUT", "The workbook has no sheets.", { hint: "Add at least one sheet before closing the stream." });
1346
1366
  if (!selected) throw noVisibleSheet();
1347
1367
  if (dynamic) addNames();
1368
+ const names = chartSheetNames(prepared.map((p) => p.sheet.name));
1369
+ const chartParts = chartQueue.map((c, k) => ({
1370
+ name: chartPartName(k + 1),
1371
+ xml: chartPartXml(resolveChartSheets(c.chart, names, c.sheet), null)
1372
+ }));
1348
1373
  const app = appXml() !== null;
1349
1374
  const overrides = [
1350
1375
  ...tableTypes(),
1351
1376
  ...prepared.flatMap((p) => p.drawing === null ? [] : [[p.drawing.name, DRAWING_CONTENT_TYPE]]),
1377
+ ...chartParts.map((c) => [c.name, CHART_CONTENT_TYPE]),
1352
1378
  ...media.entries().map((m) => [m.name, IMAGE_CONTENT_TYPES[m.name.slice(m.name.lastIndexOf(".") + 1)]])
1353
1379
  ];
1354
1380
  yield {
@@ -1360,6 +1386,10 @@ function writeWorkbookStream(options) {
1360
1386
  data: encoder.encode(rootRelsXml(core !== null, app))
1361
1387
  };
1362
1388
  yield* media.entries();
1389
+ for (const c of chartParts) yield {
1390
+ name: c.name,
1391
+ data: encoder.encode(c.xml)
1392
+ };
1363
1393
  yield* closingParts();
1364
1394
  }
1365
1395
  return createZipStream(entries(), level);
@@ -81,7 +81,12 @@ interface ReadLimits {
81
81
  readonly maxXmlTextLength: number;
82
82
  /** Maximum number of elements plus attributes in a part that is parsed into a tree (workbook, styles, relationships). Default 1 000 000. */
83
83
  readonly maxXmlTreeElements: number;
84
- /** Maximum number of cells in the workbook. Default 5 000 000 (about 0.9 GB of memory; see the README). */
84
+ /**
85
+ * Maximum number of cells in the workbook. Default 5 000 000 (about 0.9 GB of memory; see the
86
+ * README). `readWorkbook` reads charts after the cells of every sheet, and their chart groups and
87
+ * series (each counted once per chart part) count against what the cells leave of this limit;
88
+ * charts over it are skipped with `XLV_W_LIMIT_REACHED`.
89
+ */
85
90
  readonly maxCells: number;
86
91
  /**
87
92
  * Maximum total length, in UTF-16 code units, of the shared strings that cells refer to, each
@@ -112,7 +117,7 @@ declare const DEFAULT_READ_LIMITS: Readonly<ReadLimits>;
112
117
  * console.log(ERROR_CODES.includes('XLV_E_SHEET_NOT_FOUND')); // true
113
118
  * ```
114
119
  */
115
- declare const ERROR_CODES: readonly ["XLV_E_INVALID_INPUT", "XLV_E_INVALID_OPTION", "XLV_E_INVALID_ARGUMENT", "XLV_E_LIMIT_EXCEEDED", "XLV_E_NOT_ZIP", "XLV_E_UNSUPPORTED_CONTAINER", "XLV_E_ZIP_CORRUPT", "XLV_E_ZIP_UNSUPPORTED", "XLV_E_XML_MALFORMED", "XLV_E_XML_DTD_FORBIDDEN", "XLV_E_XML_ENTITY_FORBIDDEN", "XLV_E_XML_ENCODING", "XLV_E_PART_MISSING", "XLV_E_PART_INVALID", "XLV_E_INVALID_CELL_REF", "XLV_E_SHEET_NOT_FOUND", "XLV_E_TABLE_NOT_FOUND", "XLV_E_FILE_READ", "XLV_E_INVALID_VALUE", "XLV_E_INVALID_STYLE", "XLV_E_INVALID_SHEET_NAME", "XLV_E_DUPLICATE_SHEET_NAME", "XLV_E_INVALID_DEFINED_NAME", "XLV_E_INVALID_HYPERLINK", "XLV_E_INVALID_TABLE", "XLV_E_INVALID_IMAGE", "XLV_E_OVERLAPPING_MERGE", "XLV_E_FILE_EXISTS", "XLV_E_FILE_WRITE", "XLV_E_HEADER_NOT_FOUND", "XLV_E_SCHEMA_INVALID", "XLV_E_ASYNC_SCHEMA", "XLV_E_INVALID_ROWS", "XLV_E_JSON_INVALID", "XLV_E_CSV_MALFORMED", "XLV_E_NOT_SUPPORTED", "XLV_E_USAGE", "XLV_E_NOT_INSTALLED", "XLV_E_INTERNAL", "XLV_E_PATH_NOT_ALLOWED"];
120
+ declare const ERROR_CODES: readonly ["XLV_E_INVALID_INPUT", "XLV_E_INVALID_OPTION", "XLV_E_INVALID_ARGUMENT", "XLV_E_LIMIT_EXCEEDED", "XLV_E_NOT_ZIP", "XLV_E_UNSUPPORTED_CONTAINER", "XLV_E_ZIP_CORRUPT", "XLV_E_ZIP_UNSUPPORTED", "XLV_E_XML_MALFORMED", "XLV_E_XML_DTD_FORBIDDEN", "XLV_E_XML_ENTITY_FORBIDDEN", "XLV_E_XML_ENCODING", "XLV_E_PART_MISSING", "XLV_E_PART_INVALID", "XLV_E_INVALID_CELL_REF", "XLV_E_SHEET_NOT_FOUND", "XLV_E_TABLE_NOT_FOUND", "XLV_E_FILE_READ", "XLV_E_INVALID_VALUE", "XLV_E_INVALID_STYLE", "XLV_E_INVALID_SHEET_NAME", "XLV_E_DUPLICATE_SHEET_NAME", "XLV_E_INVALID_DEFINED_NAME", "XLV_E_INVALID_HYPERLINK", "XLV_E_INVALID_TABLE", "XLV_E_INVALID_IMAGE", "XLV_E_INVALID_CHART", "XLV_E_OVERLAPPING_MERGE", "XLV_E_FILE_EXISTS", "XLV_E_FILE_WRITE", "XLV_E_HEADER_NOT_FOUND", "XLV_E_SCHEMA_INVALID", "XLV_E_ASYNC_SCHEMA", "XLV_E_INVALID_ROWS", "XLV_E_JSON_INVALID", "XLV_E_CSV_MALFORMED", "XLV_E_NOT_SUPPORTED", "XLV_E_USAGE", "XLV_E_NOT_INSTALLED", "XLV_E_INTERNAL", "XLV_E_PATH_NOT_ALLOWED"];
116
121
  /**
117
122
  * Every warning code xlvane can report. Warnings never stop reading; they describe something
118
123
  * in the file that the caller may want to know about. Each one is described in docs/errors.md.
@@ -1202,6 +1207,250 @@ interface ResolvedImage {
1202
1207
  readonly description: string | null;
1203
1208
  readonly hyperlink: string | null;
1204
1209
  }
1210
+ /** Markers of a resolved anchor (see {@link ResolvedImage}). */
1211
+ type ResolvedAnchor = Pick<ResolvedImage, "from" | "to" | "ext" | "editAs">;
1212
+ /**
1213
+ * Chart types `NewSheet.addChart` writes. `column` and `bar` are both a `barChart` (vertical and
1214
+ * horizontal bars), the others are `lineChart`, `pieChart`, `scatterChart` and `areaChart`
1215
+ * (docs/facts/charts.md CH-10).
1216
+ *
1217
+ * @example
1218
+ * ```ts
1219
+ * import type { ChartType } from 'xlvane';
1220
+ *
1221
+ * const type: ChartType = 'column';
1222
+ * ```
1223
+ */
1224
+ type ChartType = "column" | "bar" | "line" | "pie" | "scatter" | "area";
1225
+ /**
1226
+ * Where a chart's legend is shown (ST_LegendPos `r`, `b`, `t`, `l`; CH-27).
1227
+ *
1228
+ * @example
1229
+ * ```ts
1230
+ * import type { ChartLegendPosition } from 'xlvane';
1231
+ *
1232
+ * const legend: ChartLegendPosition = 'bottom';
1233
+ * ```
1234
+ */
1235
+ type ChartLegendPosition = "right" | "bottom" | "top" | "left";
1236
+ /**
1237
+ * One series of a chart for `NewSheet.addChart`:
1238
+ * - `values`: a sheet-qualified range of one row or one column, such as `"'Sales'!B2:B13"` (for
1239
+ * scatter charts the y values);
1240
+ * - `categories`: the same for the category labels (for scatter charts the x values);
1241
+ * - `name`: the series name, either literal text or a reference to one cell such as `"Sales!B1"`;
1242
+ * text that reads as a sheet-qualified cell reference is always taken as a reference;
1243
+ * - `color`: the colour as six hex digits `RRGGBB` (a leading `#` is accepted). Without it the
1244
+ * series takes the next colour of the default palette (CH-35). Pie charts colour each slice
1245
+ * from the palette and do not take `color`.
1246
+ *
1247
+ * @example
1248
+ * ```ts
1249
+ * import type { ChartSeriesInput } from 'xlvane';
1250
+ *
1251
+ * const series: ChartSeriesInput = { name: 'Sales!B1', categories: 'Sales!A2:A13', values: 'Sales!B2:B13', color: '2E75B6' };
1252
+ * ```
1253
+ */
1254
+ interface ChartSeriesInput {
1255
+ readonly values: string;
1256
+ readonly categories?: string;
1257
+ readonly name?: string;
1258
+ readonly color?: string;
1259
+ }
1260
+ /**
1261
+ * Options of one chart axis: its title, and for the value axis (`y`) the fixed minimum and
1262
+ * maximum of its scale (CH-26).
1263
+ *
1264
+ * @example
1265
+ * ```ts
1266
+ * import type { ChartAxisInput } from 'xlvane';
1267
+ *
1268
+ * const y: ChartAxisInput = { title: 'Revenue', min: 0, max: 100 };
1269
+ * ```
1270
+ */
1271
+ interface ChartAxisInput {
1272
+ readonly title?: string;
1273
+ readonly min?: number;
1274
+ readonly max?: number;
1275
+ }
1276
+ /**
1277
+ * A chart for `NewSheet.addChart`. `anchor` places it like a picture (see `ImageAnchorInput`).
1278
+ * `stacked` (column, bar, line and area only) stacks the series, or with `'percent'` stacks them
1279
+ * to 100 %. `legend` defaults to `'right'`; `false` leaves the legend out. `axes.x` is the
1280
+ * category axis (the x values of a scatter chart; drawn vertically for `bar`), `axes.y` the
1281
+ * value axis; pie charts have no axes. Options left out (`undefined`) take their defaults;
1282
+ * `null` is refused. A chart has 1 to 255 series (a limit of xlvane), each an object (no holes
1283
+ * in the array), a pie chart exactly one with at most 1 000 values; titles and literal series
1284
+ * names are 1 to 255 characters without control characters. `writeWorkbook` writes the cached
1285
+ * values of at most 4 000 000 cells, with at most 8 388 608 characters of cached text once
1286
+ * escaped, for all charts of a workbook together (limits of xlvane; `writeWorkbookStream` writes
1287
+ * no caches).
1288
+ * The anchor is copied when the chart is added. A sheet name that reads as a cell reference is
1289
+ * given in quotes (`'S1'!B2:B5`); without quotes it must be exactly the name of a sheet.
1290
+ *
1291
+ * @example
1292
+ * ```ts
1293
+ * import type { ChartInput } from 'xlvane';
1294
+ *
1295
+ * const chart: ChartInput = {
1296
+ * type: 'line',
1297
+ * anchor: 'E2:L18',
1298
+ * title: 'Monthly sales',
1299
+ * series: [{ name: 'Sales!B1', categories: 'Sales!A2:A13', values: 'Sales!B2:B13' }],
1300
+ * axes: { y: { title: 'EUR', min: 0 } },
1301
+ * };
1302
+ * ```
1303
+ */
1304
+ interface ChartInput {
1305
+ readonly type: ChartType;
1306
+ readonly anchor: ImageAnchorInput;
1307
+ readonly series: readonly ChartSeriesInput[];
1308
+ readonly title?: string;
1309
+ readonly legend?: ChartLegendPosition | false;
1310
+ readonly stacked?: boolean | "percent";
1311
+ readonly axes?: {
1312
+ readonly x?: {
1313
+ readonly title?: string;
1314
+ };
1315
+ readonly y?: ChartAxisInput;
1316
+ };
1317
+ /** Name of the chart object, by default "Chart N". */
1318
+ readonly name?: string;
1319
+ /** Alternative text of the chart object. */
1320
+ readonly description?: string;
1321
+ }
1322
+ /**
1323
+ * The type of a chart group as read: a {@link ChartType} (`column` or `bar` from `barDir`), or
1324
+ * `other:` and the element name for chart types xlvane does not model, such as
1325
+ * `'other:radarChart'` or `'other:bar3DChart'`.
1326
+ *
1327
+ * @example
1328
+ * ```ts
1329
+ * import type { ChartKind } from 'xlvane';
1330
+ *
1331
+ * const kinds: ChartKind[] = ['column', 'line', 'other:doughnutChart'];
1332
+ * ```
1333
+ */
1334
+ type ChartKind = ChartType | `other:${string}`;
1335
+ /**
1336
+ * A title or series name as read: literal `text`, or a `ref`erence to a cell (the formula text as
1337
+ * stored, for example `Sheet1!$B$1`; never evaluated).
1338
+ *
1339
+ * @example
1340
+ * ```ts
1341
+ * import type { ChartText } from 'xlvane';
1342
+ *
1343
+ * const show = (t: ChartText | null): string => (t === null ? '(none)' : 'text' in t ? t.text : `=${t.ref}`);
1344
+ * ```
1345
+ */
1346
+ type ChartText = {
1347
+ readonly text: string;
1348
+ } | {
1349
+ readonly ref: string;
1350
+ };
1351
+ /**
1352
+ * An axis of a chart as read: its title and the fixed `min` and `max` of its scale, or `null`
1353
+ * where the file sets none.
1354
+ *
1355
+ * @example
1356
+ * ```ts
1357
+ * import type { ChartAxis } from 'xlvane';
1358
+ *
1359
+ * const axis: ChartAxis = { title: { text: 'EUR' }, min: 0, max: null };
1360
+ * ```
1361
+ */
1362
+ interface ChartAxis {
1363
+ readonly title: ChartText | null;
1364
+ readonly min: number | null;
1365
+ readonly max: number | null;
1366
+ }
1367
+ /**
1368
+ * A series of a chart as read. `categories` and `values` are the reference texts as stored (the
1369
+ * x and y values of a scatter series), or `null` when the series has none or holds literal data.
1370
+ *
1371
+ * @example
1372
+ * ```ts
1373
+ * import { readWorkbook, type ChartSeries } from 'xlvane';
1374
+ *
1375
+ * declare const bytes: Uint8Array;
1376
+ * const series: readonly ChartSeries[] = readWorkbook(bytes).getSheet('Report').charts[0]?.series ?? [];
1377
+ * for (const s of series) console.log(s.type, s.values);
1378
+ * ```
1379
+ */
1380
+ interface ChartSeries {
1381
+ readonly type: ChartKind;
1382
+ readonly name: ChartText | null;
1383
+ readonly categories: string | null;
1384
+ readonly values: string | null;
1385
+ }
1386
+ /**
1387
+ * A chart on a worksheet (a `graphicFrame` of the sheet's drawing and its chart part, CH-02,
1388
+ * CH-04). `types` lists the chart groups of the plot area in order; a combination chart has
1389
+ * several, for example `['column', 'line']`. `stacked` comes from the first group that has a
1390
+ * grouping (`true` for `stacked`, `'percent'` for `percentStacked`, `false` otherwise; `null`
1391
+ * for pie, scatter and unmodelled types). `title` is `null` without a title and for an automatic
1392
+ * title whose text the file does not hold. `legend` is `null` without a legend. `axes.x` is the
1393
+ * category axis (the x axis of a scatter chart) and `axes.y` the value axis of the first group
1394
+ * with axes. Charts on chart sheets are not read.
1395
+ *
1396
+ * @example
1397
+ * ```ts
1398
+ * import { readWorkbook, type SheetChart } from 'xlvane';
1399
+ *
1400
+ * declare const bytes: Uint8Array;
1401
+ * const charts: readonly SheetChart[] = readWorkbook(bytes).getSheet('Report').charts;
1402
+ * for (const c of charts) console.log(c.types.join('+'), c.series.map((s) => s.values));
1403
+ * ```
1404
+ */
1405
+ interface SheetChart {
1406
+ readonly name: string;
1407
+ readonly description: string | null;
1408
+ readonly anchor: ImageAnchor;
1409
+ readonly types: readonly ChartKind[];
1410
+ readonly stacked: boolean | "percent" | null;
1411
+ readonly title: ChartText | null;
1412
+ readonly legend: ChartLegendPosition | "topRight" | null;
1413
+ readonly axes: {
1414
+ readonly x: ChartAxis | null;
1415
+ readonly y: ChartAxis | null;
1416
+ };
1417
+ readonly series: readonly ChartSeries[];
1418
+ }
1419
+ /** A validated reference: the sheet as written by the caller (resolved at write time) and the cells. */
1420
+ interface ChartRef {
1421
+ readonly sheet: string;
1422
+ readonly range: CellRange;
1423
+ /**
1424
+ * `true` when the sheet name was given without quotes although it reads as a cell or R1C1
1425
+ * reference (such as `S1!$A$1`); it must then be exactly the name of a sheet of the workbook.
1426
+ */
1427
+ readonly unquoted?: boolean;
1428
+ }
1429
+ /** A validated series. */
1430
+ interface NormalizedSeries {
1431
+ readonly name: {
1432
+ readonly text: string;
1433
+ } | {
1434
+ readonly ref: ChartRef;
1435
+ } | null;
1436
+ readonly values: ChartRef;
1437
+ readonly categories: ChartRef | null;
1438
+ readonly color: string | null;
1439
+ }
1440
+ /** A validated chart, without its anchor. */
1441
+ interface NormalizedChart {
1442
+ readonly type: ChartType;
1443
+ readonly title: string | null;
1444
+ readonly legend: ChartLegendPosition | null;
1445
+ readonly stacked: boolean | "percent";
1446
+ readonly series: readonly NormalizedSeries[];
1447
+ readonly xTitle: string | null;
1448
+ readonly yTitle: string | null;
1449
+ readonly min: number | null;
1450
+ readonly max: number | null;
1451
+ readonly name: string | null;
1452
+ readonly description: string | null;
1453
+ }
1205
1454
  /**
1206
1455
  * A colour. A string is an RGB colour as 6 hex digits (`"FF0000"`) or ARGB as 8 hex digits
1207
1456
  * (`"80FF0000"`); colours read from files are always 8 upper-case digits. Files can also refer
@@ -2613,8 +2862,19 @@ interface Sheet {
2613
2862
  readonly hyperlinks: readonly Hyperlink[];
2614
2863
  /** Notes (comments) of the sheet, in file order (see `Note`). */
2615
2864
  readonly notes: readonly Note[];
2616
- /** Pictures of the sheet's drawing, in file order (see `SheetImage`); charts and shapes are not read. */
2865
+ /**
2866
+ * Pictures of the sheet's drawing, in file order (see `SheetImage`); shapes are not read. A
2867
+ * drawing part shared with an earlier sheet is read for that sheet only
2868
+ * (`XLV_W_SHEET_PART_SHARED`).
2869
+ */
2617
2870
  readonly images: readonly SheetImage[];
2871
+ /**
2872
+ * Charts of the sheet's drawing, in file order (see `SheetChart`): types, series references,
2873
+ * titles, legend and axes. References are never evaluated. Charts on chart sheets are not read,
2874
+ * nor charts of a drawing part shared with an earlier sheet. Chart groups and series count
2875
+ * against `limits.maxCells` after the cells (see `ReadLimits.maxCells`).
2876
+ */
2877
+ readonly charts: readonly SheetChart[];
2618
2878
  /** The background image of the sheet (`picture` element), or `null`. */
2619
2879
  readonly backgroundImage: WorkbookImage | null;
2620
2880
  /** Colour of the sheet tab (`sheetPr/tabColor`), or `null`. */
@@ -3015,6 +3275,21 @@ interface InspectSheet {
3015
3275
  readonly cell: string | null;
3016
3276
  readonly format: "png" | "jpeg" | "gif" | null;
3017
3277
  }[];
3278
+ /** Number of charts of the sheet's drawing (`Sheet.charts`). */
3279
+ readonly chartCount: number;
3280
+ /**
3281
+ * Up to ten charts: the cell of the top-left corner (or `null` for an absolute position), the
3282
+ * first ten chart group types (see `ChartKind`) and whether the chart has more
3283
+ * (`typesTruncated`), the title (`{ text }` or `{ ref }`, cut to 100 characters and `…`, or
3284
+ * `null`) and the number of series.
3285
+ */
3286
+ readonly charts: readonly {
3287
+ readonly cell: string | null;
3288
+ readonly types: readonly ChartKind[];
3289
+ readonly typesTruncated: boolean;
3290
+ readonly title: ChartText | null;
3291
+ readonly seriesCount: number;
3292
+ }[];
3018
3293
  /** `true` when the sheet is protected (`Sheet.protection.sheet`). */
3019
3294
  readonly protected: boolean;
3020
3295
  /** The print area (`Sheet.printArea`), or `null`. */
@@ -3152,6 +3427,10 @@ interface WriteSheetData {
3152
3427
  readonly images?: readonly ResolvedImage[];
3153
3428
  /** Background image (index into `WritePackageInput.images`), or `null`. */
3154
3429
  readonly background?: number | null;
3430
+ /** Charts with resolved anchors (D-K01). */
3431
+ readonly charts?: readonly (ResolvedAnchor & {
3432
+ readonly chart: NormalizedChart;
3433
+ })[];
3155
3434
  }
3156
3435
  /** Height, visibility and outline of a row. */
3157
3436
  interface RowFormat {
@@ -3579,6 +3858,11 @@ declare class NewSheet {
3579
3858
  readonly imageList: StoredImage[];
3580
3859
  /** @internal Background image (index of `NewWorkbook.addImage`), or `null`. */
3581
3860
  backgroundImage: number | null;
3861
+ /** @internal Charts in the order they were added (D-K01). */
3862
+ readonly chartList: {
3863
+ readonly anchor: ImageAnchorInput;
3864
+ readonly chart: NormalizedChart;
3865
+ }[];
3582
3866
  /** @internal Data validations in the order they were added (SR-01). */
3583
3867
  readonly validationList: DataValidation[];
3584
3868
  /** @internal Conditional formats in the order they were added (SR-07). */
@@ -3918,7 +4202,8 @@ declare class NewSheet {
3918
4202
  * two corners `{ from, to }` (with `editAs`), or a corner and a size in pixels
3919
4203
  * (`{ from, size }`), see `ImageAnchorInput`. Fractional positions and pixel sizes use the
3920
4204
  * sheet's column widths and row heights at the time the workbook is written, at 96 pixels per
3921
- * inch (TD-33).
4205
+ * inch (TD-33). The anchor is copied, so changing its object afterwards does not move the
4206
+ * picture.
3922
4207
  *
3923
4208
  * @example
3924
4209
  * ```ts
@@ -3931,6 +4216,29 @@ declare class NewSheet {
3931
4216
  * ```
3932
4217
  */
3933
4218
  addImage(image: number, anchor: ImageAnchorInput, options?: ImageOptions): this;
4219
+ /**
4220
+ * Places a chart on the sheet: a column, bar, line, pie, scatter or area chart over ranges of
4221
+ * this or another sheet of the workbook (see `ChartInput`). `anchor` places it like a picture.
4222
+ * Each series gets an explicit colour from the default palette unless it has `color`, and the
4223
+ * file holds the current cell values of the ranges as caches, as Excel writes them
4224
+ * (docs/facts/charts.md CH-19, CH-21). The sheets named in the ranges must exist when the
4225
+ * workbook is written. Charts are drawn above the sheet's pictures. The caches of all charts
4226
+ * of a workbook cover at most 4 000 000 cells and hold at most 8 388 608 characters of text as
4227
+ * written, after escaping (limits of xlvane, checked when the workbook is written;
4228
+ * `writeWorkbookStream` writes no caches). The chart options and the anchor are copied, so changing the objects afterwards
4229
+ * does not change the chart. Throws `XLV_E_INVALID_CHART`.
4230
+ *
4231
+ * @example
4232
+ * ```ts
4233
+ * import { createWorkbook } from 'xlvane';
4234
+ *
4235
+ * const workbook = createWorkbook();
4236
+ * const sales = workbook.addSheet('Sales').set('A1', 'Month').set('B1', 'Sales');
4237
+ * ['Jan', 'Feb', 'Mar'].forEach((m, i) => sales.set(`A${String(i + 2)}`, m).set(`B${String(i + 2)}`, (i + 1) * 10));
4238
+ * sales.addChart({ type: 'column', anchor: 'D2:K16', title: 'Sales', series: [{ name: 'Sales!B1', categories: 'Sales!A2:A4', values: 'Sales!B2:B4' }] });
4239
+ * ```
4240
+ */
4241
+ addChart(chart: ChartInput): this;
3934
4242
  /**
3935
4243
  * Sets the picture shown behind the cells of the sheet (`picture` element, Part 1 §18.3.1.67),
3936
4244
  * or removes it with `null`. `image` is the number `NewWorkbook.addImage` returned.
@@ -4875,6 +5183,13 @@ interface StreamSheetSpec {
4875
5183
  })[];
4876
5184
  /** Background image (a position in `WriteWorkbookStreamOptions.images`), as for `NewSheet.background`. */
4877
5185
  readonly background?: number;
5186
+ /**
5187
+ * Charts, as for `NewSheet.addChart`. The streaming writer does not keep cell values, so the
5188
+ * chart parts hold the references without caches; LibreOffice 24.2.7.2 draws such charts from
5189
+ * the cells (docs/facts/charts.md CH-20). PROVISIONAL: whether Excel shows a chart without
5190
+ * caches is not verified (R6-4). Fractional row positions assume the default row height.
5191
+ */
5192
+ readonly charts?: readonly ChartInput[];
4878
5193
  /** The rows, from row 1. Any iterable or async iterable (arrays, generators, streams of rows). */
4879
5194
  readonly rows: Iterable<StreamRowInput> | AsyncIterable<StreamRowInput>;
4880
5195
  }
@@ -4991,4 +5306,4 @@ interface WriteTableStreamOptions {
4991
5306
  * ```
4992
5307
  */
4993
5308
  declare function writeTableStream(rows: Iterable<object> | AsyncIterable<object>, options: WriteTableStreamOptions): ReadableStream<Uint8Array>;
4994
- export { InspectOptions as $, verifyPassword as $n, DataValidationOperator as $t, toJSON as A, Hyperlink as An, Workbook as At, FormulaResult as B, PrintErrors as Bn, CfValue as Bt, TableRow as C, ImageAnchorInput as Cn, Sheet as Ct, fromJSON as D, SheetImage as Dn, SheetState as Dt, WriteTableOptions as E, ImagePositionInput as En, SheetProperties as Et, CellInput as F, PageOrder as Fn, TableDefinitionColumn as Ft, SheetPropertiesOptions as G, SheetProtectionOptions as Gn, ConditionalFormatRule as Gt, NewSheet as H, PrintTitles as Hn, CfValueType as Ht, ColumnOptions as I, PageOrientation as In, TableInput as It, WriteWorkbookOptions as J, HashPasswordOptions as Jn, DataBarAxisPosition as Jt, SheetViewOptions as K, WorkbookProtection as Kn, ConditionalFormatRuleInput as Kt, CreateWorkbookOptions as L, PageSetup as Ln, TableStyleOptions as Lt, StandardSchemaV1 as M, HeaderFooter as Mn, WorkbookView as Mt, AddSheetOptions as N, PageBreaks as Nn, TableColumnInput as Nt, readTable as O, WorkbookImage as On, SheetView as Ot, CalculationOptions as P, PageMargins as Pn, TableDefinition as Pt, InspectDefinedName as Q, legacyPasswordHash as Qn, DataValidationImeMode as Qt, ERROR_VALUES as R, PageSetupOptions as Rn, TotalsRowFunction as Rt, TableResult as S, ImageAnchor as Sn, RowInfo as St, ToJSONOptions as T, ImageOptions as Tn, SheetLayout as Tt, NewWorkbook as U, SheetProtection as Un, ConditionalFormat as Ut, FreezeOptions as V, PrintOptions as Vn, CfValueInput as Vt, RowOptions as W, SheetProtectionFlags as Wn, ConditionalFormatOperator as Wt, writeWorkbook as X, PasswordVerifier as Xn, DataValidation as Xt, createWorkbook as Y, PasswordHash as Yn, DataBarDirection as Yt, InspectColumn as Z, hashPassword as Zn, DataValidationErrorStyle as Zt, JsonTable as _, ReadingOrder as _n, DefinedNameOptions as _r, DateSystem as _t, WriteWorkbookStreamOptions as a, BorderEdge as an, XlvDetails as ar, ReadOptions as at, TableColumnSpec as b, VerticalAlignment as bn, FrozenPanes as bt, OpenWorkbookStreamOptions as c, CellStyle as cn, XlvErrorInit as cr, NoteBox as ct, StreamRow as d, FontScheme as dn, XlvWarning as dr, NoteMargins as dt, DataValidationRule as en, ShaAlgorithm as er, InspectReport as et, StreamSheetInfo as f, FontStyle as fn, XlvWarningCode as fr, Cell as ft, readTableStream as g, ProtectionStyle as gn, DefinedName as gr, Conformance as gt, openWorkbookStream as h, PatternType as hn, ReadLimits as hr, ColumnInfo as ht, WriteTableStreamOptions as i, AlignmentStyle as in, XlvDetailValue as ir, inspect as it, writeTable as j, HyperlinkTarget as jn, WorkbookFormat as jt, readTableAsync as k, imageFormat as kn, SplitPanes as kt, ReadTableStreamOptions as l, Color as ln, XlvErrorJSON as lr, NoteBoxInput as lt, WorkbookStream as m, HorizontalAlignment as mn, DEFAULT_READ_LIMITS as mr, CellValue as mt, StreamRowInput as n, IconSetType as nn, ERROR_CODES as nr, InspectTypeCounts as nt, writeTableStream as o, BorderLineStyle as on, XlvError as or, readWorkbook as ot, TableStreamItem as p, GradientFill as pn, isXlvError as pr, CellType as pt, WorkbookViewOptions as q, WorkbookProtectionOptions as qn, ConditionalFormatType as qt, StreamSheetSpec as r, TimePeriod as rn, WARNING_CODES as rr, InspectValue as rt, writeWorkbookStream as s, BorderStyle as sn, XlvErrorCode as sr, Note as st, StreamDefinedName as t, DataValidationType as tn, WorkbookProperties as tr, InspectSheet as tt, STREAM_LIMIT_DEFAULTS as u, FillStyle as un, XlvLocation as ur, NoteInput as ut, ReadTableOptions as v, UnderlineStyle as vn, Formula as vt, TableValue as w, ImageFormat as wn, SheetKind as wt, TableIssue as x, AnchorMarker as xn, RichTextRun as xt, TableColumn as y, VerticalAlignRun as yn, FormulaKind as yt, ErrorValue as z, PrintCellComments as zn, CfIcon as zt };
5309
+ export { InspectOptions as $, SheetProtection as $n, DataValidationOperator as $t, toJSON as A, SheetChart as An, Workbook as At, FormulaResult as B, Hyperlink as Bn, CfValue as Bt, TableRow as C, ChartInput as Cn, isXlvError as Cr, Sheet as Ct, fromJSON as D, ChartSeriesInput as Dn, DefinedNameOptions as Dr, SheetState as Dt, WriteTableOptions as E, ChartSeries as En, DefinedName as Er, SheetProperties as Et, CellInput as F, ImageOptions as Fn, TableDefinitionColumn as Ft, SheetPropertiesOptions as G, PageOrder as Gn, ConditionalFormatRule as Gt, NewSheet as H, HeaderFooter as Hn, CfValueType as Ht, ColumnOptions as I, ImagePositionInput as In, TableInput as It, WriteWorkbookOptions as J, PageSetupOptions as Jn, DataBarAxisPosition as Jt, SheetViewOptions as K, PageOrientation as Kn, ConditionalFormatRuleInput as Kt, CreateWorkbookOptions as L, SheetImage as Ln, TableStyleOptions as Lt, StandardSchemaV1 as M, ImageAnchor as Mn, WorkbookView as Mt, AddSheetOptions as N, ImageAnchorInput as Nn, TableColumnInput as Nt, readTable as O, ChartText as On, SheetView as Ot, CalculationOptions as P, ImageFormat as Pn, TableDefinition as Pt, InspectDefinedName as Q, PrintTitles as Qn, DataValidationImeMode as Qt, ERROR_VALUES as R, WorkbookImage as Rn, TotalsRowFunction as Rt, TableResult as S, ChartAxisInput as Sn, XlvWarningCode as Sr, RowInfo as St, ToJSONOptions as T, ChartLegendPosition as Tn, ReadLimits as Tr, SheetLayout as Tt, NewWorkbook as U, PageBreaks as Un, ConditionalFormat as Ut, FreezeOptions as V, HyperlinkTarget as Vn, CfValueInput as Vt, RowOptions as W, PageMargins as Wn, ConditionalFormatOperator as Wt, writeWorkbook as X, PrintErrors as Xn, DataValidation as Xt, createWorkbook as Y, PrintCellComments as Yn, DataBarDirection as Yt, InspectColumn as Z, PrintOptions as Zn, DataValidationErrorStyle as Zt, JsonTable as _, ReadingOrder as _n, XlvErrorCode as _r, DateSystem as _t, WriteWorkbookStreamOptions as a, BorderEdge as an, PasswordHash as ar, ReadOptions as at, TableColumnSpec as b, VerticalAlignment as bn, XlvLocation as br, FrozenPanes as bt, OpenWorkbookStreamOptions as c, CellStyle as cn, legacyPasswordHash as cr, NoteBox as ct, StreamRow as d, FontScheme as dn, WorkbookProperties as dr, NoteMargins as dt, DataValidationRule as en, SheetProtectionFlags as er, InspectReport as et, StreamSheetInfo as f, FontStyle as fn, ERROR_CODES as fr, Cell as ft, readTableStream as g, ProtectionStyle as gn, XlvError as gr, Conformance as gt, openWorkbookStream as h, PatternType as hn, XlvDetails as hr, ColumnInfo as ht, WriteTableStreamOptions as i, AlignmentStyle as in, HashPasswordOptions as ir, inspect as it, writeTable as j, AnchorMarker as jn, WorkbookFormat as jt, readTableAsync as k, ChartType as kn, SplitPanes as kt, ReadTableStreamOptions as l, Color as ln, verifyPassword as lr, NoteBoxInput as lt, WorkbookStream as m, HorizontalAlignment as mn, XlvDetailValue as mr, CellValue as mt, StreamRowInput as n, IconSetType as nn, WorkbookProtection as nr, InspectTypeCounts as nt, writeTableStream as o, BorderLineStyle as on, PasswordVerifier as or, readWorkbook as ot, TableStreamItem as p, GradientFill as pn, WARNING_CODES as pr, CellType as pt, WorkbookViewOptions as q, PageSetup as qn, ConditionalFormatType as qt, StreamSheetSpec as r, TimePeriod as rn, WorkbookProtectionOptions as rr, InspectValue as rt, writeWorkbookStream as s, BorderStyle as sn, hashPassword as sr, Note as st, StreamDefinedName as t, DataValidationType as tn, SheetProtectionOptions as tr, InspectSheet as tt, STREAM_LIMIT_DEFAULTS as u, FillStyle as un, ShaAlgorithm as ur, NoteInput as ut, ReadTableOptions as v, UnderlineStyle as vn, XlvErrorInit as vr, Formula as vt, TableValue as w, ChartKind as wn, DEFAULT_READ_LIMITS as wr, SheetKind as wt, TableIssue as x, ChartAxis as xn, XlvWarning as xr, RichTextRun as xt, TableColumn as y, VerticalAlignRun as yn, XlvErrorJSON as yr, FormulaKind as yt, ErrorValue as z, imageFormat as zn, CfIcon as zt };
@@ -359,6 +359,80 @@
359
359
  "additionalProperties": false
360
360
  }
361
361
  },
362
+ "chartCount": {
363
+ "type": "integer",
364
+ "minimum": 0
365
+ },
366
+ "charts": {
367
+ "type": "array",
368
+ "items": {
369
+ "type": "object",
370
+ "properties": {
371
+ "cell": {
372
+ "anyOf": [
373
+ {
374
+ "type": "null"
375
+ },
376
+ {
377
+ "type": "string"
378
+ }
379
+ ]
380
+ },
381
+ "types": {
382
+ "type": "array",
383
+ "items": {
384
+ "type": "string"
385
+ }
386
+ },
387
+ "typesTruncated": {
388
+ "type": "boolean"
389
+ },
390
+ "title": {
391
+ "anyOf": [
392
+ {
393
+ "type": "null"
394
+ },
395
+ {
396
+ "type": "object",
397
+ "properties": {
398
+ "text": {
399
+ "type": "string"
400
+ }
401
+ },
402
+ "required": [
403
+ "text"
404
+ ],
405
+ "additionalProperties": false
406
+ },
407
+ {
408
+ "type": "object",
409
+ "properties": {
410
+ "ref": {
411
+ "type": "string"
412
+ }
413
+ },
414
+ "required": [
415
+ "ref"
416
+ ],
417
+ "additionalProperties": false
418
+ }
419
+ ]
420
+ },
421
+ "seriesCount": {
422
+ "type": "integer",
423
+ "minimum": 0
424
+ }
425
+ },
426
+ "required": [
427
+ "cell",
428
+ "types",
429
+ "typesTruncated",
430
+ "title",
431
+ "seriesCount"
432
+ ],
433
+ "additionalProperties": false
434
+ }
435
+ },
362
436
  "protected": {
363
437
  "type": "boolean"
364
438
  },
@@ -485,6 +559,8 @@
485
559
  "noteCount",
486
560
  "imageCount",
487
561
  "images",
562
+ "chartCount",
563
+ "charts",
488
564
  "notes",
489
565
  "protected",
490
566
  "printArea",