column.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. 'use strict';
  2. const _ = require('../utils/under-dash');
  3. const Enums = require('./enums');
  4. const colCache = require('../utils/col-cache');
  5. const DEFAULT_COLUMN_WIDTH = 9;
  6. // Column defines the column properties for 1 column.
  7. // This includes header rows, widths, key, (style), etc.
  8. // Worksheet will condense the columns as appropriate during serialization
  9. class Column {
  10. constructor(worksheet, number, defn) {
  11. this._worksheet = worksheet;
  12. this._number = number;
  13. if (defn !== false) {
  14. // sometimes defn will follow
  15. this.defn = defn;
  16. }
  17. }
  18. get number() {
  19. return this._number;
  20. }
  21. get worksheet() {
  22. return this._worksheet;
  23. }
  24. get letter() {
  25. return colCache.n2l(this._number);
  26. }
  27. get isCustomWidth() {
  28. return this.width !== undefined && this.width !== DEFAULT_COLUMN_WIDTH;
  29. }
  30. get defn() {
  31. return {
  32. header: this._header,
  33. key: this.key,
  34. width: this.width,
  35. style: this.style,
  36. hidden: this.hidden,
  37. outlineLevel: this.outlineLevel
  38. };
  39. }
  40. set defn(value) {
  41. if (value) {
  42. this.key = value.key;
  43. this.width = value.width !== undefined ? value.width : DEFAULT_COLUMN_WIDTH;
  44. this.outlineLevel = value.outlineLevel;
  45. if (value.style) {
  46. this.style = value.style;
  47. } else {
  48. this.style = {};
  49. }
  50. // headers must be set after style
  51. this.header = value.header;
  52. this._hidden = !!value.hidden;
  53. } else {
  54. delete this._header;
  55. delete this._key;
  56. delete this.width;
  57. this.style = {};
  58. this.outlineLevel = 0;
  59. }
  60. }
  61. get headers() {
  62. return this._header && this._header instanceof Array ? this._header : [this._header];
  63. }
  64. get header() {
  65. return this._header;
  66. }
  67. set header(value) {
  68. if (value !== undefined) {
  69. this._header = value;
  70. this.headers.forEach((text, index) => {
  71. this._worksheet.getCell(index + 1, this.number).value = text;
  72. });
  73. } else {
  74. this._header = undefined;
  75. }
  76. }
  77. get key() {
  78. return this._key;
  79. }
  80. set key(value) {
  81. const column = this._key && this._worksheet.getColumnKey(this._key);
  82. if (column === this) {
  83. this._worksheet.deleteColumnKey(this._key);
  84. }
  85. this._key = value;
  86. if (value) {
  87. this._worksheet.setColumnKey(this._key, this);
  88. }
  89. }
  90. get hidden() {
  91. return !!this._hidden;
  92. }
  93. set hidden(value) {
  94. this._hidden = value;
  95. }
  96. get outlineLevel() {
  97. return this._outlineLevel || 0;
  98. }
  99. set outlineLevel(value) {
  100. this._outlineLevel = value;
  101. }
  102. get collapsed() {
  103. return !!(this._outlineLevel && this._outlineLevel >= this._worksheet.properties.outlineLevelCol);
  104. }
  105. toString() {
  106. return JSON.stringify({
  107. key: this.key,
  108. width: this.width,
  109. headers: this.headers.length ? this.headers : undefined
  110. });
  111. }
  112. equivalentTo(other) {
  113. return this.width === other.width && this.hidden === other.hidden && this.outlineLevel === other.outlineLevel && _.isEqual(this.style, other.style);
  114. }
  115. get isDefault() {
  116. if (this.isCustomWidth) {
  117. return false;
  118. }
  119. if (this.hidden) {
  120. return false;
  121. }
  122. if (this.outlineLevel) {
  123. return false;
  124. }
  125. const s = this.style;
  126. if (s && (s.font || s.numFmt || s.alignment || s.border || s.fill || s.protection)) {
  127. return false;
  128. }
  129. return true;
  130. }
  131. get headerCount() {
  132. return this.headers.length;
  133. }
  134. eachCell(options, iteratee) {
  135. const colNumber = this.number;
  136. if (!iteratee) {
  137. iteratee = options;
  138. options = null;
  139. }
  140. this._worksheet.eachRow(options, (row, rowNumber) => {
  141. iteratee(row.getCell(colNumber), rowNumber);
  142. });
  143. }
  144. get values() {
  145. const v = [];
  146. this.eachCell((cell, rowNumber) => {
  147. if (cell && cell.type !== Enums.ValueType.Null) {
  148. v[rowNumber] = cell.value;
  149. }
  150. });
  151. return v;
  152. }
  153. set values(v) {
  154. if (!v) {
  155. return;
  156. }
  157. const colNumber = this.number;
  158. let offset = 0;
  159. if (v.hasOwnProperty('0')) {
  160. // assume contiguous array, start at row 1
  161. offset = 1;
  162. }
  163. v.forEach((value, index) => {
  164. this._worksheet.getCell(index + offset, colNumber).value = value;
  165. });
  166. }
  167. // =========================================================================
  168. // styles
  169. _applyStyle(name, value) {
  170. this.style[name] = value;
  171. this.eachCell(cell => {
  172. cell[name] = value;
  173. });
  174. return value;
  175. }
  176. get numFmt() {
  177. return this.style.numFmt;
  178. }
  179. set numFmt(value) {
  180. this._applyStyle('numFmt', value);
  181. }
  182. get font() {
  183. return this.style.font;
  184. }
  185. set font(value) {
  186. this._applyStyle('font', value);
  187. }
  188. get alignment() {
  189. return this.style.alignment;
  190. }
  191. set alignment(value) {
  192. this._applyStyle('alignment', value);
  193. }
  194. get protection() {
  195. return this.style.protection;
  196. }
  197. set protection(value) {
  198. this._applyStyle('protection', value);
  199. }
  200. get border() {
  201. return this.style.border;
  202. }
  203. set border(value) {
  204. this._applyStyle('border', value);
  205. }
  206. get fill() {
  207. return this.style.fill;
  208. }
  209. set fill(value) {
  210. this._applyStyle('fill', value);
  211. }
  212. // =============================================================================
  213. // static functions
  214. static toModel(columns) {
  215. // Convert array of Column into compressed list cols
  216. const cols = [];
  217. let col = null;
  218. if (columns) {
  219. columns.forEach((column, index) => {
  220. if (column.isDefault) {
  221. if (col) {
  222. col = null;
  223. }
  224. } else if (!col || !column.equivalentTo(col)) {
  225. col = {
  226. min: index + 1,
  227. max: index + 1,
  228. width: column.width !== undefined ? column.width : DEFAULT_COLUMN_WIDTH,
  229. style: column.style,
  230. isCustomWidth: column.isCustomWidth,
  231. hidden: column.hidden,
  232. outlineLevel: column.outlineLevel,
  233. collapsed: column.collapsed
  234. };
  235. cols.push(col);
  236. } else {
  237. col.max = index + 1;
  238. }
  239. });
  240. }
  241. return cols.length ? cols : undefined;
  242. }
  243. static fromModel(worksheet, cols) {
  244. cols = cols || [];
  245. const columns = [];
  246. let count = 1;
  247. let index = 0;
  248. /**
  249. * sort cols by min
  250. * If it is not sorted, the subsequent column configuration will be overwritten
  251. * */
  252. cols = cols.sort(function (pre, next) {
  253. return pre.min - next.min;
  254. });
  255. while (index < cols.length) {
  256. const col = cols[index++];
  257. while (count < col.min) {
  258. columns.push(new Column(worksheet, count++));
  259. }
  260. while (count <= col.max) {
  261. columns.push(new Column(worksheet, count++, col));
  262. }
  263. }
  264. return columns.length ? columns : null;
  265. }
  266. }
  267. module.exports = Column;
  268. //# sourceMappingURL=column.js.map