fix: 修复中介导入成功条数计算错误
问题: - 导入成功条数显示为负数 - 原因:成功数量计算使用 validRecords.size() - failures.size() - 但没有使用实际的数据库操作返回值 修复: - saveBatchWithUpsert 和 saveBatch 方法现在返回 int - 累加实际的数据库影响行数 - 使用 actualSuccessCount 变量跟踪真实成功数量 影响范围: - CcdiIntermediaryPersonImportServiceImpl - CcdiIntermediaryEntityImportServiceImpl
This commit is contained in:
22
doc/test-data/purchase_transaction/node_modules/exceljs/LICENSE
generated
vendored
Normal file
22
doc/test-data/purchase_transaction/node_modules/exceljs/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2019 Guyon Roche
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
3023
doc/test-data/purchase_transaction/node_modules/exceljs/README.md
generated
vendored
Normal file
3023
doc/test-data/purchase_transaction/node_modules/exceljs/README.md
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
2878
doc/test-data/purchase_transaction/node_modules/exceljs/README_zh.md
generated
vendored
Normal file
2878
doc/test-data/purchase_transaction/node_modules/exceljs/README_zh.md
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
13
doc/test-data/purchase_transaction/node_modules/exceljs/excel.js
generated
vendored
Normal file
13
doc/test-data/purchase_transaction/node_modules/exceljs/excel.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2014-2019 Guyon Roche
|
||||
* LICENCE: MIT - please refer to LICENSE file included with this module
|
||||
* or https://github.com/exceljs/exceljs/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
if (parseInt(process.versions.node.split('.')[0], 10) < 10) {
|
||||
throw new Error(
|
||||
'For node versions older than 10, please use the ES5 Import: https://github.com/exceljs/exceljs#es5-imports'
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = require('./lib/exceljs.nodejs.js');
|
||||
2035
doc/test-data/purchase_transaction/node_modules/exceljs/index.d.ts
generated
vendored
Normal file
2035
doc/test-data/purchase_transaction/node_modules/exceljs/index.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
doc/test-data/purchase_transaction/node_modules/exceljs/index.ts
generated
vendored
Normal file
2
doc/test-data/purchase_transaction/node_modules/exceljs/index.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import * as ExcelJS from './dist/es5';
|
||||
export default ExcelJS;
|
||||
191
doc/test-data/purchase_transaction/node_modules/exceljs/lib/csv/csv.js
generated
vendored
Normal file
191
doc/test-data/purchase_transaction/node_modules/exceljs/lib/csv/csv.js
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
const fs = require('fs');
|
||||
const fastCsv = require('fast-csv');
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat');
|
||||
const utc = require('dayjs/plugin/utc');
|
||||
const dayjs = require('dayjs').extend(customParseFormat).extend(utc);
|
||||
const StreamBuf = require('../utils/stream-buf');
|
||||
|
||||
const {
|
||||
fs: {exists},
|
||||
} = require('../utils/utils');
|
||||
|
||||
/* eslint-disable quote-props */
|
||||
const SpecialValues = {
|
||||
true: true,
|
||||
false: false,
|
||||
'#N/A': {error: '#N/A'},
|
||||
'#REF!': {error: '#REF!'},
|
||||
'#NAME?': {error: '#NAME?'},
|
||||
'#DIV/0!': {error: '#DIV/0!'},
|
||||
'#NULL!': {error: '#NULL!'},
|
||||
'#VALUE!': {error: '#VALUE!'},
|
||||
'#NUM!': {error: '#NUM!'},
|
||||
};
|
||||
/* eslint-ensable quote-props */
|
||||
|
||||
class CSV {
|
||||
constructor(workbook) {
|
||||
this.workbook = workbook;
|
||||
this.worksheet = null;
|
||||
}
|
||||
|
||||
async readFile(filename, options) {
|
||||
options = options || {};
|
||||
if (!(await exists(filename))) {
|
||||
throw new Error(`File not found: ${filename}`);
|
||||
}
|
||||
const stream = fs.createReadStream(filename);
|
||||
const worksheet = await this.read(stream, options);
|
||||
stream.close();
|
||||
return worksheet;
|
||||
}
|
||||
|
||||
read(stream, options) {
|
||||
options = options || {};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const worksheet = this.workbook.addWorksheet(options.sheetName);
|
||||
|
||||
const dateFormats = options.dateFormats || [
|
||||
'YYYY-MM-DD[T]HH:mm:ssZ',
|
||||
'YYYY-MM-DD[T]HH:mm:ss',
|
||||
'MM-DD-YYYY',
|
||||
'YYYY-MM-DD',
|
||||
];
|
||||
const map =
|
||||
options.map ||
|
||||
function(datum) {
|
||||
if (datum === '') {
|
||||
return null;
|
||||
}
|
||||
const datumNumber = Number(datum);
|
||||
if (!Number.isNaN(datumNumber) && datumNumber !== Infinity) {
|
||||
return datumNumber;
|
||||
}
|
||||
const dt = dateFormats.reduce((matchingDate, currentDateFormat) => {
|
||||
if (matchingDate) {
|
||||
return matchingDate;
|
||||
}
|
||||
const dayjsObj = dayjs(datum, currentDateFormat, true);
|
||||
if (dayjsObj.isValid()) {
|
||||
return dayjsObj;
|
||||
}
|
||||
return null;
|
||||
}, null);
|
||||
if (dt) {
|
||||
return new Date(dt.valueOf());
|
||||
}
|
||||
const special = SpecialValues[datum];
|
||||
if (special !== undefined) {
|
||||
return special;
|
||||
}
|
||||
return datum;
|
||||
};
|
||||
|
||||
const csvStream = fastCsv
|
||||
.parse(options.parserOptions)
|
||||
.on('data', data => {
|
||||
worksheet.addRow(data.map(map));
|
||||
})
|
||||
.on('end', () => {
|
||||
csvStream.emit('worksheet', worksheet);
|
||||
});
|
||||
|
||||
csvStream.on('worksheet', resolve).on('error', reject);
|
||||
|
||||
stream.pipe(csvStream);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 4.0. You should use `CSV#read` instead. Please follow upgrade instruction: https://github.com/exceljs/exceljs/blob/master/UPGRADE-4.0.md
|
||||
*/
|
||||
createInputStream() {
|
||||
throw new Error(
|
||||
'`CSV#createInputStream` is deprecated. You should use `CSV#read` instead. This method will be removed in version 5.0. Please follow upgrade instruction: https://github.com/exceljs/exceljs/blob/master/UPGRADE-4.0.md'
|
||||
);
|
||||
}
|
||||
|
||||
write(stream, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
options = options || {};
|
||||
// const encoding = options.encoding || 'utf8';
|
||||
// const separator = options.separator || ',';
|
||||
// const quoteChar = options.quoteChar || '\'';
|
||||
|
||||
const worksheet = this.workbook.getWorksheet(options.sheetName || options.sheetId);
|
||||
|
||||
const csvStream = fastCsv.format(options.formatterOptions);
|
||||
stream.on('finish', () => {
|
||||
resolve();
|
||||
});
|
||||
csvStream.on('error', reject);
|
||||
csvStream.pipe(stream);
|
||||
|
||||
const {dateFormat, dateUTC} = options;
|
||||
const map =
|
||||
options.map ||
|
||||
(value => {
|
||||
if (value) {
|
||||
if (value.text || value.hyperlink) {
|
||||
return value.hyperlink || value.text || '';
|
||||
}
|
||||
if (value.formula || value.result) {
|
||||
return value.result || '';
|
||||
}
|
||||
if (value instanceof Date) {
|
||||
if (dateFormat) {
|
||||
return dateUTC
|
||||
? dayjs.utc(value).format(dateFormat)
|
||||
: dayjs(value).format(dateFormat);
|
||||
}
|
||||
return dateUTC ? dayjs.utc(value).format() : dayjs(value).format();
|
||||
}
|
||||
if (value.error) {
|
||||
return value.error;
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
const includeEmptyRows = options.includeEmptyRows === undefined || options.includeEmptyRows;
|
||||
let lastRow = 1;
|
||||
if (worksheet) {
|
||||
worksheet.eachRow((row, rowNumber) => {
|
||||
if (includeEmptyRows) {
|
||||
while (lastRow++ < rowNumber - 1) {
|
||||
csvStream.write([]);
|
||||
}
|
||||
}
|
||||
const {values} = row;
|
||||
values.shift();
|
||||
csvStream.write(values.map(map));
|
||||
lastRow = rowNumber;
|
||||
});
|
||||
}
|
||||
csvStream.end();
|
||||
});
|
||||
}
|
||||
|
||||
writeFile(filename, options) {
|
||||
options = options || {};
|
||||
|
||||
const streamOptions = {
|
||||
encoding: options.encoding || 'utf8',
|
||||
};
|
||||
const stream = fs.createWriteStream(filename, streamOptions);
|
||||
|
||||
return this.write(stream, options);
|
||||
}
|
||||
|
||||
async writeBuffer(options) {
|
||||
const stream = new StreamBuf();
|
||||
await this.write(stream, options);
|
||||
return stream.read();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CSV;
|
||||
74
doc/test-data/purchase_transaction/node_modules/exceljs/lib/csv/line-buffer.js
generated
vendored
Normal file
74
doc/test-data/purchase_transaction/node_modules/exceljs/lib/csv/line-buffer.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
const {EventEmitter} = require('events');
|
||||
|
||||
class LineBuffer extends EventEmitter {
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
this.encoding = options.encoding;
|
||||
|
||||
this.buffer = null;
|
||||
|
||||
// part of cork/uncork
|
||||
this.corked = false;
|
||||
this.queue = [];
|
||||
}
|
||||
|
||||
// Events:
|
||||
// line: here is a line
|
||||
// done: all lines emitted
|
||||
|
||||
write(chunk) {
|
||||
// find line or lines in chunk and emit them if not corked
|
||||
// or queue them if corked
|
||||
const data = this.buffer ? this.buffer + chunk : chunk;
|
||||
const lines = data.split(/\r?\n/g);
|
||||
|
||||
// save the last line
|
||||
this.buffer = lines.pop();
|
||||
|
||||
lines.forEach(function(line) {
|
||||
if (this.corked) {
|
||||
this.queue.push(line);
|
||||
} else {
|
||||
this.emit('line', line);
|
||||
}
|
||||
});
|
||||
|
||||
return !this.corked;
|
||||
}
|
||||
|
||||
cork() {
|
||||
this.corked = true;
|
||||
}
|
||||
|
||||
uncork() {
|
||||
this.corked = false;
|
||||
this._flush();
|
||||
|
||||
// tell the source I'm ready again
|
||||
this.emit('drain');
|
||||
}
|
||||
|
||||
setDefaultEncoding() {
|
||||
// ?
|
||||
}
|
||||
|
||||
end() {
|
||||
if (this.buffer) {
|
||||
this.emit('line', this.buffer);
|
||||
this.buffer = null;
|
||||
}
|
||||
this.emit('done');
|
||||
}
|
||||
|
||||
_flush() {
|
||||
if (!this.corked) {
|
||||
this.queue.forEach(line => {
|
||||
this.emit('line', line);
|
||||
});
|
||||
this.queue = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = LineBuffer;
|
||||
135
doc/test-data/purchase_transaction/node_modules/exceljs/lib/csv/stream-converter.js
generated
vendored
Normal file
135
doc/test-data/purchase_transaction/node_modules/exceljs/lib/csv/stream-converter.js
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
// =======================================================================================================
|
||||
// StreamConverter
|
||||
//
|
||||
// convert between encoding schemes in a stream
|
||||
// Work in Progress - Will complete this at some point
|
||||
let jconv;
|
||||
|
||||
class StreamConverter {
|
||||
constructor(inner, options) {
|
||||
this.inner = inner;
|
||||
|
||||
options = options || {};
|
||||
this.innerEncoding = (options.innerEncoding || 'UTF8').toUpperCase();
|
||||
this.outerEncoding = (options.outerEncoding || 'UTF8').toUpperCase();
|
||||
|
||||
this.innerBOM = options.innerBOM || null;
|
||||
this.outerBOM = options.outerBOM || null;
|
||||
|
||||
this.writeStarted = false;
|
||||
}
|
||||
|
||||
convertInwards(data) {
|
||||
if (data) {
|
||||
if (typeof data === 'string') {
|
||||
data = Buffer.from(data, this.outerEncoding);
|
||||
}
|
||||
|
||||
if (this.innerEncoding !== this.outerEncoding) {
|
||||
data = jconv.convert(data, this.outerEncoding, this.innerEncoding);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
convertOutwards(data) {
|
||||
if (typeof data === 'string') {
|
||||
data = Buffer.from(data, this.innerEncoding);
|
||||
}
|
||||
|
||||
if (this.innerEncoding !== this.outerEncoding) {
|
||||
data = jconv.convert(data, this.innerEncoding, this.outerEncoding);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
addListener(event, handler) {
|
||||
this.inner.addListener(event, handler);
|
||||
}
|
||||
|
||||
removeListener(event, handler) {
|
||||
this.inner.removeListener(event, handler);
|
||||
}
|
||||
|
||||
write(data, encoding, callback) {
|
||||
if (encoding instanceof Function) {
|
||||
callback = encoding;
|
||||
encoding = undefined;
|
||||
}
|
||||
|
||||
if (!this.writeStarted) {
|
||||
// if inner encoding has BOM, write it now
|
||||
if (this.innerBOM) {
|
||||
this.inner.write(this.innerBOM);
|
||||
}
|
||||
|
||||
// if outer encoding has BOM, delete it now
|
||||
if (this.outerBOM) {
|
||||
if (data.length <= this.outerBOM.length) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
return;
|
||||
}
|
||||
const bomless = Buffer.alloc(data.length - this.outerBOM.length);
|
||||
data.copy(bomless, 0, this.outerBOM.length, data.length);
|
||||
data = bomless;
|
||||
}
|
||||
|
||||
this.writeStarted = true;
|
||||
}
|
||||
|
||||
this.inner.write(
|
||||
this.convertInwards(data),
|
||||
encoding ? this.innerEncoding : undefined,
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
read() {
|
||||
// TBD
|
||||
}
|
||||
|
||||
pipe(destination, options) {
|
||||
const reverseConverter = new StreamConverter(destination, {
|
||||
innerEncoding: this.outerEncoding,
|
||||
outerEncoding: this.innerEncoding,
|
||||
innerBOM: this.outerBOM,
|
||||
outerBOM: this.innerBOM,
|
||||
});
|
||||
|
||||
this.inner.pipe(reverseConverter, options);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.inner.close();
|
||||
}
|
||||
|
||||
on(type, callback) {
|
||||
switch (type) {
|
||||
case 'data':
|
||||
this.inner.on('data', chunk => {
|
||||
callback(this.convertOutwards(chunk));
|
||||
});
|
||||
return this;
|
||||
default:
|
||||
this.inner.on(type, callback);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
once(type, callback) {
|
||||
this.inner.once(type, callback);
|
||||
}
|
||||
|
||||
end(chunk, encoding, callback) {
|
||||
this.inner.end(this.convertInwards(chunk), this.innerEncoding, callback);
|
||||
}
|
||||
|
||||
emit(type, value) {
|
||||
this.inner.emit(type, value);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StreamConverter;
|
||||
91
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/anchor.js
generated
vendored
Normal file
91
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/anchor.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
|
||||
const colCache = require('../utils/col-cache');
|
||||
|
||||
class Anchor {
|
||||
constructor(worksheet, address, offset = 0) {
|
||||
this.worksheet = worksheet;
|
||||
|
||||
if (!address) {
|
||||
this.nativeCol = 0;
|
||||
this.nativeColOff = 0;
|
||||
this.nativeRow = 0;
|
||||
this.nativeRowOff = 0;
|
||||
} else if (typeof address === 'string') {
|
||||
const decoded = colCache.decodeAddress(address);
|
||||
this.nativeCol = decoded.col + offset;
|
||||
this.nativeColOff = 0;
|
||||
this.nativeRow = decoded.row + offset;
|
||||
this.nativeRowOff = 0;
|
||||
} else if (address.nativeCol !== undefined) {
|
||||
this.nativeCol = address.nativeCol || 0;
|
||||
this.nativeColOff = address.nativeColOff || 0;
|
||||
this.nativeRow = address.nativeRow || 0;
|
||||
this.nativeRowOff = address.nativeRowOff || 0;
|
||||
} else if (address.col !== undefined) {
|
||||
this.col = address.col + offset;
|
||||
this.row = address.row + offset;
|
||||
} else {
|
||||
this.nativeCol = 0;
|
||||
this.nativeColOff = 0;
|
||||
this.nativeRow = 0;
|
||||
this.nativeRowOff = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static asInstance(model) {
|
||||
return model instanceof Anchor || model == null ? model : new Anchor(model);
|
||||
}
|
||||
|
||||
get col() {
|
||||
return this.nativeCol + (Math.min(this.colWidth - 1, this.nativeColOff) / this.colWidth);
|
||||
}
|
||||
|
||||
set col(v) {
|
||||
this.nativeCol = Math.floor(v);
|
||||
this.nativeColOff = Math.floor((v - this.nativeCol) * this.colWidth);
|
||||
}
|
||||
|
||||
get row() {
|
||||
return this.nativeRow + (Math.min(this.rowHeight - 1, this.nativeRowOff) / this.rowHeight);
|
||||
}
|
||||
|
||||
set row(v) {
|
||||
this.nativeRow = Math.floor(v);
|
||||
this.nativeRowOff = Math.floor((v - this.nativeRow) * this.rowHeight);
|
||||
}
|
||||
|
||||
get colWidth() {
|
||||
return this.worksheet &&
|
||||
this.worksheet.getColumn(this.nativeCol + 1) &&
|
||||
this.worksheet.getColumn(this.nativeCol + 1).isCustomWidth
|
||||
? Math.floor(this.worksheet.getColumn(this.nativeCol + 1).width * 10000)
|
||||
: 640000;
|
||||
}
|
||||
|
||||
get rowHeight() {
|
||||
return this.worksheet &&
|
||||
this.worksheet.getRow(this.nativeRow + 1) &&
|
||||
this.worksheet.getRow(this.nativeRow + 1).height
|
||||
? Math.floor(this.worksheet.getRow(this.nativeRow + 1).height * 10000)
|
||||
: 180000;
|
||||
}
|
||||
|
||||
get model() {
|
||||
return {
|
||||
nativeCol: this.nativeCol,
|
||||
nativeColOff: this.nativeColOff,
|
||||
nativeRow: this.nativeRow,
|
||||
nativeRowOff: this.nativeRowOff,
|
||||
};
|
||||
}
|
||||
|
||||
set model(value) {
|
||||
this.nativeCol = value.nativeCol;
|
||||
this.nativeColOff = value.nativeColOff;
|
||||
this.nativeRow = value.nativeRow;
|
||||
this.nativeRowOff = value.nativeRowOff;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Anchor;
|
||||
1124
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/cell.js
generated
vendored
Normal file
1124
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/cell.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
320
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/column.js
generated
vendored
Normal file
320
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/column.js
generated
vendored
Normal file
@@ -0,0 +1,320 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('../utils/under-dash');
|
||||
|
||||
const Enums = require('./enums');
|
||||
const colCache = require('../utils/col-cache');
|
||||
|
||||
const DEFAULT_COLUMN_WIDTH = 9;
|
||||
|
||||
// Column defines the column properties for 1 column.
|
||||
// This includes header rows, widths, key, (style), etc.
|
||||
// Worksheet will condense the columns as appropriate during serialization
|
||||
class Column {
|
||||
constructor(worksheet, number, defn) {
|
||||
this._worksheet = worksheet;
|
||||
this._number = number;
|
||||
if (defn !== false) {
|
||||
// sometimes defn will follow
|
||||
this.defn = defn;
|
||||
}
|
||||
}
|
||||
|
||||
get number() {
|
||||
return this._number;
|
||||
}
|
||||
|
||||
get worksheet() {
|
||||
return this._worksheet;
|
||||
}
|
||||
|
||||
get letter() {
|
||||
return colCache.n2l(this._number);
|
||||
}
|
||||
|
||||
get isCustomWidth() {
|
||||
return this.width !== undefined && this.width !== DEFAULT_COLUMN_WIDTH;
|
||||
}
|
||||
|
||||
get defn() {
|
||||
return {
|
||||
header: this._header,
|
||||
key: this.key,
|
||||
width: this.width,
|
||||
style: this.style,
|
||||
hidden: this.hidden,
|
||||
outlineLevel: this.outlineLevel,
|
||||
};
|
||||
}
|
||||
|
||||
set defn(value) {
|
||||
if (value) {
|
||||
this.key = value.key;
|
||||
this.width = value.width !== undefined ? value.width : DEFAULT_COLUMN_WIDTH;
|
||||
this.outlineLevel = value.outlineLevel;
|
||||
if (value.style) {
|
||||
this.style = value.style;
|
||||
} else {
|
||||
this.style = {};
|
||||
}
|
||||
|
||||
// headers must be set after style
|
||||
this.header = value.header;
|
||||
this._hidden = !!value.hidden;
|
||||
} else {
|
||||
delete this._header;
|
||||
delete this._key;
|
||||
delete this.width;
|
||||
this.style = {};
|
||||
this.outlineLevel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
get headers() {
|
||||
return this._header && this._header instanceof Array ? this._header : [this._header];
|
||||
}
|
||||
|
||||
get header() {
|
||||
return this._header;
|
||||
}
|
||||
|
||||
set header(value) {
|
||||
if (value !== undefined) {
|
||||
this._header = value;
|
||||
this.headers.forEach((text, index) => {
|
||||
this._worksheet.getCell(index + 1, this.number).value = text;
|
||||
});
|
||||
} else {
|
||||
this._header = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
get key() {
|
||||
return this._key;
|
||||
}
|
||||
|
||||
set key(value) {
|
||||
const column = this._key && this._worksheet.getColumnKey(this._key);
|
||||
if (column === this) {
|
||||
this._worksheet.deleteColumnKey(this._key);
|
||||
}
|
||||
|
||||
this._key = value;
|
||||
if (value) {
|
||||
this._worksheet.setColumnKey(this._key, this);
|
||||
}
|
||||
}
|
||||
|
||||
get hidden() {
|
||||
return !!this._hidden;
|
||||
}
|
||||
|
||||
set hidden(value) {
|
||||
this._hidden = value;
|
||||
}
|
||||
|
||||
get outlineLevel() {
|
||||
return this._outlineLevel || 0;
|
||||
}
|
||||
|
||||
set outlineLevel(value) {
|
||||
this._outlineLevel = value;
|
||||
}
|
||||
|
||||
get collapsed() {
|
||||
return !!(
|
||||
this._outlineLevel && this._outlineLevel >= this._worksheet.properties.outlineLevelCol
|
||||
);
|
||||
}
|
||||
|
||||
toString() {
|
||||
return JSON.stringify({
|
||||
key: this.key,
|
||||
width: this.width,
|
||||
headers: this.headers.length ? this.headers : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
equivalentTo(other) {
|
||||
return (
|
||||
this.width === other.width &&
|
||||
this.hidden === other.hidden &&
|
||||
this.outlineLevel === other.outlineLevel &&
|
||||
_.isEqual(this.style, other.style)
|
||||
);
|
||||
}
|
||||
|
||||
get isDefault() {
|
||||
if (this.isCustomWidth) {
|
||||
return false;
|
||||
}
|
||||
if (this.hidden) {
|
||||
return false;
|
||||
}
|
||||
if (this.outlineLevel) {
|
||||
return false;
|
||||
}
|
||||
const s = this.style;
|
||||
if (s && (s.font || s.numFmt || s.alignment || s.border || s.fill || s.protection)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
get headerCount() {
|
||||
return this.headers.length;
|
||||
}
|
||||
|
||||
eachCell(options, iteratee) {
|
||||
const colNumber = this.number;
|
||||
if (!iteratee) {
|
||||
iteratee = options;
|
||||
options = null;
|
||||
}
|
||||
this._worksheet.eachRow(options, (row, rowNumber) => {
|
||||
iteratee(row.getCell(colNumber), rowNumber);
|
||||
});
|
||||
}
|
||||
|
||||
get values() {
|
||||
const v = [];
|
||||
this.eachCell((cell, rowNumber) => {
|
||||
if (cell && cell.type !== Enums.ValueType.Null) {
|
||||
v[rowNumber] = cell.value;
|
||||
}
|
||||
});
|
||||
return v;
|
||||
}
|
||||
|
||||
set values(v) {
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
const colNumber = this.number;
|
||||
let offset = 0;
|
||||
if (v.hasOwnProperty('0')) {
|
||||
// assume contiguous array, start at row 1
|
||||
offset = 1;
|
||||
}
|
||||
v.forEach((value, index) => {
|
||||
this._worksheet.getCell(index + offset, colNumber).value = value;
|
||||
});
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// styles
|
||||
_applyStyle(name, value) {
|
||||
this.style[name] = value;
|
||||
this.eachCell(cell => {
|
||||
cell[name] = value;
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
get numFmt() {
|
||||
return this.style.numFmt;
|
||||
}
|
||||
|
||||
set numFmt(value) {
|
||||
this._applyStyle('numFmt', value);
|
||||
}
|
||||
|
||||
get font() {
|
||||
return this.style.font;
|
||||
}
|
||||
|
||||
set font(value) {
|
||||
this._applyStyle('font', value);
|
||||
}
|
||||
|
||||
get alignment() {
|
||||
return this.style.alignment;
|
||||
}
|
||||
|
||||
set alignment(value) {
|
||||
this._applyStyle('alignment', value);
|
||||
}
|
||||
|
||||
get protection() {
|
||||
return this.style.protection;
|
||||
}
|
||||
|
||||
set protection(value) {
|
||||
this._applyStyle('protection', value);
|
||||
}
|
||||
|
||||
get border() {
|
||||
return this.style.border;
|
||||
}
|
||||
|
||||
set border(value) {
|
||||
this._applyStyle('border', value);
|
||||
}
|
||||
|
||||
get fill() {
|
||||
return this.style.fill;
|
||||
}
|
||||
|
||||
set fill(value) {
|
||||
this._applyStyle('fill', value);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// static functions
|
||||
|
||||
static toModel(columns) {
|
||||
// Convert array of Column into compressed list cols
|
||||
const cols = [];
|
||||
let col = null;
|
||||
if (columns) {
|
||||
columns.forEach((column, index) => {
|
||||
if (column.isDefault) {
|
||||
if (col) {
|
||||
col = null;
|
||||
}
|
||||
} else if (!col || !column.equivalentTo(col)) {
|
||||
col = {
|
||||
min: index + 1,
|
||||
max: index + 1,
|
||||
width: column.width !== undefined ? column.width : DEFAULT_COLUMN_WIDTH,
|
||||
style: column.style,
|
||||
isCustomWidth: column.isCustomWidth,
|
||||
hidden: column.hidden,
|
||||
outlineLevel: column.outlineLevel,
|
||||
collapsed: column.collapsed,
|
||||
};
|
||||
cols.push(col);
|
||||
} else {
|
||||
col.max = index + 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
return cols.length ? cols : undefined;
|
||||
}
|
||||
|
||||
static fromModel(worksheet, cols) {
|
||||
cols = cols || [];
|
||||
const columns = [];
|
||||
let count = 1;
|
||||
let index = 0;
|
||||
/**
|
||||
* sort cols by min
|
||||
* If it is not sorted, the subsequent column configuration will be overwritten
|
||||
* */
|
||||
cols = cols.sort(function(pre, next) {
|
||||
return pre.min - next.min;
|
||||
});
|
||||
while (index < cols.length) {
|
||||
const col = cols[index++];
|
||||
while (count < col.min) {
|
||||
columns.push(new Column(worksheet, count++));
|
||||
}
|
||||
while (count <= col.max) {
|
||||
columns.push(new Column(worksheet, count++, col));
|
||||
}
|
||||
}
|
||||
return columns.length ? columns : null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Column;
|
||||
19
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/data-validations.js
generated
vendored
Normal file
19
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/data-validations.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
class DataValidations {
|
||||
constructor(model) {
|
||||
this.model = model || {};
|
||||
}
|
||||
|
||||
add(address, validation) {
|
||||
return (this.model[address] = validation);
|
||||
}
|
||||
|
||||
find(address) {
|
||||
return this.model[address];
|
||||
}
|
||||
|
||||
remove(address) {
|
||||
this.model[address] = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DataValidations;
|
||||
234
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/data/theme1.json
generated
vendored
Normal file
234
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/data/theme1.json
generated
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
{
|
||||
"TODO:": "This file is for analysis only. Not ready for release",
|
||||
"name": "Office Theme",
|
||||
"themeElements": {
|
||||
"colorScheme": {
|
||||
"name": "Office",
|
||||
"dk1": { "type": "sys", "val": "windowText", "lastClr": "000000" },
|
||||
"lt1": { "type": "sys", "val": "window", "lastClr": "FFFFFF" },
|
||||
"dk2": { "type": "srgb", "val": "44546A" },
|
||||
"lt2": { "type": "srgb", "val": "E7E6E6" },
|
||||
"accent1": { "type": "srgb", "val": "5B9BD5" },
|
||||
"accent2": { "type": "srgb", "val": "ED7D31" },
|
||||
"accent3": { "type": "srgb", "val": "A5A5A5" },
|
||||
"accent4": { "type": "srgb", "val": "FFC000" },
|
||||
"accent5": { "type": "srgb", "val": "4472C4" },
|
||||
"accent6": { "type": "srgb", "val": "70AD47" },
|
||||
"hlink": { "type": "srgb", "val": "0563C1" },
|
||||
"folHlink": { "type": "srgb", "val": "954F72" }
|
||||
},
|
||||
"fontScheme": {
|
||||
"name": "Office",
|
||||
"majorFont": {
|
||||
"latin": { "typeface": "Calibri Light", "panose": "020F0302020204030204" },
|
||||
"ea": { "typeface": "" },
|
||||
"cs": { "typeface": "" },
|
||||
"fonts": [
|
||||
{ "script": "Jpan", "typeface": "游ゴシック Light" },
|
||||
{ "script": "Hang", "typeface": "맑은 고딕" },
|
||||
{ "script": "Hans", "typeface": "等线 Light" },
|
||||
{ "script": "Hant", "typeface": "新細明體" },
|
||||
{ "script": "Arab", "typeface": "Times New Roman" },
|
||||
{ "script": "Hebr", "typeface": "Times New Roman" },
|
||||
{ "script": "Thai", "typeface": "Tahoma" },
|
||||
{ "script": "Ethi", "typeface": "Nyala" },
|
||||
{ "script": "Beng", "typeface": "Vrinda" },
|
||||
{ "script": "Gujr", "typeface": "Shruti" },
|
||||
{ "script": "Khmr", "typeface": "MoolBoran" },
|
||||
{ "script": "Knda", "typeface": "Tunga" },
|
||||
{ "script": "Guru", "typeface": "Raavi" },
|
||||
{ "script": "Cans", "typeface": "Euphemia" },
|
||||
{ "script": "Cher", "typeface": "Plantagenet Cherokee" },
|
||||
{ "script": "Yiii", "typeface": "Microsoft Yi Baiti" },
|
||||
{ "script": "Tibt", "typeface": "Microsoft Himalaya" },
|
||||
{ "script": "Thaa", "typeface": "MV Boli" },
|
||||
{ "script": "Deva", "typeface": "Mangal" },
|
||||
{ "script": "Telu", "typeface": "Gautami" },
|
||||
{ "script": "Taml", "typeface": "Latha" },
|
||||
{ "script": "Syrc", "typeface": "Estrangelo Edessa" },
|
||||
{ "script": "Orya", "typeface": "Kalinga" },
|
||||
{ "script": "Mlym", "typeface": "Kartika" },
|
||||
{ "script": "Laoo", "typeface": "DokChampa" },
|
||||
{ "script": "Sinh", "typeface": "Iskoola Pota" },
|
||||
{ "script": "Mong", "typeface": "Mongolian Baiti" },
|
||||
{ "script": "Viet", "typeface": "Times New Roman" },
|
||||
{ "script": "Uigh", "typeface": "Microsoft Uighur" },
|
||||
{ "script": "Geor", "typeface": "Sylfaen" }
|
||||
]
|
||||
},
|
||||
"minorFont": {
|
||||
"latin": { "typeface": "Calibri Light", "panose": "020F0302020204030204" },
|
||||
"ea": { "typeface": "" },
|
||||
"cs": { "typeface": "" },
|
||||
"fonts": [
|
||||
{ "script":"Jpan", "typeface": "游ゴシック" },
|
||||
{ "script":"Hang", "typeface": "맑은 고딕" },
|
||||
{ "script":"Hans", "typeface": "等线" },
|
||||
{ "script":"Hant", "typeface": "新細明體" },
|
||||
{ "script":"Arab", "typeface": "Arial" },
|
||||
{ "script":"Hebr", "typeface": "Arial" },
|
||||
{ "script":"Thai", "typeface": "Tahoma" },
|
||||
{ "script":"Ethi", "typeface": "Nyala" },
|
||||
{ "script":"Beng", "typeface": "Vrinda" },
|
||||
{ "script":"Gujr", "typeface": "Shruti" },
|
||||
{ "script":"Khmr", "typeface": "DaunPenh" },
|
||||
{ "script":"Knda", "typeface": "Tunga" },
|
||||
{ "script":"Guru", "typeface": "Raavi" },
|
||||
{ "script":"Cans", "typeface": "Euphemia" },
|
||||
{ "script":"Cher", "typeface": "Plantagenet Cherokee" },
|
||||
{ "script":"Yiii", "typeface": "Microsoft Yi Baiti" },
|
||||
{ "script":"Tibt", "typeface": "Microsoft Himalaya" },
|
||||
{ "script":"Thaa", "typeface": "MV Boli" },
|
||||
{ "script":"Deva", "typeface": "Mangal" },
|
||||
{ "script":"Telu", "typeface": "Gautami" },
|
||||
{ "script":"Taml", "typeface": "Latha" },
|
||||
{ "script":"Syrc", "typeface": "Estrangelo Edessa" },
|
||||
{ "script":"Orya", "typeface": "Kalinga" },
|
||||
{ "script":"Mlym", "typeface": "Kartika" },
|
||||
{ "script":"Laoo", "typeface": "DokChampa" },
|
||||
{ "script":"Sinh", "typeface": "Iskoola Pota" },
|
||||
{ "script":"Mong", "typeface": "Mongolian Baiti" },
|
||||
{ "script":"Viet", "typeface": "Arial" },
|
||||
{ "script":"Uigh", "typeface": "Microsoft Uighur" },
|
||||
{ "script":"Geor", "typeface": "Sylfaen" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"fmtScheme": {
|
||||
"name": "Office",
|
||||
"fillStyleLst": [
|
||||
{ "type": "solidFill", "val": "phClr" },
|
||||
{
|
||||
"type": "gradFill",
|
||||
"rotWithShape": true,
|
||||
"gsLst": [
|
||||
{ "pos":0, "schemeClr": { "val": "phClr", "lumMod": 110000, "satMod": 105000, "tint": 67000 } },
|
||||
{ "pos":50000, "schemeClr": { "val": "phClr", "lumMod": 105000, "satMod": 103000, "tint": 73000 } },
|
||||
{ "pos":100000, "schemeClr": { "val": "phClr", "lumMod": 105000, "satMod": 109000, "tint": 81000 } }
|
||||
],
|
||||
"lin": { "ang": 5400000, "scaled": false }
|
||||
},
|
||||
{
|
||||
"type": "gradFill",
|
||||
"rotWithShape": true,
|
||||
"gsLst": [
|
||||
{ "pos":0, "schemeClr": { "val": "phClr", "satMod": 103000, "lumMod": 102000, "tint": 94000 } },
|
||||
{ "pos":50000, "schemeClr": { "val": "phClr", "satMod": 110000, "lumMod": 100000, "shade": 100000 } },
|
||||
{ "pos":100000, "schemeClr": { "val": "phClr", "lumMod": 99000, "satMod": 120000, "tint": 78000 } }
|
||||
],
|
||||
"lin": { "ang": 5400000, "scaled": false }
|
||||
}
|
||||
],
|
||||
"lnStyleLst": [
|
||||
{
|
||||
"w": 6350, "cap": "flat", "cmpd": "sng", "algn": "ctr",
|
||||
"solidFill": { "schemeClr": { "val": "phClr" } },
|
||||
"prstDash": { "val": "solid" },
|
||||
"miter": { "lim": 800000 }
|
||||
},
|
||||
{
|
||||
"w": 12700, "cap": "flat", "cmpd": "sng", "algn": "ctr",
|
||||
"solidFill": { "schemeClr": { "val": "phClr" } },
|
||||
"prstDash": { "val": "solid" },
|
||||
"miter": { "lim": 800000 }
|
||||
},
|
||||
{
|
||||
"w": 19050, "cap": "flat", "cmpd": "sng", "algn": "ctr",
|
||||
"solidFill": { "schemeClr": { "val": "phClr" } },
|
||||
"prstDash": { "val": "solid" },
|
||||
"miter": { "lim": 800000 }
|
||||
}
|
||||
],
|
||||
"effectStyleLst": [
|
||||
{ "effectLst": [] },
|
||||
{ "effectLst": [] },
|
||||
{
|
||||
"effectLst": [
|
||||
{
|
||||
"type": "outerShdw",
|
||||
"blurRad": 57150, "dist": 19050, "dir": 5400000, "algn": "ctr", "rotWithShape": false,
|
||||
"srgbClr": {
|
||||
"val": "000000",
|
||||
"alpha": {"val": 63000 }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"bgFillStyleLst": [
|
||||
{ "type": "solidFill", "schemeClr": { "val": "phClr" } },
|
||||
{ "type": "solidFill", "schemeClr": { "val": "phClr", "tint": 95000, "satMod": 170000 } },
|
||||
{
|
||||
"type": "gradFill",
|
||||
"rotWithShape": true,
|
||||
"gsLst": [
|
||||
{ "pos":0, "schemeClr": { "val": "phClr", "tint": 93000, "satMod": 150000, "shade": 90000, "lumMod": 102000 } },
|
||||
{ "pos":50000, "schemeClr": { "val": "phClr", "tint": 98000, "satMod": 130000, "shade": 73000, "lumMod": 103000 } },
|
||||
{ "pos":100000, "schemeClr": { "val": "phClr", "shade": 63000, "satMod": 120000 } }
|
||||
],
|
||||
"lin": { "ang": 5400000, "scaled": false }
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"objectDefaults": {
|
||||
"spDef": {
|
||||
"spPr": {},
|
||||
"bodyPr": {},
|
||||
"lstStyle": {},
|
||||
"style": {
|
||||
"lnRef": {
|
||||
"idx": 1,
|
||||
"schemeClr": "accent1"
|
||||
},
|
||||
"effectRef": {
|
||||
"idx": 2,
|
||||
"schemeClr": "accent1"
|
||||
},
|
||||
"fillRef": {
|
||||
"idx": 3,
|
||||
"schemeClr": "accent1"
|
||||
},
|
||||
"fontRef": {
|
||||
"idx": "minor",
|
||||
"schemeClr": "lt1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lnDef": {
|
||||
"spPr": {},
|
||||
"bodyPr": {},
|
||||
"lstStyle": {},
|
||||
"style": {
|
||||
"lnRef": {
|
||||
"idx": 2,
|
||||
"schemeClr": "accent1"
|
||||
},
|
||||
"effectRef": {
|
||||
"idx": 0,
|
||||
"schemeClr": "accent1"
|
||||
},
|
||||
"fillRef": {
|
||||
"idx": 1,
|
||||
"schemeClr": "accent1"
|
||||
},
|
||||
"fontRef": {
|
||||
"idx": "minor",
|
||||
"schemeClr": "tx1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"extraClrSchemeLst": [],
|
||||
"extLst": [
|
||||
{
|
||||
"uri": "{05A4C25C-085E-4340-85A3-A5531E510DB2}",
|
||||
"themeFamily": {
|
||||
"name": "Office Theme",
|
||||
"id": "{62F939B6-93AF-4DB8-9C6B-D6C7DFDC589F}",
|
||||
"vid": "{4A3C46E8-61CC-4603-A589-7422A47A8E4A}",
|
||||
"thm15": "http://schemas.microsoft.com/office/thememl/2012/main"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
196
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/defined-names.js
generated
vendored
Normal file
196
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/defined-names.js
generated
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('../utils/under-dash');
|
||||
const colCache = require('../utils/col-cache');
|
||||
const CellMatrix = require('../utils/cell-matrix');
|
||||
const Range = require('./range');
|
||||
|
||||
const rangeRegexp = /[$](\w+)[$](\d+)(:[$](\w+)[$](\d+))?/;
|
||||
|
||||
class DefinedNames {
|
||||
constructor() {
|
||||
this.matrixMap = {};
|
||||
}
|
||||
|
||||
getMatrix(name) {
|
||||
const matrix = this.matrixMap[name] || (this.matrixMap[name] = new CellMatrix());
|
||||
return matrix;
|
||||
}
|
||||
|
||||
// add a name to a cell. locStr in the form SheetName!$col$row or SheetName!$c1$r1:$c2:$r2
|
||||
add(locStr, name) {
|
||||
const location = colCache.decodeEx(locStr);
|
||||
this.addEx(location, name);
|
||||
}
|
||||
|
||||
addEx(location, name) {
|
||||
const matrix = this.getMatrix(name);
|
||||
if (location.top) {
|
||||
for (let col = location.left; col <= location.right; col++) {
|
||||
for (let row = location.top; row <= location.bottom; row++) {
|
||||
const address = {
|
||||
sheetName: location.sheetName,
|
||||
address: colCache.n2l(col) + row,
|
||||
row,
|
||||
col,
|
||||
};
|
||||
|
||||
matrix.addCellEx(address);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
matrix.addCellEx(location);
|
||||
}
|
||||
}
|
||||
|
||||
remove(locStr, name) {
|
||||
const location = colCache.decodeEx(locStr);
|
||||
this.removeEx(location, name);
|
||||
}
|
||||
|
||||
removeEx(location, name) {
|
||||
const matrix = this.getMatrix(name);
|
||||
matrix.removeCellEx(location);
|
||||
}
|
||||
|
||||
removeAllNames(location) {
|
||||
_.each(this.matrixMap, matrix => {
|
||||
matrix.removeCellEx(location);
|
||||
});
|
||||
}
|
||||
|
||||
forEach(callback) {
|
||||
_.each(this.matrixMap, (matrix, name) => {
|
||||
matrix.forEach(cell => {
|
||||
callback(name, cell);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// get all the names of a cell
|
||||
getNames(addressStr) {
|
||||
return this.getNamesEx(colCache.decodeEx(addressStr));
|
||||
}
|
||||
|
||||
getNamesEx(address) {
|
||||
return _.map(this.matrixMap, (matrix, name) => matrix.findCellEx(address) && name).filter(
|
||||
Boolean
|
||||
);
|
||||
}
|
||||
|
||||
_explore(matrix, cell) {
|
||||
cell.mark = false;
|
||||
const {sheetName} = cell;
|
||||
|
||||
const range = new Range(cell.row, cell.col, cell.row, cell.col, sheetName);
|
||||
let x;
|
||||
let y;
|
||||
|
||||
// grow vertical - only one col to worry about
|
||||
function vGrow(yy, edge) {
|
||||
const c = matrix.findCellAt(sheetName, yy, cell.col);
|
||||
if (!c || !c.mark) {
|
||||
return false;
|
||||
}
|
||||
range[edge] = yy;
|
||||
c.mark = false;
|
||||
return true;
|
||||
}
|
||||
for (y = cell.row - 1; vGrow(y, 'top'); y--);
|
||||
for (y = cell.row + 1; vGrow(y, 'bottom'); y++);
|
||||
|
||||
// grow horizontal - ensure all rows can grow
|
||||
function hGrow(xx, edge) {
|
||||
const cells = [];
|
||||
for (y = range.top; y <= range.bottom; y++) {
|
||||
const c = matrix.findCellAt(sheetName, y, xx);
|
||||
if (c && c.mark) {
|
||||
cells.push(c);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
range[edge] = xx;
|
||||
for (let i = 0; i < cells.length; i++) {
|
||||
cells[i].mark = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
for (x = cell.col - 1; hGrow(x, 'left'); x--);
|
||||
for (x = cell.col + 1; hGrow(x, 'right'); x++);
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
getRanges(name, matrix) {
|
||||
matrix = matrix || this.matrixMap[name];
|
||||
|
||||
if (!matrix) {
|
||||
return {name, ranges: []};
|
||||
}
|
||||
|
||||
// mark and sweep!
|
||||
matrix.forEach(cell => {
|
||||
cell.mark = true;
|
||||
});
|
||||
const ranges = matrix
|
||||
.map(cell => cell.mark && this._explore(matrix, cell))
|
||||
.filter(Boolean)
|
||||
.map(range => range.$shortRange);
|
||||
|
||||
return {
|
||||
name,
|
||||
ranges,
|
||||
};
|
||||
}
|
||||
|
||||
normaliseMatrix(matrix, sheetName) {
|
||||
// some of the cells might have shifted on specified sheet
|
||||
// need to reassign rows, cols
|
||||
matrix.forEachInSheet(sheetName, (cell, row, col) => {
|
||||
if (cell) {
|
||||
if (cell.row !== row || cell.col !== col) {
|
||||
cell.row = row;
|
||||
cell.col = col;
|
||||
cell.address = colCache.n2l(col) + row;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
spliceRows(sheetName, start, numDelete, numInsert) {
|
||||
_.each(this.matrixMap, matrix => {
|
||||
matrix.spliceRows(sheetName, start, numDelete, numInsert);
|
||||
this.normaliseMatrix(matrix, sheetName);
|
||||
});
|
||||
}
|
||||
|
||||
spliceColumns(sheetName, start, numDelete, numInsert) {
|
||||
_.each(this.matrixMap, matrix => {
|
||||
matrix.spliceColumns(sheetName, start, numDelete, numInsert);
|
||||
this.normaliseMatrix(matrix, sheetName);
|
||||
});
|
||||
}
|
||||
|
||||
get model() {
|
||||
// To get names per cell - just iterate over all names finding cells if they exist
|
||||
return _.map(this.matrixMap, (matrix, name) => this.getRanges(name, matrix)).filter(
|
||||
definedName => definedName.ranges.length
|
||||
);
|
||||
}
|
||||
|
||||
set model(value) {
|
||||
// value is [ { name, ranges }, ... ]
|
||||
const matrixMap = (this.matrixMap = {});
|
||||
value.forEach(definedName => {
|
||||
const matrix = (matrixMap[definedName.name] = new CellMatrix());
|
||||
definedName.ranges.forEach(rangeStr => {
|
||||
if (rangeRegexp.test(rangeStr.split('!').pop() || '')) {
|
||||
matrix.addCell(rangeStr);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DefinedNames;
|
||||
48
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/enums.js
generated
vendored
Normal file
48
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/enums.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
ValueType: {
|
||||
Null: 0,
|
||||
Merge: 1,
|
||||
Number: 2,
|
||||
String: 3,
|
||||
Date: 4,
|
||||
Hyperlink: 5,
|
||||
Formula: 6,
|
||||
SharedString: 7,
|
||||
RichText: 8,
|
||||
Boolean: 9,
|
||||
Error: 10,
|
||||
},
|
||||
FormulaType: {
|
||||
None: 0,
|
||||
Master: 1,
|
||||
Shared: 2,
|
||||
},
|
||||
RelationshipType: {
|
||||
None: 0,
|
||||
OfficeDocument: 1,
|
||||
Worksheet: 2,
|
||||
CalcChain: 3,
|
||||
SharedStrings: 4,
|
||||
Styles: 5,
|
||||
Theme: 6,
|
||||
Hyperlink: 7,
|
||||
},
|
||||
DocumentType: {
|
||||
Xlsx: 1,
|
||||
},
|
||||
ReadingOrder: {
|
||||
LeftToRight: 1,
|
||||
RightToLeft: 2,
|
||||
},
|
||||
ErrorValue: {
|
||||
NotApplicable: '#N/A',
|
||||
Ref: '#REF!',
|
||||
Name: '#NAME?',
|
||||
DivZero: '#DIV/0!',
|
||||
Null: '#NULL!',
|
||||
Value: '#VALUE!',
|
||||
Num: '#NUM!',
|
||||
},
|
||||
};
|
||||
59
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/image.js
generated
vendored
Normal file
59
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/image.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
const colCache = require('../utils/col-cache');
|
||||
const Anchor = require('./anchor');
|
||||
|
||||
class Image {
|
||||
constructor(worksheet, model) {
|
||||
this.worksheet = worksheet;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
get model() {
|
||||
switch (this.type) {
|
||||
case 'background':
|
||||
return {
|
||||
type: this.type,
|
||||
imageId: this.imageId,
|
||||
};
|
||||
case 'image':
|
||||
return {
|
||||
type: this.type,
|
||||
imageId: this.imageId,
|
||||
hyperlinks: this.range.hyperlinks,
|
||||
range: {
|
||||
tl: this.range.tl.model,
|
||||
br: this.range.br && this.range.br.model,
|
||||
ext: this.range.ext,
|
||||
editAs: this.range.editAs,
|
||||
},
|
||||
};
|
||||
default:
|
||||
throw new Error('Invalid Image Type');
|
||||
}
|
||||
}
|
||||
|
||||
set model({type, imageId, range, hyperlinks}) {
|
||||
this.type = type;
|
||||
this.imageId = imageId;
|
||||
|
||||
if (type === 'image') {
|
||||
if (typeof range === 'string') {
|
||||
const decoded = colCache.decode(range);
|
||||
this.range = {
|
||||
tl: new Anchor(this.worksheet, {col: decoded.left, row: decoded.top}, -1),
|
||||
br: new Anchor(this.worksheet, {col: decoded.right, row: decoded.bottom}, 0),
|
||||
editAs: 'oneCell',
|
||||
};
|
||||
} else {
|
||||
this.range = {
|
||||
tl: new Anchor(this.worksheet, range.tl, 0),
|
||||
br: range.br && new Anchor(this.worksheet, range.br, 0),
|
||||
ext: range.ext,
|
||||
editAs: range.editAs,
|
||||
hyperlinks: hyperlinks || range.hyperlinks,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Image;
|
||||
18
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/modelcontainer.js
generated
vendored
Normal file
18
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/modelcontainer.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
const XLSX = require('../xlsx/xlsx');
|
||||
|
||||
class ModelContainer {
|
||||
constructor(model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
get xlsx() {
|
||||
if (!this._xlsx) {
|
||||
this._xlsx = new XLSX(this);
|
||||
}
|
||||
return this._xlsx;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ModelContainer;
|
||||
65
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/note.js
generated
vendored
Normal file
65
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/note.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
const _ = require('../utils/under-dash');
|
||||
|
||||
class Note {
|
||||
constructor(note) {
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
get model() {
|
||||
let value = null;
|
||||
switch (typeof this.note) {
|
||||
case 'string':
|
||||
value = {
|
||||
type: 'note',
|
||||
note: {
|
||||
texts: [
|
||||
{
|
||||
text: this.note,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
break;
|
||||
default:
|
||||
value = {
|
||||
type: 'note',
|
||||
note: this.note,
|
||||
};
|
||||
break;
|
||||
}
|
||||
// Suitable for all cell comments
|
||||
return _.deepMerge({}, Note.DEFAULT_CONFIGS, value);
|
||||
}
|
||||
|
||||
set model(value) {
|
||||
const {note} = value;
|
||||
const {texts} = note;
|
||||
if (texts.length === 1 && Object.keys(texts[0]).length === 1) {
|
||||
this.note = texts[0].text;
|
||||
} else {
|
||||
this.note = note;
|
||||
}
|
||||
}
|
||||
|
||||
static fromModel(model) {
|
||||
const note = new Note();
|
||||
note.model = model;
|
||||
return note;
|
||||
}
|
||||
}
|
||||
|
||||
Note.DEFAULT_CONFIGS = {
|
||||
note: {
|
||||
margins: {
|
||||
insetmode: 'auto',
|
||||
inset: [0.13, 0.13, 0.25, 0.25],
|
||||
},
|
||||
protection: {
|
||||
locked: 'True',
|
||||
lockText: 'True',
|
||||
},
|
||||
editAs: 'absolute',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = Note;
|
||||
257
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/range.js
generated
vendored
Normal file
257
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/range.js
generated
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
const colCache = require('../utils/col-cache');
|
||||
|
||||
// used by worksheet to calculate sheet dimensions
|
||||
class Range {
|
||||
constructor() {
|
||||
this.decode(arguments);
|
||||
}
|
||||
|
||||
setTLBR(t, l, b, r, s) {
|
||||
if (arguments.length < 4) {
|
||||
// setTLBR(tl, br, s)
|
||||
const tl = colCache.decodeAddress(t);
|
||||
const br = colCache.decodeAddress(l);
|
||||
this.model = {
|
||||
top: Math.min(tl.row, br.row),
|
||||
left: Math.min(tl.col, br.col),
|
||||
bottom: Math.max(tl.row, br.row),
|
||||
right: Math.max(tl.col, br.col),
|
||||
sheetName: b,
|
||||
};
|
||||
|
||||
this.setTLBR(tl.row, tl.col, br.row, br.col, s);
|
||||
} else {
|
||||
// setTLBR(t, l, b, r, s)
|
||||
this.model = {
|
||||
top: Math.min(t, b),
|
||||
left: Math.min(l, r),
|
||||
bottom: Math.max(t, b),
|
||||
right: Math.max(l, r),
|
||||
sheetName: s,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
decode(argv) {
|
||||
switch (argv.length) {
|
||||
case 5: // [t,l,b,r,s]
|
||||
this.setTLBR(argv[0], argv[1], argv[2], argv[3], argv[4]);
|
||||
break;
|
||||
case 4: // [t,l,b,r]
|
||||
this.setTLBR(argv[0], argv[1], argv[2], argv[3]);
|
||||
break;
|
||||
|
||||
case 3: // [tl,br,s]
|
||||
this.setTLBR(argv[0], argv[1], argv[2]);
|
||||
break;
|
||||
case 2: // [tl,br]
|
||||
this.setTLBR(argv[0], argv[1]);
|
||||
break;
|
||||
|
||||
case 1: {
|
||||
const value = argv[0];
|
||||
if (value instanceof Range) {
|
||||
// copy constructor
|
||||
this.model = {
|
||||
top: value.model.top,
|
||||
left: value.model.left,
|
||||
bottom: value.model.bottom,
|
||||
right: value.model.right,
|
||||
sheetName: value.sheetName,
|
||||
};
|
||||
} else if (value instanceof Array) {
|
||||
// an arguments array
|
||||
this.decode(value);
|
||||
} else if (value.top && value.left && value.bottom && value.right) {
|
||||
// a model
|
||||
this.model = {
|
||||
top: value.top,
|
||||
left: value.left,
|
||||
bottom: value.bottom,
|
||||
right: value.right,
|
||||
sheetName: value.sheetName,
|
||||
};
|
||||
} else {
|
||||
// [sheetName!]tl:br
|
||||
const tlbr = colCache.decodeEx(value);
|
||||
if (tlbr.top) {
|
||||
this.model = {
|
||||
top: tlbr.top,
|
||||
left: tlbr.left,
|
||||
bottom: tlbr.bottom,
|
||||
right: tlbr.right,
|
||||
sheetName: tlbr.sheetName,
|
||||
};
|
||||
} else {
|
||||
this.model = {
|
||||
top: tlbr.row,
|
||||
left: tlbr.col,
|
||||
bottom: tlbr.row,
|
||||
right: tlbr.col,
|
||||
sheetName: tlbr.sheetName,
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0:
|
||||
this.model = {
|
||||
top: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Invalid number of arguments to _getDimensions() - ${argv.length}`);
|
||||
}
|
||||
}
|
||||
|
||||
get top() {
|
||||
return this.model.top || 1;
|
||||
}
|
||||
|
||||
set top(value) {
|
||||
this.model.top = value;
|
||||
}
|
||||
|
||||
get left() {
|
||||
return this.model.left || 1;
|
||||
}
|
||||
|
||||
set left(value) {
|
||||
this.model.left = value;
|
||||
}
|
||||
|
||||
get bottom() {
|
||||
return this.model.bottom || 1;
|
||||
}
|
||||
|
||||
set bottom(value) {
|
||||
this.model.bottom = value;
|
||||
}
|
||||
|
||||
get right() {
|
||||
return this.model.right || 1;
|
||||
}
|
||||
|
||||
set right(value) {
|
||||
this.model.right = value;
|
||||
}
|
||||
|
||||
get sheetName() {
|
||||
return this.model.sheetName;
|
||||
}
|
||||
|
||||
set sheetName(value) {
|
||||
this.model.sheetName = value;
|
||||
}
|
||||
|
||||
get _serialisedSheetName() {
|
||||
const {sheetName} = this.model;
|
||||
if (sheetName) {
|
||||
if (/^[a-zA-Z0-9]*$/.test(sheetName)) {
|
||||
return `${sheetName}!`;
|
||||
}
|
||||
return `'${sheetName}'!`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
expand(top, left, bottom, right) {
|
||||
if (!this.model.top || top < this.top) this.top = top;
|
||||
if (!this.model.left || left < this.left) this.left = left;
|
||||
if (!this.model.bottom || bottom > this.bottom) this.bottom = bottom;
|
||||
if (!this.model.right || right > this.right) this.right = right;
|
||||
}
|
||||
|
||||
expandRow(row) {
|
||||
if (row) {
|
||||
const {dimensions, number} = row;
|
||||
if (dimensions) {
|
||||
this.expand(number, dimensions.min, number, dimensions.max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expandToAddress(addressStr) {
|
||||
const address = colCache.decodeEx(addressStr);
|
||||
this.expand(address.row, address.col, address.row, address.col);
|
||||
}
|
||||
|
||||
get tl() {
|
||||
return colCache.n2l(this.left) + this.top;
|
||||
}
|
||||
|
||||
get $t$l() {
|
||||
return `$${colCache.n2l(this.left)}$${this.top}`;
|
||||
}
|
||||
|
||||
get br() {
|
||||
return colCache.n2l(this.right) + this.bottom;
|
||||
}
|
||||
|
||||
get $b$r() {
|
||||
return `$${colCache.n2l(this.right)}$${this.bottom}`;
|
||||
}
|
||||
|
||||
get range() {
|
||||
return `${this._serialisedSheetName + this.tl}:${this.br}`;
|
||||
}
|
||||
|
||||
get $range() {
|
||||
return `${this._serialisedSheetName + this.$t$l}:${this.$b$r}`;
|
||||
}
|
||||
|
||||
get shortRange() {
|
||||
return this.count > 1 ? this.range : this._serialisedSheetName + this.tl;
|
||||
}
|
||||
|
||||
get $shortRange() {
|
||||
return this.count > 1 ? this.$range : this._serialisedSheetName + this.$t$l;
|
||||
}
|
||||
|
||||
get count() {
|
||||
return (1 + this.bottom - this.top) * (1 + this.right - this.left);
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.range;
|
||||
}
|
||||
|
||||
intersects(other) {
|
||||
if (other.sheetName && this.sheetName && other.sheetName !== this.sheetName) return false;
|
||||
if (other.bottom < this.top) return false;
|
||||
if (other.top > this.bottom) return false;
|
||||
if (other.right < this.left) return false;
|
||||
if (other.left > this.right) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
contains(addressStr) {
|
||||
const address = colCache.decodeEx(addressStr);
|
||||
return this.containsEx(address);
|
||||
}
|
||||
|
||||
containsEx(address) {
|
||||
if (address.sheetName && this.sheetName && address.sheetName !== this.sheetName) return false;
|
||||
return (
|
||||
address.row >= this.top &&
|
||||
address.row <= this.bottom &&
|
||||
address.col >= this.left &&
|
||||
address.col <= this.right
|
||||
);
|
||||
}
|
||||
|
||||
forEachAddress(cb) {
|
||||
for (let col = this.left; col <= this.right; col++) {
|
||||
for (let row = this.top; row <= this.bottom; row++) {
|
||||
cb(colCache.encodeAddress(row, col), row, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Range;
|
||||
415
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/row.js
generated
vendored
Normal file
415
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/row.js
generated
vendored
Normal file
@@ -0,0 +1,415 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('../utils/under-dash');
|
||||
|
||||
const Enums = require('./enums');
|
||||
const colCache = require('../utils/col-cache');
|
||||
const Cell = require('./cell');
|
||||
|
||||
class Row {
|
||||
constructor(worksheet, number) {
|
||||
this._worksheet = worksheet;
|
||||
this._number = number;
|
||||
this._cells = [];
|
||||
this.style = {};
|
||||
this.outlineLevel = 0;
|
||||
}
|
||||
|
||||
// return the row number
|
||||
get number() {
|
||||
return this._number;
|
||||
}
|
||||
|
||||
get worksheet() {
|
||||
return this._worksheet;
|
||||
}
|
||||
|
||||
// Inform Streaming Writer that this row (and all rows before it) are complete
|
||||
// and ready to write. Has no effect on Worksheet document
|
||||
commit() {
|
||||
this._worksheet._commitRow(this); // eslint-disable-line no-underscore-dangle
|
||||
}
|
||||
|
||||
// helps GC by breaking cyclic references
|
||||
destroy() {
|
||||
delete this._worksheet;
|
||||
delete this._cells;
|
||||
delete this.style;
|
||||
}
|
||||
|
||||
findCell(colNumber) {
|
||||
return this._cells[colNumber - 1];
|
||||
}
|
||||
|
||||
// given {address, row, col}, find or create new cell
|
||||
getCellEx(address) {
|
||||
let cell = this._cells[address.col - 1];
|
||||
if (!cell) {
|
||||
const column = this._worksheet.getColumn(address.col);
|
||||
cell = new Cell(this, column, address.address);
|
||||
this._cells[address.col - 1] = cell;
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
// get cell by key, letter or column number
|
||||
getCell(col) {
|
||||
if (typeof col === 'string') {
|
||||
// is it a key?
|
||||
const column = this._worksheet.getColumnKey(col);
|
||||
if (column) {
|
||||
col = column.number;
|
||||
} else {
|
||||
col = colCache.l2n(col);
|
||||
}
|
||||
}
|
||||
return (
|
||||
this._cells[col - 1] ||
|
||||
this.getCellEx({
|
||||
address: colCache.encodeAddress(this._number, col),
|
||||
row: this._number,
|
||||
col,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// remove cell(s) and shift all higher cells down by count
|
||||
splice(start, count, ...inserts) {
|
||||
const nKeep = start + count;
|
||||
const nExpand = inserts.length - count;
|
||||
const nEnd = this._cells.length;
|
||||
let i;
|
||||
let cSrc;
|
||||
let cDst;
|
||||
|
||||
if (nExpand < 0) {
|
||||
// remove cells
|
||||
for (i = start + inserts.length; i <= nEnd; i++) {
|
||||
cDst = this._cells[i - 1];
|
||||
cSrc = this._cells[i - nExpand - 1];
|
||||
if (cSrc) {
|
||||
cDst = this.getCell(i);
|
||||
cDst.value = cSrc.value;
|
||||
cDst.style = cSrc.style;
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
cDst._comment = cSrc._comment;
|
||||
} else if (cDst) {
|
||||
cDst.value = null;
|
||||
cDst.style = {};
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
cDst._comment = undefined;
|
||||
}
|
||||
}
|
||||
} else if (nExpand > 0) {
|
||||
// insert new cells
|
||||
for (i = nEnd; i >= nKeep; i--) {
|
||||
cSrc = this._cells[i - 1];
|
||||
if (cSrc) {
|
||||
cDst = this.getCell(i + nExpand);
|
||||
cDst.value = cSrc.value;
|
||||
cDst.style = cSrc.style;
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
cDst._comment = cSrc._comment;
|
||||
} else {
|
||||
this._cells[i + nExpand - 1] = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now add the new values
|
||||
for (i = 0; i < inserts.length; i++) {
|
||||
cDst = this.getCell(start + i);
|
||||
cDst.value = inserts[i];
|
||||
cDst.style = {};
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
cDst._comment = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over all non-null cells in this row
|
||||
eachCell(options, iteratee) {
|
||||
if (!iteratee) {
|
||||
iteratee = options;
|
||||
options = null;
|
||||
}
|
||||
if (options && options.includeEmpty) {
|
||||
const n = this._cells.length;
|
||||
for (let i = 1; i <= n; i++) {
|
||||
iteratee(this.getCell(i), i);
|
||||
}
|
||||
} else {
|
||||
this._cells.forEach((cell, index) => {
|
||||
if (cell && cell.type !== Enums.ValueType.Null) {
|
||||
iteratee(cell, index + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Page Breaks
|
||||
addPageBreak(lft, rght) {
|
||||
const ws = this._worksheet;
|
||||
const left = Math.max(0, lft - 1) || 0;
|
||||
const right = Math.max(0, rght - 1) || 16838;
|
||||
const pb = {
|
||||
id: this._number,
|
||||
max: right,
|
||||
man: 1,
|
||||
};
|
||||
if (left) pb.min = left;
|
||||
|
||||
ws.rowBreaks.push(pb);
|
||||
}
|
||||
|
||||
// return a sparse array of cell values
|
||||
get values() {
|
||||
const values = [];
|
||||
this._cells.forEach(cell => {
|
||||
if (cell && cell.type !== Enums.ValueType.Null) {
|
||||
values[cell.col] = cell.value;
|
||||
}
|
||||
});
|
||||
return values;
|
||||
}
|
||||
|
||||
// set the values by contiguous or sparse array, or by key'd object literal
|
||||
set values(value) {
|
||||
// this operation is not additive - any prior cells are removed
|
||||
this._cells = [];
|
||||
if (!value) {
|
||||
// empty row
|
||||
} else if (value instanceof Array) {
|
||||
let offset = 0;
|
||||
if (value.hasOwnProperty('0')) {
|
||||
// contiguous array - start at column 1
|
||||
offset = 1;
|
||||
}
|
||||
value.forEach((item, index) => {
|
||||
if (item !== undefined) {
|
||||
this.getCellEx({
|
||||
address: colCache.encodeAddress(this._number, index + offset),
|
||||
row: this._number,
|
||||
col: index + offset,
|
||||
}).value = item;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// assume object with column keys
|
||||
this._worksheet.eachColumnKey((column, key) => {
|
||||
if (value[key] !== undefined) {
|
||||
this.getCellEx({
|
||||
address: colCache.encodeAddress(this._number, column.number),
|
||||
row: this._number,
|
||||
col: column.number,
|
||||
}).value = value[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if the row includes at least one cell with a value
|
||||
get hasValues() {
|
||||
return _.some(this._cells, cell => cell && cell.type !== Enums.ValueType.Null);
|
||||
}
|
||||
|
||||
get cellCount() {
|
||||
return this._cells.length;
|
||||
}
|
||||
|
||||
get actualCellCount() {
|
||||
let count = 0;
|
||||
this.eachCell(() => {
|
||||
count++;
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
// get the min and max column number for the non-null cells in this row or null
|
||||
get dimensions() {
|
||||
let min = 0;
|
||||
let max = 0;
|
||||
this._cells.forEach(cell => {
|
||||
if (cell && cell.type !== Enums.ValueType.Null) {
|
||||
if (!min || min > cell.col) {
|
||||
min = cell.col;
|
||||
}
|
||||
if (max < cell.col) {
|
||||
max = cell.col;
|
||||
}
|
||||
}
|
||||
});
|
||||
return min > 0
|
||||
? {
|
||||
min,
|
||||
max,
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// styles
|
||||
_applyStyle(name, value) {
|
||||
this.style[name] = value;
|
||||
this._cells.forEach(cell => {
|
||||
if (cell) {
|
||||
cell[name] = value;
|
||||
}
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
get numFmt() {
|
||||
return this.style.numFmt;
|
||||
}
|
||||
|
||||
set numFmt(value) {
|
||||
this._applyStyle('numFmt', value);
|
||||
}
|
||||
|
||||
get font() {
|
||||
return this.style.font;
|
||||
}
|
||||
|
||||
set font(value) {
|
||||
this._applyStyle('font', value);
|
||||
}
|
||||
|
||||
get alignment() {
|
||||
return this.style.alignment;
|
||||
}
|
||||
|
||||
set alignment(value) {
|
||||
this._applyStyle('alignment', value);
|
||||
}
|
||||
|
||||
get protection() {
|
||||
return this.style.protection;
|
||||
}
|
||||
|
||||
set protection(value) {
|
||||
this._applyStyle('protection', value);
|
||||
}
|
||||
|
||||
get border() {
|
||||
return this.style.border;
|
||||
}
|
||||
|
||||
set border(value) {
|
||||
this._applyStyle('border', value);
|
||||
}
|
||||
|
||||
get fill() {
|
||||
return this.style.fill;
|
||||
}
|
||||
|
||||
set fill(value) {
|
||||
this._applyStyle('fill', value);
|
||||
}
|
||||
|
||||
get hidden() {
|
||||
return !!this._hidden;
|
||||
}
|
||||
|
||||
set hidden(value) {
|
||||
this._hidden = value;
|
||||
}
|
||||
|
||||
get outlineLevel() {
|
||||
return this._outlineLevel || 0;
|
||||
}
|
||||
|
||||
set outlineLevel(value) {
|
||||
this._outlineLevel = value;
|
||||
}
|
||||
|
||||
get collapsed() {
|
||||
return !!(
|
||||
this._outlineLevel && this._outlineLevel >= this._worksheet.properties.outlineLevelRow
|
||||
);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
get model() {
|
||||
const cells = [];
|
||||
let min = 0;
|
||||
let max = 0;
|
||||
this._cells.forEach(cell => {
|
||||
if (cell) {
|
||||
const cellModel = cell.model;
|
||||
if (cellModel) {
|
||||
if (!min || min > cell.col) {
|
||||
min = cell.col;
|
||||
}
|
||||
if (max < cell.col) {
|
||||
max = cell.col;
|
||||
}
|
||||
cells.push(cellModel);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return this.height || cells.length
|
||||
? {
|
||||
cells,
|
||||
number: this.number,
|
||||
min,
|
||||
max,
|
||||
height: this.height,
|
||||
style: this.style,
|
||||
hidden: this.hidden,
|
||||
outlineLevel: this.outlineLevel,
|
||||
collapsed: this.collapsed,
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
set model(value) {
|
||||
if (value.number !== this._number) {
|
||||
throw new Error('Invalid row number in model');
|
||||
}
|
||||
this._cells = [];
|
||||
let previousAddress;
|
||||
value.cells.forEach(cellModel => {
|
||||
switch (cellModel.type) {
|
||||
case Cell.Types.Merge:
|
||||
// special case - don't add this types
|
||||
break;
|
||||
default: {
|
||||
let address;
|
||||
if (cellModel.address) {
|
||||
address = colCache.decodeAddress(cellModel.address);
|
||||
} else if (previousAddress) {
|
||||
// This is a <c> element without an r attribute
|
||||
// Assume that it's the cell for the next column
|
||||
const {row} = previousAddress;
|
||||
const col = previousAddress.col + 1;
|
||||
address = {
|
||||
row,
|
||||
col,
|
||||
address: colCache.encodeAddress(row, col),
|
||||
$col$row: `$${colCache.n2l(col)}$${row}`,
|
||||
};
|
||||
}
|
||||
previousAddress = address;
|
||||
const cell = this.getCellEx(address);
|
||||
cell.model = cellModel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (value.height) {
|
||||
this.height = value.height;
|
||||
} else {
|
||||
delete this.height;
|
||||
}
|
||||
|
||||
this.hidden = value.hidden;
|
||||
this.outlineLevel = value.outlineLevel || 0;
|
||||
|
||||
this.style = (value.style && JSON.parse(JSON.stringify(value.style))) || {};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Row;
|
||||
465
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/table.js
generated
vendored
Normal file
465
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/table.js
generated
vendored
Normal file
@@ -0,0 +1,465 @@
|
||||
/* eslint-disable max-classes-per-file */
|
||||
const colCache = require('../utils/col-cache');
|
||||
|
||||
class Column {
|
||||
// wrapper around column model, allowing access and manipulation
|
||||
constructor(table, column, index) {
|
||||
this.table = table;
|
||||
this.column = column;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
_set(name, value) {
|
||||
this.table.cacheState();
|
||||
this.column[name] = value;
|
||||
}
|
||||
|
||||
/* eslint-disable lines-between-class-members */
|
||||
get name() {
|
||||
return this.column.name;
|
||||
}
|
||||
set name(value) {
|
||||
this._set('name', value);
|
||||
}
|
||||
|
||||
get filterButton() {
|
||||
return this.column.filterButton;
|
||||
}
|
||||
set filterButton(value) {
|
||||
this.column.filterButton = value;
|
||||
}
|
||||
|
||||
get style() {
|
||||
return this.column.style;
|
||||
}
|
||||
set style(value) {
|
||||
this.column.style = value;
|
||||
}
|
||||
|
||||
get totalsRowLabel() {
|
||||
return this.column.totalsRowLabel;
|
||||
}
|
||||
set totalsRowLabel(value) {
|
||||
this._set('totalsRowLabel', value);
|
||||
}
|
||||
|
||||
get totalsRowFunction() {
|
||||
return this.column.totalsRowFunction;
|
||||
}
|
||||
set totalsRowFunction(value) {
|
||||
this._set('totalsRowFunction', value);
|
||||
}
|
||||
|
||||
get totalsRowResult() {
|
||||
return this.column.totalsRowResult;
|
||||
}
|
||||
set totalsRowResult(value) {
|
||||
this._set('totalsRowResult', value);
|
||||
}
|
||||
|
||||
get totalsRowFormula() {
|
||||
return this.column.totalsRowFormula;
|
||||
}
|
||||
set totalsRowFormula(value) {
|
||||
this._set('totalsRowFormula', value);
|
||||
}
|
||||
/* eslint-enable lines-between-class-members */
|
||||
}
|
||||
|
||||
class Table {
|
||||
constructor(worksheet, table) {
|
||||
this.worksheet = worksheet;
|
||||
if (table) {
|
||||
this.table = table;
|
||||
// check things are ok first
|
||||
this.validate();
|
||||
|
||||
this.store();
|
||||
}
|
||||
}
|
||||
|
||||
getFormula(column) {
|
||||
// get the correct formula to apply to the totals row
|
||||
switch (column.totalsRowFunction) {
|
||||
case 'none':
|
||||
return null;
|
||||
case 'average':
|
||||
return `SUBTOTAL(101,${this.table.name}[${column.name}])`;
|
||||
case 'countNums':
|
||||
return `SUBTOTAL(102,${this.table.name}[${column.name}])`;
|
||||
case 'count':
|
||||
return `SUBTOTAL(103,${this.table.name}[${column.name}])`;
|
||||
case 'max':
|
||||
return `SUBTOTAL(104,${this.table.name}[${column.name}])`;
|
||||
case 'min':
|
||||
return `SUBTOTAL(105,${this.table.name}[${column.name}])`;
|
||||
case 'stdDev':
|
||||
return `SUBTOTAL(106,${this.table.name}[${column.name}])`;
|
||||
case 'var':
|
||||
return `SUBTOTAL(107,${this.table.name}[${column.name}])`;
|
||||
case 'sum':
|
||||
return `SUBTOTAL(109,${this.table.name}[${column.name}])`;
|
||||
case 'custom':
|
||||
return column.totalsRowFormula;
|
||||
default:
|
||||
throw new Error(`Invalid Totals Row Function: ${column.totalsRowFunction}`);
|
||||
}
|
||||
}
|
||||
|
||||
get width() {
|
||||
// width of the table
|
||||
return this.table.columns.length;
|
||||
}
|
||||
|
||||
get height() {
|
||||
// height of the table data
|
||||
return this.table.rows.length;
|
||||
}
|
||||
|
||||
get filterHeight() {
|
||||
// height of the table data plus optional header row
|
||||
return this.height + (this.table.headerRow ? 1 : 0);
|
||||
}
|
||||
|
||||
get tableHeight() {
|
||||
// full height of the table on the sheet
|
||||
return this.filterHeight + (this.table.totalsRow ? 1 : 0);
|
||||
}
|
||||
|
||||
validate() {
|
||||
const {table} = this;
|
||||
// set defaults and check is valid
|
||||
const assign = (o, name, dflt) => {
|
||||
if (o[name] === undefined) {
|
||||
o[name] = dflt;
|
||||
}
|
||||
};
|
||||
assign(table, 'headerRow', true);
|
||||
assign(table, 'totalsRow', false);
|
||||
|
||||
assign(table, 'style', {});
|
||||
assign(table.style, 'theme', 'TableStyleMedium2');
|
||||
assign(table.style, 'showFirstColumn', false);
|
||||
assign(table.style, 'showLastColumn', false);
|
||||
assign(table.style, 'showRowStripes', false);
|
||||
assign(table.style, 'showColumnStripes', false);
|
||||
|
||||
const assert = (test, message) => {
|
||||
if (!test) {
|
||||
throw new Error(message);
|
||||
}
|
||||
};
|
||||
assert(table.ref, 'Table must have ref');
|
||||
assert(table.columns, 'Table must have column definitions');
|
||||
assert(table.rows, 'Table must have row definitions');
|
||||
|
||||
table.tl = colCache.decodeAddress(table.ref);
|
||||
const {row, col} = table.tl;
|
||||
assert(row > 0, 'Table must be on valid row');
|
||||
assert(col > 0, 'Table must be on valid col');
|
||||
|
||||
const {width, filterHeight, tableHeight} = this;
|
||||
|
||||
// autoFilterRef is a range that includes optional headers only
|
||||
table.autoFilterRef = colCache.encode(row, col, row + filterHeight - 1, col + width - 1);
|
||||
|
||||
// tableRef is a range that includes optional headers and totals
|
||||
table.tableRef = colCache.encode(row, col, row + tableHeight - 1, col + width - 1);
|
||||
|
||||
table.columns.forEach((column, i) => {
|
||||
assert(column.name, `Column ${i} must have a name`);
|
||||
if (i === 0) {
|
||||
assign(column, 'totalsRowLabel', 'Total');
|
||||
} else {
|
||||
assign(column, 'totalsRowFunction', 'none');
|
||||
column.totalsRowFormula = this.getFormula(column);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
store() {
|
||||
// where the table needs to store table data, headers, footers in
|
||||
// the sheet...
|
||||
const assignStyle = (cell, style) => {
|
||||
if (style) {
|
||||
Object.keys(style).forEach(key => {
|
||||
cell[key] = style[key];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const {worksheet, table} = this;
|
||||
const {row, col} = table.tl;
|
||||
let count = 0;
|
||||
if (table.headerRow) {
|
||||
const r = worksheet.getRow(row + count++);
|
||||
table.columns.forEach((column, j) => {
|
||||
const {style, name} = column;
|
||||
const cell = r.getCell(col + j);
|
||||
cell.value = name;
|
||||
assignStyle(cell, style);
|
||||
});
|
||||
}
|
||||
table.rows.forEach(data => {
|
||||
const r = worksheet.getRow(row + count++);
|
||||
data.forEach((value, j) => {
|
||||
const cell = r.getCell(col + j);
|
||||
cell.value = value;
|
||||
|
||||
assignStyle(cell, table.columns[j].style);
|
||||
});
|
||||
});
|
||||
|
||||
if (table.totalsRow) {
|
||||
const r = worksheet.getRow(row + count++);
|
||||
table.columns.forEach((column, j) => {
|
||||
const cell = r.getCell(col + j);
|
||||
if (j === 0) {
|
||||
cell.value = column.totalsRowLabel;
|
||||
} else {
|
||||
const formula = this.getFormula(column);
|
||||
if (formula) {
|
||||
cell.value = {
|
||||
formula: column.totalsRowFormula,
|
||||
result: column.totalsRowResult,
|
||||
};
|
||||
} else {
|
||||
cell.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
assignStyle(cell, column.style);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
load(worksheet) {
|
||||
// where the table will read necessary features from a loaded sheet
|
||||
const {table} = this;
|
||||
const {row, col} = table.tl;
|
||||
let count = 0;
|
||||
if (table.headerRow) {
|
||||
const r = worksheet.getRow(row + count++);
|
||||
table.columns.forEach((column, j) => {
|
||||
const cell = r.getCell(col + j);
|
||||
cell.value = column.name;
|
||||
});
|
||||
}
|
||||
table.rows.forEach(data => {
|
||||
const r = worksheet.getRow(row + count++);
|
||||
data.forEach((value, j) => {
|
||||
const cell = r.getCell(col + j);
|
||||
cell.value = value;
|
||||
});
|
||||
});
|
||||
|
||||
if (table.totalsRow) {
|
||||
const r = worksheet.getRow(row + count++);
|
||||
table.columns.forEach((column, j) => {
|
||||
const cell = r.getCell(col + j);
|
||||
if (j === 0) {
|
||||
cell.value = column.totalsRowLabel;
|
||||
} else {
|
||||
const formula = this.getFormula(column);
|
||||
if (formula) {
|
||||
cell.value = {
|
||||
formula: column.totalsRowFormula,
|
||||
result: column.totalsRowResult,
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get model() {
|
||||
return this.table;
|
||||
}
|
||||
|
||||
set model(value) {
|
||||
this.table = value;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// TODO: Mutating methods
|
||||
cacheState() {
|
||||
if (!this._cache) {
|
||||
this._cache = {
|
||||
ref: this.ref,
|
||||
width: this.width,
|
||||
tableHeight: this.tableHeight,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
commit() {
|
||||
// changes may have been made that might have on-sheet effects
|
||||
if (!this._cache) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check things are ok first
|
||||
this.validate();
|
||||
|
||||
const ref = colCache.decodeAddress(this._cache.ref);
|
||||
if (this.ref !== this._cache.ref) {
|
||||
// wipe out whole table footprint at previous location
|
||||
for (let i = 0; i < this._cache.tableHeight; i++) {
|
||||
const row = this.worksheet.getRow(ref.row + i);
|
||||
for (let j = 0; j < this._cache.width; j++) {
|
||||
const cell = row.getCell(ref.col + j);
|
||||
cell.value = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// clear out below table if it has shrunk
|
||||
for (let i = this.tableHeight; i < this._cache.tableHeight; i++) {
|
||||
const row = this.worksheet.getRow(ref.row + i);
|
||||
for (let j = 0; j < this._cache.width; j++) {
|
||||
const cell = row.getCell(ref.col + j);
|
||||
cell.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
// clear out to right of table if it has lost columns
|
||||
for (let i = 0; i < this.tableHeight; i++) {
|
||||
const row = this.worksheet.getRow(ref.row + i);
|
||||
for (let j = this.width; j < this._cache.width; j++) {
|
||||
const cell = row.getCell(ref.col + j);
|
||||
cell.value = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.store();
|
||||
}
|
||||
|
||||
addRow(values, rowNumber) {
|
||||
// Add a row of data, either insert at rowNumber or append
|
||||
this.cacheState();
|
||||
|
||||
if (rowNumber === undefined) {
|
||||
this.table.rows.push(values);
|
||||
} else {
|
||||
this.table.rows.splice(rowNumber, 0, values);
|
||||
}
|
||||
}
|
||||
|
||||
removeRows(rowIndex, count = 1) {
|
||||
// Remove a rows of data
|
||||
this.cacheState();
|
||||
this.table.rows.splice(rowIndex, count);
|
||||
}
|
||||
|
||||
getColumn(colIndex) {
|
||||
const column = this.table.columns[colIndex];
|
||||
return new Column(this, column, colIndex);
|
||||
}
|
||||
|
||||
addColumn(column, values, colIndex) {
|
||||
// Add a new column, including column defn and values
|
||||
// Inserts at colNumber or adds to the right
|
||||
this.cacheState();
|
||||
|
||||
if (colIndex === undefined) {
|
||||
this.table.columns.push(column);
|
||||
this.table.rows.forEach((row, i) => {
|
||||
row.push(values[i]);
|
||||
});
|
||||
} else {
|
||||
this.table.columns.splice(colIndex, 0, column);
|
||||
this.table.rows.forEach((row, i) => {
|
||||
row.splice(colIndex, 0, values[i]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
removeColumns(colIndex, count = 1) {
|
||||
// Remove a column with data
|
||||
this.cacheState();
|
||||
|
||||
this.table.columns.splice(colIndex, count);
|
||||
this.table.rows.forEach(row => {
|
||||
row.splice(colIndex, count);
|
||||
});
|
||||
}
|
||||
|
||||
_assign(target, prop, value) {
|
||||
this.cacheState();
|
||||
target[prop] = value;
|
||||
}
|
||||
|
||||
/* eslint-disable lines-between-class-members */
|
||||
get ref() {
|
||||
return this.table.ref;
|
||||
}
|
||||
set ref(value) {
|
||||
this._assign(this.table, 'ref', value);
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.table.name;
|
||||
}
|
||||
set name(value) {
|
||||
this.table.name = value;
|
||||
}
|
||||
|
||||
get displayName() {
|
||||
return this.table.displyName || this.table.name;
|
||||
}
|
||||
set displayNamename(value) {
|
||||
this.table.displayName = value;
|
||||
}
|
||||
|
||||
get headerRow() {
|
||||
return this.table.headerRow;
|
||||
}
|
||||
set headerRow(value) {
|
||||
this._assign(this.table, 'headerRow', value);
|
||||
}
|
||||
|
||||
get totalsRow() {
|
||||
return this.table.totalsRow;
|
||||
}
|
||||
set totalsRow(value) {
|
||||
this._assign(this.table, 'totalsRow', value);
|
||||
}
|
||||
|
||||
get theme() {
|
||||
return this.table.style.name;
|
||||
}
|
||||
set theme(value) {
|
||||
this.table.style.name = value;
|
||||
}
|
||||
|
||||
get showFirstColumn() {
|
||||
return this.table.style.showFirstColumn;
|
||||
}
|
||||
set showFirstColumn(value) {
|
||||
this.table.style.showFirstColumn = value;
|
||||
}
|
||||
|
||||
get showLastColumn() {
|
||||
return this.table.style.showLastColumn;
|
||||
}
|
||||
set showLastColumn(value) {
|
||||
this.table.style.showLastColumn = value;
|
||||
}
|
||||
|
||||
get showRowStripes() {
|
||||
return this.table.style.showRowStripes;
|
||||
}
|
||||
set showRowStripes(value) {
|
||||
this.table.style.showRowStripes = value;
|
||||
}
|
||||
|
||||
get showColumnStripes() {
|
||||
return this.table.style.showColumnStripes;
|
||||
}
|
||||
set showColumnStripes(value) {
|
||||
this.table.style.showColumnStripes = value;
|
||||
}
|
||||
/* eslint-enable lines-between-class-members */
|
||||
}
|
||||
|
||||
module.exports = Table;
|
||||
221
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/workbook.js
generated
vendored
Normal file
221
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/workbook.js
generated
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
'use strict';
|
||||
|
||||
const Worksheet = require('./worksheet');
|
||||
const DefinedNames = require('./defined-names');
|
||||
const XLSX = require('../xlsx/xlsx');
|
||||
const CSV = require('../csv/csv');
|
||||
|
||||
// Workbook requirements
|
||||
// Load and Save from file and stream
|
||||
// Access/Add/Delete individual worksheets
|
||||
// Manage String table, Hyperlink table, etc.
|
||||
// Manage scaffolding for contained objects to write to/read from
|
||||
|
||||
class Workbook {
|
||||
constructor() {
|
||||
this.category = '';
|
||||
this.company = '';
|
||||
this.created = new Date();
|
||||
this.description = '';
|
||||
this.keywords = '';
|
||||
this.manager = '';
|
||||
this.modified = this.created;
|
||||
this.properties = {};
|
||||
this.calcProperties = {};
|
||||
this._worksheets = [];
|
||||
this.subject = '';
|
||||
this.title = '';
|
||||
this.views = [];
|
||||
this.media = [];
|
||||
this._definedNames = new DefinedNames();
|
||||
}
|
||||
|
||||
get xlsx() {
|
||||
if (!this._xlsx) this._xlsx = new XLSX(this);
|
||||
return this._xlsx;
|
||||
}
|
||||
|
||||
get csv() {
|
||||
if (!this._csv) this._csv = new CSV(this);
|
||||
return this._csv;
|
||||
}
|
||||
|
||||
get nextId() {
|
||||
// find the next unique spot to add worksheet
|
||||
for (let i = 1; i < this._worksheets.length; i++) {
|
||||
if (!this._worksheets[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return this._worksheets.length || 1;
|
||||
}
|
||||
|
||||
addWorksheet(name, options) {
|
||||
const id = this.nextId;
|
||||
|
||||
// if options is a color, call it tabColor (and signal deprecated message)
|
||||
if (options) {
|
||||
if (typeof options === 'string') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.trace(
|
||||
'tabColor argument is now deprecated. Please use workbook.addWorksheet(name, {properties: { tabColor: { argb: "rbg value" } }'
|
||||
);
|
||||
options = {
|
||||
properties: {
|
||||
tabColor: {argb: options},
|
||||
},
|
||||
};
|
||||
} else if (options.argb || options.theme || options.indexed) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.trace(
|
||||
'tabColor argument is now deprecated. Please use workbook.addWorksheet(name, {properties: { tabColor: { ... } }'
|
||||
);
|
||||
options = {
|
||||
properties: {
|
||||
tabColor: options,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const lastOrderNo = this._worksheets.reduce((acc, ws) => ((ws && ws.orderNo) > acc ? ws.orderNo : acc), 0);
|
||||
const worksheetOptions = Object.assign({}, options, {
|
||||
id,
|
||||
name,
|
||||
orderNo: lastOrderNo + 1,
|
||||
workbook: this,
|
||||
});
|
||||
|
||||
const worksheet = new Worksheet(worksheetOptions);
|
||||
|
||||
this._worksheets[id] = worksheet;
|
||||
return worksheet;
|
||||
}
|
||||
|
||||
removeWorksheetEx(worksheet) {
|
||||
delete this._worksheets[worksheet.id];
|
||||
}
|
||||
|
||||
removeWorksheet(id) {
|
||||
const worksheet = this.getWorksheet(id);
|
||||
if (worksheet) {
|
||||
worksheet.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
getWorksheet(id) {
|
||||
if (id === undefined) {
|
||||
return this._worksheets.find(Boolean);
|
||||
}
|
||||
if (typeof id === 'number') {
|
||||
return this._worksheets[id];
|
||||
}
|
||||
if (typeof id === 'string') {
|
||||
return this._worksheets.find(worksheet => worksheet && worksheet.name === id);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
get worksheets() {
|
||||
// return a clone of _worksheets
|
||||
return this._worksheets
|
||||
.slice(1)
|
||||
.sort((a, b) => a.orderNo - b.orderNo)
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
eachSheet(iteratee) {
|
||||
this.worksheets.forEach(sheet => {
|
||||
iteratee(sheet, sheet.id);
|
||||
});
|
||||
}
|
||||
|
||||
get definedNames() {
|
||||
return this._definedNames;
|
||||
}
|
||||
|
||||
clearThemes() {
|
||||
// Note: themes are not an exposed feature, meddle at your peril!
|
||||
this._themes = undefined;
|
||||
}
|
||||
|
||||
addImage(image) {
|
||||
// TODO: validation?
|
||||
const id = this.media.length;
|
||||
this.media.push(Object.assign({}, image, {type: 'image'}));
|
||||
return id;
|
||||
}
|
||||
|
||||
getImage(id) {
|
||||
return this.media[id];
|
||||
}
|
||||
|
||||
get model() {
|
||||
return {
|
||||
creator: this.creator || 'Unknown',
|
||||
lastModifiedBy: this.lastModifiedBy || 'Unknown',
|
||||
lastPrinted: this.lastPrinted,
|
||||
created: this.created,
|
||||
modified: this.modified,
|
||||
properties: this.properties,
|
||||
worksheets: this.worksheets.map(worksheet => worksheet.model),
|
||||
sheets: this.worksheets.map(ws => ws.model).filter(Boolean),
|
||||
definedNames: this._definedNames.model,
|
||||
views: this.views,
|
||||
company: this.company,
|
||||
manager: this.manager,
|
||||
title: this.title,
|
||||
subject: this.subject,
|
||||
keywords: this.keywords,
|
||||
category: this.category,
|
||||
description: this.description,
|
||||
language: this.language,
|
||||
revision: this.revision,
|
||||
contentStatus: this.contentStatus,
|
||||
themes: this._themes,
|
||||
media: this.media,
|
||||
calcProperties: this.calcProperties,
|
||||
};
|
||||
}
|
||||
|
||||
set model(value) {
|
||||
this.creator = value.creator;
|
||||
this.lastModifiedBy = value.lastModifiedBy;
|
||||
this.lastPrinted = value.lastPrinted;
|
||||
this.created = value.created;
|
||||
this.modified = value.modified;
|
||||
this.company = value.company;
|
||||
this.manager = value.manager;
|
||||
this.title = value.title;
|
||||
this.subject = value.subject;
|
||||
this.keywords = value.keywords;
|
||||
this.category = value.category;
|
||||
this.description = value.description;
|
||||
this.language = value.language;
|
||||
this.revision = value.revision;
|
||||
this.contentStatus = value.contentStatus;
|
||||
|
||||
this.properties = value.properties;
|
||||
this.calcProperties = value.calcProperties;
|
||||
this._worksheets = [];
|
||||
value.worksheets.forEach(worksheetModel => {
|
||||
const {id, name, state} = worksheetModel;
|
||||
const orderNo = value.sheets && value.sheets.findIndex(ws => ws.id === id);
|
||||
const worksheet = (this._worksheets[id] = new Worksheet({
|
||||
id,
|
||||
name,
|
||||
orderNo,
|
||||
state,
|
||||
workbook: this,
|
||||
}));
|
||||
worksheet.model = worksheetModel;
|
||||
});
|
||||
|
||||
this._definedNames.model = value.definedNames;
|
||||
this.views = value.views;
|
||||
this._themes = value.themes;
|
||||
this.media = value.media || [];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Workbook;
|
||||
927
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/worksheet.js
generated
vendored
Normal file
927
doc/test-data/purchase_transaction/node_modules/exceljs/lib/doc/worksheet.js
generated
vendored
Normal file
@@ -0,0 +1,927 @@
|
||||
const _ = require('../utils/under-dash');
|
||||
|
||||
const colCache = require('../utils/col-cache');
|
||||
const Range = require('./range');
|
||||
const Row = require('./row');
|
||||
const Column = require('./column');
|
||||
const Enums = require('./enums');
|
||||
const Image = require('./image');
|
||||
const Table = require('./table');
|
||||
const DataValidations = require('./data-validations');
|
||||
const Encryptor = require('../utils/encryptor');
|
||||
const {copyStyle} = require('../utils/copy-style');
|
||||
|
||||
// Worksheet requirements
|
||||
// Operate as sheet inside workbook or standalone
|
||||
// Load and Save from file and stream
|
||||
// Access/Add/Delete individual cells
|
||||
// Manage column widths and row heights
|
||||
|
||||
class Worksheet {
|
||||
constructor(options) {
|
||||
options = options || {};
|
||||
this._workbook = options.workbook;
|
||||
|
||||
// in a workbook, each sheet will have a number
|
||||
this.id = options.id;
|
||||
this.orderNo = options.orderNo;
|
||||
|
||||
// and a name
|
||||
this.name = options.name;
|
||||
|
||||
// add a state
|
||||
this.state = options.state || 'visible';
|
||||
|
||||
// rows allows access organised by row. Sparse array of arrays indexed by row-1, col
|
||||
// Note: _rows is zero based. Must subtract 1 to go from cell.row to index
|
||||
this._rows = [];
|
||||
|
||||
// column definitions
|
||||
this._columns = null;
|
||||
|
||||
// column keys (addRow convenience): key ==> this._collumns index
|
||||
this._keys = {};
|
||||
|
||||
// keep record of all merges
|
||||
this._merges = {};
|
||||
|
||||
// record of all row and column pageBreaks
|
||||
this.rowBreaks = [];
|
||||
|
||||
// for tabColor, default row height, outline levels, etc
|
||||
this.properties = Object.assign(
|
||||
{},
|
||||
{
|
||||
defaultRowHeight: 15,
|
||||
dyDescent: 55,
|
||||
outlineLevelCol: 0,
|
||||
outlineLevelRow: 0,
|
||||
},
|
||||
options.properties
|
||||
);
|
||||
|
||||
// for all things printing
|
||||
this.pageSetup = Object.assign(
|
||||
{},
|
||||
{
|
||||
margins: {left: 0.7, right: 0.7, top: 0.75, bottom: 0.75, header: 0.3, footer: 0.3},
|
||||
orientation: 'portrait',
|
||||
horizontalDpi: 4294967295,
|
||||
verticalDpi: 4294967295,
|
||||
fitToPage: !!(
|
||||
options.pageSetup &&
|
||||
(options.pageSetup.fitToWidth || options.pageSetup.fitToHeight) &&
|
||||
!options.pageSetup.scale
|
||||
),
|
||||
pageOrder: 'downThenOver',
|
||||
blackAndWhite: false,
|
||||
draft: false,
|
||||
cellComments: 'None',
|
||||
errors: 'displayed',
|
||||
scale: 100,
|
||||
fitToWidth: 1,
|
||||
fitToHeight: 1,
|
||||
paperSize: undefined,
|
||||
showRowColHeaders: false,
|
||||
showGridLines: false,
|
||||
firstPageNumber: undefined,
|
||||
horizontalCentered: false,
|
||||
verticalCentered: false,
|
||||
rowBreaks: null,
|
||||
colBreaks: null,
|
||||
},
|
||||
options.pageSetup
|
||||
);
|
||||
|
||||
this.headerFooter = Object.assign(
|
||||
{},
|
||||
{
|
||||
differentFirst: false,
|
||||
differentOddEven: false,
|
||||
oddHeader: null,
|
||||
oddFooter: null,
|
||||
evenHeader: null,
|
||||
evenFooter: null,
|
||||
firstHeader: null,
|
||||
firstFooter: null,
|
||||
},
|
||||
options.headerFooter
|
||||
);
|
||||
|
||||
this.dataValidations = new DataValidations();
|
||||
|
||||
// for freezepanes, split, zoom, gridlines, etc
|
||||
this.views = options.views || [];
|
||||
|
||||
this.autoFilter = options.autoFilter || null;
|
||||
|
||||
// for images, etc
|
||||
this._media = [];
|
||||
|
||||
// worksheet protection
|
||||
this.sheetProtection = null;
|
||||
|
||||
// for tables
|
||||
this.tables = {};
|
||||
|
||||
this.conditionalFormattings = [];
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
set name(name) {
|
||||
if (name === undefined) {
|
||||
name = `sheet${this.id}`;
|
||||
}
|
||||
|
||||
if (this._name === name) return;
|
||||
|
||||
if (typeof name !== 'string') {
|
||||
throw new Error('The name has to be a string.');
|
||||
}
|
||||
|
||||
if (name === '') {
|
||||
throw new Error('The name can\'t be empty.');
|
||||
}
|
||||
|
||||
if (name === 'History') {
|
||||
throw new Error('The name "History" is protected. Please use a different name.');
|
||||
}
|
||||
|
||||
// Illegal character in worksheet name: asterisk (*), question mark (?),
|
||||
// colon (:), forward slash (/ \), or bracket ([])
|
||||
if (/[*?:/\\[\]]/.test(name)) {
|
||||
throw new Error(`Worksheet name ${name} cannot include any of the following characters: * ? : \\ / [ ]`);
|
||||
}
|
||||
|
||||
if (/(^')|('$)/.test(name)) {
|
||||
throw new Error(`The first or last character of worksheet name cannot be a single quotation mark: ${name}`);
|
||||
}
|
||||
|
||||
if (name && name.length > 31) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`Worksheet name ${name} exceeds 31 chars. This will be truncated`);
|
||||
name = name.substring(0, 31);
|
||||
}
|
||||
|
||||
if (this._workbook._worksheets.find(ws => ws && ws.name.toLowerCase() === name.toLowerCase())) {
|
||||
throw new Error(`Worksheet name already exists: ${name}`);
|
||||
}
|
||||
|
||||
this._name = name;
|
||||
}
|
||||
|
||||
get workbook() {
|
||||
return this._workbook;
|
||||
}
|
||||
|
||||
// when you're done with this worksheet, call this to remove from workbook
|
||||
destroy() {
|
||||
this._workbook.removeWorksheetEx(this);
|
||||
}
|
||||
|
||||
// Get the bounding range of the cells in this worksheet
|
||||
get dimensions() {
|
||||
const dimensions = new Range();
|
||||
this._rows.forEach(row => {
|
||||
if (row) {
|
||||
const rowDims = row.dimensions;
|
||||
if (rowDims) {
|
||||
dimensions.expand(row.number, rowDims.min, row.number, rowDims.max);
|
||||
}
|
||||
}
|
||||
});
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Columns
|
||||
|
||||
// get the current columns array.
|
||||
get columns() {
|
||||
return this._columns;
|
||||
}
|
||||
|
||||
// set the columns from an array of column definitions.
|
||||
// Note: any headers defined will overwrite existing values.
|
||||
set columns(value) {
|
||||
// calculate max header row count
|
||||
this._headerRowCount = value.reduce((pv, cv) => {
|
||||
const headerCount = (cv.header && 1) || (cv.headers && cv.headers.length) || 0;
|
||||
return Math.max(pv, headerCount);
|
||||
}, 0);
|
||||
|
||||
// construct Column objects
|
||||
let count = 1;
|
||||
const columns = (this._columns = []);
|
||||
value.forEach(defn => {
|
||||
const column = new Column(this, count++, false);
|
||||
columns.push(column);
|
||||
column.defn = defn;
|
||||
});
|
||||
}
|
||||
|
||||
getColumnKey(key) {
|
||||
return this._keys[key];
|
||||
}
|
||||
|
||||
setColumnKey(key, value) {
|
||||
this._keys[key] = value;
|
||||
}
|
||||
|
||||
deleteColumnKey(key) {
|
||||
delete this._keys[key];
|
||||
}
|
||||
|
||||
eachColumnKey(f) {
|
||||
_.each(this._keys, f);
|
||||
}
|
||||
|
||||
// get a single column by col number. If it doesn't exist, create it and any gaps before it
|
||||
getColumn(c) {
|
||||
if (typeof c === 'string') {
|
||||
// if it matches a key'd column, return that
|
||||
const col = this._keys[c];
|
||||
if (col) return col;
|
||||
|
||||
// otherwise, assume letter
|
||||
c = colCache.l2n(c);
|
||||
}
|
||||
if (!this._columns) {
|
||||
this._columns = [];
|
||||
}
|
||||
if (c > this._columns.length) {
|
||||
let n = this._columns.length + 1;
|
||||
while (n <= c) {
|
||||
this._columns.push(new Column(this, n++));
|
||||
}
|
||||
}
|
||||
return this._columns[c - 1];
|
||||
}
|
||||
|
||||
spliceColumns(start, count, ...inserts) {
|
||||
const rows = this._rows;
|
||||
const nRows = rows.length;
|
||||
if (inserts.length > 0) {
|
||||
// must iterate over all rows whether they exist yet or not
|
||||
for (let i = 0; i < nRows; i++) {
|
||||
const rowArguments = [start, count];
|
||||
// eslint-disable-next-line no-loop-func
|
||||
inserts.forEach(insert => {
|
||||
rowArguments.push(insert[i] || null);
|
||||
});
|
||||
const row = this.getRow(i + 1);
|
||||
// eslint-disable-next-line prefer-spread
|
||||
row.splice.apply(row, rowArguments);
|
||||
}
|
||||
} else {
|
||||
// nothing to insert, so just splice all rows
|
||||
this._rows.forEach(r => {
|
||||
if (r) {
|
||||
r.splice(start, count);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// splice column definitions
|
||||
const nExpand = inserts.length - count;
|
||||
const nKeep = start + count;
|
||||
const nEnd = this._columns.length;
|
||||
if (nExpand < 0) {
|
||||
for (let i = start + inserts.length; i <= nEnd; i++) {
|
||||
this.getColumn(i).defn = this.getColumn(i - nExpand).defn;
|
||||
}
|
||||
} else if (nExpand > 0) {
|
||||
for (let i = nEnd; i >= nKeep; i--) {
|
||||
this.getColumn(i + nExpand).defn = this.getColumn(i).defn;
|
||||
}
|
||||
}
|
||||
for (let i = start; i < start + inserts.length; i++) {
|
||||
this.getColumn(i).defn = null;
|
||||
}
|
||||
|
||||
// account for defined names
|
||||
this.workbook.definedNames.spliceColumns(this.name, start, count, inserts.length);
|
||||
}
|
||||
|
||||
get lastColumn() {
|
||||
return this.getColumn(this.columnCount);
|
||||
}
|
||||
|
||||
get columnCount() {
|
||||
let maxCount = 0;
|
||||
this.eachRow(row => {
|
||||
maxCount = Math.max(maxCount, row.cellCount);
|
||||
});
|
||||
return maxCount;
|
||||
}
|
||||
|
||||
get actualColumnCount() {
|
||||
// performance nightmare - for each row, counts all the columns used
|
||||
const counts = [];
|
||||
let count = 0;
|
||||
this.eachRow(row => {
|
||||
row.eachCell(({col}) => {
|
||||
if (!counts[col]) {
|
||||
counts[col] = true;
|
||||
count++;
|
||||
}
|
||||
});
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Rows
|
||||
|
||||
_commitRow() {
|
||||
// nop - allows streaming reader to fill a document
|
||||
}
|
||||
|
||||
get _lastRowNumber() {
|
||||
// need to cope with results of splice
|
||||
const rows = this._rows;
|
||||
let n = rows.length;
|
||||
while (n > 0 && rows[n - 1] === undefined) {
|
||||
n--;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
get _nextRow() {
|
||||
return this._lastRowNumber + 1;
|
||||
}
|
||||
|
||||
get lastRow() {
|
||||
if (this._rows.length) {
|
||||
return this._rows[this._rows.length - 1];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// find a row (if exists) by row number
|
||||
findRow(r) {
|
||||
return this._rows[r - 1];
|
||||
}
|
||||
|
||||
// find multiple rows (if exists) by row number
|
||||
findRows(start, length) {
|
||||
return this._rows.slice(start - 1, start - 1 + length);
|
||||
}
|
||||
|
||||
get rowCount() {
|
||||
return this._lastRowNumber;
|
||||
}
|
||||
|
||||
get actualRowCount() {
|
||||
// counts actual rows that have actual data
|
||||
let count = 0;
|
||||
this.eachRow(() => {
|
||||
count++;
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
// get a row by row number.
|
||||
getRow(r) {
|
||||
let row = this._rows[r - 1];
|
||||
if (!row) {
|
||||
row = this._rows[r - 1] = new Row(this, r);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
// get multiple rows by row number.
|
||||
getRows(start, length) {
|
||||
if (length < 1) return undefined;
|
||||
const rows = [];
|
||||
for (let i = start; i < start + length; i++) {
|
||||
rows.push(this.getRow(i));
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
addRow(value, style = 'n') {
|
||||
const rowNo = this._nextRow;
|
||||
const row = this.getRow(rowNo);
|
||||
row.values = value;
|
||||
this._setStyleOption(rowNo, style[0] === 'i' ? style : 'n');
|
||||
return row;
|
||||
}
|
||||
|
||||
addRows(value, style = 'n') {
|
||||
const rows = [];
|
||||
value.forEach(row => {
|
||||
rows.push(this.addRow(row, style));
|
||||
});
|
||||
return rows;
|
||||
}
|
||||
|
||||
insertRow(pos, value, style = 'n') {
|
||||
this.spliceRows(pos, 0, value);
|
||||
this._setStyleOption(pos, style);
|
||||
return this.getRow(pos);
|
||||
}
|
||||
|
||||
insertRows(pos, values, style = 'n') {
|
||||
this.spliceRows(pos, 0, ...values);
|
||||
if (style !== 'n') {
|
||||
// copy over the styles
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
if (style[0] === 'o' && this.findRow(values.length + pos + i) !== undefined) {
|
||||
this._copyStyle(values.length + pos + i, pos + i, style[1] === '+');
|
||||
} else if (style[0] === 'i' && this.findRow(pos - 1) !== undefined) {
|
||||
this._copyStyle(pos - 1, pos + i, style[1] === '+');
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.getRows(pos, values.length);
|
||||
}
|
||||
|
||||
// set row at position to same style as of either pervious row (option 'i') or next row (option 'o')
|
||||
_setStyleOption(pos, style = 'n') {
|
||||
if (style[0] === 'o' && this.findRow(pos + 1) !== undefined) {
|
||||
this._copyStyle(pos + 1, pos, style[1] === '+');
|
||||
} else if (style[0] === 'i' && this.findRow(pos - 1) !== undefined) {
|
||||
this._copyStyle(pos - 1, pos, style[1] === '+');
|
||||
}
|
||||
}
|
||||
|
||||
_copyStyle(src, dest, styleEmpty = false) {
|
||||
const rSrc = this.getRow(src);
|
||||
const rDst = this.getRow(dest);
|
||||
rDst.style = copyStyle(rSrc.style);
|
||||
// eslint-disable-next-line no-loop-func
|
||||
rSrc.eachCell({includeEmpty: styleEmpty}, (cell, colNumber) => {
|
||||
rDst.getCell(colNumber).style = copyStyle(cell.style);
|
||||
});
|
||||
rDst.height = rSrc.height;
|
||||
}
|
||||
|
||||
duplicateRow(rowNum, count, insert = false) {
|
||||
// create count duplicates of rowNum
|
||||
// either inserting new or overwriting existing rows
|
||||
|
||||
const rSrc = this._rows[rowNum - 1];
|
||||
const inserts = new Array(count).fill(rSrc.values);
|
||||
this.spliceRows(rowNum + 1, insert ? 0 : count, ...inserts);
|
||||
|
||||
// now copy styles...
|
||||
for (let i = 0; i < count; i++) {
|
||||
const rDst = this._rows[rowNum + i];
|
||||
rDst.style = rSrc.style;
|
||||
rDst.height = rSrc.height;
|
||||
// eslint-disable-next-line no-loop-func
|
||||
rSrc.eachCell({includeEmpty: true}, (cell, colNumber) => {
|
||||
rDst.getCell(colNumber).style = cell.style;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
spliceRows(start, count, ...inserts) {
|
||||
// same problem as row.splice, except worse.
|
||||
const nKeep = start + count;
|
||||
const nInserts = inserts.length;
|
||||
const nExpand = nInserts - count;
|
||||
const nEnd = this._rows.length;
|
||||
let i;
|
||||
let rSrc;
|
||||
if (nExpand < 0) {
|
||||
// remove rows
|
||||
if (start === nEnd) {
|
||||
this._rows[nEnd - 1] = undefined;
|
||||
}
|
||||
for (i = nKeep; i <= nEnd; i++) {
|
||||
rSrc = this._rows[i - 1];
|
||||
if (rSrc) {
|
||||
const rDst = this.getRow(i + nExpand);
|
||||
rDst.values = rSrc.values;
|
||||
rDst.style = rSrc.style;
|
||||
rDst.height = rSrc.height;
|
||||
// eslint-disable-next-line no-loop-func
|
||||
rSrc.eachCell({includeEmpty: true}, (cell, colNumber) => {
|
||||
rDst.getCell(colNumber).style = cell.style;
|
||||
});
|
||||
this._rows[i - 1] = undefined;
|
||||
} else {
|
||||
this._rows[i + nExpand - 1] = undefined;
|
||||
}
|
||||
}
|
||||
} else if (nExpand > 0) {
|
||||
// insert new cells
|
||||
for (i = nEnd; i >= nKeep; i--) {
|
||||
rSrc = this._rows[i - 1];
|
||||
if (rSrc) {
|
||||
const rDst = this.getRow(i + nExpand);
|
||||
rDst.values = rSrc.values;
|
||||
rDst.style = rSrc.style;
|
||||
rDst.height = rSrc.height;
|
||||
// eslint-disable-next-line no-loop-func
|
||||
rSrc.eachCell({includeEmpty: true}, (cell, colNumber) => {
|
||||
rDst.getCell(colNumber).style = cell.style;
|
||||
|
||||
// remerge cells accounting for insert offset
|
||||
if (cell._value.constructor.name === 'MergeValue') {
|
||||
const cellToBeMerged = this.getRow(cell._row._number + nInserts).getCell(colNumber);
|
||||
const prevMaster = cell._value._master;
|
||||
const newMaster = this.getRow(prevMaster._row._number + nInserts).getCell(prevMaster._column._number);
|
||||
cellToBeMerged.merge(newMaster);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this._rows[i + nExpand - 1] = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now copy over the new values
|
||||
for (i = 0; i < nInserts; i++) {
|
||||
const rDst = this.getRow(start + i);
|
||||
rDst.style = {};
|
||||
rDst.values = inserts[i];
|
||||
}
|
||||
|
||||
// account for defined names
|
||||
this.workbook.definedNames.spliceRows(this.name, start, count, nInserts);
|
||||
}
|
||||
|
||||
// iterate over every row in the worksheet, including maybe empty rows
|
||||
eachRow(options, iteratee) {
|
||||
if (!iteratee) {
|
||||
iteratee = options;
|
||||
options = undefined;
|
||||
}
|
||||
if (options && options.includeEmpty) {
|
||||
const n = this._rows.length;
|
||||
for (let i = 1; i <= n; i++) {
|
||||
iteratee(this.getRow(i), i);
|
||||
}
|
||||
} else {
|
||||
this._rows.forEach(row => {
|
||||
if (row && row.hasValues) {
|
||||
iteratee(row, row.number);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// return all rows as sparse array
|
||||
getSheetValues() {
|
||||
const rows = [];
|
||||
this._rows.forEach(row => {
|
||||
if (row) {
|
||||
rows[row.number] = row.values;
|
||||
}
|
||||
});
|
||||
return rows;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Cells
|
||||
|
||||
// returns the cell at [r,c] or address given by r. If not found, return undefined
|
||||
findCell(r, c) {
|
||||
const address = colCache.getAddress(r, c);
|
||||
const row = this._rows[address.row - 1];
|
||||
return row ? row.findCell(address.col) : undefined;
|
||||
}
|
||||
|
||||
// return the cell at [r,c] or address given by r. If not found, create a new one.
|
||||
getCell(r, c) {
|
||||
const address = colCache.getAddress(r, c);
|
||||
const row = this.getRow(address.row);
|
||||
return row.getCellEx(address);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Merge
|
||||
|
||||
// convert the range defined by ['tl:br'], [tl,br] or [t,l,b,r] into a single 'merged' cell
|
||||
mergeCells(...cells) {
|
||||
const dimensions = new Range(cells);
|
||||
this._mergeCellsInternal(dimensions);
|
||||
}
|
||||
|
||||
mergeCellsWithoutStyle(...cells) {
|
||||
const dimensions = new Range(cells);
|
||||
this._mergeCellsInternal(dimensions, true);
|
||||
}
|
||||
|
||||
_mergeCellsInternal(dimensions, ignoreStyle) {
|
||||
// check cells aren't already merged
|
||||
_.each(this._merges, merge => {
|
||||
if (merge.intersects(dimensions)) {
|
||||
throw new Error('Cannot merge already merged cells');
|
||||
}
|
||||
});
|
||||
|
||||
// apply merge
|
||||
const master = this.getCell(dimensions.top, dimensions.left);
|
||||
for (let i = dimensions.top; i <= dimensions.bottom; i++) {
|
||||
for (let j = dimensions.left; j <= dimensions.right; j++) {
|
||||
// merge all but the master cell
|
||||
if (i > dimensions.top || j > dimensions.left) {
|
||||
this.getCell(i, j).merge(master, ignoreStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// index merge
|
||||
this._merges[master.address] = dimensions;
|
||||
}
|
||||
|
||||
_unMergeMaster(master) {
|
||||
// master is always top left of a rectangle
|
||||
const merge = this._merges[master.address];
|
||||
if (merge) {
|
||||
for (let i = merge.top; i <= merge.bottom; i++) {
|
||||
for (let j = merge.left; j <= merge.right; j++) {
|
||||
this.getCell(i, j).unmerge();
|
||||
}
|
||||
}
|
||||
delete this._merges[master.address];
|
||||
}
|
||||
}
|
||||
|
||||
get hasMerges() {
|
||||
// return true if this._merges has a merge object
|
||||
return _.some(this._merges, Boolean);
|
||||
}
|
||||
|
||||
// scan the range defined by ['tl:br'], [tl,br] or [t,l,b,r] and if any cell is part of a merge,
|
||||
// un-merge the group. Note this function can affect multiple merges and merge-blocks are
|
||||
// atomic - either they're all merged or all un-merged.
|
||||
unMergeCells(...cells) {
|
||||
const dimensions = new Range(cells);
|
||||
|
||||
// find any cells in that range and unmerge them
|
||||
for (let i = dimensions.top; i <= dimensions.bottom; i++) {
|
||||
for (let j = dimensions.left; j <= dimensions.right; j++) {
|
||||
const cell = this.findCell(i, j);
|
||||
if (cell) {
|
||||
if (cell.type === Enums.ValueType.Merge) {
|
||||
// this cell merges to another master
|
||||
this._unMergeMaster(cell.master);
|
||||
} else if (this._merges[cell.address]) {
|
||||
// this cell is a master
|
||||
this._unMergeMaster(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Shared/Array Formula
|
||||
fillFormula(range, formula, results, shareType = 'shared') {
|
||||
// Define formula for top-left cell and share to rest
|
||||
const decoded = colCache.decode(range);
|
||||
const {top, left, bottom, right} = decoded;
|
||||
const width = right - left + 1;
|
||||
const masterAddress = colCache.encodeAddress(top, left);
|
||||
const isShared = shareType === 'shared';
|
||||
|
||||
// work out result accessor
|
||||
let getResult;
|
||||
if (typeof results === 'function') {
|
||||
getResult = results;
|
||||
} else if (Array.isArray(results)) {
|
||||
if (Array.isArray(results[0])) {
|
||||
getResult = (row, col) => results[row - top][col - left];
|
||||
} else {
|
||||
// eslint-disable-next-line no-mixed-operators
|
||||
getResult = (row, col) => results[(row - top) * width + (col - left)];
|
||||
}
|
||||
} else {
|
||||
getResult = () => undefined;
|
||||
}
|
||||
let first = true;
|
||||
for (let r = top; r <= bottom; r++) {
|
||||
for (let c = left; c <= right; c++) {
|
||||
if (first) {
|
||||
this.getCell(r, c).value = {
|
||||
shareType,
|
||||
formula,
|
||||
ref: range,
|
||||
result: getResult(r, c),
|
||||
};
|
||||
first = false;
|
||||
} else {
|
||||
this.getCell(r, c).value = isShared
|
||||
? {
|
||||
sharedFormula: masterAddress,
|
||||
result: getResult(r, c),
|
||||
}
|
||||
: getResult(r, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Images
|
||||
addImage(imageId, range) {
|
||||
const model = {
|
||||
type: 'image',
|
||||
imageId,
|
||||
range,
|
||||
};
|
||||
this._media.push(new Image(this, model));
|
||||
}
|
||||
|
||||
getImages() {
|
||||
return this._media.filter(m => m.type === 'image');
|
||||
}
|
||||
|
||||
addBackgroundImage(imageId) {
|
||||
const model = {
|
||||
type: 'background',
|
||||
imageId,
|
||||
};
|
||||
this._media.push(new Image(this, model));
|
||||
}
|
||||
|
||||
getBackgroundImageId() {
|
||||
const image = this._media.find(m => m.type === 'background');
|
||||
return image && image.imageId;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Worksheet Protection
|
||||
protect(password, options) {
|
||||
// TODO: make this function truly async
|
||||
// perhaps marshal to worker thread or something
|
||||
return new Promise(resolve => {
|
||||
this.sheetProtection = {
|
||||
sheet: true,
|
||||
};
|
||||
if (options && 'spinCount' in options) {
|
||||
// force spinCount to be integer >= 0
|
||||
options.spinCount = Number.isFinite(options.spinCount) ? Math.round(Math.max(0, options.spinCount)) : 100000;
|
||||
}
|
||||
if (password) {
|
||||
this.sheetProtection.algorithmName = 'SHA-512';
|
||||
this.sheetProtection.saltValue = Encryptor.randomBytes(16).toString('base64');
|
||||
this.sheetProtection.spinCount = options && 'spinCount' in options ? options.spinCount : 100000; // allow user specified spinCount
|
||||
this.sheetProtection.hashValue = Encryptor.convertPasswordToHash(
|
||||
password,
|
||||
'SHA512',
|
||||
this.sheetProtection.saltValue,
|
||||
this.sheetProtection.spinCount
|
||||
);
|
||||
}
|
||||
if (options) {
|
||||
this.sheetProtection = Object.assign(this.sheetProtection, options);
|
||||
if (!password && 'spinCount' in options) {
|
||||
delete this.sheetProtection.spinCount;
|
||||
}
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
unprotect() {
|
||||
this.sheetProtection = null;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Tables
|
||||
addTable(model) {
|
||||
const table = new Table(this, model);
|
||||
this.tables[model.name] = table;
|
||||
return table;
|
||||
}
|
||||
|
||||
getTable(name) {
|
||||
return this.tables[name];
|
||||
}
|
||||
|
||||
removeTable(name) {
|
||||
delete this.tables[name];
|
||||
}
|
||||
|
||||
getTables() {
|
||||
return Object.values(this.tables);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Conditional Formatting
|
||||
addConditionalFormatting(cf) {
|
||||
this.conditionalFormattings.push(cf);
|
||||
}
|
||||
|
||||
removeConditionalFormatting(filter) {
|
||||
if (typeof filter === 'number') {
|
||||
this.conditionalFormattings.splice(filter, 1);
|
||||
} else if (filter instanceof Function) {
|
||||
this.conditionalFormattings = this.conditionalFormattings.filter(filter);
|
||||
} else {
|
||||
this.conditionalFormattings = [];
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Deprecated
|
||||
get tabColor() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.trace('worksheet.tabColor property is now deprecated. Please use worksheet.properties.tabColor');
|
||||
return this.properties.tabColor;
|
||||
}
|
||||
|
||||
set tabColor(value) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.trace('worksheet.tabColor property is now deprecated. Please use worksheet.properties.tabColor');
|
||||
this.properties.tabColor = value;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Model
|
||||
|
||||
get model() {
|
||||
const model = {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
dataValidations: this.dataValidations.model,
|
||||
properties: this.properties,
|
||||
state: this.state,
|
||||
pageSetup: this.pageSetup,
|
||||
headerFooter: this.headerFooter,
|
||||
rowBreaks: this.rowBreaks,
|
||||
views: this.views,
|
||||
autoFilter: this.autoFilter,
|
||||
media: this._media.map(medium => medium.model),
|
||||
sheetProtection: this.sheetProtection,
|
||||
tables: Object.values(this.tables).map(table => table.model),
|
||||
conditionalFormattings: this.conditionalFormattings,
|
||||
};
|
||||
|
||||
// =================================================
|
||||
// columns
|
||||
model.cols = Column.toModel(this.columns);
|
||||
|
||||
// ==========================================================
|
||||
// Rows
|
||||
const rows = (model.rows = []);
|
||||
const dimensions = (model.dimensions = new Range());
|
||||
this._rows.forEach(row => {
|
||||
const rowModel = row && row.model;
|
||||
if (rowModel) {
|
||||
dimensions.expand(rowModel.number, rowModel.min, rowModel.number, rowModel.max);
|
||||
rows.push(rowModel);
|
||||
}
|
||||
});
|
||||
|
||||
// ==========================================================
|
||||
// Merges
|
||||
model.merges = [];
|
||||
_.each(this._merges, merge => {
|
||||
model.merges.push(merge.range);
|
||||
});
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
_parseRows(model) {
|
||||
this._rows = [];
|
||||
model.rows.forEach(rowModel => {
|
||||
const row = new Row(this, rowModel.number);
|
||||
this._rows[row.number - 1] = row;
|
||||
row.model = rowModel;
|
||||
});
|
||||
}
|
||||
|
||||
_parseMergeCells(model) {
|
||||
_.each(model.mergeCells, merge => {
|
||||
// Do not merge styles when importing an Excel file
|
||||
// since each cell may have different styles intentionally.
|
||||
this.mergeCellsWithoutStyle(merge);
|
||||
});
|
||||
}
|
||||
|
||||
set model(value) {
|
||||
this.name = value.name;
|
||||
this._columns = Column.fromModel(this, value.cols);
|
||||
this._parseRows(value);
|
||||
|
||||
this._parseMergeCells(value);
|
||||
this.dataValidations = new DataValidations(value.dataValidations);
|
||||
this.properties = value.properties;
|
||||
this.pageSetup = value.pageSetup;
|
||||
this.headerFooter = value.headerFooter;
|
||||
this.views = value.views;
|
||||
this.autoFilter = value.autoFilter;
|
||||
this._media = value.media.map(medium => new Image(this, medium));
|
||||
this.sheetProtection = value.sheetProtection;
|
||||
this.tables = value.tables.reduce((tables, table) => {
|
||||
const t = new Table();
|
||||
t.model = table;
|
||||
tables[table.name] = t;
|
||||
return tables;
|
||||
}, {});
|
||||
this.conditionalFormattings = value.conditionalFormattings;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Worksheet;
|
||||
13
doc/test-data/purchase_transaction/node_modules/exceljs/lib/exceljs.bare.js
generated
vendored
Normal file
13
doc/test-data/purchase_transaction/node_modules/exceljs/lib/exceljs.bare.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// this bundle is built without polyfill leaving apps the freedom to add their own
|
||||
const ExcelJS = {
|
||||
Workbook: require('./doc/workbook'),
|
||||
};
|
||||
|
||||
// Object.assign mono-fill
|
||||
const Enums = require('./doc/enums');
|
||||
|
||||
Object.keys(Enums).forEach(key => {
|
||||
ExcelJS[key] = Enums[key];
|
||||
});
|
||||
|
||||
module.exports = ExcelJS;
|
||||
36
doc/test-data/purchase_transaction/node_modules/exceljs/lib/exceljs.browser.js
generated
vendored
Normal file
36
doc/test-data/purchase_transaction/node_modules/exceljs/lib/exceljs.browser.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies,node/no-unpublished-require */
|
||||
require('core-js/modules/es.promise');
|
||||
require('core-js/modules/es.promise.finally');
|
||||
require('core-js/modules/es.object.assign');
|
||||
require('core-js/modules/es.object.keys');
|
||||
require('core-js/modules/es.object.values');
|
||||
require('core-js/modules/es.symbol');
|
||||
require('core-js/modules/es.symbol.async-iterator');
|
||||
// required by core-js/modules/es.promise Promise.all
|
||||
require('core-js/modules/es.array.iterator');
|
||||
// required by node_modules/saxes/saxes.js SaxesParser.captureTo
|
||||
require('core-js/modules/es.array.includes');
|
||||
// required by lib/doc/workbook.js Workbook.model
|
||||
require('core-js/modules/es.array.find-index');
|
||||
// required by lib/doc/workbook.js Workbook.addWorksheet and Workbook.getWorksheet
|
||||
require('core-js/modules/es.array.find');
|
||||
// required by node_modules/saxes/saxes.js SaxesParser.getCode10
|
||||
require('core-js/modules/es.string.from-code-point');
|
||||
// required by lib/xlsx/xform/sheet/data-validations-xform.js DataValidationsXform.parseClose
|
||||
require('core-js/modules/es.string.includes');
|
||||
// required by lib/utils/utils.js utils.validInt and lib/csv/csv.js CSV.read
|
||||
require('core-js/modules/es.number.is-nan');
|
||||
require('regenerator-runtime/runtime');
|
||||
|
||||
const ExcelJS = {
|
||||
Workbook: require('./doc/workbook'),
|
||||
};
|
||||
|
||||
// Object.assign mono-fill
|
||||
const Enums = require('./doc/enums');
|
||||
|
||||
Object.keys(Enums).forEach(key => {
|
||||
ExcelJS[key] = Enums[key];
|
||||
});
|
||||
|
||||
module.exports = ExcelJS;
|
||||
14
doc/test-data/purchase_transaction/node_modules/exceljs/lib/exceljs.nodejs.js
generated
vendored
Normal file
14
doc/test-data/purchase_transaction/node_modules/exceljs/lib/exceljs.nodejs.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
const ExcelJS = {
|
||||
Workbook: require('./doc/workbook'),
|
||||
ModelContainer: require('./doc/modelcontainer'),
|
||||
stream: {
|
||||
xlsx: {
|
||||
WorkbookWriter: require('./stream/xlsx/workbook-writer'),
|
||||
WorkbookReader: require('./stream/xlsx/workbook-reader'),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Object.assign(ExcelJS, require('./doc/enums'));
|
||||
|
||||
module.exports = ExcelJS;
|
||||
83
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/hyperlink-reader.js
generated
vendored
Normal file
83
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/hyperlink-reader.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
const {EventEmitter} = require('events');
|
||||
const parseSax = require('../../utils/parse-sax');
|
||||
|
||||
const Enums = require('../../doc/enums');
|
||||
const RelType = require('../../xlsx/rel-type');
|
||||
|
||||
class HyperlinkReader extends EventEmitter {
|
||||
constructor({workbook, id, iterator, options}) {
|
||||
super();
|
||||
|
||||
this.workbook = workbook;
|
||||
this.id = id;
|
||||
this.iterator = iterator;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
get count() {
|
||||
return (this.hyperlinks && this.hyperlinks.length) || 0;
|
||||
}
|
||||
|
||||
each(fn) {
|
||||
return this.hyperlinks.forEach(fn);
|
||||
}
|
||||
|
||||
async read() {
|
||||
const {iterator, options} = this;
|
||||
let emitHyperlinks = false;
|
||||
let hyperlinks = null;
|
||||
switch (options.hyperlinks) {
|
||||
case 'emit':
|
||||
emitHyperlinks = true;
|
||||
break;
|
||||
case 'cache':
|
||||
this.hyperlinks = hyperlinks = {};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!emitHyperlinks && !hyperlinks) {
|
||||
this.emit('finished');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
for await (const events of parseSax(iterator)) {
|
||||
for (const {eventType, value} of events) {
|
||||
if (eventType === 'opentag') {
|
||||
const node = value;
|
||||
if (node.name === 'Relationship') {
|
||||
const rId = node.attributes.Id;
|
||||
switch (node.attributes.Type) {
|
||||
case RelType.Hyperlink:
|
||||
{
|
||||
const relationship = {
|
||||
type: Enums.RelationshipType.Styles,
|
||||
rId,
|
||||
target: node.attributes.Target,
|
||||
targetMode: node.attributes.TargetMode,
|
||||
};
|
||||
if (emitHyperlinks) {
|
||||
this.emit('hyperlink', relationship);
|
||||
} else {
|
||||
hyperlinks[relationship.rId] = relationship;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.emit('finished');
|
||||
} catch (error) {
|
||||
this.emit('error', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HyperlinkReader;
|
||||
121
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/sheet-comments-writer.js
generated
vendored
Normal file
121
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/sheet-comments-writer.js
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
const XmlStream = require('../../utils/xml-stream');
|
||||
const RelType = require('../../xlsx/rel-type');
|
||||
const colCache = require('../../utils/col-cache');
|
||||
const CommentXform = require('../../xlsx/xform/comment/comment-xform');
|
||||
const VmlShapeXform = require('../../xlsx/xform/comment/vml-shape-xform');
|
||||
|
||||
class SheetCommentsWriter {
|
||||
constructor(worksheet, sheetRelsWriter, options) {
|
||||
// in a workbook, each sheet will have a number
|
||||
this.id = options.id;
|
||||
this.count = 0;
|
||||
this._worksheet = worksheet;
|
||||
this._workbook = options.workbook;
|
||||
this._sheetRelsWriter = sheetRelsWriter;
|
||||
}
|
||||
|
||||
get commentsStream() {
|
||||
if (!this._commentsStream) {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
this._commentsStream = this._workbook._openStream(`/xl/comments${this.id}.xml`);
|
||||
}
|
||||
return this._commentsStream;
|
||||
}
|
||||
|
||||
get vmlStream() {
|
||||
if (!this._vmlStream) {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
this._vmlStream = this._workbook._openStream(`xl/drawings/vmlDrawing${this.id}.vml`);
|
||||
}
|
||||
return this._vmlStream;
|
||||
}
|
||||
|
||||
_addRelationships() {
|
||||
const commentRel = {
|
||||
Type: RelType.Comments,
|
||||
Target: `../comments${this.id}.xml`,
|
||||
};
|
||||
this._sheetRelsWriter.addRelationship(commentRel);
|
||||
|
||||
const vmlDrawingRel = {
|
||||
Type: RelType.VmlDrawing,
|
||||
Target: `../drawings/vmlDrawing${this.id}.vml`,
|
||||
};
|
||||
this.vmlRelId = this._sheetRelsWriter.addRelationship(vmlDrawingRel);
|
||||
}
|
||||
|
||||
_addCommentRefs() {
|
||||
this._workbook.commentRefs.push({
|
||||
commentName: `comments${this.id}`,
|
||||
vmlDrawing: `vmlDrawing${this.id}`,
|
||||
});
|
||||
}
|
||||
|
||||
_writeOpen() {
|
||||
this.commentsStream.write(
|
||||
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
|
||||
'<comments xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">' +
|
||||
'<authors><author>Author</author></authors>' +
|
||||
'<commentList>'
|
||||
);
|
||||
this.vmlStream.write(
|
||||
'<?xml version="1.0" encoding="UTF-8"?>' +
|
||||
'<xml xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:x="urn:schemas-microsoft-com:office:excel">' +
|
||||
'<o:shapelayout v:ext="edit">' +
|
||||
'<o:idmap v:ext="edit" data="1" />' +
|
||||
'</o:shapelayout>' +
|
||||
'<v:shapetype id="_x0000_t202" coordsize="21600,21600" o:spt="202" path="m,l,21600r21600,l21600,xe">' +
|
||||
'<v:stroke joinstyle="miter" />' +
|
||||
'<v:path gradientshapeok="t" o:connecttype="rect" />' +
|
||||
'</v:shapetype>'
|
||||
);
|
||||
}
|
||||
|
||||
_writeComment(comment, index) {
|
||||
const commentXform = new CommentXform();
|
||||
const commentsXmlStream = new XmlStream();
|
||||
commentXform.render(commentsXmlStream, comment);
|
||||
this.commentsStream.write(commentsXmlStream.xml);
|
||||
|
||||
const vmlShapeXform = new VmlShapeXform();
|
||||
const vmlXmlStream = new XmlStream();
|
||||
vmlShapeXform.render(vmlXmlStream, comment, index);
|
||||
this.vmlStream.write(vmlXmlStream.xml);
|
||||
}
|
||||
|
||||
_writeClose() {
|
||||
this.commentsStream.write('</commentList></comments>');
|
||||
this.vmlStream.write('</xml>');
|
||||
}
|
||||
|
||||
addComments(comments) {
|
||||
if (comments && comments.length) {
|
||||
if (!this.startedData) {
|
||||
this._worksheet.comments = [];
|
||||
this._writeOpen();
|
||||
this._addRelationships();
|
||||
this._addCommentRefs();
|
||||
this.startedData = true;
|
||||
}
|
||||
|
||||
comments.forEach(item => {
|
||||
item.refAddress = colCache.decodeAddress(item.ref);
|
||||
});
|
||||
|
||||
comments.forEach(comment => {
|
||||
this._writeComment(comment, this.count);
|
||||
this.count += 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
commit() {
|
||||
if (this.count) {
|
||||
this._writeClose();
|
||||
this.commentsStream.end();
|
||||
this.vmlStream.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SheetCommentsWriter;
|
||||
119
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/sheet-rels-writer.js
generated
vendored
Normal file
119
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/sheet-rels-writer.js
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
/* eslint-disable max-classes-per-file */
|
||||
const utils = require('../../utils/utils');
|
||||
const RelType = require('../../xlsx/rel-type');
|
||||
|
||||
class HyperlinksProxy {
|
||||
constructor(sheetRelsWriter) {
|
||||
this.writer = sheetRelsWriter;
|
||||
}
|
||||
|
||||
push(hyperlink) {
|
||||
this.writer.addHyperlink(hyperlink);
|
||||
}
|
||||
}
|
||||
|
||||
class SheetRelsWriter {
|
||||
constructor(options) {
|
||||
// in a workbook, each sheet will have a number
|
||||
this.id = options.id;
|
||||
|
||||
// count of all relationships
|
||||
this.count = 0;
|
||||
|
||||
// keep record of all hyperlinks
|
||||
this._hyperlinks = [];
|
||||
|
||||
this._workbook = options.workbook;
|
||||
}
|
||||
|
||||
get stream() {
|
||||
if (!this._stream) {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
this._stream = this._workbook._openStream(`/xl/worksheets/_rels/sheet${this.id}.xml.rels`);
|
||||
}
|
||||
return this._stream;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._hyperlinks.length;
|
||||
}
|
||||
|
||||
each(fn) {
|
||||
return this._hyperlinks.forEach(fn);
|
||||
}
|
||||
|
||||
get hyperlinksProxy() {
|
||||
return this._hyperlinksProxy || (this._hyperlinksProxy = new HyperlinksProxy(this));
|
||||
}
|
||||
|
||||
addHyperlink(hyperlink) {
|
||||
// Write to stream
|
||||
const relationship = {
|
||||
Target: hyperlink.target,
|
||||
Type: RelType.Hyperlink,
|
||||
TargetMode: 'External',
|
||||
};
|
||||
const rId = this._writeRelationship(relationship);
|
||||
|
||||
// store sheet stuff for later
|
||||
this._hyperlinks.push({
|
||||
rId,
|
||||
address: hyperlink.address,
|
||||
});
|
||||
}
|
||||
|
||||
addMedia(media) {
|
||||
return this._writeRelationship(media);
|
||||
}
|
||||
|
||||
addRelationship(rel) {
|
||||
return this._writeRelationship(rel);
|
||||
}
|
||||
|
||||
commit() {
|
||||
if (this.count) {
|
||||
// write xml utro
|
||||
this._writeClose();
|
||||
// and close stream
|
||||
this.stream.end();
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================
|
||||
_writeOpen() {
|
||||
this.stream.write(
|
||||
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">`
|
||||
);
|
||||
}
|
||||
|
||||
_writeRelationship(relationship) {
|
||||
if (!this.count) {
|
||||
this._writeOpen();
|
||||
}
|
||||
|
||||
const rId = `rId${++this.count}`;
|
||||
|
||||
if (relationship.TargetMode) {
|
||||
this.stream.write(
|
||||
`<Relationship Id="${rId}"` +
|
||||
` Type="${relationship.Type}"` +
|
||||
` Target="${utils.xmlEncode(relationship.Target)}"` +
|
||||
` TargetMode="${relationship.TargetMode}"` +
|
||||
'/>'
|
||||
);
|
||||
} else {
|
||||
this.stream.write(
|
||||
`<Relationship Id="${rId}" Type="${relationship.Type}" Target="${relationship.Target}"/>`
|
||||
);
|
||||
}
|
||||
|
||||
return rId;
|
||||
}
|
||||
|
||||
_writeClose() {
|
||||
this.stream.write('</Relationships>');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SheetRelsWriter;
|
||||
337
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/workbook-reader.js
generated
vendored
Normal file
337
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/workbook-reader.js
generated
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
const fs = require('fs');
|
||||
const {EventEmitter} = require('events');
|
||||
const {PassThrough, Readable} = require('readable-stream');
|
||||
const nodeStream = require('stream');
|
||||
const unzip = require('unzipper');
|
||||
const tmp = require('tmp');
|
||||
const iterateStream = require('../../utils/iterate-stream');
|
||||
const parseSax = require('../../utils/parse-sax');
|
||||
|
||||
const StyleManager = require('../../xlsx/xform/style/styles-xform');
|
||||
const WorkbookXform = require('../../xlsx/xform/book/workbook-xform');
|
||||
const RelationshipsXform = require('../../xlsx/xform/core/relationships-xform');
|
||||
|
||||
const WorksheetReader = require('./worksheet-reader');
|
||||
const HyperlinkReader = require('./hyperlink-reader');
|
||||
|
||||
tmp.setGracefulCleanup();
|
||||
|
||||
class WorkbookReader extends EventEmitter {
|
||||
constructor(input, options = {}) {
|
||||
super();
|
||||
|
||||
this.input = input;
|
||||
|
||||
this.options = {
|
||||
worksheets: 'emit',
|
||||
sharedStrings: 'cache',
|
||||
hyperlinks: 'ignore',
|
||||
styles: 'ignore',
|
||||
entries: 'ignore',
|
||||
...options,
|
||||
};
|
||||
|
||||
this.styles = new StyleManager();
|
||||
this.styles.init();
|
||||
}
|
||||
|
||||
_getStream(input) {
|
||||
if (input instanceof nodeStream.Readable || input instanceof Readable) {
|
||||
return input;
|
||||
}
|
||||
if (typeof input === 'string') {
|
||||
return fs.createReadStream(input);
|
||||
}
|
||||
throw new Error(`Could not recognise input: ${input}`);
|
||||
}
|
||||
|
||||
async read(input, options) {
|
||||
try {
|
||||
for await (const {eventType, value} of this.parse(input, options)) {
|
||||
switch (eventType) {
|
||||
case 'shared-strings':
|
||||
this.emit(eventType, value);
|
||||
break;
|
||||
case 'worksheet':
|
||||
this.emit(eventType, value);
|
||||
await value.read();
|
||||
break;
|
||||
case 'hyperlinks':
|
||||
this.emit(eventType, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.emit('end');
|
||||
this.emit('finished');
|
||||
} catch (error) {
|
||||
this.emit('error', error);
|
||||
}
|
||||
}
|
||||
|
||||
async *[Symbol.asyncIterator]() {
|
||||
for await (const {eventType, value} of this.parse()) {
|
||||
if (eventType === 'worksheet') {
|
||||
yield value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async *parse(input, options) {
|
||||
if (options) this.options = options;
|
||||
const stream = (this.stream = this._getStream(input || this.input));
|
||||
const zip = unzip.Parse({forceStream: true});
|
||||
stream.pipe(zip);
|
||||
|
||||
// worksheets, deferred for parsing after shared strings reading
|
||||
const waitingWorkSheets = [];
|
||||
|
||||
for await (const entry of iterateStream(zip)) {
|
||||
let match;
|
||||
let sheetNo;
|
||||
switch (entry.path) {
|
||||
case '_rels/.rels':
|
||||
break;
|
||||
case 'xl/_rels/workbook.xml.rels':
|
||||
await this._parseRels(entry);
|
||||
break;
|
||||
case 'xl/workbook.xml':
|
||||
await this._parseWorkbook(entry);
|
||||
break;
|
||||
case 'xl/sharedStrings.xml':
|
||||
yield* this._parseSharedStrings(entry);
|
||||
break;
|
||||
case 'xl/styles.xml':
|
||||
await this._parseStyles(entry);
|
||||
break;
|
||||
default:
|
||||
if (entry.path.match(/xl\/worksheets\/sheet\d+[.]xml/)) {
|
||||
match = entry.path.match(/xl\/worksheets\/sheet(\d+)[.]xml/);
|
||||
sheetNo = match[1];
|
||||
if (this.sharedStrings && this.workbookRels) {
|
||||
yield* this._parseWorksheet(iterateStream(entry), sheetNo);
|
||||
} else {
|
||||
// create temp file for each worksheet
|
||||
await new Promise((resolve, reject) => {
|
||||
tmp.file((err, path, fd, tempFileCleanupCallback) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
waitingWorkSheets.push({sheetNo, path, tempFileCleanupCallback});
|
||||
|
||||
const tempStream = fs.createWriteStream(path);
|
||||
tempStream.on('error', reject);
|
||||
entry.pipe(tempStream);
|
||||
return tempStream.on('finish', () => {
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
} else if (entry.path.match(/xl\/worksheets\/_rels\/sheet\d+[.]xml.rels/)) {
|
||||
match = entry.path.match(/xl\/worksheets\/_rels\/sheet(\d+)[.]xml.rels/);
|
||||
sheetNo = match[1];
|
||||
yield* this._parseHyperlinks(iterateStream(entry), sheetNo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
entry.autodrain();
|
||||
}
|
||||
|
||||
for (const {sheetNo, path, tempFileCleanupCallback} of waitingWorkSheets) {
|
||||
let fileStream = fs.createReadStream(path);
|
||||
// TODO: Remove once node v8 is deprecated
|
||||
// Detect and upgrade old fileStreams
|
||||
if (!fileStream[Symbol.asyncIterator]) {
|
||||
fileStream = fileStream.pipe(new PassThrough());
|
||||
}
|
||||
yield* this._parseWorksheet(fileStream, sheetNo);
|
||||
tempFileCleanupCallback();
|
||||
}
|
||||
}
|
||||
|
||||
_emitEntry(payload) {
|
||||
if (this.options.entries === 'emit') {
|
||||
this.emit('entry', payload);
|
||||
}
|
||||
}
|
||||
|
||||
async _parseRels(entry) {
|
||||
const xform = new RelationshipsXform();
|
||||
this.workbookRels = await xform.parseStream(iterateStream(entry));
|
||||
}
|
||||
|
||||
async _parseWorkbook(entry) {
|
||||
this._emitEntry({type: 'workbook'});
|
||||
|
||||
const workbook = new WorkbookXform();
|
||||
await workbook.parseStream(iterateStream(entry));
|
||||
|
||||
this.properties = workbook.map.workbookPr;
|
||||
this.model = workbook.model;
|
||||
}
|
||||
|
||||
async *_parseSharedStrings(entry) {
|
||||
this._emitEntry({type: 'shared-strings'});
|
||||
switch (this.options.sharedStrings) {
|
||||
case 'cache':
|
||||
this.sharedStrings = [];
|
||||
break;
|
||||
case 'emit':
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
let text = null;
|
||||
let richText = [];
|
||||
let index = 0;
|
||||
let font = null;
|
||||
for await (const events of parseSax(iterateStream(entry))) {
|
||||
for (const {eventType, value} of events) {
|
||||
if (eventType === 'opentag') {
|
||||
const node = value;
|
||||
switch (node.name) {
|
||||
case 'b':
|
||||
font = font || {};
|
||||
font.bold = true;
|
||||
break;
|
||||
case 'charset':
|
||||
font = font || {};
|
||||
font.charset = parseInt(node.attributes.charset, 10);
|
||||
break;
|
||||
case 'color':
|
||||
font = font || {};
|
||||
font.color = {};
|
||||
if (node.attributes.rgb) {
|
||||
font.color.argb = node.attributes.argb;
|
||||
}
|
||||
if (node.attributes.val) {
|
||||
font.color.argb = node.attributes.val;
|
||||
}
|
||||
if (node.attributes.theme) {
|
||||
font.color.theme = node.attributes.theme;
|
||||
}
|
||||
break;
|
||||
case 'family':
|
||||
font = font || {};
|
||||
font.family = parseInt(node.attributes.val, 10);
|
||||
break;
|
||||
case 'i':
|
||||
font = font || {};
|
||||
font.italic = true;
|
||||
break;
|
||||
case 'outline':
|
||||
font = font || {};
|
||||
font.outline = true;
|
||||
break;
|
||||
case 'rFont':
|
||||
font = font || {};
|
||||
font.name = node.value;
|
||||
break;
|
||||
case 'si':
|
||||
font = null;
|
||||
richText = [];
|
||||
text = null;
|
||||
break;
|
||||
case 'sz':
|
||||
font = font || {};
|
||||
font.size = parseInt(node.attributes.val, 10);
|
||||
break;
|
||||
case 'strike':
|
||||
break;
|
||||
case 't':
|
||||
text = null;
|
||||
break;
|
||||
case 'u':
|
||||
font = font || {};
|
||||
font.underline = true;
|
||||
break;
|
||||
case 'vertAlign':
|
||||
font = font || {};
|
||||
font.vertAlign = node.attributes.val;
|
||||
break;
|
||||
}
|
||||
} else if (eventType === 'text') {
|
||||
text = text ? text + value : value;
|
||||
} else if (eventType === 'closetag') {
|
||||
const node = value;
|
||||
switch (node.name) {
|
||||
case 'r':
|
||||
richText.push({
|
||||
font,
|
||||
text,
|
||||
});
|
||||
|
||||
font = null;
|
||||
text = null;
|
||||
break;
|
||||
case 'si':
|
||||
if (this.options.sharedStrings === 'cache') {
|
||||
this.sharedStrings.push(richText.length ? {richText} : text);
|
||||
} else if (this.options.sharedStrings === 'emit') {
|
||||
yield {index: index++, text: richText.length ? {richText} : text};
|
||||
}
|
||||
|
||||
richText = [];
|
||||
font = null;
|
||||
text = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _parseStyles(entry) {
|
||||
this._emitEntry({type: 'styles'});
|
||||
if (this.options.styles === 'cache') {
|
||||
this.styles = new StyleManager();
|
||||
await this.styles.parseStream(iterateStream(entry));
|
||||
}
|
||||
}
|
||||
|
||||
*_parseWorksheet(iterator, sheetNo) {
|
||||
this._emitEntry({type: 'worksheet', id: sheetNo});
|
||||
const worksheetReader = new WorksheetReader({
|
||||
workbook: this,
|
||||
id: sheetNo,
|
||||
iterator,
|
||||
options: this.options,
|
||||
});
|
||||
|
||||
const matchingRel = (this.workbookRels || []).find(rel => rel.Target === `worksheets/sheet${sheetNo}.xml`);
|
||||
const matchingSheet = matchingRel && (this.model.sheets || []).find(sheet => sheet.rId === matchingRel.Id);
|
||||
if (matchingSheet) {
|
||||
worksheetReader.id = matchingSheet.id;
|
||||
worksheetReader.name = matchingSheet.name;
|
||||
worksheetReader.state = matchingSheet.state;
|
||||
}
|
||||
if (this.options.worksheets === 'emit') {
|
||||
yield {eventType: 'worksheet', value: worksheetReader};
|
||||
}
|
||||
}
|
||||
|
||||
*_parseHyperlinks(iterator, sheetNo) {
|
||||
this._emitEntry({type: 'hyperlinks', id: sheetNo});
|
||||
const hyperlinksReader = new HyperlinkReader({
|
||||
workbook: this,
|
||||
id: sheetNo,
|
||||
iterator,
|
||||
options: this.options,
|
||||
});
|
||||
if (this.options.hyperlinks === 'emit') {
|
||||
yield {eventType: 'hyperlinks', value: hyperlinksReader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for reference - these are the valid values for options
|
||||
WorkbookReader.Options = {
|
||||
worksheets: ['emit', 'ignore'],
|
||||
sharedStrings: ['cache', 'emit', 'ignore'],
|
||||
hyperlinks: ['cache', 'emit', 'ignore'],
|
||||
styles: ['cache', 'ignore'],
|
||||
entries: ['emit', 'ignore'],
|
||||
};
|
||||
|
||||
module.exports = WorkbookReader;
|
||||
347
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/workbook-writer.js
generated
vendored
Normal file
347
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/workbook-writer.js
generated
vendored
Normal file
@@ -0,0 +1,347 @@
|
||||
const fs = require('fs');
|
||||
const Archiver = require('archiver');
|
||||
|
||||
const StreamBuf = require('../../utils/stream-buf');
|
||||
|
||||
const RelType = require('../../xlsx/rel-type');
|
||||
const StylesXform = require('../../xlsx/xform/style/styles-xform');
|
||||
const SharedStrings = require('../../utils/shared-strings');
|
||||
const DefinedNames = require('../../doc/defined-names');
|
||||
|
||||
const CoreXform = require('../../xlsx/xform/core/core-xform');
|
||||
const RelationshipsXform = require('../../xlsx/xform/core/relationships-xform');
|
||||
const ContentTypesXform = require('../../xlsx/xform/core/content-types-xform');
|
||||
const AppXform = require('../../xlsx/xform/core/app-xform');
|
||||
const WorkbookXform = require('../../xlsx/xform/book/workbook-xform');
|
||||
const SharedStringsXform = require('../../xlsx/xform/strings/shared-strings-xform');
|
||||
|
||||
const WorksheetWriter = require('./worksheet-writer');
|
||||
|
||||
const theme1Xml = require('../../xlsx/xml/theme1.js');
|
||||
|
||||
class WorkbookWriter {
|
||||
constructor(options) {
|
||||
options = options || {};
|
||||
|
||||
this.created = options.created || new Date();
|
||||
this.modified = options.modified || this.created;
|
||||
this.creator = options.creator || 'ExcelJS';
|
||||
this.lastModifiedBy = options.lastModifiedBy || 'ExcelJS';
|
||||
this.lastPrinted = options.lastPrinted;
|
||||
|
||||
// using shared strings creates a smaller xlsx file but may use more memory
|
||||
this.useSharedStrings = options.useSharedStrings || false;
|
||||
this.sharedStrings = new SharedStrings();
|
||||
|
||||
// style manager
|
||||
this.styles = options.useStyles ? new StylesXform(true) : new StylesXform.Mock(true);
|
||||
|
||||
// defined names
|
||||
this._definedNames = new DefinedNames();
|
||||
|
||||
this._worksheets = [];
|
||||
this.views = [];
|
||||
|
||||
this.zipOptions = options.zip;
|
||||
|
||||
this.media = [];
|
||||
this.commentRefs = [];
|
||||
|
||||
this.zip = Archiver('zip', this.zipOptions);
|
||||
if (options.stream) {
|
||||
this.stream = options.stream;
|
||||
} else if (options.filename) {
|
||||
this.stream = fs.createWriteStream(options.filename);
|
||||
} else {
|
||||
this.stream = new StreamBuf();
|
||||
}
|
||||
this.zip.pipe(this.stream);
|
||||
|
||||
// these bits can be added right now
|
||||
this.promise = Promise.all([this.addThemes(), this.addOfficeRels()]);
|
||||
}
|
||||
|
||||
get definedNames() {
|
||||
return this._definedNames;
|
||||
}
|
||||
|
||||
_openStream(path) {
|
||||
const stream = new StreamBuf({bufSize: 65536, batch: true});
|
||||
this.zip.append(stream, {name: path});
|
||||
stream.on('finish', () => {
|
||||
stream.emit('zipped');
|
||||
});
|
||||
return stream;
|
||||
}
|
||||
|
||||
_commitWorksheets() {
|
||||
const commitWorksheet = function(worksheet) {
|
||||
if (!worksheet.committed) {
|
||||
return new Promise(resolve => {
|
||||
worksheet.stream.on('zipped', () => {
|
||||
resolve();
|
||||
});
|
||||
worksheet.commit();
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
// if there are any uncommitted worksheets, commit them now and wait
|
||||
const promises = this._worksheets.map(commitWorksheet);
|
||||
if (promises.length) {
|
||||
return Promise.all(promises);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
async commit() {
|
||||
// commit all worksheets, then add suplimentary files
|
||||
await this.promise;
|
||||
await this.addMedia();
|
||||
await this._commitWorksheets();
|
||||
await Promise.all([
|
||||
this.addContentTypes(),
|
||||
this.addApp(),
|
||||
this.addCore(),
|
||||
this.addSharedStrings(),
|
||||
this.addStyles(),
|
||||
this.addWorkbookRels(),
|
||||
]);
|
||||
await this.addWorkbook();
|
||||
return this._finalize();
|
||||
}
|
||||
|
||||
get nextId() {
|
||||
// find the next unique spot to add worksheet
|
||||
let i;
|
||||
for (i = 1; i < this._worksheets.length; i++) {
|
||||
if (!this._worksheets[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return this._worksheets.length || 1;
|
||||
}
|
||||
|
||||
addImage(image) {
|
||||
const id = this.media.length;
|
||||
const medium = Object.assign({}, image, {type: 'image', name: `image${id}.${image.extension}`});
|
||||
this.media.push(medium);
|
||||
return id;
|
||||
}
|
||||
|
||||
getImage(id) {
|
||||
return this.media[id];
|
||||
}
|
||||
|
||||
addWorksheet(name, options) {
|
||||
// it's possible to add a worksheet with different than default
|
||||
// shared string handling
|
||||
// in fact, it's even possible to switch it mid-sheet
|
||||
options = options || {};
|
||||
const useSharedStrings =
|
||||
options.useSharedStrings !== undefined ? options.useSharedStrings : this.useSharedStrings;
|
||||
|
||||
if (options.tabColor) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.trace('tabColor option has moved to { properties: tabColor: {...} }');
|
||||
options.properties = Object.assign(
|
||||
{
|
||||
tabColor: options.tabColor,
|
||||
},
|
||||
options.properties
|
||||
);
|
||||
}
|
||||
|
||||
const id = this.nextId;
|
||||
name = name || `sheet${id}`;
|
||||
|
||||
const worksheet = new WorksheetWriter({
|
||||
id,
|
||||
name,
|
||||
workbook: this,
|
||||
useSharedStrings,
|
||||
properties: options.properties,
|
||||
state: options.state,
|
||||
pageSetup: options.pageSetup,
|
||||
views: options.views,
|
||||
autoFilter: options.autoFilter,
|
||||
headerFooter: options.headerFooter,
|
||||
});
|
||||
|
||||
this._worksheets[id] = worksheet;
|
||||
return worksheet;
|
||||
}
|
||||
|
||||
getWorksheet(id) {
|
||||
if (id === undefined) {
|
||||
return this._worksheets.find(() => true);
|
||||
}
|
||||
if (typeof id === 'number') {
|
||||
return this._worksheets[id];
|
||||
}
|
||||
if (typeof id === 'string') {
|
||||
return this._worksheets.find(worksheet => worksheet && worksheet.name === id);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
addStyles() {
|
||||
return new Promise(resolve => {
|
||||
this.zip.append(this.styles.xml, {name: 'xl/styles.xml'});
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
addThemes() {
|
||||
return new Promise(resolve => {
|
||||
this.zip.append(theme1Xml, {name: 'xl/theme/theme1.xml'});
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
addOfficeRels() {
|
||||
return new Promise(resolve => {
|
||||
const xform = new RelationshipsXform();
|
||||
const xml = xform.toXml([
|
||||
{Id: 'rId1', Type: RelType.OfficeDocument, Target: 'xl/workbook.xml'},
|
||||
{Id: 'rId2', Type: RelType.CoreProperties, Target: 'docProps/core.xml'},
|
||||
{Id: 'rId3', Type: RelType.ExtenderProperties, Target: 'docProps/app.xml'},
|
||||
]);
|
||||
this.zip.append(xml, {name: '/_rels/.rels'});
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
addContentTypes() {
|
||||
return new Promise(resolve => {
|
||||
const model = {
|
||||
worksheets: this._worksheets.filter(Boolean),
|
||||
sharedStrings: this.sharedStrings,
|
||||
commentRefs: this.commentRefs,
|
||||
media: this.media,
|
||||
};
|
||||
const xform = new ContentTypesXform();
|
||||
const xml = xform.toXml(model);
|
||||
this.zip.append(xml, {name: '[Content_Types].xml'});
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
addMedia() {
|
||||
return Promise.all(
|
||||
this.media.map(medium => {
|
||||
if (medium.type === 'image') {
|
||||
const filename = `xl/media/${medium.name}`;
|
||||
if (medium.filename) {
|
||||
return this.zip.file(medium.filename, {name: filename});
|
||||
}
|
||||
if (medium.buffer) {
|
||||
return this.zip.append(medium.buffer, {name: filename});
|
||||
}
|
||||
if (medium.base64) {
|
||||
const dataimg64 = medium.base64;
|
||||
const content = dataimg64.substring(dataimg64.indexOf(',') + 1);
|
||||
return this.zip.append(content, {name: filename, base64: true});
|
||||
}
|
||||
}
|
||||
throw new Error('Unsupported media');
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
addApp() {
|
||||
return new Promise(resolve => {
|
||||
const model = {
|
||||
worksheets: this._worksheets.filter(Boolean),
|
||||
};
|
||||
const xform = new AppXform();
|
||||
const xml = xform.toXml(model);
|
||||
this.zip.append(xml, {name: 'docProps/app.xml'});
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
addCore() {
|
||||
return new Promise(resolve => {
|
||||
const coreXform = new CoreXform();
|
||||
const xml = coreXform.toXml(this);
|
||||
this.zip.append(xml, {name: 'docProps/core.xml'});
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
addSharedStrings() {
|
||||
if (this.sharedStrings.count) {
|
||||
return new Promise(resolve => {
|
||||
const sharedStringsXform = new SharedStringsXform();
|
||||
const xml = sharedStringsXform.toXml(this.sharedStrings);
|
||||
this.zip.append(xml, {name: '/xl/sharedStrings.xml'});
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
addWorkbookRels() {
|
||||
let count = 1;
|
||||
const relationships = [
|
||||
{Id: `rId${count++}`, Type: RelType.Styles, Target: 'styles.xml'},
|
||||
{Id: `rId${count++}`, Type: RelType.Theme, Target: 'theme/theme1.xml'},
|
||||
];
|
||||
if (this.sharedStrings.count) {
|
||||
relationships.push({
|
||||
Id: `rId${count++}`,
|
||||
Type: RelType.SharedStrings,
|
||||
Target: 'sharedStrings.xml',
|
||||
});
|
||||
}
|
||||
this._worksheets.forEach(worksheet => {
|
||||
if (worksheet) {
|
||||
worksheet.rId = `rId${count++}`;
|
||||
relationships.push({
|
||||
Id: worksheet.rId,
|
||||
Type: RelType.Worksheet,
|
||||
Target: `worksheets/sheet${worksheet.id}.xml`,
|
||||
});
|
||||
}
|
||||
});
|
||||
return new Promise(resolve => {
|
||||
const xform = new RelationshipsXform();
|
||||
const xml = xform.toXml(relationships);
|
||||
this.zip.append(xml, {name: '/xl/_rels/workbook.xml.rels'});
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
addWorkbook() {
|
||||
const {zip} = this;
|
||||
const model = {
|
||||
worksheets: this._worksheets.filter(Boolean),
|
||||
definedNames: this._definedNames.model,
|
||||
views: this.views,
|
||||
properties: {},
|
||||
calcProperties: {},
|
||||
};
|
||||
|
||||
return new Promise(resolve => {
|
||||
const xform = new WorkbookXform();
|
||||
xform.prepare(model);
|
||||
zip.append(xform.toXml(model), {name: '/xl/workbook.xml'});
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
_finalize() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.stream.on('error', reject);
|
||||
this.stream.on('finish', () => {
|
||||
resolve(this);
|
||||
});
|
||||
this.zip.on('error', reject);
|
||||
|
||||
this.zip.finalize();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WorkbookWriter;
|
||||
374
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/worksheet-reader.js
generated
vendored
Normal file
374
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/worksheet-reader.js
generated
vendored
Normal file
@@ -0,0 +1,374 @@
|
||||
const {EventEmitter} = require('events');
|
||||
const parseSax = require('../../utils/parse-sax');
|
||||
|
||||
const _ = require('../../utils/under-dash');
|
||||
const utils = require('../../utils/utils');
|
||||
const colCache = require('../../utils/col-cache');
|
||||
const Dimensions = require('../../doc/range');
|
||||
|
||||
const Row = require('../../doc/row');
|
||||
const Column = require('../../doc/column');
|
||||
|
||||
class WorksheetReader extends EventEmitter {
|
||||
constructor({workbook, id, iterator, options}) {
|
||||
super();
|
||||
|
||||
this.workbook = workbook;
|
||||
this.id = id;
|
||||
this.iterator = iterator;
|
||||
this.options = options || {};
|
||||
|
||||
// and a name
|
||||
this.name = `Sheet${this.id}`;
|
||||
|
||||
// column definitions
|
||||
this._columns = null;
|
||||
this._keys = {};
|
||||
|
||||
// keep a record of dimensions
|
||||
this._dimensions = new Dimensions();
|
||||
}
|
||||
|
||||
// destroy - not a valid operation for a streaming writer
|
||||
// even though some streamers might be able to, it's a bad idea.
|
||||
destroy() {
|
||||
throw new Error('Invalid Operation: destroy');
|
||||
}
|
||||
|
||||
// return the current dimensions of the writer
|
||||
get dimensions() {
|
||||
return this._dimensions;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Columns
|
||||
|
||||
// get the current columns array.
|
||||
get columns() {
|
||||
return this._columns;
|
||||
}
|
||||
|
||||
// get a single column by col number. If it doesn't exist, it and any gaps before it
|
||||
// are created.
|
||||
getColumn(c) {
|
||||
if (typeof c === 'string') {
|
||||
// if it matches a key'd column, return that
|
||||
const col = this._keys[c];
|
||||
if (col) {
|
||||
return col;
|
||||
}
|
||||
|
||||
// otherise, assume letter
|
||||
c = colCache.l2n(c);
|
||||
}
|
||||
if (!this._columns) {
|
||||
this._columns = [];
|
||||
}
|
||||
if (c > this._columns.length) {
|
||||
let n = this._columns.length + 1;
|
||||
while (n <= c) {
|
||||
this._columns.push(new Column(this, n++));
|
||||
}
|
||||
}
|
||||
return this._columns[c - 1];
|
||||
}
|
||||
|
||||
getColumnKey(key) {
|
||||
return this._keys[key];
|
||||
}
|
||||
|
||||
setColumnKey(key, value) {
|
||||
this._keys[key] = value;
|
||||
}
|
||||
|
||||
deleteColumnKey(key) {
|
||||
delete this._keys[key];
|
||||
}
|
||||
|
||||
eachColumnKey(f) {
|
||||
_.each(this._keys, f);
|
||||
}
|
||||
|
||||
async read() {
|
||||
try {
|
||||
for await (const events of this.parse()) {
|
||||
for (const {eventType, value} of events) {
|
||||
this.emit(eventType, value);
|
||||
}
|
||||
}
|
||||
this.emit('finished');
|
||||
} catch (error) {
|
||||
this.emit('error', error);
|
||||
}
|
||||
}
|
||||
|
||||
async *[Symbol.asyncIterator]() {
|
||||
for await (const events of this.parse()) {
|
||||
for (const {eventType, value} of events) {
|
||||
if (eventType === 'row') {
|
||||
yield value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async *parse() {
|
||||
const {iterator, options} = this;
|
||||
let emitSheet = false;
|
||||
let emitHyperlinks = false;
|
||||
let hyperlinks = null;
|
||||
switch (options.worksheets) {
|
||||
case 'emit':
|
||||
emitSheet = true;
|
||||
break;
|
||||
case 'prep':
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (options.hyperlinks) {
|
||||
case 'emit':
|
||||
emitHyperlinks = true;
|
||||
break;
|
||||
case 'cache':
|
||||
this.hyperlinks = hyperlinks = {};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!emitSheet && !emitHyperlinks && !hyperlinks) {
|
||||
return;
|
||||
}
|
||||
|
||||
// references
|
||||
const {sharedStrings, styles, properties} = this.workbook;
|
||||
|
||||
// xml position
|
||||
let inCols = false;
|
||||
let inRows = false;
|
||||
let inHyperlinks = false;
|
||||
|
||||
// parse state
|
||||
let cols = null;
|
||||
let row = null;
|
||||
let c = null;
|
||||
let current = null;
|
||||
for await (const events of parseSax(iterator)) {
|
||||
const worksheetEvents = [];
|
||||
for (const {eventType, value} of events) {
|
||||
if (eventType === 'opentag') {
|
||||
const node = value;
|
||||
if (emitSheet) {
|
||||
switch (node.name) {
|
||||
case 'cols':
|
||||
inCols = true;
|
||||
cols = [];
|
||||
break;
|
||||
case 'sheetData':
|
||||
inRows = true;
|
||||
break;
|
||||
|
||||
case 'col':
|
||||
if (inCols) {
|
||||
cols.push({
|
||||
min: parseInt(node.attributes.min, 10),
|
||||
max: parseInt(node.attributes.max, 10),
|
||||
width: parseFloat(node.attributes.width),
|
||||
styleId: parseInt(node.attributes.style || '0', 10),
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case 'row':
|
||||
if (inRows) {
|
||||
const r = parseInt(node.attributes.r, 10);
|
||||
row = new Row(this, r);
|
||||
if (node.attributes.ht) {
|
||||
row.height = parseFloat(node.attributes.ht);
|
||||
}
|
||||
if (node.attributes.s) {
|
||||
const styleId = parseInt(node.attributes.s, 10);
|
||||
const style = styles.getStyleModel(styleId);
|
||||
if (style) {
|
||||
row.style = style;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (row) {
|
||||
c = {
|
||||
ref: node.attributes.r,
|
||||
s: parseInt(node.attributes.s, 10),
|
||||
t: node.attributes.t,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
if (c) {
|
||||
current = c.f = {text: ''};
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
if (c) {
|
||||
current = c.v = {text: ''};
|
||||
}
|
||||
break;
|
||||
case 'is':
|
||||
case 't':
|
||||
if (c) {
|
||||
current = c.v = {text: ''};
|
||||
}
|
||||
break;
|
||||
case 'mergeCell':
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
//
|
||||
if (emitHyperlinks || hyperlinks) {
|
||||
switch (node.name) {
|
||||
case 'hyperlinks':
|
||||
inHyperlinks = true;
|
||||
break;
|
||||
case 'hyperlink':
|
||||
if (inHyperlinks) {
|
||||
const hyperlink = {
|
||||
ref: node.attributes.ref,
|
||||
rId: node.attributes['r:id'],
|
||||
};
|
||||
if (emitHyperlinks) {
|
||||
worksheetEvents.push({eventType: 'hyperlink', value: hyperlink});
|
||||
} else {
|
||||
hyperlinks[hyperlink.ref] = hyperlink;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (eventType === 'text') {
|
||||
// only text data is for sheet values
|
||||
if (emitSheet) {
|
||||
if (current) {
|
||||
current.text += value;
|
||||
}
|
||||
}
|
||||
} else if (eventType === 'closetag') {
|
||||
const node = value;
|
||||
if (emitSheet) {
|
||||
switch (node.name) {
|
||||
case 'cols':
|
||||
inCols = false;
|
||||
this._columns = Column.fromModel(cols);
|
||||
break;
|
||||
case 'sheetData':
|
||||
inRows = false;
|
||||
break;
|
||||
|
||||
case 'row':
|
||||
this._dimensions.expandRow(row);
|
||||
worksheetEvents.push({eventType: 'row', value: row});
|
||||
row = null;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (row && c) {
|
||||
const address = colCache.decodeAddress(c.ref);
|
||||
const cell = row.getCell(address.col);
|
||||
if (c.s) {
|
||||
const style = styles.getStyleModel(c.s);
|
||||
if (style) {
|
||||
cell.style = style;
|
||||
}
|
||||
}
|
||||
|
||||
if (c.f) {
|
||||
const cellValue = {
|
||||
formula: c.f.text,
|
||||
};
|
||||
if (c.v) {
|
||||
if (c.t === 'str') {
|
||||
cellValue.result = utils.xmlDecode(c.v.text);
|
||||
} else {
|
||||
cellValue.result = parseFloat(c.v.text);
|
||||
}
|
||||
}
|
||||
cell.value = cellValue;
|
||||
} else if (c.v) {
|
||||
switch (c.t) {
|
||||
case 's': {
|
||||
const index = parseInt(c.v.text, 10);
|
||||
if (sharedStrings) {
|
||||
cell.value = sharedStrings[index];
|
||||
} else {
|
||||
cell.value = {
|
||||
sharedString: index,
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'inlineStr':
|
||||
case 'str':
|
||||
cell.value = utils.xmlDecode(c.v.text);
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
cell.value = {error: c.v.text};
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
cell.value = parseInt(c.v.text, 10) !== 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (utils.isDateFmt(cell.numFmt)) {
|
||||
cell.value = utils.excelToDate(
|
||||
parseFloat(c.v.text),
|
||||
properties.model && properties.model.date1904
|
||||
);
|
||||
} else {
|
||||
cell.value = parseFloat(c.v.text);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hyperlinks) {
|
||||
const hyperlink = hyperlinks[c.ref];
|
||||
if (hyperlink) {
|
||||
cell.text = cell.value;
|
||||
cell.value = undefined;
|
||||
cell.hyperlink = hyperlink;
|
||||
}
|
||||
}
|
||||
c = null;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (emitHyperlinks || hyperlinks) {
|
||||
switch (node.name) {
|
||||
case 'hyperlinks':
|
||||
inHyperlinks = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (worksheetEvents.length > 0) {
|
||||
yield worksheetEvents;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WorksheetReader;
|
||||
717
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/worksheet-writer.js
generated
vendored
Normal file
717
doc/test-data/purchase_transaction/node_modules/exceljs/lib/stream/xlsx/worksheet-writer.js
generated
vendored
Normal file
@@ -0,0 +1,717 @@
|
||||
const _ = require('../../utils/under-dash');
|
||||
|
||||
const RelType = require('../../xlsx/rel-type');
|
||||
|
||||
const colCache = require('../../utils/col-cache');
|
||||
const Encryptor = require('../../utils/encryptor');
|
||||
const Dimensions = require('../../doc/range');
|
||||
const StringBuf = require('../../utils/string-buf');
|
||||
|
||||
const Row = require('../../doc/row');
|
||||
const Column = require('../../doc/column');
|
||||
|
||||
const SheetRelsWriter = require('./sheet-rels-writer');
|
||||
const SheetCommentsWriter = require('./sheet-comments-writer');
|
||||
const DataValidations = require('../../doc/data-validations');
|
||||
|
||||
const xmlBuffer = new StringBuf();
|
||||
|
||||
// ============================================================================================
|
||||
// Xforms
|
||||
const ListXform = require('../../xlsx/xform/list-xform');
|
||||
const DataValidationsXform = require('../../xlsx/xform/sheet/data-validations-xform');
|
||||
const SheetPropertiesXform = require('../../xlsx/xform/sheet/sheet-properties-xform');
|
||||
const SheetFormatPropertiesXform = require('../../xlsx/xform/sheet/sheet-format-properties-xform');
|
||||
const ColXform = require('../../xlsx/xform/sheet/col-xform');
|
||||
const RowXform = require('../../xlsx/xform/sheet/row-xform');
|
||||
const HyperlinkXform = require('../../xlsx/xform/sheet/hyperlink-xform');
|
||||
const SheetViewXform = require('../../xlsx/xform/sheet/sheet-view-xform');
|
||||
const SheetProtectionXform = require('../../xlsx/xform/sheet/sheet-protection-xform');
|
||||
const PageMarginsXform = require('../../xlsx/xform/sheet/page-margins-xform');
|
||||
const PageSetupXform = require('../../xlsx/xform/sheet/page-setup-xform');
|
||||
const AutoFilterXform = require('../../xlsx/xform/sheet/auto-filter-xform');
|
||||
const PictureXform = require('../../xlsx/xform/sheet/picture-xform');
|
||||
const ConditionalFormattingsXform = require('../../xlsx/xform/sheet/cf/conditional-formattings-xform');
|
||||
const HeaderFooterXform = require('../../xlsx/xform/sheet/header-footer-xform');
|
||||
const RowBreaksXform = require('../../xlsx/xform/sheet/row-breaks-xform');
|
||||
|
||||
// since prepare and render are functional, we can use singletons
|
||||
const xform = {
|
||||
dataValidations: new DataValidationsXform(),
|
||||
sheetProperties: new SheetPropertiesXform(),
|
||||
sheetFormatProperties: new SheetFormatPropertiesXform(),
|
||||
columns: new ListXform({tag: 'cols', length: false, childXform: new ColXform()}),
|
||||
row: new RowXform(),
|
||||
hyperlinks: new ListXform({tag: 'hyperlinks', length: false, childXform: new HyperlinkXform()}),
|
||||
sheetViews: new ListXform({tag: 'sheetViews', length: false, childXform: new SheetViewXform()}),
|
||||
sheetProtection: new SheetProtectionXform(),
|
||||
pageMargins: new PageMarginsXform(),
|
||||
pageSeteup: new PageSetupXform(),
|
||||
autoFilter: new AutoFilterXform(),
|
||||
picture: new PictureXform(),
|
||||
conditionalFormattings: new ConditionalFormattingsXform(),
|
||||
headerFooter: new HeaderFooterXform(),
|
||||
rowBreaks: new RowBreaksXform(),
|
||||
};
|
||||
|
||||
// ============================================================================================
|
||||
|
||||
class WorksheetWriter {
|
||||
constructor(options) {
|
||||
// in a workbook, each sheet will have a number
|
||||
this.id = options.id;
|
||||
|
||||
// and a name
|
||||
this.name = options.name || `Sheet${this.id}`;
|
||||
|
||||
// add a state
|
||||
this.state = options.state || 'visible';
|
||||
|
||||
// rows are stored here while they need to be worked on.
|
||||
// when they are committed, they will be deleted.
|
||||
this._rows = [];
|
||||
|
||||
// column definitions
|
||||
this._columns = null;
|
||||
|
||||
// column keys (addRow convenience): key ==> this._columns index
|
||||
this._keys = {};
|
||||
|
||||
// keep a record of all row and column pageBreaks
|
||||
this._merges = [];
|
||||
this._merges.add = function() {}; // ignore cell instruction
|
||||
|
||||
// keep record of all hyperlinks
|
||||
this._sheetRelsWriter = new SheetRelsWriter(options);
|
||||
|
||||
this._sheetCommentsWriter = new SheetCommentsWriter(this, this._sheetRelsWriter, options);
|
||||
|
||||
// keep a record of dimensions
|
||||
this._dimensions = new Dimensions();
|
||||
|
||||
// first uncommitted row
|
||||
this._rowZero = 1;
|
||||
|
||||
// committed flag
|
||||
this.committed = false;
|
||||
|
||||
// for data validations
|
||||
this.dataValidations = new DataValidations();
|
||||
|
||||
// for sharing formulae
|
||||
this._formulae = {};
|
||||
this._siFormulae = 0;
|
||||
|
||||
// keep a record of conditionalFormattings
|
||||
this.conditionalFormatting = [];
|
||||
|
||||
// keep a record of all row and column pageBreaks
|
||||
this.rowBreaks = [];
|
||||
|
||||
// for default row height, outline levels, etc
|
||||
this.properties = Object.assign(
|
||||
{},
|
||||
{
|
||||
defaultRowHeight: 15,
|
||||
dyDescent: 55,
|
||||
outlineLevelCol: 0,
|
||||
outlineLevelRow: 0,
|
||||
},
|
||||
options.properties
|
||||
);
|
||||
|
||||
this.headerFooter = Object.assign(
|
||||
{},
|
||||
{
|
||||
differentFirst: false,
|
||||
differentOddEven: false,
|
||||
oddHeader: null,
|
||||
oddFooter: null,
|
||||
evenHeader: null,
|
||||
evenFooter: null,
|
||||
firstHeader: null,
|
||||
firstFooter: null,
|
||||
},
|
||||
options.headerFooter
|
||||
);
|
||||
|
||||
// for all things printing
|
||||
this.pageSetup = Object.assign(
|
||||
{},
|
||||
{
|
||||
margins: {left: 0.7, right: 0.7, top: 0.75, bottom: 0.75, header: 0.3, footer: 0.3},
|
||||
orientation: 'portrait',
|
||||
horizontalDpi: 4294967295,
|
||||
verticalDpi: 4294967295,
|
||||
fitToPage: !!(
|
||||
options.pageSetup &&
|
||||
(options.pageSetup.fitToWidth || options.pageSetup.fitToHeight) &&
|
||||
!options.pageSetup.scale
|
||||
),
|
||||
pageOrder: 'downThenOver',
|
||||
blackAndWhite: false,
|
||||
draft: false,
|
||||
cellComments: 'None',
|
||||
errors: 'displayed',
|
||||
scale: 100,
|
||||
fitToWidth: 1,
|
||||
fitToHeight: 1,
|
||||
paperSize: undefined,
|
||||
showRowColHeaders: false,
|
||||
showGridLines: false,
|
||||
horizontalCentered: false,
|
||||
verticalCentered: false,
|
||||
rowBreaks: null,
|
||||
colBreaks: null,
|
||||
},
|
||||
options.pageSetup
|
||||
);
|
||||
|
||||
// using shared strings creates a smaller xlsx file but may use more memory
|
||||
this.useSharedStrings = options.useSharedStrings || false;
|
||||
|
||||
this._workbook = options.workbook;
|
||||
|
||||
this.hasComments = false;
|
||||
|
||||
// views
|
||||
this._views = options.views || [];
|
||||
|
||||
// auto filter
|
||||
this.autoFilter = options.autoFilter || null;
|
||||
|
||||
this._media = [];
|
||||
|
||||
// worksheet protection
|
||||
this.sheetProtection = null;
|
||||
|
||||
// start writing to stream now
|
||||
this._writeOpenWorksheet();
|
||||
|
||||
this.startedData = false;
|
||||
}
|
||||
|
||||
get workbook() {
|
||||
return this._workbook;
|
||||
}
|
||||
|
||||
get stream() {
|
||||
if (!this._stream) {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
this._stream = this._workbook._openStream(`/xl/worksheets/sheet${this.id}.xml`);
|
||||
|
||||
// pause stream to prevent 'data' events
|
||||
this._stream.pause();
|
||||
}
|
||||
return this._stream;
|
||||
}
|
||||
|
||||
// destroy - not a valid operation for a streaming writer
|
||||
// even though some streamers might be able to, it's a bad idea.
|
||||
destroy() {
|
||||
throw new Error('Invalid Operation: destroy');
|
||||
}
|
||||
|
||||
commit() {
|
||||
if (this.committed) {
|
||||
return;
|
||||
}
|
||||
// commit all rows
|
||||
this._rows.forEach(cRow => {
|
||||
if (cRow) {
|
||||
// write the row to the stream
|
||||
this._writeRow(cRow);
|
||||
}
|
||||
});
|
||||
|
||||
// we _cannot_ accept new rows from now on
|
||||
this._rows = null;
|
||||
|
||||
if (!this.startedData) {
|
||||
this._writeOpenSheetData();
|
||||
}
|
||||
this._writeCloseSheetData();
|
||||
this._writeAutoFilter();
|
||||
this._writeMergeCells();
|
||||
|
||||
// for some reason, Excel can't handle dimensions at the bottom of the file
|
||||
// this._writeDimensions();
|
||||
|
||||
this._writeHyperlinks();
|
||||
this._writeConditionalFormatting();
|
||||
this._writeDataValidations();
|
||||
this._writeSheetProtection();
|
||||
this._writePageMargins();
|
||||
this._writePageSetup();
|
||||
this._writeBackground();
|
||||
this._writeHeaderFooter();
|
||||
this._writeRowBreaks();
|
||||
|
||||
// Legacy Data tag for comments
|
||||
this._writeLegacyData();
|
||||
|
||||
this._writeCloseWorksheet();
|
||||
// signal end of stream to workbook
|
||||
this.stream.end();
|
||||
|
||||
this._sheetCommentsWriter.commit();
|
||||
// also commit the hyperlinks if any
|
||||
this._sheetRelsWriter.commit();
|
||||
|
||||
this.committed = true;
|
||||
}
|
||||
|
||||
// return the current dimensions of the writer
|
||||
get dimensions() {
|
||||
return this._dimensions;
|
||||
}
|
||||
|
||||
get views() {
|
||||
return this._views;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Columns
|
||||
|
||||
// get the current columns array.
|
||||
get columns() {
|
||||
return this._columns;
|
||||
}
|
||||
|
||||
// set the columns from an array of column definitions.
|
||||
// Note: any headers defined will overwrite existing values.
|
||||
set columns(value) {
|
||||
// calculate max header row count
|
||||
this._headerRowCount = value.reduce((pv, cv) => {
|
||||
const headerCount = (cv.header && 1) || (cv.headers && cv.headers.length) || 0;
|
||||
return Math.max(pv, headerCount);
|
||||
}, 0);
|
||||
|
||||
// construct Column objects
|
||||
let count = 1;
|
||||
const columns = (this._columns = []);
|
||||
value.forEach(defn => {
|
||||
const column = new Column(this, count++, false);
|
||||
columns.push(column);
|
||||
column.defn = defn;
|
||||
});
|
||||
}
|
||||
|
||||
getColumnKey(key) {
|
||||
return this._keys[key];
|
||||
}
|
||||
|
||||
setColumnKey(key, value) {
|
||||
this._keys[key] = value;
|
||||
}
|
||||
|
||||
deleteColumnKey(key) {
|
||||
delete this._keys[key];
|
||||
}
|
||||
|
||||
eachColumnKey(f) {
|
||||
_.each(this._keys, f);
|
||||
}
|
||||
|
||||
// get a single column by col number. If it doesn't exist, it and any gaps before it
|
||||
// are created.
|
||||
getColumn(c) {
|
||||
if (typeof c === 'string') {
|
||||
// if it matches a key'd column, return that
|
||||
const col = this._keys[c];
|
||||
if (col) return col;
|
||||
|
||||
// otherwise, assume letter
|
||||
c = colCache.l2n(c);
|
||||
}
|
||||
if (!this._columns) {
|
||||
this._columns = [];
|
||||
}
|
||||
if (c > this._columns.length) {
|
||||
let n = this._columns.length + 1;
|
||||
while (n <= c) {
|
||||
this._columns.push(new Column(this, n++));
|
||||
}
|
||||
}
|
||||
return this._columns[c - 1];
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Rows
|
||||
get _nextRow() {
|
||||
return this._rowZero + this._rows.length;
|
||||
}
|
||||
|
||||
// iterate over every uncommitted row in the worksheet, including maybe empty rows
|
||||
eachRow(options, iteratee) {
|
||||
if (!iteratee) {
|
||||
iteratee = options;
|
||||
options = undefined;
|
||||
}
|
||||
if (options && options.includeEmpty) {
|
||||
const n = this._nextRow;
|
||||
for (let i = this._rowZero; i < n; i++) {
|
||||
iteratee(this.getRow(i), i);
|
||||
}
|
||||
} else {
|
||||
this._rows.forEach(row => {
|
||||
if (row.hasValues) {
|
||||
iteratee(row, row.number);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_commitRow(cRow) {
|
||||
// since rows must be written in order, we commit all rows up till and including cRow
|
||||
let found = false;
|
||||
while (this._rows.length && !found) {
|
||||
const row = this._rows.shift();
|
||||
this._rowZero++;
|
||||
if (row) {
|
||||
this._writeRow(row);
|
||||
found = row.number === cRow.number;
|
||||
this._rowZero = row.number + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get lastRow() {
|
||||
// returns last uncommitted row
|
||||
if (this._rows.length) {
|
||||
return this._rows[this._rows.length - 1];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// find a row (if exists) by row number
|
||||
findRow(rowNumber) {
|
||||
const index = rowNumber - this._rowZero;
|
||||
return this._rows[index];
|
||||
}
|
||||
|
||||
getRow(rowNumber) {
|
||||
const index = rowNumber - this._rowZero;
|
||||
|
||||
// may fail if rows have been comitted
|
||||
if (index < 0) {
|
||||
throw new Error('Out of bounds: this row has been committed');
|
||||
}
|
||||
let row = this._rows[index];
|
||||
if (!row) {
|
||||
this._rows[index] = row = new Row(this, rowNumber);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
addRow(value) {
|
||||
const row = new Row(this, this._nextRow);
|
||||
this._rows[row.number - this._rowZero] = row;
|
||||
row.values = value;
|
||||
return row;
|
||||
}
|
||||
|
||||
// ================================================================================
|
||||
// Cells
|
||||
|
||||
// returns the cell at [r,c] or address given by r. If not found, return undefined
|
||||
findCell(r, c) {
|
||||
const address = colCache.getAddress(r, c);
|
||||
const row = this.findRow(address.row);
|
||||
return row ? row.findCell(address.column) : undefined;
|
||||
}
|
||||
|
||||
// return the cell at [r,c] or address given by r. If not found, create a new one.
|
||||
getCell(r, c) {
|
||||
const address = colCache.getAddress(r, c);
|
||||
const row = this.getRow(address.row);
|
||||
return row.getCellEx(address);
|
||||
}
|
||||
|
||||
mergeCells(...cells) {
|
||||
// may fail if rows have been comitted
|
||||
const dimensions = new Dimensions(cells);
|
||||
|
||||
// check cells aren't already merged
|
||||
this._merges.forEach(merge => {
|
||||
if (merge.intersects(dimensions)) {
|
||||
throw new Error('Cannot merge already merged cells');
|
||||
}
|
||||
});
|
||||
|
||||
// apply merge
|
||||
const master = this.getCell(dimensions.top, dimensions.left);
|
||||
for (let i = dimensions.top; i <= dimensions.bottom; i++) {
|
||||
for (let j = dimensions.left; j <= dimensions.right; j++) {
|
||||
if (i > dimensions.top || j > dimensions.left) {
|
||||
this.getCell(i, j).merge(master);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// index merge
|
||||
this._merges.push(dimensions);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Conditional Formatting
|
||||
addConditionalFormatting(cf) {
|
||||
this.conditionalFormatting.push(cf);
|
||||
}
|
||||
|
||||
removeConditionalFormatting(filter) {
|
||||
if (typeof filter === 'number') {
|
||||
this.conditionalFormatting.splice(filter, 1);
|
||||
} else if (filter instanceof Function) {
|
||||
this.conditionalFormatting = this.conditionalFormatting.filter(filter);
|
||||
} else {
|
||||
this.conditionalFormatting = [];
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
||||
addBackgroundImage(imageId) {
|
||||
this._background = {
|
||||
imageId,
|
||||
};
|
||||
}
|
||||
|
||||
getBackgroundImageId() {
|
||||
return this._background && this._background.imageId;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Worksheet Protection
|
||||
protect(password, options) {
|
||||
// TODO: make this function truly async
|
||||
// perhaps marshal to worker thread or something
|
||||
return new Promise(resolve => {
|
||||
this.sheetProtection = {
|
||||
sheet: true,
|
||||
};
|
||||
if (options && 'spinCount' in options) {
|
||||
// force spinCount to be integer >= 0
|
||||
options.spinCount = Number.isFinite(options.spinCount) ? Math.round(Math.max(0, options.spinCount)) : 100000;
|
||||
}
|
||||
if (password) {
|
||||
this.sheetProtection.algorithmName = 'SHA-512';
|
||||
this.sheetProtection.saltValue = Encryptor.randomBytes(16).toString('base64');
|
||||
this.sheetProtection.spinCount = options && 'spinCount' in options ? options.spinCount : 100000; // allow user specified spinCount
|
||||
this.sheetProtection.hashValue = Encryptor.convertPasswordToHash(
|
||||
password,
|
||||
'SHA512',
|
||||
this.sheetProtection.saltValue,
|
||||
this.sheetProtection.spinCount
|
||||
);
|
||||
}
|
||||
if (options) {
|
||||
this.sheetProtection = Object.assign(this.sheetProtection, options);
|
||||
if (!password && 'spinCount' in options) {
|
||||
delete this.sheetProtection.spinCount;
|
||||
}
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
unprotect() {
|
||||
this.sheetProtection = null;
|
||||
}
|
||||
|
||||
// ================================================================================
|
||||
|
||||
_write(text) {
|
||||
xmlBuffer.reset();
|
||||
xmlBuffer.addText(text);
|
||||
this.stream.write(xmlBuffer);
|
||||
}
|
||||
|
||||
_writeSheetProperties(xmlBuf, properties, pageSetup) {
|
||||
const sheetPropertiesModel = {
|
||||
outlineProperties: properties && properties.outlineProperties,
|
||||
tabColor: properties && properties.tabColor,
|
||||
pageSetup:
|
||||
pageSetup && pageSetup.fitToPage
|
||||
? {
|
||||
fitToPage: pageSetup.fitToPage,
|
||||
}
|
||||
: undefined,
|
||||
};
|
||||
|
||||
xmlBuf.addText(xform.sheetProperties.toXml(sheetPropertiesModel));
|
||||
}
|
||||
|
||||
_writeSheetFormatProperties(xmlBuf, properties) {
|
||||
const sheetFormatPropertiesModel = properties
|
||||
? {
|
||||
defaultRowHeight: properties.defaultRowHeight,
|
||||
dyDescent: properties.dyDescent,
|
||||
outlineLevelCol: properties.outlineLevelCol,
|
||||
outlineLevelRow: properties.outlineLevelRow,
|
||||
}
|
||||
: undefined;
|
||||
if (properties.defaultColWidth) {
|
||||
sheetFormatPropertiesModel.defaultColWidth = properties.defaultColWidth;
|
||||
}
|
||||
|
||||
xmlBuf.addText(xform.sheetFormatProperties.toXml(sheetFormatPropertiesModel));
|
||||
}
|
||||
|
||||
_writeOpenWorksheet() {
|
||||
xmlBuffer.reset();
|
||||
|
||||
xmlBuffer.addText('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>');
|
||||
xmlBuffer.addText(
|
||||
'<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"' +
|
||||
' xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"' +
|
||||
' xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"' +
|
||||
' mc:Ignorable="x14ac"' +
|
||||
' xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">'
|
||||
);
|
||||
|
||||
this._writeSheetProperties(xmlBuffer, this.properties, this.pageSetup);
|
||||
|
||||
xmlBuffer.addText(xform.sheetViews.toXml(this.views));
|
||||
|
||||
this._writeSheetFormatProperties(xmlBuffer, this.properties);
|
||||
|
||||
this.stream.write(xmlBuffer);
|
||||
}
|
||||
|
||||
_writeColumns() {
|
||||
const cols = Column.toModel(this.columns);
|
||||
if (cols) {
|
||||
xform.columns.prepare(cols, {styles: this._workbook.styles});
|
||||
this.stream.write(xform.columns.toXml(cols));
|
||||
}
|
||||
}
|
||||
|
||||
_writeOpenSheetData() {
|
||||
this._write('<sheetData>');
|
||||
}
|
||||
|
||||
_writeRow(row) {
|
||||
if (!this.startedData) {
|
||||
this._writeColumns();
|
||||
this._writeOpenSheetData();
|
||||
this.startedData = true;
|
||||
}
|
||||
|
||||
if (row.hasValues || row.height) {
|
||||
const {model} = row;
|
||||
const options = {
|
||||
styles: this._workbook.styles,
|
||||
sharedStrings: this.useSharedStrings ? this._workbook.sharedStrings : undefined,
|
||||
hyperlinks: this._sheetRelsWriter.hyperlinksProxy,
|
||||
merges: this._merges,
|
||||
formulae: this._formulae,
|
||||
siFormulae: this._siFormulae,
|
||||
comments: [],
|
||||
};
|
||||
xform.row.prepare(model, options);
|
||||
this.stream.write(xform.row.toXml(model));
|
||||
|
||||
if (options.comments.length) {
|
||||
this.hasComments = true;
|
||||
this._sheetCommentsWriter.addComments(options.comments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_writeCloseSheetData() {
|
||||
this._write('</sheetData>');
|
||||
}
|
||||
|
||||
_writeMergeCells() {
|
||||
if (this._merges.length) {
|
||||
xmlBuffer.reset();
|
||||
xmlBuffer.addText(`<mergeCells count="${this._merges.length}">`);
|
||||
this._merges.forEach(merge => {
|
||||
xmlBuffer.addText(`<mergeCell ref="${merge}"/>`);
|
||||
});
|
||||
xmlBuffer.addText('</mergeCells>');
|
||||
|
||||
this.stream.write(xmlBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
_writeHyperlinks() {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
this.stream.write(xform.hyperlinks.toXml(this._sheetRelsWriter._hyperlinks));
|
||||
}
|
||||
|
||||
_writeConditionalFormatting() {
|
||||
const options = {
|
||||
styles: this._workbook.styles,
|
||||
};
|
||||
xform.conditionalFormattings.prepare(this.conditionalFormatting, options);
|
||||
this.stream.write(xform.conditionalFormattings.toXml(this.conditionalFormatting));
|
||||
}
|
||||
|
||||
_writeRowBreaks() {
|
||||
this.stream.write(xform.rowBreaks.toXml(this.rowBreaks));
|
||||
}
|
||||
|
||||
_writeDataValidations() {
|
||||
this.stream.write(xform.dataValidations.toXml(this.dataValidations.model));
|
||||
}
|
||||
|
||||
_writeSheetProtection() {
|
||||
this.stream.write(xform.sheetProtection.toXml(this.sheetProtection));
|
||||
}
|
||||
|
||||
_writePageMargins() {
|
||||
this.stream.write(xform.pageMargins.toXml(this.pageSetup.margins));
|
||||
}
|
||||
|
||||
_writePageSetup() {
|
||||
this.stream.write(xform.pageSeteup.toXml(this.pageSetup));
|
||||
}
|
||||
|
||||
_writeHeaderFooter() {
|
||||
this.stream.write(xform.headerFooter.toXml(this.headerFooter));
|
||||
}
|
||||
|
||||
_writeAutoFilter() {
|
||||
this.stream.write(xform.autoFilter.toXml(this.autoFilter));
|
||||
}
|
||||
|
||||
_writeBackground() {
|
||||
if (this._background) {
|
||||
if (this._background.imageId !== undefined) {
|
||||
const image = this._workbook.getImage(this._background.imageId);
|
||||
const pictureId = this._sheetRelsWriter.addMedia({
|
||||
Target: `../media/${image.name}`,
|
||||
Type: RelType.Image,
|
||||
});
|
||||
|
||||
this._background = {
|
||||
...this._background,
|
||||
rId: pictureId,
|
||||
};
|
||||
}
|
||||
this.stream.write(xform.picture.toXml({rId: this._background.rId}));
|
||||
}
|
||||
}
|
||||
|
||||
_writeLegacyData() {
|
||||
if (this.hasComments) {
|
||||
xmlBuffer.reset();
|
||||
xmlBuffer.addText(`<legacyDrawing r:id="${this._sheetCommentsWriter.vmlRelId}"/>`);
|
||||
this.stream.write(xmlBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
_writeDimensions() {
|
||||
// for some reason, Excel can't handle dimensions at the bottom of the file
|
||||
// and we don't know the dimensions until the commit, so don't write them.
|
||||
// this._write('<dimension ref="' + this._dimensions + '"/>');
|
||||
}
|
||||
|
||||
_writeCloseWorksheet() {
|
||||
this._write('</worksheet>');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WorksheetWriter;
|
||||
15
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/auto-drain.js
generated
vendored
Normal file
15
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/auto-drain.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
const {EventEmitter} = require('events');
|
||||
|
||||
// =============================================================================
|
||||
// AutoDrain - kind of /dev/null
|
||||
class AutoDrain extends EventEmitter {
|
||||
write(chunk) {
|
||||
this.emit('data', chunk);
|
||||
}
|
||||
|
||||
end() {
|
||||
this.emit('end');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AutoDrain;
|
||||
14
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/browser-buffer-decode.js
generated
vendored
Normal file
14
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/browser-buffer-decode.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||
const textDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8');
|
||||
|
||||
function bufferToString(chunk) {
|
||||
if (typeof chunk === 'string') {
|
||||
return chunk;
|
||||
}
|
||||
if (textDecoder) {
|
||||
return textDecoder.decode(chunk);
|
||||
}
|
||||
return chunk.toString();
|
||||
}
|
||||
|
||||
exports.bufferToString = bufferToString;
|
||||
15
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/browser-buffer-encode.js
generated
vendored
Normal file
15
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/browser-buffer-encode.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
||||
const textEncoder = typeof TextEncoder === 'undefined' ? null : new TextEncoder('utf-8');
|
||||
const {Buffer} = require('buffer');
|
||||
|
||||
function stringToBuffer(str) {
|
||||
if (typeof str !== 'string') {
|
||||
return str;
|
||||
}
|
||||
if (textEncoder) {
|
||||
return Buffer.from(textEncoder.encode(str).buffer);
|
||||
}
|
||||
return Buffer.from(str);
|
||||
}
|
||||
|
||||
exports.stringToBuffer = stringToBuffer;
|
||||
165
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/cell-matrix.js
generated
vendored
Normal file
165
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/cell-matrix.js
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
const _ = require('./under-dash');
|
||||
const colCache = require('./col-cache');
|
||||
|
||||
class CellMatrix {
|
||||
constructor(template) {
|
||||
this.template = template;
|
||||
this.sheets = {};
|
||||
}
|
||||
|
||||
addCell(addressStr) {
|
||||
this.addCellEx(colCache.decodeEx(addressStr));
|
||||
}
|
||||
|
||||
getCell(addressStr) {
|
||||
return this.findCellEx(colCache.decodeEx(addressStr), true);
|
||||
}
|
||||
|
||||
findCell(addressStr) {
|
||||
return this.findCellEx(colCache.decodeEx(addressStr), false);
|
||||
}
|
||||
|
||||
findCellAt(sheetName, rowNumber, colNumber) {
|
||||
const sheet = this.sheets[sheetName];
|
||||
const row = sheet && sheet[rowNumber];
|
||||
return row && row[colNumber];
|
||||
}
|
||||
|
||||
addCellEx(address) {
|
||||
if (address.top) {
|
||||
for (let row = address.top; row <= address.bottom; row++) {
|
||||
for (let col = address.left; col <= address.right; col++) {
|
||||
this.getCellAt(address.sheetName, row, col);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.findCellEx(address, true);
|
||||
}
|
||||
}
|
||||
|
||||
getCellEx(address) {
|
||||
return this.findCellEx(address, true);
|
||||
}
|
||||
|
||||
findCellEx(address, create) {
|
||||
const sheet = this.findSheet(address, create);
|
||||
const row = this.findSheetRow(sheet, address, create);
|
||||
return this.findRowCell(row, address, create);
|
||||
}
|
||||
|
||||
getCellAt(sheetName, rowNumber, colNumber) {
|
||||
const sheet = this.sheets[sheetName] || (this.sheets[sheetName] = []);
|
||||
const row = sheet[rowNumber] || (sheet[rowNumber] = []);
|
||||
const cell =
|
||||
row[colNumber] ||
|
||||
(row[colNumber] = {
|
||||
sheetName,
|
||||
address: colCache.n2l(colNumber) + rowNumber,
|
||||
row: rowNumber,
|
||||
col: colNumber,
|
||||
});
|
||||
return cell;
|
||||
}
|
||||
|
||||
removeCellEx(address) {
|
||||
const sheet = this.findSheet(address);
|
||||
if (!sheet) {
|
||||
return;
|
||||
}
|
||||
const row = this.findSheetRow(sheet, address);
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
delete row[address.col];
|
||||
}
|
||||
|
||||
forEachInSheet(sheetName, callback) {
|
||||
const sheet = this.sheets[sheetName];
|
||||
if (sheet) {
|
||||
sheet.forEach((row, rowNumber) => {
|
||||
if (row) {
|
||||
row.forEach((cell, colNumber) => {
|
||||
if (cell) {
|
||||
callback(cell, rowNumber, colNumber);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
forEach(callback) {
|
||||
_.each(this.sheets, (sheet, sheetName) => {
|
||||
this.forEachInSheet(sheetName, callback);
|
||||
});
|
||||
}
|
||||
|
||||
map(callback) {
|
||||
const results = [];
|
||||
this.forEach(cell => {
|
||||
results.push(callback(cell));
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
findSheet(address, create) {
|
||||
const name = address.sheetName;
|
||||
if (this.sheets[name]) {
|
||||
return this.sheets[name];
|
||||
}
|
||||
if (create) {
|
||||
return (this.sheets[name] = []);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
findSheetRow(sheet, address, create) {
|
||||
const {row} = address;
|
||||
if (sheet && sheet[row]) {
|
||||
return sheet[row];
|
||||
}
|
||||
if (create) {
|
||||
return (sheet[row] = []);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
findRowCell(row, address, create) {
|
||||
const {col} = address;
|
||||
if (row && row[col]) {
|
||||
return row[col];
|
||||
}
|
||||
if (create) {
|
||||
return (row[col] = this.template
|
||||
? Object.assign(address, JSON.parse(JSON.stringify(this.template)))
|
||||
: address);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
spliceRows(sheetName, start, numDelete, numInsert) {
|
||||
const sheet = this.sheets[sheetName];
|
||||
if (sheet) {
|
||||
const inserts = [];
|
||||
for (let i = 0; i < numInsert; i++) {
|
||||
inserts.push([]);
|
||||
}
|
||||
sheet.splice(start, numDelete, ...inserts);
|
||||
}
|
||||
}
|
||||
|
||||
spliceColumns(sheetName, start, numDelete, numInsert) {
|
||||
const sheet = this.sheets[sheetName];
|
||||
if (sheet) {
|
||||
const inserts = [];
|
||||
for (let i = 0; i < numInsert; i++) {
|
||||
inserts.push(null);
|
||||
}
|
||||
_.each(sheet, row => {
|
||||
row.splice(start, numDelete, ...inserts);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CellMatrix;
|
||||
287
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/col-cache.js
generated
vendored
Normal file
287
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/col-cache.js
generated
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
const addressRegex = /^[A-Z]+\d+$/;
|
||||
// =========================================================================
|
||||
// Column Letter to Number conversion
|
||||
const colCache = {
|
||||
_dictionary: [
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'I',
|
||||
'J',
|
||||
'K',
|
||||
'L',
|
||||
'M',
|
||||
'N',
|
||||
'O',
|
||||
'P',
|
||||
'Q',
|
||||
'R',
|
||||
'S',
|
||||
'T',
|
||||
'U',
|
||||
'V',
|
||||
'W',
|
||||
'X',
|
||||
'Y',
|
||||
'Z',
|
||||
],
|
||||
_l2nFill: 0,
|
||||
_l2n: {},
|
||||
_n2l: [],
|
||||
_level(n) {
|
||||
if (n <= 26) {
|
||||
return 1;
|
||||
}
|
||||
if (n <= 26 * 26) {
|
||||
return 2;
|
||||
}
|
||||
return 3;
|
||||
},
|
||||
_fill(level) {
|
||||
let c;
|
||||
let v;
|
||||
let l1;
|
||||
let l2;
|
||||
let l3;
|
||||
let n = 1;
|
||||
if (level >= 4) {
|
||||
throw new Error('Out of bounds. Excel supports columns from 1 to 16384');
|
||||
}
|
||||
if (this._l2nFill < 1 && level >= 1) {
|
||||
while (n <= 26) {
|
||||
c = this._dictionary[n - 1];
|
||||
this._n2l[n] = c;
|
||||
this._l2n[c] = n;
|
||||
n++;
|
||||
}
|
||||
this._l2nFill = 1;
|
||||
}
|
||||
if (this._l2nFill < 2 && level >= 2) {
|
||||
n = 27;
|
||||
while (n <= 26 + (26 * 26)) {
|
||||
v = n - (26 + 1);
|
||||
l1 = v % 26;
|
||||
l2 = Math.floor(v / 26);
|
||||
c = this._dictionary[l2] + this._dictionary[l1];
|
||||
this._n2l[n] = c;
|
||||
this._l2n[c] = n;
|
||||
n++;
|
||||
}
|
||||
this._l2nFill = 2;
|
||||
}
|
||||
if (this._l2nFill < 3 && level >= 3) {
|
||||
n = 26 + (26 * 26) + 1;
|
||||
while (n <= 16384) {
|
||||
v = n - ((26 * 26) + 26 + 1);
|
||||
l1 = v % 26;
|
||||
l2 = Math.floor(v / 26) % 26;
|
||||
l3 = Math.floor(v / (26 * 26));
|
||||
c = this._dictionary[l3] + this._dictionary[l2] + this._dictionary[l1];
|
||||
this._n2l[n] = c;
|
||||
this._l2n[c] = n;
|
||||
n++;
|
||||
}
|
||||
this._l2nFill = 3;
|
||||
}
|
||||
},
|
||||
l2n(l) {
|
||||
if (!this._l2n[l]) {
|
||||
this._fill(l.length);
|
||||
}
|
||||
if (!this._l2n[l]) {
|
||||
throw new Error(`Out of bounds. Invalid column letter: ${l}`);
|
||||
}
|
||||
return this._l2n[l];
|
||||
},
|
||||
n2l(n) {
|
||||
if (n < 1 || n > 16384) {
|
||||
throw new Error(`${n} is out of bounds. Excel supports columns from 1 to 16384`);
|
||||
}
|
||||
if (!this._n2l[n]) {
|
||||
this._fill(this._level(n));
|
||||
}
|
||||
return this._n2l[n];
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
// Address processing
|
||||
_hash: {},
|
||||
|
||||
// check if value looks like an address
|
||||
validateAddress(value) {
|
||||
if (!addressRegex.test(value)) {
|
||||
throw new Error(`Invalid Address: ${value}`);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// convert address string into structure
|
||||
decodeAddress(value) {
|
||||
const addr = value.length < 5 && this._hash[value];
|
||||
if (addr) {
|
||||
return addr;
|
||||
}
|
||||
let hasCol = false;
|
||||
let col = '';
|
||||
let colNumber = 0;
|
||||
let hasRow = false;
|
||||
let row = '';
|
||||
let rowNumber = 0;
|
||||
for (let i = 0, char; i < value.length; i++) {
|
||||
char = value.charCodeAt(i);
|
||||
// col should before row
|
||||
if (!hasRow && char >= 65 && char <= 90) {
|
||||
// 65 = 'A'.charCodeAt(0)
|
||||
// 90 = 'Z'.charCodeAt(0)
|
||||
hasCol = true;
|
||||
col += value[i];
|
||||
// colNumber starts from 1
|
||||
colNumber = (colNumber * 26) + char - 64;
|
||||
} else if (char >= 48 && char <= 57) {
|
||||
// 48 = '0'.charCodeAt(0)
|
||||
// 57 = '9'.charCodeAt(0)
|
||||
hasRow = true;
|
||||
row += value[i];
|
||||
// rowNumber starts from 0
|
||||
rowNumber = (rowNumber * 10) + char - 48;
|
||||
} else if (hasRow && hasCol && char !== 36) {
|
||||
// 36 = '$'.charCodeAt(0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasCol) {
|
||||
colNumber = undefined;
|
||||
} else if (colNumber > 16384) {
|
||||
throw new Error(`Out of bounds. Invalid column letter: ${col}`);
|
||||
}
|
||||
if (!hasRow) {
|
||||
rowNumber = undefined;
|
||||
}
|
||||
|
||||
// in case $row$col
|
||||
value = col + row;
|
||||
|
||||
const address = {
|
||||
address: value,
|
||||
col: colNumber,
|
||||
row: rowNumber,
|
||||
$col$row: `$${col}$${row}`,
|
||||
};
|
||||
|
||||
// mem fix - cache only the tl 100x100 square
|
||||
if (colNumber <= 100 && rowNumber <= 100) {
|
||||
this._hash[value] = address;
|
||||
this._hash[address.$col$row] = address;
|
||||
}
|
||||
|
||||
return address;
|
||||
},
|
||||
|
||||
// convert r,c into structure (if only 1 arg, assume r is address string)
|
||||
getAddress(r, c) {
|
||||
if (c) {
|
||||
const address = this.n2l(c) + r;
|
||||
return this.decodeAddress(address);
|
||||
}
|
||||
return this.decodeAddress(r);
|
||||
},
|
||||
|
||||
// convert [address], [tl:br] into address structures
|
||||
decode(value) {
|
||||
const parts = value.split(':');
|
||||
if (parts.length === 2) {
|
||||
const tl = this.decodeAddress(parts[0]);
|
||||
const br = this.decodeAddress(parts[1]);
|
||||
const result = {
|
||||
top: Math.min(tl.row, br.row),
|
||||
left: Math.min(tl.col, br.col),
|
||||
bottom: Math.max(tl.row, br.row),
|
||||
right: Math.max(tl.col, br.col),
|
||||
};
|
||||
// reconstruct tl, br and dimensions
|
||||
result.tl = this.n2l(result.left) + result.top;
|
||||
result.br = this.n2l(result.right) + result.bottom;
|
||||
result.dimensions = `${result.tl}:${result.br}`;
|
||||
return result;
|
||||
}
|
||||
return this.decodeAddress(value);
|
||||
},
|
||||
|
||||
// convert [sheetName!][$]col[$]row[[$]col[$]row] into address or range structures
|
||||
decodeEx(value) {
|
||||
const groups = value.match(/(?:(?:(?:'((?:[^']|'')*)')|([^'^ !]*))!)?(.*)/);
|
||||
|
||||
const sheetName = groups[1] || groups[2]; // Qouted and unqouted groups
|
||||
const reference = groups[3]; // Remaining address
|
||||
|
||||
const parts = reference.split(':');
|
||||
if (parts.length > 1) {
|
||||
let tl = this.decodeAddress(parts[0]);
|
||||
let br = this.decodeAddress(parts[1]);
|
||||
const top = Math.min(tl.row, br.row);
|
||||
const left = Math.min(tl.col, br.col);
|
||||
const bottom = Math.max(tl.row, br.row);
|
||||
const right = Math.max(tl.col, br.col);
|
||||
|
||||
tl = this.n2l(left) + top;
|
||||
br = this.n2l(right) + bottom;
|
||||
|
||||
return {
|
||||
top,
|
||||
left,
|
||||
bottom,
|
||||
right,
|
||||
sheetName,
|
||||
tl: {address: tl, col: left, row: top, $col$row: `$${this.n2l(left)}$${top}`, sheetName},
|
||||
br: {
|
||||
address: br,
|
||||
col: right,
|
||||
row: bottom,
|
||||
$col$row: `$${this.n2l(right)}$${bottom}`,
|
||||
sheetName,
|
||||
},
|
||||
dimensions: `${tl}:${br}`,
|
||||
};
|
||||
}
|
||||
if (reference.startsWith('#')) {
|
||||
return sheetName ? {sheetName, error: reference} : {error: reference};
|
||||
}
|
||||
|
||||
const address = this.decodeAddress(reference);
|
||||
return sheetName ? {sheetName, ...address} : address;
|
||||
},
|
||||
|
||||
// convert row,col into address string
|
||||
encodeAddress(row, col) {
|
||||
return colCache.n2l(col) + row;
|
||||
},
|
||||
|
||||
// convert row,col into string address or t,l,b,r into range
|
||||
encode() {
|
||||
switch (arguments.length) {
|
||||
case 2:
|
||||
return colCache.encodeAddress(arguments[0], arguments[1]);
|
||||
case 4:
|
||||
return `${colCache.encodeAddress(arguments[0], arguments[1])}:${colCache.encodeAddress(
|
||||
arguments[2],
|
||||
arguments[3]
|
||||
)}`;
|
||||
default:
|
||||
throw new Error('Can only encode with 2 or 4 arguments');
|
||||
}
|
||||
},
|
||||
|
||||
// return true if address is contained within range
|
||||
inRange(range, address) {
|
||||
const [left, top, , right, bottom] = range;
|
||||
const [col, row] = address;
|
||||
return col >= left && col <= right && row >= top && row <= bottom;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = colCache;
|
||||
43
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/copy-style.js
generated
vendored
Normal file
43
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/copy-style.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
const oneDepthCopy = (obj, nestKeys) => ({
|
||||
...obj,
|
||||
...nestKeys.reduce((memo, key) => {
|
||||
if (obj[key]) memo[key] = {...obj[key]};
|
||||
return memo;
|
||||
}, {}),
|
||||
});
|
||||
|
||||
const setIfExists = (src, dst, key, nestKeys = []) => {
|
||||
if (src[key]) dst[key] = oneDepthCopy(src[key], nestKeys);
|
||||
};
|
||||
|
||||
const isEmptyObj = obj => Object.keys(obj).length === 0;
|
||||
|
||||
const copyStyle = style => {
|
||||
if (!style) return style;
|
||||
if (isEmptyObj(style)) return {};
|
||||
|
||||
const copied = {...style};
|
||||
|
||||
setIfExists(style, copied, 'font', ['color']);
|
||||
setIfExists(style, copied, 'alignment');
|
||||
setIfExists(style, copied, 'protection');
|
||||
if (style.border) {
|
||||
setIfExists(style, copied, 'border');
|
||||
setIfExists(style.border, copied.border, 'top', ['color']);
|
||||
setIfExists(style.border, copied.border, 'left', ['color']);
|
||||
setIfExists(style.border, copied.border, 'bottom', ['color']);
|
||||
setIfExists(style.border, copied.border, 'right', ['color']);
|
||||
setIfExists(style.border, copied.border, 'diagonal', ['color']);
|
||||
}
|
||||
|
||||
if (style.fill) {
|
||||
setIfExists(style, copied, 'fill', ['fgColor', 'bgColor', 'center']);
|
||||
if (style.fill.stops) {
|
||||
copied.fill.stops = style.fill.stops.map(s => oneDepthCopy(s, ['color']));
|
||||
}
|
||||
}
|
||||
|
||||
return copied;
|
||||
};
|
||||
|
||||
exports.copyStyle = copyStyle;
|
||||
55
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/encryptor.js
generated
vendored
Normal file
55
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/encryptor.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
const crypto = require('crypto');
|
||||
|
||||
const Encryptor = {
|
||||
/**
|
||||
* Calculate a hash of the concatenated buffers with the given algorithm.
|
||||
* @param {string} algorithm - The hash algorithm.
|
||||
* @returns {Buffer} The hash
|
||||
*/
|
||||
hash(algorithm, ...buffers) {
|
||||
const hash = crypto.createHash(algorithm);
|
||||
hash.update(Buffer.concat(buffers));
|
||||
return hash.digest();
|
||||
},
|
||||
/**
|
||||
* Convert a password into an encryption key
|
||||
* @param {string} password - The password
|
||||
* @param {string} hashAlgorithm - The hash algoritm
|
||||
* @param {string} saltValue - The salt value
|
||||
* @param {number} spinCount - The spin count
|
||||
* @param {number} keyBits - The length of the key in bits
|
||||
* @param {Buffer} blockKey - The block key
|
||||
* @returns {Buffer} The encryption key
|
||||
*/
|
||||
convertPasswordToHash(password, hashAlgorithm, saltValue, spinCount) {
|
||||
hashAlgorithm = hashAlgorithm.toLowerCase();
|
||||
const hashes = crypto.getHashes();
|
||||
if (hashes.indexOf(hashAlgorithm) < 0) {
|
||||
throw new Error(`Hash algorithm '${hashAlgorithm}' not supported!`);
|
||||
}
|
||||
|
||||
// Password must be in unicode buffer
|
||||
const passwordBuffer = Buffer.from(password, 'utf16le');
|
||||
// Generate the initial hash
|
||||
let key = this.hash(hashAlgorithm, Buffer.from(saltValue, 'base64'), passwordBuffer);
|
||||
// Now regenerate until spin count
|
||||
for (let i = 0; i < spinCount; i++) {
|
||||
const iterator = Buffer.alloc(4);
|
||||
// this is the 'special' element of Excel password hashing
|
||||
// that stops us from using crypto.pbkdf2()
|
||||
iterator.writeUInt32LE(i, 0);
|
||||
key = this.hash(hashAlgorithm, key, iterator);
|
||||
}
|
||||
return key.toString('base64');
|
||||
},
|
||||
/**
|
||||
* Generates cryptographically strong pseudo-random data.
|
||||
* @param size The size argument is a number indicating the number of bytes to generate.
|
||||
*/
|
||||
randomBytes(size) {
|
||||
return crypto.randomBytes(size);
|
||||
},
|
||||
};
|
||||
module.exports = Encryptor;
|
||||
48
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/iterate-stream.js
generated
vendored
Normal file
48
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/iterate-stream.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
module.exports = async function* iterateStream(stream) {
|
||||
const contents = [];
|
||||
stream.on('data', data => contents.push(data));
|
||||
|
||||
let resolveStreamEndedPromise;
|
||||
const streamEndedPromise = new Promise(resolve => (resolveStreamEndedPromise = resolve));
|
||||
|
||||
let ended = false;
|
||||
stream.on('end', () => {
|
||||
ended = true;
|
||||
resolveStreamEndedPromise();
|
||||
});
|
||||
|
||||
let error = false;
|
||||
stream.on('error', err => {
|
||||
error = err;
|
||||
resolveStreamEndedPromise();
|
||||
});
|
||||
|
||||
while (!ended || contents.length > 0) {
|
||||
if (contents.length === 0) {
|
||||
stream.resume();
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await Promise.race([once(stream, 'data'), streamEndedPromise]);
|
||||
} else {
|
||||
stream.pause();
|
||||
const data = contents.shift();
|
||||
yield data;
|
||||
}
|
||||
if (error) throw error;
|
||||
}
|
||||
resolveStreamEndedPromise();
|
||||
};
|
||||
|
||||
function once(eventEmitter, type) {
|
||||
// TODO: Use require('events').once when node v10 is dropped
|
||||
return new Promise(resolve => {
|
||||
let fired = false;
|
||||
const handler = () => {
|
||||
if (!fired) {
|
||||
fired = true;
|
||||
eventEmitter.removeListener(type, handler);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
eventEmitter.addListener(type, handler);
|
||||
});
|
||||
}
|
||||
30
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/parse-sax.js
generated
vendored
Normal file
30
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/parse-sax.js
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
const {SaxesParser} = require('saxes');
|
||||
const {PassThrough} = require('readable-stream');
|
||||
const {bufferToString} = require('./browser-buffer-decode');
|
||||
|
||||
module.exports = async function* (iterable) {
|
||||
// TODO: Remove once node v8 is deprecated
|
||||
// Detect and upgrade old streams
|
||||
if (iterable.pipe && !iterable[Symbol.asyncIterator]) {
|
||||
iterable = iterable.pipe(new PassThrough());
|
||||
}
|
||||
const saxesParser = new SaxesParser();
|
||||
let error;
|
||||
saxesParser.on('error', err => {
|
||||
error = err;
|
||||
});
|
||||
let events = [];
|
||||
saxesParser.on('opentag', value => events.push({eventType: 'opentag', value}));
|
||||
saxesParser.on('text', value => events.push({eventType: 'text', value}));
|
||||
saxesParser.on('closetag', value => events.push({eventType: 'closetag', value}));
|
||||
for await (const chunk of iterable) {
|
||||
saxesParser.write(bufferToString(chunk));
|
||||
// saxesParser.write and saxesParser.on() are synchronous,
|
||||
// so we can only reach the below line once all events have been emitted
|
||||
if (error) throw error;
|
||||
// As a performance optimization, we gather all events instead of passing
|
||||
// them one by one, which would cause each event to go through the event queue
|
||||
yield events;
|
||||
events = [];
|
||||
}
|
||||
};
|
||||
44
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/shared-formula.js
generated
vendored
Normal file
44
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/shared-formula.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
const colCache = require('./col-cache');
|
||||
|
||||
// const cellRefRegex = /(([a-z_\-0-9]*)!)?[$]?([a-z]+)[$]?([1-9][0-9]*)/i;
|
||||
const replacementCandidateRx = /(([a-z_\-0-9]*)!)?([a-z0-9_$]{2,})([(])?/gi;
|
||||
const CRrx = /^([$])?([a-z]+)([$])?([1-9][0-9]*)$/i;
|
||||
|
||||
function slideFormula(formula, fromCell, toCell) {
|
||||
const offset = colCache.decode(fromCell);
|
||||
const to = colCache.decode(toCell);
|
||||
return formula.replace(
|
||||
replacementCandidateRx,
|
||||
(refMatch, sheet, sheetMaybe, addrPart, trailingParen) => {
|
||||
if (trailingParen) {
|
||||
return refMatch;
|
||||
}
|
||||
const match = CRrx.exec(addrPart);
|
||||
if (match) {
|
||||
const colDollar = match[1];
|
||||
const colStr = match[2].toUpperCase();
|
||||
const rowDollar = match[3];
|
||||
const rowStr = match[4];
|
||||
if (colStr.length > 3 || (colStr.length === 3 && colStr > 'XFD')) {
|
||||
// > XFD is the highest col number in excel 2007 and beyond, so this is a named range
|
||||
return refMatch;
|
||||
}
|
||||
let col = colCache.l2n(colStr);
|
||||
let row = parseInt(rowStr, 10);
|
||||
if (!colDollar) {
|
||||
col += to.col - offset.col;
|
||||
}
|
||||
if (!rowDollar) {
|
||||
row += to.row - offset.row;
|
||||
}
|
||||
const res = (sheet || '') + (colDollar || '') + colCache.n2l(col) + (rowDollar || '') + row;
|
||||
return res;
|
||||
}
|
||||
return refMatch;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
slideFormula,
|
||||
};
|
||||
35
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/shared-strings.js
generated
vendored
Normal file
35
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/shared-strings.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
class SharedStrings {
|
||||
constructor() {
|
||||
this._values = [];
|
||||
this._totalRefs = 0;
|
||||
this._hash = Object.create(null);
|
||||
}
|
||||
|
||||
get count() {
|
||||
return this._values.length;
|
||||
}
|
||||
|
||||
get values() {
|
||||
return this._values;
|
||||
}
|
||||
|
||||
get totalRefs() {
|
||||
return this._totalRefs;
|
||||
}
|
||||
|
||||
getString(index) {
|
||||
return this._values[index];
|
||||
}
|
||||
|
||||
add(value) {
|
||||
let index = this._hash[value];
|
||||
if (index === undefined) {
|
||||
index = this._hash[value] = this._values.length;
|
||||
this._values.push(value);
|
||||
}
|
||||
this._totalRefs++;
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SharedStrings;
|
||||
72
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/stream-base64.js
generated
vendored
Normal file
72
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/stream-base64.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
const Stream = require('readable-stream');
|
||||
|
||||
// =============================================================================
|
||||
// StreamBase64 - A utility to convert to/from base64 stream
|
||||
// Note: does not buffer data, must be piped
|
||||
class StreamBase64 extends Stream.Duplex {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// consuming pipe streams go here
|
||||
this.pipes = [];
|
||||
}
|
||||
|
||||
// writable
|
||||
// event drain - if write returns false (which it won't), indicates when safe to write again.
|
||||
// finish - end() has been called
|
||||
// pipe(src) - pipe() has been called on readable
|
||||
// unpipe(src) - unpipe() has been called on readable
|
||||
// error - duh
|
||||
|
||||
write(/* data, encoding */) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cork() {}
|
||||
|
||||
uncork() {}
|
||||
|
||||
end(/* chunk, encoding, callback */) {}
|
||||
|
||||
// readable
|
||||
// event readable - some data is now available
|
||||
// event data - switch to flowing mode - feeds chunks to handler
|
||||
// event end - no more data
|
||||
// event close - optional, indicates upstream close
|
||||
// event error - duh
|
||||
read(/* size */) {}
|
||||
|
||||
setEncoding(encoding) {
|
||||
// causes stream.read or stream.on('data) to return strings of encoding instead of Buffer objects
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
pause() {}
|
||||
|
||||
resume() {}
|
||||
|
||||
isPaused() {}
|
||||
|
||||
pipe(destination) {
|
||||
// add destination to pipe list & write current buffer
|
||||
this.pipes.push(destination);
|
||||
}
|
||||
|
||||
unpipe(destination) {
|
||||
// remove destination from pipe list
|
||||
this.pipes = this.pipes.filter(pipe => pipe !== destination);
|
||||
}
|
||||
|
||||
unshift(/* chunk */) {
|
||||
// some numpty has read some data that's not for them and they want to put it back!
|
||||
// Might implement this some day
|
||||
throw new Error('Not Implemented');
|
||||
}
|
||||
|
||||
wrap(/* stream */) {
|
||||
// not implemented
|
||||
throw new Error('Not Implemented');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StreamBase64;
|
||||
364
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/stream-buf.js
generated
vendored
Normal file
364
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/stream-buf.js
generated
vendored
Normal file
@@ -0,0 +1,364 @@
|
||||
/* eslint-disable max-classes-per-file */
|
||||
const Stream = require('readable-stream');
|
||||
|
||||
const utils = require('./utils');
|
||||
const StringBuf = require('./string-buf');
|
||||
|
||||
// =============================================================================
|
||||
// data chunks - encapsulating incoming data
|
||||
class StringChunk {
|
||||
constructor(data, encoding) {
|
||||
this._data = data;
|
||||
this._encoding = encoding;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this.toBuffer().length;
|
||||
}
|
||||
|
||||
// copy to target buffer
|
||||
copy(target, targetOffset, offset, length) {
|
||||
return this.toBuffer().copy(target, targetOffset, offset, length);
|
||||
}
|
||||
|
||||
toBuffer() {
|
||||
if (!this._buffer) {
|
||||
this._buffer = Buffer.from(this._data, this._encoding);
|
||||
}
|
||||
return this._buffer;
|
||||
}
|
||||
}
|
||||
|
||||
class StringBufChunk {
|
||||
constructor(data) {
|
||||
this._data = data;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._data.length;
|
||||
}
|
||||
|
||||
// copy to target buffer
|
||||
copy(target, targetOffset, offset, length) {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
return this._data._buf.copy(target, targetOffset, offset, length);
|
||||
}
|
||||
|
||||
toBuffer() {
|
||||
return this._data.toBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
class BufferChunk {
|
||||
constructor(data) {
|
||||
this._data = data;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._data.length;
|
||||
}
|
||||
|
||||
// copy to target buffer
|
||||
copy(target, targetOffset, offset, length) {
|
||||
this._data.copy(target, targetOffset, offset, length);
|
||||
}
|
||||
|
||||
toBuffer() {
|
||||
return this._data;
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ReadWriteBuf - a single buffer supporting simple read-write
|
||||
class ReadWriteBuf {
|
||||
constructor(size) {
|
||||
this.size = size;
|
||||
// the buffer
|
||||
this.buffer = Buffer.alloc(size);
|
||||
// read index
|
||||
this.iRead = 0;
|
||||
// write index
|
||||
this.iWrite = 0;
|
||||
}
|
||||
|
||||
toBuffer() {
|
||||
if (this.iRead === 0 && this.iWrite === this.size) {
|
||||
return this.buffer;
|
||||
}
|
||||
|
||||
const buf = Buffer.alloc(this.iWrite - this.iRead);
|
||||
this.buffer.copy(buf, 0, this.iRead, this.iWrite);
|
||||
return buf;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this.iWrite - this.iRead;
|
||||
}
|
||||
|
||||
get eod() {
|
||||
return this.iRead === this.iWrite;
|
||||
}
|
||||
|
||||
get full() {
|
||||
return this.iWrite === this.size;
|
||||
}
|
||||
|
||||
read(size) {
|
||||
let buf;
|
||||
// read size bytes from buffer and return buffer
|
||||
if (size === 0) {
|
||||
// special case - return null if no data requested
|
||||
return null;
|
||||
}
|
||||
|
||||
if (size === undefined || size >= this.length) {
|
||||
// if no size specified or size is at least what we have then return all of the bytes
|
||||
buf = this.toBuffer();
|
||||
this.iRead = this.iWrite;
|
||||
return buf;
|
||||
}
|
||||
|
||||
// otherwise return a chunk
|
||||
buf = Buffer.alloc(size);
|
||||
this.buffer.copy(buf, 0, this.iRead, size);
|
||||
this.iRead += size;
|
||||
return buf;
|
||||
}
|
||||
|
||||
write(chunk, offset, length) {
|
||||
// write as many bytes from data from optional source offset
|
||||
// and return number of bytes written
|
||||
const size = Math.min(length, this.size - this.iWrite);
|
||||
chunk.copy(this.buffer, this.iWrite, offset, offset + size);
|
||||
this.iWrite += size;
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// StreamBuf - a multi-purpose read-write stream
|
||||
// As MemBuf - write as much data as you like. Then call toBuffer() to consolidate
|
||||
// As StreamHub - pipe to multiple writables
|
||||
// As readable stream - feed data into the writable part and have some other code read from it.
|
||||
|
||||
// Note: Not sure why but StreamBuf does not like JS "class" sugar. It fails the
|
||||
// integration tests
|
||||
const StreamBuf = function(options) {
|
||||
options = options || {};
|
||||
this.bufSize = options.bufSize || 1024 * 1024;
|
||||
this.buffers = [];
|
||||
|
||||
// batch mode fills a buffer completely before passing the data on
|
||||
// to pipes or 'readable' event listeners
|
||||
this.batch = options.batch || false;
|
||||
|
||||
this.corked = false;
|
||||
// where in the current writable buffer we're up to
|
||||
this.inPos = 0;
|
||||
|
||||
// where in the current readable buffer we've read up to
|
||||
this.outPos = 0;
|
||||
|
||||
// consuming pipe streams go here
|
||||
this.pipes = [];
|
||||
|
||||
// controls emit('data')
|
||||
this.paused = false;
|
||||
|
||||
this.encoding = null;
|
||||
};
|
||||
|
||||
utils.inherits(StreamBuf, Stream.Duplex, {
|
||||
toBuffer() {
|
||||
switch (this.buffers.length) {
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return this.buffers[0].toBuffer();
|
||||
default:
|
||||
return Buffer.concat(this.buffers.map(rwBuf => rwBuf.toBuffer()));
|
||||
}
|
||||
},
|
||||
|
||||
// writable
|
||||
// event drain - if write returns false (which it won't), indicates when safe to write again.
|
||||
// finish - end() has been called
|
||||
// pipe(src) - pipe() has been called on readable
|
||||
// unpipe(src) - unpipe() has been called on readable
|
||||
// error - duh
|
||||
|
||||
_getWritableBuffer() {
|
||||
if (this.buffers.length) {
|
||||
const last = this.buffers[this.buffers.length - 1];
|
||||
if (!last.full) {
|
||||
return last;
|
||||
}
|
||||
}
|
||||
const buf = new ReadWriteBuf(this.bufSize);
|
||||
this.buffers.push(buf);
|
||||
return buf;
|
||||
},
|
||||
|
||||
async _pipe(chunk) {
|
||||
const write = function(pipe) {
|
||||
return new Promise(resolve => {
|
||||
pipe.write(chunk.toBuffer(), () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
await Promise.all(this.pipes.map(write));
|
||||
},
|
||||
_writeToBuffers(chunk) {
|
||||
let inPos = 0;
|
||||
const inLen = chunk.length;
|
||||
while (inPos < inLen) {
|
||||
// find writable buffer
|
||||
const buffer = this._getWritableBuffer();
|
||||
|
||||
// write some data
|
||||
inPos += buffer.write(chunk, inPos, inLen - inPos);
|
||||
}
|
||||
},
|
||||
async write(data, encoding, callback) {
|
||||
if (encoding instanceof Function) {
|
||||
callback = encoding;
|
||||
encoding = 'utf8';
|
||||
}
|
||||
callback = callback || utils.nop;
|
||||
|
||||
// encapsulate data into a chunk
|
||||
let chunk;
|
||||
if (data instanceof StringBuf) {
|
||||
chunk = new StringBufChunk(data);
|
||||
} else if (data instanceof Buffer) {
|
||||
chunk = new BufferChunk(data);
|
||||
} else if (typeof data === 'string' || data instanceof String || data instanceof ArrayBuffer) {
|
||||
chunk = new StringChunk(data, encoding);
|
||||
} else {
|
||||
throw new Error('Chunk must be one of type String, Buffer or StringBuf.');
|
||||
}
|
||||
|
||||
// now, do something with the chunk
|
||||
if (this.pipes.length) {
|
||||
if (this.batch) {
|
||||
this._writeToBuffers(chunk);
|
||||
while (!this.corked && this.buffers.length > 1) {
|
||||
this._pipe(this.buffers.shift());
|
||||
}
|
||||
} else if (!this.corked) {
|
||||
await this._pipe(chunk);
|
||||
callback();
|
||||
} else {
|
||||
this._writeToBuffers(chunk);
|
||||
process.nextTick(callback);
|
||||
}
|
||||
} else {
|
||||
if (!this.paused) {
|
||||
this.emit('data', chunk.toBuffer());
|
||||
}
|
||||
|
||||
this._writeToBuffers(chunk);
|
||||
this.emit('readable');
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
cork() {
|
||||
this.corked = true;
|
||||
},
|
||||
_flush(/* destination */) {
|
||||
// if we have comsumers...
|
||||
if (this.pipes.length) {
|
||||
// and there's stuff not written
|
||||
while (this.buffers.length) {
|
||||
this._pipe(this.buffers.shift());
|
||||
}
|
||||
}
|
||||
},
|
||||
uncork() {
|
||||
this.corked = false;
|
||||
this._flush();
|
||||
},
|
||||
end(chunk, encoding, callback) {
|
||||
const writeComplete = error => {
|
||||
if (error) {
|
||||
callback(error);
|
||||
} else {
|
||||
this._flush();
|
||||
this.pipes.forEach(pipe => {
|
||||
pipe.end();
|
||||
});
|
||||
this.emit('finish');
|
||||
}
|
||||
};
|
||||
if (chunk) {
|
||||
this.write(chunk, encoding, writeComplete);
|
||||
} else {
|
||||
writeComplete();
|
||||
}
|
||||
},
|
||||
|
||||
// readable
|
||||
// event readable - some data is now available
|
||||
// event data - switch to flowing mode - feeds chunks to handler
|
||||
// event end - no more data
|
||||
// event close - optional, indicates upstream close
|
||||
// event error - duh
|
||||
read(size) {
|
||||
let buffers;
|
||||
// read min(buffer, size || infinity)
|
||||
if (size) {
|
||||
buffers = [];
|
||||
while (size && this.buffers.length && !this.buffers[0].eod) {
|
||||
const first = this.buffers[0];
|
||||
const buffer = first.read(size);
|
||||
size -= buffer.length;
|
||||
buffers.push(buffer);
|
||||
if (first.eod && first.full) {
|
||||
this.buffers.shift();
|
||||
}
|
||||
}
|
||||
return Buffer.concat(buffers);
|
||||
}
|
||||
|
||||
buffers = this.buffers.map(buf => buf.toBuffer()).filter(Boolean);
|
||||
this.buffers = [];
|
||||
return Buffer.concat(buffers);
|
||||
},
|
||||
setEncoding(encoding) {
|
||||
// causes stream.read or stream.on('data) to return strings of encoding instead of Buffer objects
|
||||
this.encoding = encoding;
|
||||
},
|
||||
pause() {
|
||||
this.paused = true;
|
||||
},
|
||||
resume() {
|
||||
this.paused = false;
|
||||
},
|
||||
isPaused() {
|
||||
return !!this.paused;
|
||||
},
|
||||
pipe(destination) {
|
||||
// add destination to pipe list & write current buffer
|
||||
this.pipes.push(destination);
|
||||
if (!this.paused && this.buffers.length) {
|
||||
this.end();
|
||||
}
|
||||
},
|
||||
unpipe(destination) {
|
||||
// remove destination from pipe list
|
||||
this.pipes = this.pipes.filter(pipe => pipe !== destination);
|
||||
},
|
||||
unshift(/* chunk */) {
|
||||
// some numpty has read some data that's not for them and they want to put it back!
|
||||
// Might implement this some day
|
||||
throw new Error('Not Implemented');
|
||||
},
|
||||
wrap(/* stream */) {
|
||||
// not implemented
|
||||
throw new Error('Not Implemented');
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = StreamBuf;
|
||||
82
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/string-buf.js
generated
vendored
Normal file
82
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/string-buf.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// StringBuf - a way to keep string memory operations to a minimum
|
||||
// while building the strings for the xml files
|
||||
class StringBuf {
|
||||
constructor(options) {
|
||||
this._buf = Buffer.alloc((options && options.size) || 16384);
|
||||
this._encoding = (options && options.encoding) || 'utf8';
|
||||
|
||||
// where in the buffer we are at
|
||||
this._inPos = 0;
|
||||
|
||||
// for use by toBuffer()
|
||||
this._buffer = undefined;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._inPos;
|
||||
}
|
||||
|
||||
get capacity() {
|
||||
return this._buf.length;
|
||||
}
|
||||
|
||||
get buffer() {
|
||||
return this._buf;
|
||||
}
|
||||
|
||||
toBuffer() {
|
||||
// return the current data as a single enclosing buffer
|
||||
if (!this._buffer) {
|
||||
this._buffer = Buffer.alloc(this.length);
|
||||
this._buf.copy(this._buffer, 0, 0, this.length);
|
||||
}
|
||||
return this._buffer;
|
||||
}
|
||||
|
||||
reset(position) {
|
||||
position = position || 0;
|
||||
this._buffer = undefined;
|
||||
this._inPos = position;
|
||||
}
|
||||
|
||||
_grow(min) {
|
||||
let size = this._buf.length * 2;
|
||||
while (size < min) {
|
||||
size *= 2;
|
||||
}
|
||||
const buf = Buffer.alloc(size);
|
||||
this._buf.copy(buf, 0);
|
||||
this._buf = buf;
|
||||
}
|
||||
|
||||
addText(text) {
|
||||
this._buffer = undefined;
|
||||
|
||||
let inPos = this._inPos + this._buf.write(text, this._inPos, this._encoding);
|
||||
|
||||
// if we've hit (or nearing capacity), grow the buf
|
||||
while (inPos >= this._buf.length - 4) {
|
||||
this._grow(this._inPos + text.length);
|
||||
|
||||
// keep trying to write until we've completely written the text
|
||||
inPos = this._inPos + this._buf.write(text, this._inPos, this._encoding);
|
||||
}
|
||||
|
||||
this._inPos = inPos;
|
||||
}
|
||||
|
||||
addStringBuf(inBuf) {
|
||||
if (inBuf.length) {
|
||||
this._buffer = undefined;
|
||||
|
||||
if (this.length + inBuf.length > this.capacity) {
|
||||
this._grow(this.length + inBuf.length);
|
||||
}
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
inBuf._buf.copy(this._buf, this._inPos, 0, inBuf.length);
|
||||
this._inPos += inBuf.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StringBuf;
|
||||
35
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/string-builder.js
generated
vendored
Normal file
35
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/string-builder.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// StringBuilder - a way to keep string memory operations to a minimum
|
||||
// while building the strings for the xml files
|
||||
class StringBuilder {
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._buf.length;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this._buf.join('');
|
||||
}
|
||||
|
||||
reset(position) {
|
||||
if (position) {
|
||||
while (this._buf.length > position) {
|
||||
this._buf.pop();
|
||||
}
|
||||
} else {
|
||||
this._buf = [];
|
||||
}
|
||||
}
|
||||
|
||||
addText(text) {
|
||||
this._buf.push(text);
|
||||
}
|
||||
|
||||
addStringBuf(inBuf) {
|
||||
this._buf.push(inBuf.toString());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StringBuilder;
|
||||
67
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/stuttered-pipe.js
generated
vendored
Normal file
67
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/stuttered-pipe.js
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
const events = require('events');
|
||||
|
||||
// =============================================================================
|
||||
// StutteredPipe - Used to slow down streaming so GC can get a look in
|
||||
class StutteredPipe extends events.EventEmitter {
|
||||
constructor(readable, writable, options) {
|
||||
super();
|
||||
|
||||
options = options || {};
|
||||
|
||||
this.readable = readable;
|
||||
this.writable = writable;
|
||||
this.bufSize = options.bufSize || 16384;
|
||||
this.autoPause = options.autoPause || false;
|
||||
|
||||
this.paused = false;
|
||||
this.eod = false;
|
||||
this.scheduled = null;
|
||||
|
||||
readable.on('end', () => {
|
||||
this.eod = true;
|
||||
writable.end();
|
||||
});
|
||||
|
||||
// need to have some way to communicate speed of stream
|
||||
// back from the consumer
|
||||
readable.on('readable', () => {
|
||||
if (!this.paused) {
|
||||
this.resume();
|
||||
}
|
||||
});
|
||||
this._schedule();
|
||||
}
|
||||
|
||||
pause() {
|
||||
this.paused = true;
|
||||
}
|
||||
|
||||
resume() {
|
||||
if (!this.eod) {
|
||||
if (this.scheduled !== null) {
|
||||
clearImmediate(this.scheduled);
|
||||
}
|
||||
this._schedule();
|
||||
}
|
||||
}
|
||||
|
||||
_schedule() {
|
||||
this.scheduled = setImmediate(() => {
|
||||
this.scheduled = null;
|
||||
if (!this.eod && !this.paused) {
|
||||
const data = this.readable.read(this.bufSize);
|
||||
if (data && data.length) {
|
||||
this.writable.write(data);
|
||||
|
||||
if (!this.paused && !this.autoPause) {
|
||||
this._schedule();
|
||||
}
|
||||
} else if (!this.paused) {
|
||||
this._schedule();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StutteredPipe;
|
||||
24
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/typed-stack.js
generated
vendored
Normal file
24
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/typed-stack.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
class TypedStack {
|
||||
constructor(type) {
|
||||
this._type = type;
|
||||
this._stack = [];
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this._stack.length;
|
||||
}
|
||||
|
||||
pop() {
|
||||
const tos = this._stack.pop();
|
||||
return tos || new this._type();
|
||||
}
|
||||
|
||||
push(instance) {
|
||||
if (!(instance instanceof this._type)) {
|
||||
throw new Error('Invalid type pushed to TypedStack');
|
||||
}
|
||||
this._stack.push(instance);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TypedStack;
|
||||
184
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/under-dash.js
generated
vendored
Normal file
184
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/under-dash.js
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
const {toString} = Object.prototype;
|
||||
const escapeHtmlRegex = /["&<>]/;
|
||||
const _ = {
|
||||
each: function each(obj, cb) {
|
||||
if (obj) {
|
||||
if (Array.isArray(obj)) {
|
||||
obj.forEach(cb);
|
||||
} else {
|
||||
Object.keys(obj).forEach(key => {
|
||||
cb(obj[key], key);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
some: function some(obj, cb) {
|
||||
if (obj) {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.some(cb);
|
||||
}
|
||||
return Object.keys(obj).some(key => cb(obj[key], key));
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
every: function every(obj, cb) {
|
||||
if (obj) {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.every(cb);
|
||||
}
|
||||
return Object.keys(obj).every(key => cb(obj[key], key));
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
map: function map(obj, cb) {
|
||||
if (obj) {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map(cb);
|
||||
}
|
||||
return Object.keys(obj).map(key => cb(obj[key], key));
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
keyBy(a, p) {
|
||||
return a.reduce((o, v) => {
|
||||
o[v[p]] = v;
|
||||
return o;
|
||||
}, {});
|
||||
},
|
||||
|
||||
isEqual: function isEqual(a, b) {
|
||||
const aType = typeof a;
|
||||
const bType = typeof b;
|
||||
const aArray = Array.isArray(a);
|
||||
const bArray = Array.isArray(b);
|
||||
let keys;
|
||||
|
||||
if (aType !== bType) {
|
||||
return false;
|
||||
}
|
||||
switch (typeof a) {
|
||||
case 'object':
|
||||
if (aArray || bArray) {
|
||||
if (aArray && bArray) {
|
||||
return (
|
||||
a.length === b.length &&
|
||||
a.every((aValue, index) => {
|
||||
const bValue = b[index];
|
||||
return _.isEqual(aValue, bValue);
|
||||
})
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a === null || b === null) {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
// Compare object keys and values
|
||||
keys = Object.keys(a);
|
||||
|
||||
if (Object.keys(b).length !== keys.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const key of keys) {
|
||||
if (!b.hasOwnProperty(key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return _.every(a, (aValue, key) => {
|
||||
const bValue = b[key];
|
||||
return _.isEqual(aValue, bValue);
|
||||
});
|
||||
|
||||
default:
|
||||
return a === b;
|
||||
}
|
||||
},
|
||||
|
||||
escapeHtml(html) {
|
||||
const regexResult = escapeHtmlRegex.exec(html);
|
||||
if (!regexResult) return html;
|
||||
|
||||
let result = '';
|
||||
let escape = '';
|
||||
let lastIndex = 0;
|
||||
let i = regexResult.index;
|
||||
for (; i < html.length; i++) {
|
||||
switch (html.charAt(i)) {
|
||||
case '"':
|
||||
escape = '"';
|
||||
break;
|
||||
case '&':
|
||||
escape = '&';
|
||||
break;
|
||||
case '\'':
|
||||
escape = ''';
|
||||
break;
|
||||
case '<':
|
||||
escape = '<';
|
||||
break;
|
||||
case '>':
|
||||
escape = '>';
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
if (lastIndex !== i) result += html.substring(lastIndex, i);
|
||||
lastIndex = i + 1;
|
||||
result += escape;
|
||||
}
|
||||
if (lastIndex !== i) return result + html.substring(lastIndex, i);
|
||||
return result;
|
||||
},
|
||||
|
||||
strcmp(a, b) {
|
||||
if (a < b) return -1;
|
||||
if (a > b) return 1;
|
||||
return 0;
|
||||
},
|
||||
|
||||
isUndefined(val) {
|
||||
return toString.call(val) === '[object Undefined]';
|
||||
},
|
||||
|
||||
isObject(val) {
|
||||
return toString.call(val) === '[object Object]';
|
||||
},
|
||||
|
||||
deepMerge() {
|
||||
const target = arguments[0] || {};
|
||||
const {length} = arguments;
|
||||
// eslint-disable-next-line one-var
|
||||
let src, clone, copyIsArray;
|
||||
|
||||
function assignValue(val, key) {
|
||||
src = target[key];
|
||||
copyIsArray = Array.isArray(val);
|
||||
if (_.isObject(val) || copyIsArray) {
|
||||
if (copyIsArray) {
|
||||
copyIsArray = false;
|
||||
clone = src && Array.isArray(src) ? src : [];
|
||||
} else {
|
||||
clone = src && _.isObject(src) ? src : {};
|
||||
}
|
||||
target[key] = _.deepMerge(clone, val);
|
||||
} else if (!_.isUndefined(val)) {
|
||||
target[key] = val;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
_.each(arguments[i], assignValue);
|
||||
}
|
||||
return target;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = _;
|
||||
172
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/utils.js
generated
vendored
Normal file
172
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/utils.js
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
const fs = require('fs');
|
||||
|
||||
// useful stuff
|
||||
const inherits = function(cls, superCtor, statics, prototype) {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
cls.super_ = superCtor;
|
||||
|
||||
if (!prototype) {
|
||||
prototype = statics;
|
||||
statics = null;
|
||||
}
|
||||
|
||||
if (statics) {
|
||||
Object.keys(statics).forEach(i => {
|
||||
Object.defineProperty(cls, i, Object.getOwnPropertyDescriptor(statics, i));
|
||||
});
|
||||
}
|
||||
|
||||
const properties = {
|
||||
constructor: {
|
||||
value: cls,
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
configurable: true,
|
||||
},
|
||||
};
|
||||
if (prototype) {
|
||||
Object.keys(prototype).forEach(i => {
|
||||
properties[i] = Object.getOwnPropertyDescriptor(prototype, i);
|
||||
});
|
||||
}
|
||||
|
||||
cls.prototype = Object.create(superCtor.prototype, properties);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-control-regex
|
||||
const xmlDecodeRegex = /[<>&'"\x7F\x00-\x08\x0B-\x0C\x0E-\x1F]/;
|
||||
const utils = {
|
||||
nop() {},
|
||||
promiseImmediate(value) {
|
||||
return new Promise(resolve => {
|
||||
if (global.setImmediate) {
|
||||
setImmediate(() => {
|
||||
resolve(value);
|
||||
});
|
||||
} else {
|
||||
// poorman's setImmediate - must wait at least 1ms
|
||||
setTimeout(() => {
|
||||
resolve(value);
|
||||
}, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
inherits,
|
||||
dateToExcel(d, date1904) {
|
||||
return 25569 + ( d.getTime() / (24 * 3600 * 1000) ) - (date1904 ? 1462 : 0);
|
||||
},
|
||||
excelToDate(v, date1904) {
|
||||
const millisecondSinceEpoch = Math.round((v - 25569 + (date1904 ? 1462 : 0)) * 24 * 3600 * 1000);
|
||||
return new Date(millisecondSinceEpoch);
|
||||
},
|
||||
parsePath(filepath) {
|
||||
const last = filepath.lastIndexOf('/');
|
||||
return {
|
||||
path: filepath.substring(0, last),
|
||||
name: filepath.substring(last + 1),
|
||||
};
|
||||
},
|
||||
getRelsPath(filepath) {
|
||||
const path = utils.parsePath(filepath);
|
||||
return `${path.path}/_rels/${path.name}.rels`;
|
||||
},
|
||||
xmlEncode(text) {
|
||||
const regexResult = xmlDecodeRegex.exec(text);
|
||||
if (!regexResult) return text;
|
||||
|
||||
let result = '';
|
||||
let escape = '';
|
||||
let lastIndex = 0;
|
||||
let i = regexResult.index;
|
||||
for (; i < text.length; i++) {
|
||||
const charCode = text.charCodeAt(i);
|
||||
switch (charCode) {
|
||||
case 34: // "
|
||||
escape = '"';
|
||||
break;
|
||||
case 38: // &
|
||||
escape = '&';
|
||||
break;
|
||||
case 39: // '
|
||||
escape = ''';
|
||||
break;
|
||||
case 60: // <
|
||||
escape = '<';
|
||||
break;
|
||||
case 62: // >
|
||||
escape = '>';
|
||||
break;
|
||||
case 127:
|
||||
escape = '';
|
||||
break;
|
||||
default: {
|
||||
if (charCode <= 31 && (charCode <= 8 || (charCode >= 11 && charCode !== 13))) {
|
||||
escape = '';
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (lastIndex !== i) result += text.substring(lastIndex, i);
|
||||
lastIndex = i + 1;
|
||||
if (escape) result += escape;
|
||||
}
|
||||
if (lastIndex !== i) return result + text.substring(lastIndex, i);
|
||||
return result;
|
||||
},
|
||||
xmlDecode(text) {
|
||||
return text.replace(/&([a-z]*);/g, c => {
|
||||
switch (c) {
|
||||
case '<':
|
||||
return '<';
|
||||
case '>':
|
||||
return '>';
|
||||
case '&':
|
||||
return '&';
|
||||
case ''':
|
||||
return '\'';
|
||||
case '"':
|
||||
return '"';
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
});
|
||||
},
|
||||
validInt(value) {
|
||||
const i = parseInt(value, 10);
|
||||
return !Number.isNaN(i) ? i : 0;
|
||||
},
|
||||
|
||||
isDateFmt(fmt) {
|
||||
if (!fmt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// must remove all chars inside quotes and []
|
||||
fmt = fmt.replace(/\[[^\]]*]/g, '');
|
||||
fmt = fmt.replace(/"[^"]*"/g, '');
|
||||
// then check for date formatting chars
|
||||
const result = fmt.match(/[ymdhMsb]+/) !== null;
|
||||
return result;
|
||||
},
|
||||
|
||||
fs: {
|
||||
exists(path) {
|
||||
return new Promise(resolve => {
|
||||
fs.access(path, fs.constants.F_OK, err => {
|
||||
resolve(!err);
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
toIsoDateString(dt) {
|
||||
return dt.toIsoString().subsstr(0, 10);
|
||||
},
|
||||
|
||||
parseBoolean(value) {
|
||||
return value === true || value === 'true' || value === 1 || value === '1';
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = utils;
|
||||
169
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/xml-stream.js
generated
vendored
Normal file
169
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/xml-stream.js
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
const _ = require('./under-dash');
|
||||
|
||||
const utils = require('./utils');
|
||||
|
||||
// constants
|
||||
const OPEN_ANGLE = '<';
|
||||
const CLOSE_ANGLE = '>';
|
||||
const OPEN_ANGLE_SLASH = '</';
|
||||
const CLOSE_SLASH_ANGLE = '/>';
|
||||
|
||||
function pushAttribute(xml, name, value) {
|
||||
xml.push(` ${name}="${utils.xmlEncode(value.toString())}"`);
|
||||
}
|
||||
function pushAttributes(xml, attributes) {
|
||||
if (attributes) {
|
||||
const tmp = [];
|
||||
_.each(attributes, (value, name) => {
|
||||
if (value !== undefined) {
|
||||
pushAttribute(tmp, name, value);
|
||||
}
|
||||
});
|
||||
xml.push(tmp.join(""));
|
||||
}
|
||||
}
|
||||
|
||||
class XmlStream {
|
||||
constructor() {
|
||||
this._xml = [];
|
||||
this._stack = [];
|
||||
this._rollbacks = [];
|
||||
}
|
||||
|
||||
get tos() {
|
||||
return this._stack.length ? this._stack[this._stack.length - 1] : undefined;
|
||||
}
|
||||
|
||||
get cursor() {
|
||||
// handy way to track whether anything has been added
|
||||
return this._xml.length;
|
||||
}
|
||||
|
||||
openXml(docAttributes) {
|
||||
const xml = this._xml;
|
||||
// <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
xml.push('<?xml');
|
||||
pushAttributes(xml, docAttributes);
|
||||
xml.push('?>\n');
|
||||
}
|
||||
|
||||
openNode(name, attributes) {
|
||||
const parent = this.tos;
|
||||
const xml = this._xml;
|
||||
if (parent && this.open) {
|
||||
xml.push(CLOSE_ANGLE);
|
||||
}
|
||||
|
||||
this._stack.push(name);
|
||||
|
||||
// start streaming node
|
||||
xml.push(OPEN_ANGLE);
|
||||
xml.push(name);
|
||||
pushAttributes(xml, attributes);
|
||||
this.leaf = true;
|
||||
this.open = true;
|
||||
}
|
||||
|
||||
addAttribute(name, value) {
|
||||
if (!this.open) {
|
||||
throw new Error('Cannot write attributes to node if it is not open');
|
||||
}
|
||||
if (value !== undefined) {
|
||||
pushAttribute(this._xml, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
addAttributes(attrs) {
|
||||
if (!this.open) {
|
||||
throw new Error('Cannot write attributes to node if it is not open');
|
||||
}
|
||||
pushAttributes(this._xml, attrs);
|
||||
}
|
||||
|
||||
writeText(text) {
|
||||
const xml = this._xml;
|
||||
if (this.open) {
|
||||
xml.push(CLOSE_ANGLE);
|
||||
this.open = false;
|
||||
}
|
||||
this.leaf = false;
|
||||
xml.push(utils.xmlEncode(text.toString()));
|
||||
}
|
||||
|
||||
writeXml(xml) {
|
||||
if (this.open) {
|
||||
this._xml.push(CLOSE_ANGLE);
|
||||
this.open = false;
|
||||
}
|
||||
this.leaf = false;
|
||||
this._xml.push(xml);
|
||||
}
|
||||
|
||||
closeNode() {
|
||||
const node = this._stack.pop();
|
||||
const xml = this._xml;
|
||||
if (this.leaf) {
|
||||
xml.push(CLOSE_SLASH_ANGLE);
|
||||
} else {
|
||||
xml.push(OPEN_ANGLE_SLASH);
|
||||
xml.push(node);
|
||||
xml.push(CLOSE_ANGLE);
|
||||
}
|
||||
this.open = false;
|
||||
this.leaf = false;
|
||||
}
|
||||
|
||||
leafNode(name, attributes, text) {
|
||||
this.openNode(name, attributes);
|
||||
if (text !== undefined) {
|
||||
// zeros need to be written
|
||||
this.writeText(text);
|
||||
}
|
||||
this.closeNode();
|
||||
}
|
||||
|
||||
closeAll() {
|
||||
while (this._stack.length) {
|
||||
this.closeNode();
|
||||
}
|
||||
}
|
||||
|
||||
addRollback() {
|
||||
this._rollbacks.push({
|
||||
xml: this._xml.length,
|
||||
stack: this._stack.length,
|
||||
leaf: this.leaf,
|
||||
open: this.open,
|
||||
});
|
||||
return this.cursor;
|
||||
}
|
||||
|
||||
commit() {
|
||||
this._rollbacks.pop();
|
||||
}
|
||||
|
||||
rollback() {
|
||||
const r = this._rollbacks.pop();
|
||||
if (this._xml.length > r.xml) {
|
||||
this._xml.splice(r.xml, this._xml.length - r.xml);
|
||||
}
|
||||
if (this._stack.length > r.stack) {
|
||||
this._stack.splice(r.stack, this._stack.length - r.stack);
|
||||
}
|
||||
this.leaf = r.leaf;
|
||||
this.open = r.open;
|
||||
}
|
||||
|
||||
get xml() {
|
||||
this.closeAll();
|
||||
return this._xml.join('');
|
||||
}
|
||||
}
|
||||
|
||||
XmlStream.StdDocAttributes = {
|
||||
version: '1.0',
|
||||
encoding: 'UTF-8',
|
||||
standalone: 'yes',
|
||||
};
|
||||
|
||||
module.exports = XmlStream;
|
||||
87
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/zip-stream.js
generated
vendored
Normal file
87
doc/test-data/purchase_transaction/node_modules/exceljs/lib/utils/zip-stream.js
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
const events = require('events');
|
||||
const JSZip = require('jszip');
|
||||
|
||||
const StreamBuf = require('./stream-buf');
|
||||
const {stringToBuffer} = require('./browser-buffer-encode');
|
||||
|
||||
// =============================================================================
|
||||
// The ZipWriter class
|
||||
// Packs streamed data into an output zip stream
|
||||
class ZipWriter extends events.EventEmitter {
|
||||
constructor(options) {
|
||||
super();
|
||||
this.options = Object.assign(
|
||||
{
|
||||
type: 'nodebuffer',
|
||||
compression: 'DEFLATE',
|
||||
},
|
||||
options
|
||||
);
|
||||
|
||||
this.zip = new JSZip();
|
||||
this.stream = new StreamBuf();
|
||||
}
|
||||
|
||||
append(data, options) {
|
||||
if (options.hasOwnProperty('base64') && options.base64) {
|
||||
this.zip.file(options.name, data, {base64: true});
|
||||
} else {
|
||||
// https://www.npmjs.com/package/process
|
||||
if (process.browser && typeof data === 'string') {
|
||||
// use TextEncoder in browser
|
||||
data = stringToBuffer(data);
|
||||
}
|
||||
this.zip.file(options.name, data);
|
||||
}
|
||||
}
|
||||
|
||||
async finalize() {
|
||||
const content = await this.zip.generateAsync(this.options);
|
||||
this.stream.end(content);
|
||||
this.emit('finish');
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Stream.Readable interface
|
||||
read(size) {
|
||||
return this.stream.read(size);
|
||||
}
|
||||
|
||||
setEncoding(encoding) {
|
||||
return this.stream.setEncoding(encoding);
|
||||
}
|
||||
|
||||
pause() {
|
||||
return this.stream.pause();
|
||||
}
|
||||
|
||||
resume() {
|
||||
return this.stream.resume();
|
||||
}
|
||||
|
||||
isPaused() {
|
||||
return this.stream.isPaused();
|
||||
}
|
||||
|
||||
pipe(destination, options) {
|
||||
return this.stream.pipe(destination, options);
|
||||
}
|
||||
|
||||
unpipe(destination) {
|
||||
return this.stream.unpipe(destination);
|
||||
}
|
||||
|
||||
unshift(chunk) {
|
||||
return this.stream.unshift(chunk);
|
||||
}
|
||||
|
||||
wrap(stream) {
|
||||
return this.stream.wrap(stream);
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
module.exports = {
|
||||
ZipWriter,
|
||||
};
|
||||
11
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/.rels
generated
vendored
Normal file
11
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/.rels
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
||||
<%relationships.forEach(function(r) {%>
|
||||
<Relationship
|
||||
Id="<%=r.rId%>"
|
||||
Type="<%=r.type%>"
|
||||
Target="<%=r.target%>" <% if (r.targetMode) {%>
|
||||
TargetMode="<%=r.targetMode%>"<%}%>
|
||||
/>
|
||||
<%});%>
|
||||
</Relationships>
|
||||
6
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/calcChain.xml
generated
vendored
Normal file
6
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/calcChain.xml
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<calcChain xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
|
||||
<% formulae.forEach(function(formula) { %>
|
||||
<c r="<%=formula.address%>" i="<%=formula.i%>" <% if(formula.l) { %>l="<%=formula.l%>"<% } %>/>
|
||||
<% }); %>
|
||||
</calcChain>
|
||||
7
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/core.xml
generated
vendored
Normal file
7
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/core.xml
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<dc:creator><%=creator%></dc:creator>
|
||||
<cp:lastModifiedBy><%=lastModifiedBy%></cp:lastModifiedBy>
|
||||
<dcterms:created xsi:type="dcterms:W3CDTF"><%=created.toISOString().replace(/\.\d{3}/,"")%></dcterms:created>
|
||||
<dcterms:modified xsi:type="dcterms:W3CDTF"><%=modified.toISOString().replace(/\.\d{3}/,"")%></dcterms:modified>
|
||||
</cp:coreProperties>
|
||||
153
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/defaultnumformats.js
generated
vendored
Normal file
153
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/defaultnumformats.js
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
module.exports = {
|
||||
0: {f: 'General'},
|
||||
1: {f: '0'},
|
||||
2: {f: '0.00'},
|
||||
3: {f: '#,##0'},
|
||||
4: {f: '#,##0.00'},
|
||||
9: {f: '0%'},
|
||||
10: {f: '0.00%'},
|
||||
11: {f: '0.00E+00'},
|
||||
12: {f: '# ?/?'},
|
||||
13: {f: '# ??/??'},
|
||||
14: {f: 'mm-dd-yy'},
|
||||
15: {f: 'd-mmm-yy'},
|
||||
16: {f: 'd-mmm'},
|
||||
17: {f: 'mmm-yy'},
|
||||
18: {f: 'h:mm AM/PM'},
|
||||
19: {f: 'h:mm:ss AM/PM'},
|
||||
20: {f: 'h:mm'},
|
||||
21: {f: 'h:mm:ss'},
|
||||
22: {f: 'm/d/yy "h":mm'},
|
||||
|
||||
27: {
|
||||
'zh-tw': '[$-404]e/m/d',
|
||||
'zh-cn': 'yyyy"年"m"月"',
|
||||
'ja-jp': '[$-411]ge.m.d',
|
||||
'ko-kr': 'yyyy"年" mm"月" dd"日"',
|
||||
},
|
||||
28: {
|
||||
'zh-tw': '[$-404]e"年"m"月"d"日"',
|
||||
'zh-cn': 'm"月"d"日"',
|
||||
'ja-jp': '[$-411]ggge"年"m"月"d"日"',
|
||||
'ko-kr': 'mm-dd',
|
||||
},
|
||||
29: {
|
||||
'zh-tw': '[$-404]e"年"m"月"d"日"',
|
||||
'zh-cn': 'm"月"d"日"',
|
||||
'ja-jp': '[$-411]ggge"年"m"月"d"日"',
|
||||
'ko-kr': 'mm-dd',
|
||||
},
|
||||
30: {'zh-tw': 'm/d/yy ', 'zh-cn': 'm-d-yy', 'ja-jp': 'm/d/yy', 'ko-kr': 'mm-dd-yy'},
|
||||
31: {
|
||||
'zh-tw': 'yyyy"年"m"月"d"日"',
|
||||
'zh-cn': 'yyyy"年"m"月"d"日"',
|
||||
'ja-jp': 'yyyy"年"m"月"d"日"',
|
||||
'ko-kr': 'yyyy"년" mm"월" dd"일"',
|
||||
},
|
||||
32: {
|
||||
'zh-tw': 'hh"時"mm"分"',
|
||||
'zh-cn': 'h"时"mm"分"',
|
||||
'ja-jp': 'h"時"mm"分"',
|
||||
'ko-kr': 'h"시" mm"분"',
|
||||
},
|
||||
33: {
|
||||
'zh-tw': 'hh"時"mm"分"ss"秒"',
|
||||
'zh-cn': 'h"时"mm"分"ss"秒"',
|
||||
'ja-jp': 'h"時"mm"分"ss"秒"',
|
||||
'ko-kr': 'h"시" mm"분" ss"초"',
|
||||
},
|
||||
34: {
|
||||
'zh-tw': '上午/下午 hh"時"mm"分"',
|
||||
'zh-cn': '上午/下午 h"时"mm"分"',
|
||||
'ja-jp': 'yyyy"年"m"月"',
|
||||
'ko-kr': 'yyyy-mm-dd',
|
||||
},
|
||||
35: {
|
||||
'zh-tw': '上午/下午 hh"時"mm"分"ss"秒"',
|
||||
'zh-cn': '上午/下午 h"时"mm"分"ss"秒"',
|
||||
'ja-jp': 'm"月"d"日"',
|
||||
'ko-kr': 'yyyy-mm-dd',
|
||||
},
|
||||
36: {
|
||||
'zh-tw': '[$-404]e/m/d',
|
||||
'zh-cn': 'yyyy"年"m"月"',
|
||||
'ja-jp': '[$-411]ge.m.d',
|
||||
'ko-kr': 'yyyy"年" mm"月" dd"日"',
|
||||
},
|
||||
|
||||
37: {f: '#,##0 ;(#,##0)'},
|
||||
38: {f: '#,##0 ;[Red](#,##0)'},
|
||||
39: {f: '#,##0.00 ;(#,##0.00)'},
|
||||
40: {f: '#,##0.00 ;[Red](#,##0.00)'},
|
||||
45: {f: 'mm:ss'},
|
||||
46: {f: '[h]:mm:ss'},
|
||||
47: {f: 'mmss.0'},
|
||||
48: {f: '##0.0E+0'},
|
||||
49: {f: '@'},
|
||||
|
||||
50: {
|
||||
'zh-tw': '[$-404]e/m/d',
|
||||
'zh-cn': 'yyyy"年"m"月"',
|
||||
'ja-jp': '[$-411]ge.m.d',
|
||||
'ko-kr': 'yyyy"年" mm"月" dd"日"',
|
||||
},
|
||||
51: {
|
||||
'zh-tw': '[$-404]e"年"m"月"d"日"',
|
||||
'zh-cn': 'm"月"d"日"',
|
||||
'ja-jp': '[$-411]ggge"年"m"月"d"日"',
|
||||
'ko-kr': 'mm-dd',
|
||||
},
|
||||
52: {
|
||||
'zh-tw': '上午/下午 hh"時"mm"分"',
|
||||
'zh-cn': 'yyyy"年"m"月"',
|
||||
'ja-jp': 'yyyy"年"m"月"',
|
||||
'ko-kr': 'yyyy-mm-dd',
|
||||
},
|
||||
53: {
|
||||
'zh-tw': '上午/下午 hh"時"mm"分"ss"秒"',
|
||||
'zh-cn': 'm"月"d"日"',
|
||||
'ja-jp': 'm"月"d"日"',
|
||||
'ko-kr': 'yyyy-mm-dd',
|
||||
},
|
||||
54: {
|
||||
'zh-tw': '[$-404]e"年"m"月"d"日"',
|
||||
'zh-cn': 'm"月"d"日"',
|
||||
'ja-jp': '[$-411]ggge"年"m"月"d"日"',
|
||||
'ko-kr': 'mm-dd',
|
||||
},
|
||||
55: {
|
||||
'zh-tw': '上午/下午 hh"時"mm"分"',
|
||||
'zh-cn': '上午/下午 h"时"mm"分"',
|
||||
'ja-jp': 'yyyy"年"m"月"',
|
||||
'ko-kr': 'yyyy-mm-dd',
|
||||
},
|
||||
56: {
|
||||
'zh-tw': '上午/下午 hh"時"mm"分"ss"秒"',
|
||||
'zh-cn': '上午/下午 h"时"mm"分"ss"秒"',
|
||||
'ja-jp': 'm"月"d"日"',
|
||||
'ko-kr': 'yyyy-mm-dd',
|
||||
},
|
||||
57: {
|
||||
'zh-tw': '[$-404]e/m/d',
|
||||
'zh-cn': 'yyyy"年"m"月"',
|
||||
'ja-jp': '[$-411]ge.m.d',
|
||||
'ko-kr': 'yyyy"年" mm"月" dd"日"',
|
||||
},
|
||||
58: {
|
||||
'zh-tw': '[$-404]e"年"m"月"d"日"',
|
||||
'zh-cn': 'm"月"d"日"',
|
||||
'ja-jp': '[$-411]ggge"年"m"月"d"日"',
|
||||
'ko-kr': 'mm-dd',
|
||||
},
|
||||
|
||||
59: {'th-th': 't0'},
|
||||
60: {'th-th': 't0.00'},
|
||||
61: {'th-th': 't#,##0'},
|
||||
62: {'th-th': 't#,##0.00'},
|
||||
67: {'th-th': 't0%'},
|
||||
68: {'th-th': 't0.00%'},
|
||||
69: {'th-th': 't# ?/?'},
|
||||
70: {'th-th': 't# ??/??'},
|
||||
|
||||
81: {'th-th': 'd/m/bb'},
|
||||
};
|
||||
21
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/rel-type.js
generated
vendored
Normal file
21
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/rel-type.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
OfficeDocument:
|
||||
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument',
|
||||
Worksheet: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet',
|
||||
CalcChain: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain',
|
||||
SharedStrings:
|
||||
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings',
|
||||
Styles: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles',
|
||||
Theme: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme',
|
||||
Hyperlink: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
|
||||
Image: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
|
||||
CoreProperties:
|
||||
'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties',
|
||||
ExtenderProperties:
|
||||
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties',
|
||||
Comments: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments',
|
||||
VmlDrawing: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing',
|
||||
Table: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/table',
|
||||
};
|
||||
41
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/styles.xml
generated
vendored
Normal file
41
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/styles.xml
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<styleSheet
|
||||
xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="x14ac"
|
||||
xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
|
||||
<% if (numFmts.length) { %><numFmts count="<%=numFmts.length%>">
|
||||
<%numFmts.forEach(function(nf) {%><%=nf.xml%>
|
||||
<%});%>
|
||||
</numFmts>
|
||||
<% } %>
|
||||
<fonts count="<%=fonts.length%>" x14ac:knownFonts="1">
|
||||
<%fonts.forEach(function(font) {%><%=font.xml%>
|
||||
<%})%>
|
||||
</fonts>
|
||||
<fills count="<%=fills.length%>">
|
||||
<%fills.forEach(function(fill) {%><%=fill.xml%>
|
||||
<%});%>
|
||||
</fills>
|
||||
<borders count="<%=borders.length%>">
|
||||
<%borders.forEach(function(border) {%><%=border.xml%>
|
||||
<%});%>
|
||||
</borders>
|
||||
<cellStyleXfs count="1">
|
||||
<xf numFmtId="0" fontId="0" fillId="0" borderId="0"/>
|
||||
</cellStyleXfs>
|
||||
<cellXfs count="<%=styles.length%>">
|
||||
<%styles.forEach(function(style) {%><%=style.xml%>
|
||||
<%});%>
|
||||
</cellXfs>
|
||||
<cellStyles count="1">
|
||||
<cellStyle name="Normal" xfId="0" builtinId="0"/>
|
||||
</cellStyles>
|
||||
<dxfs count="0"/>
|
||||
<tableStyles count="0" defaultTableStyle="TableStyleMedium2" defaultPivotStyle="PivotStyleLight16"/>
|
||||
<extLst>
|
||||
<ext uri="{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main">
|
||||
<x14:slicerStyles defaultSlicerStyle="SlicerStyleLight1"/>
|
||||
</ext>
|
||||
</extLst>
|
||||
</styleSheet>
|
||||
16
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/workbook.xml
generated
vendored
Normal file
16
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/workbook.xml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<workbook
|
||||
xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
|
||||
<fileVersion appName="xl" lastEdited="5" lowestEdited="5" rupBuild="9303"/>
|
||||
<workbookPr defaultThemeVersion="124226"/>
|
||||
<bookViews>
|
||||
<workbookView xWindow="480" yWindow="60" windowWidth="18195" windowHeight="8505"/>
|
||||
</bookViews>
|
||||
<sheets>
|
||||
<% worksheets.forEach(function(worksheet) { %><sheet name="<%=worksheet.name%>" state="<%=worksheet.state%>" sheetId="<%=worksheet.id%>" r:id="<%=worksheet.rId%>"/>
|
||||
<% }); %>
|
||||
</sheets>
|
||||
<%=definedNames.xml%>
|
||||
<calcPr calcId="145621"/>
|
||||
</workbook>
|
||||
145
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/base-xform.js
generated
vendored
Normal file
145
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/base-xform.js
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
const parseSax = require('../../utils/parse-sax');
|
||||
const XmlStream = require('../../utils/xml-stream');
|
||||
|
||||
/* 'virtual' methods used as a form of documentation */
|
||||
/* eslint-disable class-methods-use-this */
|
||||
|
||||
// Base class for Xforms
|
||||
class BaseXform {
|
||||
// constructor(/* model, name */) {}
|
||||
|
||||
// ============================================================
|
||||
// Virtual Interface
|
||||
prepare(/* model, options */) {
|
||||
// optional preparation (mutation) of model so it is ready for write
|
||||
}
|
||||
|
||||
render(/* xmlStream, model */) {
|
||||
// convert model to xml
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
// XML node opened
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
// chunk of text encountered for current node
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
// XML node closed
|
||||
}
|
||||
|
||||
reconcile(model, options) {
|
||||
// optional post-parse step (opposite to prepare)
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
reset() {
|
||||
// to make sure parses don't bleed to next iteration
|
||||
this.model = null;
|
||||
|
||||
// if we have a map - reset them too
|
||||
if (this.map) {
|
||||
Object.values(this.map).forEach(xform => {
|
||||
if (xform instanceof BaseXform) {
|
||||
xform.reset();
|
||||
} else if (xform.xform) {
|
||||
xform.xform.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
mergeModel(obj) {
|
||||
// set obj's props to this.model
|
||||
this.model = Object.assign(this.model || {}, obj);
|
||||
}
|
||||
|
||||
async parse(saxParser) {
|
||||
for await (const events of saxParser) {
|
||||
for (const {eventType, value} of events) {
|
||||
if (eventType === 'opentag') {
|
||||
this.parseOpen(value);
|
||||
} else if (eventType === 'text') {
|
||||
this.parseText(value);
|
||||
} else if (eventType === 'closetag') {
|
||||
if (!this.parseClose(value.name)) {
|
||||
return this.model;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.model;
|
||||
}
|
||||
|
||||
async parseStream(stream) {
|
||||
return this.parse(parseSax(stream));
|
||||
}
|
||||
|
||||
get xml() {
|
||||
// convenience function to get the xml of this.model
|
||||
// useful for manager types that are built during the prepare phase
|
||||
return this.toXml(this.model);
|
||||
}
|
||||
|
||||
toXml(model) {
|
||||
const xmlStream = new XmlStream();
|
||||
this.render(xmlStream, model);
|
||||
return xmlStream.xml;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Useful Utilities
|
||||
static toAttribute(value, dflt, always = false) {
|
||||
if (value === undefined) {
|
||||
if (always) {
|
||||
return dflt;
|
||||
}
|
||||
} else if (always || value !== dflt) {
|
||||
return value.toString();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static toStringAttribute(value, dflt, always = false) {
|
||||
return BaseXform.toAttribute(value, dflt, always);
|
||||
}
|
||||
|
||||
static toStringValue(attr, dflt) {
|
||||
return attr === undefined ? dflt : attr;
|
||||
}
|
||||
|
||||
static toBoolAttribute(value, dflt, always = false) {
|
||||
if (value === undefined) {
|
||||
if (always) {
|
||||
return dflt;
|
||||
}
|
||||
} else if (always || value !== dflt) {
|
||||
return value ? '1' : '0';
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static toBoolValue(attr, dflt) {
|
||||
return attr === undefined ? dflt : attr === '1';
|
||||
}
|
||||
|
||||
static toIntAttribute(value, dflt, always = false) {
|
||||
return BaseXform.toAttribute(value, dflt, always);
|
||||
}
|
||||
|
||||
static toIntValue(attr, dflt) {
|
||||
return attr === undefined ? dflt : parseInt(attr, 10);
|
||||
}
|
||||
|
||||
static toFloatAttribute(value, dflt, always = false) {
|
||||
return BaseXform.toAttribute(value, dflt, always);
|
||||
}
|
||||
|
||||
static toFloatValue(attr, dflt) {
|
||||
return attr === undefined ? dflt : parseFloat(attr);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseXform;
|
||||
91
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/defined-name-xform.js
generated
vendored
Normal file
91
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/defined-name-xform.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
const colCache = require('../../../utils/col-cache');
|
||||
|
||||
class DefinedNamesXform extends BaseXform {
|
||||
render(xmlStream, model) {
|
||||
// <definedNames>
|
||||
// <definedName name="name">name.ranges.join(',')</definedName>
|
||||
// <definedName name="_xlnm.Print_Area" localSheetId="0">name.ranges.join(',')</definedName>
|
||||
// </definedNames>
|
||||
xmlStream.openNode('definedName', {
|
||||
name: model.name,
|
||||
localSheetId: model.localSheetId,
|
||||
});
|
||||
xmlStream.writeText(model.ranges.join(','));
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case 'definedName':
|
||||
this._parsedName = node.attributes.name;
|
||||
this._parsedLocalSheetId = node.attributes.localSheetId;
|
||||
this._parsedText = [];
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
this._parsedText.push(text);
|
||||
}
|
||||
|
||||
parseClose() {
|
||||
this.model = {
|
||||
name: this._parsedName,
|
||||
ranges: extractRanges(this._parsedText.join('')),
|
||||
};
|
||||
if (this._parsedLocalSheetId !== undefined) {
|
||||
this.model.localSheetId = parseInt(this._parsedLocalSheetId, 10);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isValidRange(range) {
|
||||
try {
|
||||
colCache.decodeEx(range);
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function extractRanges(parsedText) {
|
||||
const ranges = [];
|
||||
let quotesOpened = false;
|
||||
let last = '';
|
||||
parsedText.split(',').forEach(item => {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
const quotes = (item.match(/'/g) || []).length;
|
||||
|
||||
if (!quotes) {
|
||||
if (quotesOpened) {
|
||||
last += `${item},`;
|
||||
} else if (isValidRange(item)) {
|
||||
ranges.push(item);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const quotesEven = quotes % 2 === 0;
|
||||
|
||||
if (!quotesOpened && quotesEven && isValidRange(item)) {
|
||||
ranges.push(item);
|
||||
} else if (quotesOpened && !quotesEven) {
|
||||
quotesOpened = false;
|
||||
if (isValidRange(last + item)) {
|
||||
ranges.push(last + item);
|
||||
}
|
||||
last = '';
|
||||
} else {
|
||||
quotesOpened = true;
|
||||
last += `${item},`;
|
||||
}
|
||||
});
|
||||
return ranges;
|
||||
}
|
||||
|
||||
module.exports = DefinedNamesXform;
|
||||
34
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/sheet-xform.js
generated
vendored
Normal file
34
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/sheet-xform.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
const utils = require('../../../utils/utils');
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class WorksheetXform extends BaseXform {
|
||||
render(xmlStream, model) {
|
||||
xmlStream.leafNode('sheet', {
|
||||
sheetId: model.id,
|
||||
name: model.name,
|
||||
state: model.state,
|
||||
'r:id': model.rId,
|
||||
});
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (node.name === 'sheet') {
|
||||
this.model = {
|
||||
name: utils.xmlDecode(node.attributes.name),
|
||||
id: parseInt(node.attributes.sheetId, 10),
|
||||
state: node.attributes.state,
|
||||
rId: node.attributes['r:id'],
|
||||
};
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WorksheetXform;
|
||||
26
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/workbook-calc-properties-xform.js
generated
vendored
Normal file
26
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/workbook-calc-properties-xform.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class WorkbookCalcPropertiesXform extends BaseXform {
|
||||
render(xmlStream, model) {
|
||||
xmlStream.leafNode('calcPr', {
|
||||
calcId: 171027,
|
||||
fullCalcOnLoad: model.fullCalcOnLoad ? 1 : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (node.name === 'calcPr') {
|
||||
this.model = {};
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WorkbookCalcPropertiesXform;
|
||||
29
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/workbook-properties-xform.js
generated
vendored
Normal file
29
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/workbook-properties-xform.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class WorksheetPropertiesXform extends BaseXform {
|
||||
render(xmlStream, model) {
|
||||
xmlStream.leafNode('workbookPr', {
|
||||
date1904: model.date1904 ? 1 : undefined,
|
||||
defaultThemeVersion: 164011,
|
||||
filterPrivacy: 1,
|
||||
});
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (node.name === 'workbookPr') {
|
||||
this.model = {
|
||||
date1904: node.attributes.date1904 === '1',
|
||||
};
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WorksheetPropertiesXform;
|
||||
53
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/workbook-view-xform.js
generated
vendored
Normal file
53
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/workbook-view-xform.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class WorkbookViewXform extends BaseXform {
|
||||
render(xmlStream, model) {
|
||||
const attributes = {
|
||||
xWindow: model.x || 0,
|
||||
yWindow: model.y || 0,
|
||||
windowWidth: model.width || 12000,
|
||||
windowHeight: model.height || 24000,
|
||||
firstSheet: model.firstSheet,
|
||||
activeTab: model.activeTab,
|
||||
};
|
||||
if (model.visibility && model.visibility !== 'visible') {
|
||||
attributes.visibility = model.visibility;
|
||||
}
|
||||
xmlStream.leafNode('workbookView', attributes);
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (node.name === 'workbookView') {
|
||||
const model = (this.model = {});
|
||||
const addS = function(name, value, dflt) {
|
||||
const s = value !== undefined ? (model[name] = value) : dflt;
|
||||
if (s !== undefined) {
|
||||
model[name] = s;
|
||||
}
|
||||
};
|
||||
const addN = function(name, value, dflt) {
|
||||
const n = value !== undefined ? (model[name] = parseInt(value, 10)) : dflt;
|
||||
if (n !== undefined) {
|
||||
model[name] = n;
|
||||
}
|
||||
};
|
||||
addN('x', node.attributes.xWindow, 0);
|
||||
addN('y', node.attributes.yWindow, 0);
|
||||
addN('width', node.attributes.windowWidth, 25000);
|
||||
addN('height', node.attributes.windowHeight, 10000);
|
||||
addS('visibility', node.attributes.visibility, 'visible');
|
||||
addN('activeTab', node.attributes.activeTab, undefined);
|
||||
addN('firstSheet', node.attributes.firstSheet, undefined);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WorkbookViewXform;
|
||||
255
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/workbook-xform.js
generated
vendored
Normal file
255
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/book/workbook-xform.js
generated
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
const _ = require('../../../utils/under-dash');
|
||||
|
||||
const colCache = require('../../../utils/col-cache');
|
||||
const XmlStream = require('../../../utils/xml-stream');
|
||||
|
||||
const BaseXform = require('../base-xform');
|
||||
const StaticXform = require('../static-xform');
|
||||
const ListXform = require('../list-xform');
|
||||
const DefinedNameXform = require('./defined-name-xform');
|
||||
const SheetXform = require('./sheet-xform');
|
||||
const WorkbookViewXform = require('./workbook-view-xform');
|
||||
const WorkbookPropertiesXform = require('./workbook-properties-xform');
|
||||
const WorkbookCalcPropertiesXform = require('./workbook-calc-properties-xform');
|
||||
|
||||
class WorkbookXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.map = {
|
||||
fileVersion: WorkbookXform.STATIC_XFORMS.fileVersion,
|
||||
workbookPr: new WorkbookPropertiesXform(),
|
||||
bookViews: new ListXform({
|
||||
tag: 'bookViews',
|
||||
count: false,
|
||||
childXform: new WorkbookViewXform(),
|
||||
}),
|
||||
sheets: new ListXform({tag: 'sheets', count: false, childXform: new SheetXform()}),
|
||||
definedNames: new ListXform({
|
||||
tag: 'definedNames',
|
||||
count: false,
|
||||
childXform: new DefinedNameXform(),
|
||||
}),
|
||||
calcPr: new WorkbookCalcPropertiesXform(),
|
||||
};
|
||||
}
|
||||
|
||||
prepare(model) {
|
||||
model.sheets = model.worksheets;
|
||||
|
||||
// collate all the print areas from all of the sheets and add them to the defined names
|
||||
const printAreas = [];
|
||||
let index = 0; // sheets is sparse array - calc index manually
|
||||
model.sheets.forEach(sheet => {
|
||||
if (sheet.pageSetup && sheet.pageSetup.printArea) {
|
||||
sheet.pageSetup.printArea.split('&&').forEach(printArea => {
|
||||
const printAreaComponents = printArea.split(':');
|
||||
const definedName = {
|
||||
name: '_xlnm.Print_Area',
|
||||
ranges: [`'${sheet.name}'!$${printAreaComponents[0]}:$${printAreaComponents[1]}`],
|
||||
localSheetId: index,
|
||||
};
|
||||
printAreas.push(definedName);
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
sheet.pageSetup &&
|
||||
(sheet.pageSetup.printTitlesRow || sheet.pageSetup.printTitlesColumn)
|
||||
) {
|
||||
const ranges = [];
|
||||
|
||||
if (sheet.pageSetup.printTitlesColumn) {
|
||||
const titlesColumns = sheet.pageSetup.printTitlesColumn.split(':');
|
||||
ranges.push(`'${sheet.name}'!$${titlesColumns[0]}:$${titlesColumns[1]}`);
|
||||
}
|
||||
|
||||
if (sheet.pageSetup.printTitlesRow) {
|
||||
const titlesRows = sheet.pageSetup.printTitlesRow.split(':');
|
||||
ranges.push(`'${sheet.name}'!$${titlesRows[0]}:$${titlesRows[1]}`);
|
||||
}
|
||||
|
||||
const definedName = {
|
||||
name: '_xlnm.Print_Titles',
|
||||
ranges,
|
||||
localSheetId: index,
|
||||
};
|
||||
|
||||
printAreas.push(definedName);
|
||||
}
|
||||
index++;
|
||||
});
|
||||
if (printAreas.length) {
|
||||
model.definedNames = model.definedNames.concat(printAreas);
|
||||
}
|
||||
|
||||
(model.media || []).forEach((medium, i) => {
|
||||
// assign name
|
||||
medium.name = medium.type + (i + 1);
|
||||
});
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openXml(XmlStream.StdDocAttributes);
|
||||
xmlStream.openNode('workbook', WorkbookXform.WORKBOOK_ATTRIBUTES);
|
||||
|
||||
this.map.fileVersion.render(xmlStream);
|
||||
this.map.workbookPr.render(xmlStream, model.properties);
|
||||
this.map.bookViews.render(xmlStream, model.views);
|
||||
this.map.sheets.render(xmlStream, model.sheets);
|
||||
this.map.definedNames.render(xmlStream, model.definedNames);
|
||||
this.map.calcPr.render(xmlStream, model.calcProperties);
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case 'workbook':
|
||||
return true;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case 'workbook':
|
||||
this.model = {
|
||||
sheets: this.map.sheets.model,
|
||||
properties: this.map.workbookPr.model || {},
|
||||
views: this.map.bookViews.model,
|
||||
calcProperties: {},
|
||||
};
|
||||
if (this.map.definedNames.model) {
|
||||
this.model.definedNames = this.map.definedNames.model;
|
||||
}
|
||||
|
||||
return false;
|
||||
default:
|
||||
// not quite sure how we get here!
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
reconcile(model) {
|
||||
const rels = (model.workbookRels || []).reduce((map, rel) => {
|
||||
map[rel.Id] = rel;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
// reconcile sheet ids, rIds and names
|
||||
const worksheets = [];
|
||||
let worksheet;
|
||||
let index = 0;
|
||||
|
||||
(model.sheets || []).forEach(sheet => {
|
||||
const rel = rels[sheet.rId];
|
||||
if (!rel) {
|
||||
return;
|
||||
}
|
||||
// if rel.Target start with `[space]/xl/` or `/xl/` , then it will be replaced with `''` and spliced behind `xl/`,
|
||||
// otherwise it will be spliced directly behind `xl/`. i.g.
|
||||
worksheet = model.worksheetHash[`xl/${rel.Target.replace(/^(\s|\/xl\/)+/, '')}`];
|
||||
// If there are "chartsheets" in the file, rel.Target will
|
||||
// come out as chartsheets/sheet1.xml or similar here, and
|
||||
// that won't be in model.worksheetHash.
|
||||
// As we don't have the infrastructure to support chartsheets,
|
||||
// we will ignore them for now:
|
||||
if (worksheet) {
|
||||
worksheet.name = sheet.name;
|
||||
worksheet.id = sheet.id;
|
||||
worksheet.state = sheet.state;
|
||||
worksheets[index++] = worksheet;
|
||||
}
|
||||
});
|
||||
|
||||
// reconcile print areas
|
||||
const definedNames = [];
|
||||
_.each(model.definedNames, definedName => {
|
||||
if (definedName.name === '_xlnm.Print_Area') {
|
||||
worksheet = worksheets[definedName.localSheetId];
|
||||
if (worksheet) {
|
||||
if (!worksheet.pageSetup) {
|
||||
worksheet.pageSetup = {};
|
||||
}
|
||||
const range = colCache.decodeEx(definedName.ranges[0]);
|
||||
worksheet.pageSetup.printArea = worksheet.pageSetup.printArea
|
||||
? `${worksheet.pageSetup.printArea}&&${range.dimensions}`
|
||||
: range.dimensions;
|
||||
}
|
||||
} else if (definedName.name === '_xlnm.Print_Titles') {
|
||||
worksheet = worksheets[definedName.localSheetId];
|
||||
if (worksheet) {
|
||||
if (!worksheet.pageSetup) {
|
||||
worksheet.pageSetup = {};
|
||||
}
|
||||
|
||||
const rangeString = definedName.ranges.join(',');
|
||||
|
||||
const dollarRegex = /\$/g;
|
||||
|
||||
const rowRangeRegex = /\$\d+:\$\d+/;
|
||||
const rowRangeMatches = rangeString.match(rowRangeRegex);
|
||||
|
||||
if (rowRangeMatches && rowRangeMatches.length) {
|
||||
const range = rowRangeMatches[0];
|
||||
worksheet.pageSetup.printTitlesRow = range.replace(dollarRegex, '');
|
||||
}
|
||||
|
||||
const columnRangeRegex = /\$[A-Z]+:\$[A-Z]+/;
|
||||
const columnRangeMatches = rangeString.match(columnRangeRegex);
|
||||
|
||||
if (columnRangeMatches && columnRangeMatches.length) {
|
||||
const range = columnRangeMatches[0];
|
||||
worksheet.pageSetup.printTitlesColumn = range.replace(dollarRegex, '');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
definedNames.push(definedName);
|
||||
}
|
||||
});
|
||||
model.definedNames = definedNames;
|
||||
|
||||
// used by sheets to build their image models
|
||||
model.media.forEach((media, i) => {
|
||||
media.index = i;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
WorkbookXform.WORKBOOK_ATTRIBUTES = {
|
||||
xmlns: 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
|
||||
'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
|
||||
'xmlns:mc': 'http://schemas.openxmlformats.org/markup-compatibility/2006',
|
||||
'mc:Ignorable': 'x15',
|
||||
'xmlns:x15': 'http://schemas.microsoft.com/office/spreadsheetml/2010/11/main',
|
||||
};
|
||||
WorkbookXform.STATIC_XFORMS = {
|
||||
fileVersion: new StaticXform({
|
||||
tag: 'fileVersion',
|
||||
$: {appName: 'xl', lastEdited: 5, lowestEdited: 5, rupBuild: 9303},
|
||||
}),
|
||||
};
|
||||
|
||||
module.exports = WorkbookXform;
|
||||
105
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/comment-xform.js
generated
vendored
Normal file
105
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/comment-xform.js
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
const RichTextXform = require('../strings/rich-text-xform');
|
||||
const utils = require('../../../utils/utils');
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
/**
|
||||
<comment ref="B1" authorId="0">
|
||||
<text>
|
||||
<r>
|
||||
<rPr>
|
||||
<b/>
|
||||
<sz val="9"/>
|
||||
<rFont val="宋体"/>
|
||||
<charset val="134"/>
|
||||
</rPr>
|
||||
<t>51422:</t>
|
||||
</r>
|
||||
<r>
|
||||
<rPr>
|
||||
<sz val="9"/>
|
||||
<rFont val="宋体"/>
|
||||
<charset val="134"/>
|
||||
</rPr>
|
||||
<t xml:space="preserve"> test</t>
|
||||
</r>
|
||||
</text>
|
||||
</comment>
|
||||
*/
|
||||
|
||||
const CommentXform = (module.exports = function(model) {
|
||||
this.model = model;
|
||||
});
|
||||
|
||||
utils.inherits(CommentXform, BaseXform, {
|
||||
get tag() {
|
||||
return 'r';
|
||||
},
|
||||
|
||||
get richTextXform() {
|
||||
if (!this._richTextXform) {
|
||||
this._richTextXform = new RichTextXform();
|
||||
}
|
||||
return this._richTextXform;
|
||||
},
|
||||
|
||||
render(xmlStream, model) {
|
||||
model = model || this.model;
|
||||
|
||||
xmlStream.openNode('comment', {
|
||||
ref: model.ref,
|
||||
authorId: 0,
|
||||
});
|
||||
xmlStream.openNode('text');
|
||||
if (model && model.note && model.note.texts) {
|
||||
model.note.texts.forEach(text => {
|
||||
this.richTextXform.render(xmlStream, text);
|
||||
});
|
||||
}
|
||||
xmlStream.closeNode();
|
||||
xmlStream.closeNode();
|
||||
},
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case 'comment':
|
||||
this.model = {
|
||||
type: 'note',
|
||||
note: {
|
||||
texts: [],
|
||||
},
|
||||
...node.attributes,
|
||||
};
|
||||
return true;
|
||||
case 'r':
|
||||
this.parser = this.richTextXform;
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
},
|
||||
parseClose(name) {
|
||||
switch (name) {
|
||||
case 'comment':
|
||||
return false;
|
||||
case 'r':
|
||||
this.model.note.texts.push(this.parser.model);
|
||||
this.parser = undefined;
|
||||
return true;
|
||||
default:
|
||||
if (this.parser) {
|
||||
this.parser.parseClose(name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
});
|
||||
82
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/comments-xform.js
generated
vendored
Normal file
82
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/comments-xform.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
const XmlStream = require('../../../utils/xml-stream');
|
||||
const utils = require('../../../utils/utils');
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
const CommentXform = require('./comment-xform');
|
||||
|
||||
const CommentsXform = (module.exports = function() {
|
||||
this.map = {
|
||||
comment: new CommentXform(),
|
||||
};
|
||||
});
|
||||
|
||||
utils.inherits(
|
||||
CommentsXform,
|
||||
BaseXform,
|
||||
{
|
||||
COMMENTS_ATTRIBUTES: {
|
||||
xmlns: 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
|
||||
},
|
||||
},
|
||||
{
|
||||
render(xmlStream, model) {
|
||||
model = model || this.model;
|
||||
xmlStream.openXml(XmlStream.StdDocAttributes);
|
||||
xmlStream.openNode('comments', CommentsXform.COMMENTS_ATTRIBUTES);
|
||||
|
||||
// authors
|
||||
// TODO: support authors properly
|
||||
xmlStream.openNode('authors');
|
||||
xmlStream.leafNode('author', null, 'Author');
|
||||
xmlStream.closeNode();
|
||||
|
||||
// comments
|
||||
xmlStream.openNode('commentList');
|
||||
model.comments.forEach(comment => {
|
||||
this.map.comment.render(xmlStream, comment);
|
||||
});
|
||||
xmlStream.closeNode();
|
||||
xmlStream.closeNode();
|
||||
},
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case 'commentList':
|
||||
this.model = {
|
||||
comments: [],
|
||||
};
|
||||
return true;
|
||||
case 'comment':
|
||||
this.parser = this.map.comment;
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
},
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
},
|
||||
parseClose(name) {
|
||||
switch (name) {
|
||||
case 'commentList':
|
||||
return false;
|
||||
case 'comment':
|
||||
this.model.comments.push(this.parser.model);
|
||||
this.parser = undefined;
|
||||
return true;
|
||||
default:
|
||||
if (this.parser) {
|
||||
this.parser.parseClose(name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
39
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/style/vml-position-xform.js
generated
vendored
Normal file
39
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/style/vml-position-xform.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
const BaseXform = require('../../base-xform');
|
||||
|
||||
class VmlPositionXform extends BaseXform {
|
||||
constructor(model) {
|
||||
super();
|
||||
this._model = model;
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return this._model && this._model.tag;
|
||||
}
|
||||
|
||||
render(xmlStream, model, type) {
|
||||
if (model === type[2]) {
|
||||
xmlStream.leafNode(this.tag);
|
||||
} else if (this.tag === 'x:SizeWithCells' && model === type[1]) {
|
||||
xmlStream.leafNode(this.tag);
|
||||
}
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.model = {};
|
||||
this.model[this.tag] = true;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VmlPositionXform;
|
||||
36
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/style/vml-protection-xform.js
generated
vendored
Normal file
36
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/style/vml-protection-xform.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
const BaseXform = require('../../base-xform');
|
||||
|
||||
class VmlProtectionXform extends BaseXform {
|
||||
constructor(model) {
|
||||
super();
|
||||
this._model = model;
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return this._model && this._model.tag;
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.leafNode(this.tag, null, model);
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.text = '';
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
parseClose() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VmlProtectionXform;
|
||||
60
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/vml-anchor-xform.js
generated
vendored
Normal file
60
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/vml-anchor-xform.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
// render the triangle in the cell for the comment
|
||||
class VmlAnchorXform extends BaseXform {
|
||||
get tag() {
|
||||
return 'x:Anchor';
|
||||
}
|
||||
|
||||
getAnchorRect(anchor) {
|
||||
const l = Math.floor(anchor.left);
|
||||
const lf = Math.floor((anchor.left - l) * 68);
|
||||
const t = Math.floor(anchor.top);
|
||||
const tf = Math.floor((anchor.top - t) * 18);
|
||||
const r = Math.floor(anchor.right);
|
||||
const rf = Math.floor((anchor.right - r) * 68);
|
||||
const b = Math.floor(anchor.bottom);
|
||||
const bf = Math.floor((anchor.bottom - b) * 18);
|
||||
return [l, lf, t, tf, r, rf, b, bf];
|
||||
}
|
||||
|
||||
getDefaultRect(ref) {
|
||||
const l = ref.col;
|
||||
const lf = 6;
|
||||
const t = Math.max(ref.row - 2, 0);
|
||||
const tf = 14;
|
||||
const r = l + 2;
|
||||
const rf = 2;
|
||||
const b = t + 4;
|
||||
const bf = 16;
|
||||
return [l, lf, t, tf, r, rf, b, bf];
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
const rect = model.anchor
|
||||
? this.getAnchorRect(model.anchor)
|
||||
: this.getDefaultRect(model.refAddress);
|
||||
|
||||
xmlStream.leafNode('x:Anchor', null, rect.join(', '));
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.text = '';
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
parseClose() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VmlAnchorXform;
|
||||
95
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/vml-client-data-xform.js
generated
vendored
Normal file
95
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/vml-client-data-xform.js
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
const VmlAnchorXform = require('./vml-anchor-xform');
|
||||
const VmlProtectionXform = require('./style/vml-protection-xform');
|
||||
const VmlPositionXform = require('./style/vml-position-xform');
|
||||
|
||||
const POSITION_TYPE = ['twoCells', 'oneCells', 'absolute'];
|
||||
|
||||
class VmlClientDataXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
this.map = {
|
||||
'x:Anchor': new VmlAnchorXform(),
|
||||
'x:Locked': new VmlProtectionXform({tag: 'x:Locked'}),
|
||||
'x:LockText': new VmlProtectionXform({tag: 'x:LockText'}),
|
||||
'x:SizeWithCells': new VmlPositionXform({tag: 'x:SizeWithCells'}),
|
||||
'x:MoveWithCells': new VmlPositionXform({tag: 'x:MoveWithCells'}),
|
||||
};
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return 'x:ClientData';
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
const {protection, editAs} = model.note;
|
||||
xmlStream.openNode(this.tag, {ObjectType: 'Note'});
|
||||
this.map['x:MoveWithCells'].render(xmlStream, editAs, POSITION_TYPE);
|
||||
this.map['x:SizeWithCells'].render(xmlStream, editAs, POSITION_TYPE);
|
||||
this.map['x:Anchor'].render(xmlStream, model);
|
||||
this.map['x:Locked'].render(xmlStream, protection.locked);
|
||||
xmlStream.leafNode('x:AutoFill', null, 'False');
|
||||
this.map['x:LockText'].render(xmlStream, protection.lockText);
|
||||
xmlStream.leafNode('x:Row', null, model.refAddress.row - 1);
|
||||
xmlStream.leafNode('x:Column', null, model.refAddress.col - 1);
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.reset();
|
||||
this.model = {
|
||||
anchor: [],
|
||||
protection: {},
|
||||
editAs: '',
|
||||
};
|
||||
break;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
this.normalizeModel();
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
normalizeModel() {
|
||||
const position = Object.assign(
|
||||
{},
|
||||
this.map['x:MoveWithCells'].model,
|
||||
this.map['x:SizeWithCells'].model
|
||||
);
|
||||
const len = Object.keys(position).length;
|
||||
this.model.editAs = POSITION_TYPE[len];
|
||||
this.model.anchor = this.map['x:Anchor'].text;
|
||||
this.model.protection.locked = this.map['x:Locked'].text;
|
||||
this.model.protection.lockText = this.map['x:LockText'].text;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VmlClientDataXform;
|
||||
107
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/vml-notes-xform.js
generated
vendored
Normal file
107
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/vml-notes-xform.js
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
const XmlStream = require('../../../utils/xml-stream');
|
||||
|
||||
const BaseXform = require('../base-xform');
|
||||
const VmlShapeXform = require('./vml-shape-xform');
|
||||
|
||||
// This class is (currently) single purposed to insert the triangle
|
||||
// drawing icons on commented cells
|
||||
class VmlNotesXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
this.map = {
|
||||
'v:shape': new VmlShapeXform(),
|
||||
};
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return 'xml';
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openXml(XmlStream.StdDocAttributes);
|
||||
xmlStream.openNode(this.tag, VmlNotesXform.DRAWING_ATTRIBUTES);
|
||||
|
||||
xmlStream.openNode('o:shapelayout', {'v:ext': 'edit'});
|
||||
xmlStream.leafNode('o:idmap', {'v:ext': 'edit', data: 1});
|
||||
xmlStream.closeNode();
|
||||
|
||||
xmlStream.openNode('v:shapetype', {
|
||||
id: '_x0000_t202',
|
||||
coordsize: '21600,21600',
|
||||
'o:spt': 202,
|
||||
path: 'm,l,21600r21600,l21600,xe',
|
||||
});
|
||||
xmlStream.leafNode('v:stroke', {joinstyle: 'miter'});
|
||||
xmlStream.leafNode('v:path', {gradientshapeok: 't', 'o:connecttype': 'rect'});
|
||||
xmlStream.closeNode();
|
||||
|
||||
model.comments.forEach((item, index) => {
|
||||
this.map['v:shape'].render(xmlStream, item, index);
|
||||
});
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.reset();
|
||||
this.model = {
|
||||
comments: [],
|
||||
};
|
||||
break;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.model.comments.push(this.parser.model);
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
return false;
|
||||
default:
|
||||
// could be some unrecognised tags
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
reconcile(model, options) {
|
||||
model.anchors.forEach(anchor => {
|
||||
if (anchor.br) {
|
||||
this.map['xdr:twoCellAnchor'].reconcile(anchor, options);
|
||||
} else {
|
||||
this.map['xdr:oneCellAnchor'].reconcile(anchor, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
VmlNotesXform.DRAWING_ATTRIBUTES = {
|
||||
'xmlns:v': 'urn:schemas-microsoft-com:vml',
|
||||
'xmlns:o': 'urn:schemas-microsoft-com:office:office',
|
||||
'xmlns:x': 'urn:schemas-microsoft-com:office:excel',
|
||||
};
|
||||
|
||||
module.exports = VmlNotesXform;
|
||||
95
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/vml-shape-xform.js
generated
vendored
Normal file
95
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/vml-shape-xform.js
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
const VmlTextboxXform = require('./vml-textbox-xform');
|
||||
const VmlClientDataXform = require('./vml-client-data-xform');
|
||||
|
||||
class VmlShapeXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
this.map = {
|
||||
'v:textbox': new VmlTextboxXform(),
|
||||
'x:ClientData': new VmlClientDataXform(),
|
||||
};
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return 'v:shape';
|
||||
}
|
||||
|
||||
render(xmlStream, model, index) {
|
||||
xmlStream.openNode('v:shape', VmlShapeXform.V_SHAPE_ATTRIBUTES(model, index));
|
||||
|
||||
xmlStream.leafNode('v:fill', {color2: 'infoBackground [80]'});
|
||||
xmlStream.leafNode('v:shadow', {color: 'none [81]', obscured: 't'});
|
||||
xmlStream.leafNode('v:path', {'o:connecttype': 'none'});
|
||||
this.map['v:textbox'].render(xmlStream, model);
|
||||
this.map['x:ClientData'].render(xmlStream, model);
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.reset();
|
||||
this.model = {
|
||||
margins: {
|
||||
insetmode: node.attributes['o:insetmode'],
|
||||
},
|
||||
anchor: '',
|
||||
editAs: '',
|
||||
protection: {},
|
||||
};
|
||||
break;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
this.model.margins.inset = this.map['v:textbox'].model && this.map['v:textbox'].model.inset;
|
||||
this.model.protection =
|
||||
this.map['x:ClientData'].model && this.map['x:ClientData'].model.protection;
|
||||
this.model.anchor = this.map['x:ClientData'].model && this.map['x:ClientData'].model.anchor;
|
||||
this.model.editAs = this.map['x:ClientData'].model && this.map['x:ClientData'].model.editAs;
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VmlShapeXform.V_SHAPE_ATTRIBUTES = (model, index) => ({
|
||||
id: `_x0000_s${1025 + index}`,
|
||||
type: '#_x0000_t202',
|
||||
style:
|
||||
'position:absolute; margin-left:105.3pt;margin-top:10.5pt;width:97.8pt;height:59.1pt;z-index:1;visibility:hidden',
|
||||
fillcolor: 'infoBackground [80]',
|
||||
strokecolor: 'none [81]',
|
||||
'o:insetmode': model.note.margins && model.note.margins.insetmode,
|
||||
});
|
||||
|
||||
module.exports = VmlShapeXform;
|
||||
64
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/vml-textbox-xform.js
generated
vendored
Normal file
64
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/comment/vml-textbox-xform.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class VmlTextboxXform extends BaseXform {
|
||||
get tag() {
|
||||
return 'v:textbox';
|
||||
}
|
||||
|
||||
conversionUnit(value, multiple, unit) {
|
||||
return `${parseFloat(value) * multiple.toFixed(2)}${unit}`;
|
||||
}
|
||||
|
||||
reverseConversionUnit(inset) {
|
||||
return (inset || '').split(',').map(margin => {
|
||||
return Number(parseFloat(this.conversionUnit(parseFloat(margin), 0.1, '')).toFixed(2));
|
||||
});
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
const attributes = {
|
||||
style: 'mso-direction-alt:auto',
|
||||
};
|
||||
if (model && model.note) {
|
||||
let {inset} = model.note && model.note.margins;
|
||||
if (Array.isArray(inset)) {
|
||||
inset = inset
|
||||
.map(margin => {
|
||||
return this.conversionUnit(margin, 10, 'mm');
|
||||
})
|
||||
.join(',');
|
||||
}
|
||||
if (inset) {
|
||||
attributes.inset = inset;
|
||||
}
|
||||
}
|
||||
xmlStream.openNode('v:textbox', attributes);
|
||||
xmlStream.leafNode('div', {style: 'text-align:left'});
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.model = {
|
||||
inset: this.reverseConversionUnit(node.attributes.inset),
|
||||
};
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose(name) {
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VmlTextboxXform;
|
||||
56
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/composite-xform.js
generated
vendored
Normal file
56
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/composite-xform.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
const BaseXform = require('./base-xform');
|
||||
|
||||
/* 'virtual' methods used as a form of documentation */
|
||||
/* eslint-disable class-methods-use-this */
|
||||
|
||||
// base class for xforms that are composed of other xforms
|
||||
// offers some default implementations
|
||||
class CompositeXform extends BaseXform {
|
||||
createNewModel(node) {
|
||||
return {};
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
// Typical pattern for composite xform
|
||||
this.parser = this.parser || this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (node.name === this.tag) {
|
||||
this.model = this.createNewModel(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
// Default implementation. Send text to child parser
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
onParserClose(name, parser) {
|
||||
// parseClose has seen a child parser close
|
||||
// now need to incorporate into this.model somehow
|
||||
this.model[name] = parser.model;
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
// Default implementation
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.onParserClose(name, this.parser);
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return name !== this.tag;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CompositeXform;
|
||||
32
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/app-heading-pairs-xform.js
generated
vendored
Normal file
32
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/app-heading-pairs-xform.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class AppHeadingPairsXform extends BaseXform {
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openNode('HeadingPairs');
|
||||
xmlStream.openNode('vt:vector', {size: 2, baseType: 'variant'});
|
||||
|
||||
xmlStream.openNode('vt:variant');
|
||||
xmlStream.leafNode('vt:lpstr', undefined, 'Worksheets');
|
||||
xmlStream.closeNode();
|
||||
|
||||
xmlStream.openNode('vt:variant');
|
||||
xmlStream.leafNode('vt:i4', undefined, model.length);
|
||||
xmlStream.closeNode();
|
||||
|
||||
xmlStream.closeNode();
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
// no parsing
|
||||
return node.name === 'HeadingPairs';
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose(name) {
|
||||
return name !== 'HeadingPairs';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AppHeadingPairsXform;
|
||||
28
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/app-titles-of-parts-xform.js
generated
vendored
Normal file
28
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/app-titles-of-parts-xform.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class AppTitlesOfPartsXform extends BaseXform {
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openNode('TitlesOfParts');
|
||||
xmlStream.openNode('vt:vector', {size: model.length, baseType: 'lpstr'});
|
||||
|
||||
model.forEach(sheet => {
|
||||
xmlStream.leafNode('vt:lpstr', undefined, sheet.name);
|
||||
});
|
||||
|
||||
xmlStream.closeNode();
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
// no parsing
|
||||
return node.name === 'TitlesOfParts';
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose(name) {
|
||||
return name !== 'TitlesOfParts';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AppTitlesOfPartsXform;
|
||||
100
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/app-xform.js
generated
vendored
Normal file
100
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/app-xform.js
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
const XmlStream = require('../../../utils/xml-stream');
|
||||
const BaseXform = require('../base-xform');
|
||||
const StringXform = require('../simple/string-xform');
|
||||
|
||||
const AppHeadingPairsXform = require('./app-heading-pairs-xform');
|
||||
const AppTitleOfPartsXform = require('./app-titles-of-parts-xform');
|
||||
|
||||
class AppXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.map = {
|
||||
Company: new StringXform({tag: 'Company'}),
|
||||
Manager: new StringXform({tag: 'Manager'}),
|
||||
HeadingPairs: new AppHeadingPairsXform(),
|
||||
TitleOfParts: new AppTitleOfPartsXform(),
|
||||
};
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openXml(XmlStream.StdDocAttributes);
|
||||
|
||||
xmlStream.openNode('Properties', AppXform.PROPERTY_ATTRIBUTES);
|
||||
|
||||
xmlStream.leafNode('Application', undefined, 'Microsoft Excel');
|
||||
xmlStream.leafNode('DocSecurity', undefined, '0');
|
||||
xmlStream.leafNode('ScaleCrop', undefined, 'false');
|
||||
|
||||
this.map.HeadingPairs.render(xmlStream, model.worksheets);
|
||||
this.map.TitleOfParts.render(xmlStream, model.worksheets);
|
||||
this.map.Company.render(xmlStream, model.company || '');
|
||||
this.map.Manager.render(xmlStream, model.manager);
|
||||
|
||||
xmlStream.leafNode('LinksUpToDate', undefined, 'false');
|
||||
xmlStream.leafNode('SharedDoc', undefined, 'false');
|
||||
xmlStream.leafNode('HyperlinksChanged', undefined, 'false');
|
||||
xmlStream.leafNode('AppVersion', undefined, '16.0300');
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case 'Properties':
|
||||
return true;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
// there's a lot we don't bother to parse
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case 'Properties':
|
||||
this.model = {
|
||||
worksheets: this.map.TitleOfParts.model,
|
||||
company: this.map.Company.model,
|
||||
manager: this.map.Manager.model,
|
||||
};
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AppXform.DateFormat = function(dt) {
|
||||
return dt.toISOString().replace(/[.]\d{3,6}/, '');
|
||||
};
|
||||
|
||||
AppXform.DateAttrs = {'xsi:type': 'dcterms:W3CDTF'};
|
||||
|
||||
AppXform.PROPERTY_ATTRIBUTES = {
|
||||
xmlns: 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties',
|
||||
'xmlns:vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
|
||||
};
|
||||
|
||||
module.exports = AppXform;
|
||||
120
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/content-types-xform.js
generated
vendored
Normal file
120
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/content-types-xform.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
const XmlStream = require('../../../utils/xml-stream');
|
||||
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
// used for rendering the [Content_Types].xml file
|
||||
// not used for parsing
|
||||
class ContentTypesXform extends BaseXform {
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openXml(XmlStream.StdDocAttributes);
|
||||
|
||||
xmlStream.openNode('Types', ContentTypesXform.PROPERTY_ATTRIBUTES);
|
||||
|
||||
const mediaHash = {};
|
||||
(model.media || []).forEach(medium => {
|
||||
if (medium.type === 'image') {
|
||||
const imageType = medium.extension;
|
||||
if (!mediaHash[imageType]) {
|
||||
mediaHash[imageType] = true;
|
||||
xmlStream.leafNode('Default', {Extension: imageType, ContentType: `image/${imageType}`});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
xmlStream.leafNode('Default', {
|
||||
Extension: 'rels',
|
||||
ContentType: 'application/vnd.openxmlformats-package.relationships+xml',
|
||||
});
|
||||
xmlStream.leafNode('Default', {Extension: 'xml', ContentType: 'application/xml'});
|
||||
|
||||
xmlStream.leafNode('Override', {
|
||||
PartName: '/xl/workbook.xml',
|
||||
ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml',
|
||||
});
|
||||
|
||||
model.worksheets.forEach(worksheet => {
|
||||
const name = `/xl/worksheets/sheet${worksheet.id}.xml`;
|
||||
xmlStream.leafNode('Override', {
|
||||
PartName: name,
|
||||
ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml',
|
||||
});
|
||||
});
|
||||
|
||||
xmlStream.leafNode('Override', {
|
||||
PartName: '/xl/theme/theme1.xml',
|
||||
ContentType: 'application/vnd.openxmlformats-officedocument.theme+xml',
|
||||
});
|
||||
xmlStream.leafNode('Override', {
|
||||
PartName: '/xl/styles.xml',
|
||||
ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml',
|
||||
});
|
||||
|
||||
const hasSharedStrings = model.sharedStrings && model.sharedStrings.count;
|
||||
if (hasSharedStrings) {
|
||||
xmlStream.leafNode('Override', {
|
||||
PartName: '/xl/sharedStrings.xml',
|
||||
ContentType:
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml',
|
||||
});
|
||||
}
|
||||
|
||||
if (model.tables) {
|
||||
model.tables.forEach(table => {
|
||||
xmlStream.leafNode('Override', {
|
||||
PartName: `/xl/tables/${table.target}`,
|
||||
ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (model.drawings) {
|
||||
model.drawings.forEach(drawing => {
|
||||
xmlStream.leafNode('Override', {
|
||||
PartName: `/xl/drawings/${drawing.name}.xml`,
|
||||
ContentType: 'application/vnd.openxmlformats-officedocument.drawing+xml',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (model.commentRefs) {
|
||||
xmlStream.leafNode('Default', {
|
||||
Extension: 'vml',
|
||||
ContentType: 'application/vnd.openxmlformats-officedocument.vmlDrawing',
|
||||
});
|
||||
|
||||
model.commentRefs.forEach(({commentName}) => {
|
||||
xmlStream.leafNode('Override', {
|
||||
PartName: `/xl/${commentName}.xml`,
|
||||
ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
xmlStream.leafNode('Override', {
|
||||
PartName: '/docProps/core.xml',
|
||||
ContentType: 'application/vnd.openxmlformats-package.core-properties+xml',
|
||||
});
|
||||
xmlStream.leafNode('Override', {
|
||||
PartName: '/docProps/app.xml',
|
||||
ContentType: 'application/vnd.openxmlformats-officedocument.extended-properties+xml',
|
||||
});
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen() {
|
||||
return false;
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ContentTypesXform.PROPERTY_ATTRIBUTES = {
|
||||
xmlns: 'http://schemas.openxmlformats.org/package/2006/content-types',
|
||||
};
|
||||
|
||||
module.exports = ContentTypesXform;
|
||||
136
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/core-xform.js
generated
vendored
Normal file
136
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/core-xform.js
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
const XmlStream = require('../../../utils/xml-stream');
|
||||
const BaseXform = require('../base-xform');
|
||||
const DateXform = require('../simple/date-xform');
|
||||
const StringXform = require('../simple/string-xform');
|
||||
const IntegerXform = require('../simple/integer-xform');
|
||||
|
||||
class CoreXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.map = {
|
||||
'dc:creator': new StringXform({tag: 'dc:creator'}),
|
||||
'dc:title': new StringXform({tag: 'dc:title'}),
|
||||
'dc:subject': new StringXform({tag: 'dc:subject'}),
|
||||
'dc:description': new StringXform({tag: 'dc:description'}),
|
||||
'dc:identifier': new StringXform({tag: 'dc:identifier'}),
|
||||
'dc:language': new StringXform({tag: 'dc:language'}),
|
||||
'cp:keywords': new StringXform({tag: 'cp:keywords'}),
|
||||
'cp:category': new StringXform({tag: 'cp:category'}),
|
||||
'cp:lastModifiedBy': new StringXform({tag: 'cp:lastModifiedBy'}),
|
||||
'cp:lastPrinted': new DateXform({tag: 'cp:lastPrinted', format: CoreXform.DateFormat}),
|
||||
'cp:revision': new IntegerXform({tag: 'cp:revision'}),
|
||||
'cp:version': new StringXform({tag: 'cp:version'}),
|
||||
'cp:contentStatus': new StringXform({tag: 'cp:contentStatus'}),
|
||||
'cp:contentType': new StringXform({tag: 'cp:contentType'}),
|
||||
'dcterms:created': new DateXform({
|
||||
tag: 'dcterms:created',
|
||||
attrs: CoreXform.DateAttrs,
|
||||
format: CoreXform.DateFormat,
|
||||
}),
|
||||
'dcterms:modified': new DateXform({
|
||||
tag: 'dcterms:modified',
|
||||
attrs: CoreXform.DateAttrs,
|
||||
format: CoreXform.DateFormat,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openXml(XmlStream.StdDocAttributes);
|
||||
|
||||
xmlStream.openNode('cp:coreProperties', CoreXform.CORE_PROPERTY_ATTRIBUTES);
|
||||
|
||||
this.map['dc:creator'].render(xmlStream, model.creator);
|
||||
this.map['dc:title'].render(xmlStream, model.title);
|
||||
this.map['dc:subject'].render(xmlStream, model.subject);
|
||||
this.map['dc:description'].render(xmlStream, model.description);
|
||||
this.map['dc:identifier'].render(xmlStream, model.identifier);
|
||||
this.map['dc:language'].render(xmlStream, model.language);
|
||||
this.map['cp:keywords'].render(xmlStream, model.keywords);
|
||||
this.map['cp:category'].render(xmlStream, model.category);
|
||||
this.map['cp:lastModifiedBy'].render(xmlStream, model.lastModifiedBy);
|
||||
this.map['cp:lastPrinted'].render(xmlStream, model.lastPrinted);
|
||||
this.map['cp:revision'].render(xmlStream, model.revision);
|
||||
this.map['cp:version'].render(xmlStream, model.version);
|
||||
this.map['cp:contentStatus'].render(xmlStream, model.contentStatus);
|
||||
this.map['cp:contentType'].render(xmlStream, model.contentType);
|
||||
this.map['dcterms:created'].render(xmlStream, model.created);
|
||||
this.map['dcterms:modified'].render(xmlStream, model.modified);
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case 'cp:coreProperties':
|
||||
case 'coreProperties':
|
||||
return true;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
throw new Error(`Unexpected xml node in parseOpen: ${JSON.stringify(node)}`);
|
||||
}
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case 'cp:coreProperties':
|
||||
case 'coreProperties':
|
||||
this.model = {
|
||||
creator: this.map['dc:creator'].model,
|
||||
title: this.map['dc:title'].model,
|
||||
subject: this.map['dc:subject'].model,
|
||||
description: this.map['dc:description'].model,
|
||||
identifier: this.map['dc:identifier'].model,
|
||||
language: this.map['dc:language'].model,
|
||||
keywords: this.map['cp:keywords'].model,
|
||||
category: this.map['cp:category'].model,
|
||||
lastModifiedBy: this.map['cp:lastModifiedBy'].model,
|
||||
lastPrinted: this.map['cp:lastPrinted'].model,
|
||||
revision: this.map['cp:revision'].model,
|
||||
contentStatus: this.map['cp:contentStatus'].model,
|
||||
contentType: this.map['cp:contentType'].model,
|
||||
created: this.map['dcterms:created'].model,
|
||||
modified: this.map['dcterms:modified'].model,
|
||||
};
|
||||
return false;
|
||||
default:
|
||||
throw new Error(`Unexpected xml node in parseClose: ${name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CoreXform.DateFormat = function(dt) {
|
||||
return dt.toISOString().replace(/[.]\d{3}/, '');
|
||||
};
|
||||
CoreXform.DateAttrs = {'xsi:type': 'dcterms:W3CDTF'};
|
||||
|
||||
CoreXform.CORE_PROPERTY_ATTRIBUTES = {
|
||||
'xmlns:cp': 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties',
|
||||
'xmlns:dc': 'http://purl.org/dc/elements/1.1/',
|
||||
'xmlns:dcterms': 'http://purl.org/dc/terms/',
|
||||
'xmlns:dcmitype': 'http://purl.org/dc/dcmitype/',
|
||||
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
};
|
||||
|
||||
module.exports = CoreXform;
|
||||
25
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/relationship-xform.js
generated
vendored
Normal file
25
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/relationship-xform.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class RelationshipXform extends BaseXform {
|
||||
render(xmlStream, model) {
|
||||
xmlStream.leafNode('Relationship', model);
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case 'Relationship':
|
||||
this.model = node.attributes;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RelationshipXform;
|
||||
73
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/relationships-xform.js
generated
vendored
Normal file
73
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/core/relationships-xform.js
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
const XmlStream = require('../../../utils/xml-stream');
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
const RelationshipXform = require('./relationship-xform');
|
||||
|
||||
class RelationshipsXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.map = {
|
||||
Relationship: new RelationshipXform(),
|
||||
};
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
model = model || this._values;
|
||||
xmlStream.openXml(XmlStream.StdDocAttributes);
|
||||
xmlStream.openNode('Relationships', RelationshipsXform.RELATIONSHIPS_ATTRIBUTES);
|
||||
|
||||
model.forEach(relationship => {
|
||||
this.map.Relationship.render(xmlStream, relationship);
|
||||
});
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case 'Relationships':
|
||||
this.model = [];
|
||||
return true;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
throw new Error(`Unexpected xml node in parseOpen: ${JSON.stringify(node)}`);
|
||||
}
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.model.push(this.parser.model);
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case 'Relationships':
|
||||
return false;
|
||||
default:
|
||||
throw new Error(`Unexpected xml node in parseClose: ${name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RelationshipsXform.RELATIONSHIPS_ATTRIBUTES = {
|
||||
xmlns: 'http://schemas.openxmlformats.org/package/2006/relationships',
|
||||
};
|
||||
|
||||
module.exports = RelationshipsXform;
|
||||
48
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/base-cell-anchor-xform.js
generated
vendored
Normal file
48
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/base-cell-anchor-xform.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class BaseCellAnchorXform extends BaseXform {
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.reset();
|
||||
this.model = {
|
||||
range: {
|
||||
editAs: node.attributes.editAs || 'oneCell',
|
||||
},
|
||||
};
|
||||
break;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
reconcilePicture(model, options) {
|
||||
if (model && model.rId) {
|
||||
const rel = options.rels[model.rId];
|
||||
const match = rel.Target.match(/.*\/media\/(.+[.][a-zA-Z]{3,4})/);
|
||||
if (match) {
|
||||
const name = match[1];
|
||||
const mediaId = options.mediaIndex[name];
|
||||
return options.media[mediaId];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseCellAnchorXform;
|
||||
71
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/blip-fill-xform.js
generated
vendored
Normal file
71
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/blip-fill-xform.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
const BlipXform = require('./blip-xform');
|
||||
|
||||
class BlipFillXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.map = {
|
||||
'a:blip': new BlipXform(),
|
||||
};
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return 'xdr:blipFill';
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openNode(this.tag);
|
||||
|
||||
this.map['a:blip'].render(xmlStream, model);
|
||||
|
||||
// TODO: options for this + parsing
|
||||
xmlStream.openNode('a:stretch');
|
||||
xmlStream.leafNode('a:fillRect');
|
||||
xmlStream.closeNode();
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.reset();
|
||||
break;
|
||||
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
this.model = this.map['a:blip'].model;
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BlipFillXform;
|
||||
42
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/blip-xform.js
generated
vendored
Normal file
42
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/blip-xform.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class BlipXform extends BaseXform {
|
||||
get tag() {
|
||||
return 'a:blip';
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.leafNode(this.tag, {
|
||||
'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
|
||||
'r:embed': model.rId,
|
||||
cstate: 'print',
|
||||
});
|
||||
// TODO: handle children (e.g. a:extLst=>a:ext=>a14:useLocalDpi
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.model = {
|
||||
rId: node.attributes['r:embed'],
|
||||
};
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose(name) {
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
return false;
|
||||
default:
|
||||
// unprocessed internal nodes
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BlipXform;
|
||||
38
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/c-nv-pic-pr-xform.js
generated
vendored
Normal file
38
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/c-nv-pic-pr-xform.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class CNvPicPrXform extends BaseXform {
|
||||
get tag() {
|
||||
return 'xdr:cNvPicPr';
|
||||
}
|
||||
|
||||
render(xmlStream) {
|
||||
xmlStream.openNode(this.tag);
|
||||
xmlStream.leafNode('a:picLocks', {
|
||||
noChangeAspect: '1',
|
||||
});
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose(name) {
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
return false;
|
||||
default:
|
||||
// unprocessed internal nodes
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CNvPicPrXform;
|
||||
68
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/c-nv-pr-xform.js
generated
vendored
Normal file
68
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/c-nv-pr-xform.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
const HlickClickXform = require('./hlink-click-xform');
|
||||
const ExtLstXform = require('./ext-lst-xform');
|
||||
|
||||
class CNvPrXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.map = {
|
||||
'a:hlinkClick': new HlickClickXform(),
|
||||
'a:extLst': new ExtLstXform(),
|
||||
};
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return 'xdr:cNvPr';
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openNode(this.tag, {
|
||||
id: model.index,
|
||||
name: `Picture ${model.index}`,
|
||||
});
|
||||
this.map['a:hlinkClick'].render(xmlStream, model);
|
||||
this.map['a:extLst'].render(xmlStream, model);
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.reset();
|
||||
break;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
this.model = this.map['a:hlinkClick'].model;
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CNvPrXform;
|
||||
77
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/cell-position-xform.js
generated
vendored
Normal file
77
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/cell-position-xform.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
const IntegerXform = require('../simple/integer-xform');
|
||||
|
||||
class CellPositionXform extends BaseXform {
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
this.tag = options.tag;
|
||||
this.map = {
|
||||
'xdr:col': new IntegerXform({tag: 'xdr:col', zero: true}),
|
||||
'xdr:colOff': new IntegerXform({tag: 'xdr:colOff', zero: true}),
|
||||
'xdr:row': new IntegerXform({tag: 'xdr:row', zero: true}),
|
||||
'xdr:rowOff': new IntegerXform({tag: 'xdr:rowOff', zero: true}),
|
||||
};
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openNode(this.tag);
|
||||
|
||||
this.map['xdr:col'].render(xmlStream, model.nativeCol);
|
||||
this.map['xdr:colOff'].render(xmlStream, model.nativeColOff);
|
||||
|
||||
this.map['xdr:row'].render(xmlStream, model.nativeRow);
|
||||
this.map['xdr:rowOff'].render(xmlStream, model.nativeRowOff);
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.reset();
|
||||
break;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
this.model = {
|
||||
nativeCol: this.map['xdr:col'].model,
|
||||
nativeColOff: this.map['xdr:colOff'].model,
|
||||
nativeRow: this.map['xdr:row'].model,
|
||||
nativeRowOff: this.map['xdr:rowOff'].model,
|
||||
};
|
||||
return false;
|
||||
default:
|
||||
// not quite sure how we get here!
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CellPositionXform;
|
||||
109
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/drawing-xform.js
generated
vendored
Normal file
109
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/drawing-xform.js
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
const colCache = require('../../../utils/col-cache');
|
||||
const XmlStream = require('../../../utils/xml-stream');
|
||||
|
||||
const BaseXform = require('../base-xform');
|
||||
const TwoCellAnchorXform = require('./two-cell-anchor-xform');
|
||||
const OneCellAnchorXform = require('./one-cell-anchor-xform');
|
||||
|
||||
function getAnchorType(model) {
|
||||
const range = typeof model.range === 'string' ? colCache.decode(model.range) : model.range;
|
||||
|
||||
return range.br ? 'xdr:twoCellAnchor' : 'xdr:oneCellAnchor';
|
||||
}
|
||||
|
||||
class DrawingXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.map = {
|
||||
'xdr:twoCellAnchor': new TwoCellAnchorXform(),
|
||||
'xdr:oneCellAnchor': new OneCellAnchorXform(),
|
||||
};
|
||||
}
|
||||
|
||||
prepare(model) {
|
||||
model.anchors.forEach((item, index) => {
|
||||
item.anchorType = getAnchorType(item);
|
||||
const anchor = this.map[item.anchorType];
|
||||
anchor.prepare(item, {index});
|
||||
});
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return 'xdr:wsDr';
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openXml(XmlStream.StdDocAttributes);
|
||||
xmlStream.openNode(this.tag, DrawingXform.DRAWING_ATTRIBUTES);
|
||||
|
||||
model.anchors.forEach(item => {
|
||||
const anchor = this.map[item.anchorType];
|
||||
anchor.render(xmlStream, item);
|
||||
});
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.reset();
|
||||
this.model = {
|
||||
anchors: [],
|
||||
};
|
||||
break;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
parseText(text) {
|
||||
if (this.parser) {
|
||||
this.parser.parseText(text);
|
||||
}
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.model.anchors.push(this.parser.model);
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
return false;
|
||||
default:
|
||||
// could be some unrecognised tags
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
reconcile(model, options) {
|
||||
model.anchors.forEach(anchor => {
|
||||
if (anchor.br) {
|
||||
this.map['xdr:twoCellAnchor'].reconcile(anchor, options);
|
||||
} else {
|
||||
this.map['xdr:oneCellAnchor'].reconcile(anchor, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DrawingXform.DRAWING_ATTRIBUTES = {
|
||||
'xmlns:xdr': 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing',
|
||||
'xmlns:a': 'http://schemas.openxmlformats.org/drawingml/2006/main',
|
||||
};
|
||||
|
||||
module.exports = DrawingXform;
|
||||
43
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/ext-lst-xform.js
generated
vendored
Normal file
43
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/ext-lst-xform.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class ExtLstXform extends BaseXform {
|
||||
get tag() {
|
||||
return 'a:extLst';
|
||||
}
|
||||
|
||||
render(xmlStream) {
|
||||
xmlStream.openNode(this.tag);
|
||||
xmlStream.openNode('a:ext', {
|
||||
uri: '{FF2B5EF4-FFF2-40B4-BE49-F238E27FC236}',
|
||||
});
|
||||
xmlStream.leafNode('a16:creationId', {
|
||||
'xmlns:a16': 'http://schemas.microsoft.com/office/drawing/2014/main',
|
||||
id: '{00000000-0008-0000-0000-000002000000}',
|
||||
});
|
||||
xmlStream.closeNode();
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose(name) {
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
return false;
|
||||
default:
|
||||
// unprocessed internal nodes
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ExtLstXform;
|
||||
44
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/ext-xform.js
generated
vendored
Normal file
44
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/ext-xform.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
/** https://en.wikipedia.org/wiki/Office_Open_XML_file_formats#DrawingML */
|
||||
const EMU_PER_PIXEL_AT_96_DPI = 9525;
|
||||
|
||||
class ExtXform extends BaseXform {
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
this.tag = options.tag;
|
||||
this.map = {};
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openNode(this.tag);
|
||||
|
||||
const width = Math.floor(model.width * EMU_PER_PIXEL_AT_96_DPI);
|
||||
const height = Math.floor(model.height * EMU_PER_PIXEL_AT_96_DPI);
|
||||
|
||||
xmlStream.addAttribute('cx', width);
|
||||
xmlStream.addAttribute('cy', height);
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (node.name === this.tag) {
|
||||
this.model = {
|
||||
width: parseInt(node.attributes.cx || '0', 10) / EMU_PER_PIXEL_AT_96_DPI,
|
||||
height: parseInt(node.attributes.cy || '0', 10) / EMU_PER_PIXEL_AT_96_DPI,
|
||||
};
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
parseText(/* text */) {}
|
||||
|
||||
parseClose(/* name */) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ExtXform;
|
||||
41
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/hlink-click-xform.js
generated
vendored
Normal file
41
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/hlink-click-xform.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
|
||||
class HLinkClickXform extends BaseXform {
|
||||
get tag() {
|
||||
return 'a:hlinkClick';
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
if (!(model.hyperlinks && model.hyperlinks.rId)) {
|
||||
return;
|
||||
}
|
||||
xmlStream.leafNode(this.tag, {
|
||||
'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
|
||||
'r:id': model.hyperlinks.rId,
|
||||
tooltip: model.hyperlinks.tooltip,
|
||||
});
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.model = {
|
||||
hyperlinks: {
|
||||
rId: node.attributes['r:id'],
|
||||
tooltip: node.attributes.tooltip,
|
||||
},
|
||||
};
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = HLinkClickXform;
|
||||
65
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/nv-pic-pr-xform.js
generated
vendored
Normal file
65
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/nv-pic-pr-xform.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
const CNvPrXform = require('./c-nv-pr-xform');
|
||||
const CNvPicPrXform = require('./c-nv-pic-pr-xform');
|
||||
|
||||
class NvPicPrXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.map = {
|
||||
'xdr:cNvPr': new CNvPrXform(),
|
||||
'xdr:cNvPicPr': new CNvPicPrXform(),
|
||||
};
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return 'xdr:nvPicPr';
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openNode(this.tag);
|
||||
this.map['xdr:cNvPr'].render(xmlStream, model);
|
||||
this.map['xdr:cNvPicPr'].render(xmlStream, model);
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.reset();
|
||||
break;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
this.model = this.map['xdr:cNvPr'].model;
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NvPicPrXform;
|
||||
63
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/one-cell-anchor-xform.js
generated
vendored
Normal file
63
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/one-cell-anchor-xform.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
const BaseCellAnchorXform = require('./base-cell-anchor-xform');
|
||||
const StaticXform = require('../static-xform');
|
||||
|
||||
const CellPositionXform = require('./cell-position-xform');
|
||||
const ExtXform = require('./ext-xform');
|
||||
const PicXform = require('./pic-xform');
|
||||
|
||||
class OneCellAnchorXform extends BaseCellAnchorXform {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.map = {
|
||||
'xdr:from': new CellPositionXform({tag: 'xdr:from'}),
|
||||
'xdr:ext': new ExtXform({tag: 'xdr:ext'}),
|
||||
'xdr:pic': new PicXform(),
|
||||
'xdr:clientData': new StaticXform({tag: 'xdr:clientData'}),
|
||||
};
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return 'xdr:oneCellAnchor';
|
||||
}
|
||||
|
||||
prepare(model, options) {
|
||||
this.map['xdr:pic'].prepare(model.picture, options);
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openNode(this.tag, {editAs: model.range.editAs || 'oneCell'});
|
||||
|
||||
this.map['xdr:from'].render(xmlStream, model.range.tl);
|
||||
this.map['xdr:ext'].render(xmlStream, model.range.ext);
|
||||
this.map['xdr:pic'].render(xmlStream, model.picture);
|
||||
this.map['xdr:clientData'].render(xmlStream, {});
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
this.model.range.tl = this.map['xdr:from'].model;
|
||||
this.model.range.ext = this.map['xdr:ext'].model;
|
||||
this.model.picture = this.map['xdr:pic'].model;
|
||||
return false;
|
||||
default:
|
||||
// could be some unrecognised tags
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
reconcile(model, options) {
|
||||
model.medium = this.reconcilePicture(model.picture, options);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = OneCellAnchorXform;
|
||||
77
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/pic-xform.js
generated
vendored
Normal file
77
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/pic-xform.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
const BaseXform = require('../base-xform');
|
||||
const StaticXform = require('../static-xform');
|
||||
|
||||
const BlipFillXform = require('./blip-fill-xform');
|
||||
const NvPicPrXform = require('./nv-pic-pr-xform');
|
||||
|
||||
const spPrJSON = require('./sp-pr');
|
||||
|
||||
class PicXform extends BaseXform {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.map = {
|
||||
'xdr:nvPicPr': new NvPicPrXform(),
|
||||
'xdr:blipFill': new BlipFillXform(),
|
||||
'xdr:spPr': new StaticXform(spPrJSON),
|
||||
};
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return 'xdr:pic';
|
||||
}
|
||||
|
||||
prepare(model, options) {
|
||||
model.index = options.index + 1;
|
||||
}
|
||||
|
||||
render(xmlStream, model) {
|
||||
xmlStream.openNode(this.tag);
|
||||
|
||||
this.map['xdr:nvPicPr'].render(xmlStream, model);
|
||||
this.map['xdr:blipFill'].render(xmlStream, model);
|
||||
this.map['xdr:spPr'].render(xmlStream, model);
|
||||
|
||||
xmlStream.closeNode();
|
||||
}
|
||||
|
||||
parseOpen(node) {
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
return true;
|
||||
}
|
||||
switch (node.name) {
|
||||
case this.tag:
|
||||
this.reset();
|
||||
break;
|
||||
default:
|
||||
this.parser = this.map[node.name];
|
||||
if (this.parser) {
|
||||
this.parser.parseOpen(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
parseText() {}
|
||||
|
||||
parseClose(name) {
|
||||
if (this.parser) {
|
||||
if (!this.parser.parseClose(name)) {
|
||||
this.mergeModel(this.parser.model);
|
||||
this.parser = undefined;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
switch (name) {
|
||||
case this.tag:
|
||||
return false;
|
||||
default:
|
||||
// not quite sure how we get here!
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PicXform;
|
||||
17
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/sp-pr.js
generated
vendored
Normal file
17
doc/test-data/purchase_transaction/node_modules/exceljs/lib/xlsx/xform/drawing/sp-pr.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
tag: 'xdr:spPr',
|
||||
c: [
|
||||
{
|
||||
tag: 'a:xfrm',
|
||||
c: [
|
||||
{tag: 'a:off', $: {x: '0', y: '0'}},
|
||||
{tag: 'a:ext', $: {cx: '0', cy: '0'}},
|
||||
],
|
||||
},
|
||||
{
|
||||
tag: 'a:prstGeom',
|
||||
$: {prst: 'rect'},
|
||||
c: [{tag: 'a:avLst'}],
|
||||
},
|
||||
],
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user