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.
		
		
		
		
		
			
		
			
				
					
					
						
							314 lines
						
					
					
						
							6.8 KiB
						
					
					
				
			
		
		
	
	
							314 lines
						
					
					
						
							6.8 KiB
						
					
					
				| '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;
 | |
|     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;
 |