Skip to content

Commit

Permalink
1842: New xlsx option for ignoring certain nodes for improved perform…
Browse files Browse the repository at this point in the history
…ance (#2132)

* 1842: New xlsx option for ignoring certain nodes for improved performance

* Included test file

* Added typescript typings

* optimizing ifs

* new line EOF

* Update README.md - available options

---------

Co-authored-by: Willem Le Roux <willemleroux@safeguardglobal.com>
Co-authored-by: Siemienik Pawel <hi@siemienik.com>
  • Loading branch information
3 people committed Sep 21, 2023
1 parent 4abccf5 commit 3178efd
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 19 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2159,6 +2159,12 @@ faster or more resilient.

#### Reading XLSX[](#contents)<!-- Link generated with jump2header -->

Options supported when reading CSV files.

| Field | Required | Type |Description |
| ---------------- | ----------- | ----------- | ----------- |
| ignoreNodes | N | Array | A list of node names to ignore while loading the XLSX document. Improves performance in some situations. <br/> Available: `sheetPr`, `dimension`, `sheetViews `, `sheetFormatPr`, `cols `, `sheetData`, `autoFilter `, `mergeCells `, `rowBreaks`, `hyperlinks `, `pageMargins`, `dataValidations`, `pageSetup`, `headerFooter `, `printOptions `, `picture`, `drawing`, `sheetProtection`, `tableParts `, `conditionalFormatting`, `extLst`,|

```javascript
// read from a file
const workbook = new Excel.Workbook();
Expand All @@ -2176,6 +2182,16 @@ await workbook.xlsx.read(stream);
const workbook = new Excel.Workbook();
await workbook.xlsx.load(data);
// ... use workbook


// using additional options
const workbook = new Excel.Workbook();
await workbook.xlsx.load(data, {
ignoreNodes: [
'dataValidations' // ignores the workbook's Data Validations
],
});
// ... use workbook
```

#### Writing XLSX[](#contents)<!-- Link generated with jump2header -->
Expand Down
13 changes: 10 additions & 3 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,13 @@ export interface JSZipGeneratorOptions {
};
}

export interface XlsxReadOptions {
/**
* The list of XML node names to ignore while parsing an XLSX file
*/
ignoreNodes: string[];
}

export interface XlsxWriteOptions extends stream.xlsx.WorkbookWriterOptions {
/**
* The option passed to JsZip#generateAsync(options)
Expand All @@ -1468,19 +1475,19 @@ export interface Xlsx {
/**
* read from a file
*/
readFile(path: string): Promise<Workbook>;
readFile(path: string, options?: Partial<XlsxReadOptions>): Promise<Workbook>;

/**
* read from a stream
* @param stream
*/
read(stream: import('stream').Stream): Promise<Workbook>;
read(stream: import('stream').Stream, options?: Partial<XlsxReadOptions>): Promise<Workbook>;

/**
* load from an array buffer
* @param buffer
*/
load(buffer: Buffer): Promise<Workbook>;
load(buffer: Buffer, options?: Partial<XlsxReadOptions>): Promise<Workbook>;

/**
* write to a buffer
Expand Down
19 changes: 8 additions & 11 deletions lib/xlsx/xform/sheet/worksheet-xform.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ class WorkSheetXform extends BaseXform {
constructor(options) {
super();

const {maxRows, maxCols} = options || {};
const {maxRows, maxCols, ignoreNodes} = options || {};

this.ignoreNodes = ignoreNodes || [];

this.map = {
sheetPr: new SheetPropertiesXform(),
dimension: new DimensionXform(),
Expand Down Expand Up @@ -221,9 +224,7 @@ class WorkSheetXform extends BaseXform {
});
}
let rIdImage =
this.preImageId === medium.imageId
? drawingRelsHash[medium.imageId]
: drawingRelsHash[drawing.rels.length];
this.preImageId === medium.imageId ? drawingRelsHash[medium.imageId] : drawingRelsHash[drawing.rels.length];
if (!rIdImage) {
rIdImage = nextRid(drawing.rels);
drawingRelsHash[drawing.rels.length] = rIdImage;
Expand Down Expand Up @@ -368,8 +369,8 @@ class WorkSheetXform extends BaseXform {
return true;
}

this.parser = this.map[node.name];
if (this.parser) {
if (this.map[node.name] && !this.ignoreNodes.includes(node.name)) {
this.parser = this.map[node.name];
this.parser.parseOpen(node);
}
return true;
Expand Down Expand Up @@ -405,11 +406,7 @@ class WorkSheetXform extends BaseXform {
false,
margins: this.map.pageMargins.model,
};
const pageSetup = Object.assign(
sheetProperties,
this.map.pageSetup.model,
this.map.printOptions.model
);
const pageSetup = Object.assign(sheetProperties, this.map.pageSetup.model, this.map.printOptions.model);
const conditionalFormattings = mergeConditionalFormattings(
this.map.conditionalFormatting.model,
this.map.extLst.model && this.map.extLst.model['x14:conditionalFormattings']
Expand Down
11 changes: 6 additions & 5 deletions lib/xlsx/xlsx.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const TableXform = require('./xform/table/table-xform');
const CommentsXform = require('./xform/comment/comments-xform');
const VmlNotesXform = require('./xform/comment/vml-notes-xform');

const theme1Xml = require('./xml/theme1.js');
const theme1Xml = require('./xml/theme1');

function fsReadFileAsync(filename, options) {
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -285,9 +285,11 @@ class XLSX {
entryName = entryName.substr(1);
}
let stream;
if (entryName.match(/xl\/media\//) ||
if (
entryName.match(/xl\/media\//) ||
// themes are not parsed as stream
entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/)) {
entryName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/)
) {
stream = new PassThrough();
stream.write(await entry.async('nodebuffer'));
} else {
Expand Down Expand Up @@ -597,8 +599,7 @@ class XLSX {
model.created = model.created || new Date();
model.modified = model.modified || new Date();

model.useSharedStrings =
options.useSharedStrings !== undefined ? options.useSharedStrings : true;
model.useSharedStrings = options.useSharedStrings !== undefined ? options.useSharedStrings : true;
model.useStyles = options.useStyles !== undefined ? options.useStyles : true;

// Manage the shared strings
Expand Down
1 change: 1 addition & 0 deletions spec/integration/data/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!*.xlsx
Binary file added spec/integration/data/test-issue-1842.xlsx
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const {join} = require('path');
const {readFileSync} = require('fs');

const ExcelJS = verquire('exceljs');

const fileName = './spec/integration/data/test-issue-1842.xlsx';

describe('github issues', () => {
describe('issue 1842 - Memory overload when unnecessary dataValidations apply', () => {
it('when using readFile', async () => {
const wb = new ExcelJS.Workbook();
await wb.xlsx.readFile(fileName, {
ignoreNodes: ['dataValidations'],
});

// arriving here is success
expect(true).to.equal(true);
});

it('when loading an in memory buffer', async () => {
const filePath = join(process.cwd(), fileName);
const buffer = readFileSync(filePath);
const wb = new ExcelJS.Workbook();
await wb.xlsx.load(buffer, {
ignoreNodes: ['dataValidations'],
});

// arriving here is success
expect(true).to.equal(true);
});
});
});

0 comments on commit 3178efd

Please sign in to comment.