You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					718 lines
				
				21 KiB
			
		
		
			
		
	
	
					718 lines
				
				21 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								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;
							 |