cell.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. "use strict";
  2. /* eslint-disable max-classes-per-file */
  3. const colCache = require('../utils/col-cache');
  4. const _ = require('../utils/under-dash');
  5. const Enums = require('./enums');
  6. const {
  7. slideFormula
  8. } = require('../utils/shared-formula');
  9. const Note = require('./note');
  10. // Cell requirements
  11. // Operate inside a worksheet
  12. // Store and retrieve a value with a range of types: text, number, date, hyperlink, reference, formula, etc.
  13. // Manage/use and manipulate cell format either as local to cell or inherited from column or row.
  14. class Cell {
  15. constructor(row, column, address) {
  16. if (!row || !column) {
  17. throw new Error('A Cell needs a Row');
  18. }
  19. this._row = row;
  20. this._column = column;
  21. colCache.validateAddress(address);
  22. this._address = address;
  23. // TODO: lazy evaluation of this._value
  24. this._value = Value.create(Cell.Types.Null, this);
  25. this.style = this._mergeStyle(row.style, column.style, {});
  26. this._mergeCount = 0;
  27. }
  28. get worksheet() {
  29. return this._row.worksheet;
  30. }
  31. get workbook() {
  32. return this._row.worksheet.workbook;
  33. }
  34. // help GC by removing cyclic (and other) references
  35. destroy() {
  36. delete this.style;
  37. delete this._value;
  38. delete this._row;
  39. delete this._column;
  40. delete this._address;
  41. }
  42. // =========================================================================
  43. // Styles stuff
  44. get numFmt() {
  45. return this.style.numFmt;
  46. }
  47. set numFmt(value) {
  48. this.style.numFmt = value;
  49. }
  50. get font() {
  51. return this.style.font;
  52. }
  53. set font(value) {
  54. this.style.font = value;
  55. }
  56. get alignment() {
  57. return this.style.alignment;
  58. }
  59. set alignment(value) {
  60. this.style.alignment = value;
  61. }
  62. get border() {
  63. return this.style.border;
  64. }
  65. set border(value) {
  66. this.style.border = value;
  67. }
  68. get fill() {
  69. return this.style.fill;
  70. }
  71. set fill(value) {
  72. this.style.fill = value;
  73. }
  74. get protection() {
  75. return this.style.protection;
  76. }
  77. set protection(value) {
  78. this.style.protection = value;
  79. }
  80. _mergeStyle(rowStyle, colStyle, style) {
  81. const numFmt = rowStyle && rowStyle.numFmt || colStyle && colStyle.numFmt;
  82. if (numFmt) style.numFmt = numFmt;
  83. const font = rowStyle && rowStyle.font || colStyle && colStyle.font;
  84. if (font) style.font = font;
  85. const alignment = rowStyle && rowStyle.alignment || colStyle && colStyle.alignment;
  86. if (alignment) style.alignment = alignment;
  87. const border = rowStyle && rowStyle.border || colStyle && colStyle.border;
  88. if (border) style.border = border;
  89. const fill = rowStyle && rowStyle.fill || colStyle && colStyle.fill;
  90. if (fill) style.fill = fill;
  91. const protection = rowStyle && rowStyle.protection || colStyle && colStyle.protection;
  92. if (protection) style.protection = protection;
  93. return style;
  94. }
  95. // =========================================================================
  96. // return the address for this cell
  97. get address() {
  98. return this._address;
  99. }
  100. get row() {
  101. return this._row.number;
  102. }
  103. get col() {
  104. return this._column.number;
  105. }
  106. get $col$row() {
  107. return `$${this._column.letter}$${this.row}`;
  108. }
  109. // =========================================================================
  110. // Value stuff
  111. get type() {
  112. return this._value.type;
  113. }
  114. get effectiveType() {
  115. return this._value.effectiveType;
  116. }
  117. toCsvString() {
  118. return this._value.toCsvString();
  119. }
  120. // =========================================================================
  121. // Merge stuff
  122. addMergeRef() {
  123. this._mergeCount++;
  124. }
  125. releaseMergeRef() {
  126. this._mergeCount--;
  127. }
  128. get isMerged() {
  129. return this._mergeCount > 0 || this.type === Cell.Types.Merge;
  130. }
  131. merge(master, ignoreStyle) {
  132. this._value.release();
  133. this._value = Value.create(Cell.Types.Merge, this, master);
  134. if (!ignoreStyle) {
  135. this.style = master.style;
  136. }
  137. }
  138. unmerge() {
  139. if (this.type === Cell.Types.Merge) {
  140. this._value.release();
  141. this._value = Value.create(Cell.Types.Null, this);
  142. this.style = this._mergeStyle(this._row.style, this._column.style, {});
  143. }
  144. }
  145. isMergedTo(master) {
  146. if (this._value.type !== Cell.Types.Merge) return false;
  147. return this._value.isMergedTo(master);
  148. }
  149. get master() {
  150. if (this.type === Cell.Types.Merge) {
  151. return this._value.master;
  152. }
  153. return this; // an unmerged cell is its own master
  154. }
  155. get isHyperlink() {
  156. return this._value.type === Cell.Types.Hyperlink;
  157. }
  158. get hyperlink() {
  159. return this._value.hyperlink;
  160. }
  161. // return the value
  162. get value() {
  163. return this._value.value;
  164. }
  165. // set the value - can be number, string or raw
  166. set value(v) {
  167. // special case - merge cells set their master's value
  168. if (this.type === Cell.Types.Merge) {
  169. this._value.master.value = v;
  170. return;
  171. }
  172. this._value.release();
  173. // assign value
  174. this._value = Value.create(Value.getType(v), this, v);
  175. }
  176. get note() {
  177. return this._comment && this._comment.note;
  178. }
  179. set note(note) {
  180. this._comment = new Note(note);
  181. }
  182. get text() {
  183. return this._value.toString();
  184. }
  185. get html() {
  186. return _.escapeHtml(this.text);
  187. }
  188. toString() {
  189. return this.text;
  190. }
  191. _upgradeToHyperlink(hyperlink) {
  192. // if this cell is a string, turn it into a Hyperlink
  193. if (this.type === Cell.Types.String) {
  194. this._value = Value.create(Cell.Types.Hyperlink, this, {
  195. text: this._value.value,
  196. hyperlink
  197. });
  198. }
  199. }
  200. // =========================================================================
  201. // Formula stuff
  202. get formula() {
  203. return this._value.formula;
  204. }
  205. get result() {
  206. return this._value.result;
  207. }
  208. get formulaType() {
  209. return this._value.formulaType;
  210. }
  211. // =========================================================================
  212. // Name stuff
  213. get fullAddress() {
  214. const {
  215. worksheet
  216. } = this._row;
  217. return {
  218. sheetName: worksheet.name,
  219. address: this.address,
  220. row: this.row,
  221. col: this.col
  222. };
  223. }
  224. get name() {
  225. return this.names[0];
  226. }
  227. set name(value) {
  228. this.names = [value];
  229. }
  230. get names() {
  231. return this.workbook.definedNames.getNamesEx(this.fullAddress);
  232. }
  233. set names(value) {
  234. const {
  235. definedNames
  236. } = this.workbook;
  237. definedNames.removeAllNames(this.fullAddress);
  238. value.forEach(name => {
  239. definedNames.addEx(this.fullAddress, name);
  240. });
  241. }
  242. addName(name) {
  243. this.workbook.definedNames.addEx(this.fullAddress, name);
  244. }
  245. removeName(name) {
  246. this.workbook.definedNames.removeEx(this.fullAddress, name);
  247. }
  248. removeAllNames() {
  249. this.workbook.definedNames.removeAllNames(this.fullAddress);
  250. }
  251. // =========================================================================
  252. // Data Validation stuff
  253. get _dataValidations() {
  254. return this.worksheet.dataValidations;
  255. }
  256. get dataValidation() {
  257. return this._dataValidations.find(this.address);
  258. }
  259. set dataValidation(value) {
  260. this._dataValidations.add(this.address, value);
  261. }
  262. // =========================================================================
  263. // Model stuff
  264. get model() {
  265. const {
  266. model
  267. } = this._value;
  268. model.style = this.style;
  269. if (this._comment) {
  270. model.comment = this._comment.model;
  271. }
  272. return model;
  273. }
  274. set model(value) {
  275. this._value.release();
  276. this._value = Value.create(value.type, this);
  277. this._value.model = value;
  278. if (value.comment) {
  279. switch (value.comment.type) {
  280. case 'note':
  281. this._comment = Note.fromModel(value.comment);
  282. break;
  283. }
  284. }
  285. if (value.style) {
  286. this.style = value.style;
  287. } else {
  288. this.style = {};
  289. }
  290. }
  291. }
  292. Cell.Types = Enums.ValueType;
  293. // =============================================================================
  294. // Internal Value Types
  295. class NullValue {
  296. constructor(cell) {
  297. this.model = {
  298. address: cell.address,
  299. type: Cell.Types.Null
  300. };
  301. }
  302. get value() {
  303. return null;
  304. }
  305. set value(value) {
  306. // nothing to do
  307. }
  308. get type() {
  309. return Cell.Types.Null;
  310. }
  311. get effectiveType() {
  312. return Cell.Types.Null;
  313. }
  314. get address() {
  315. return this.model.address;
  316. }
  317. set address(value) {
  318. this.model.address = value;
  319. }
  320. toCsvString() {
  321. return '';
  322. }
  323. release() {}
  324. toString() {
  325. return '';
  326. }
  327. }
  328. class NumberValue {
  329. constructor(cell, value) {
  330. this.model = {
  331. address: cell.address,
  332. type: Cell.Types.Number,
  333. value
  334. };
  335. }
  336. get value() {
  337. return this.model.value;
  338. }
  339. set value(value) {
  340. this.model.value = value;
  341. }
  342. get type() {
  343. return Cell.Types.Number;
  344. }
  345. get effectiveType() {
  346. return Cell.Types.Number;
  347. }
  348. get address() {
  349. return this.model.address;
  350. }
  351. set address(value) {
  352. this.model.address = value;
  353. }
  354. toCsvString() {
  355. return this.model.value.toString();
  356. }
  357. release() {}
  358. toString() {
  359. return this.model.value.toString();
  360. }
  361. }
  362. class StringValue {
  363. constructor(cell, value) {
  364. this.model = {
  365. address: cell.address,
  366. type: Cell.Types.String,
  367. value
  368. };
  369. }
  370. get value() {
  371. return this.model.value;
  372. }
  373. set value(value) {
  374. this.model.value = value;
  375. }
  376. get type() {
  377. return Cell.Types.String;
  378. }
  379. get effectiveType() {
  380. return Cell.Types.String;
  381. }
  382. get address() {
  383. return this.model.address;
  384. }
  385. set address(value) {
  386. this.model.address = value;
  387. }
  388. toCsvString() {
  389. return `"${this.model.value.replace(/"/g, '""')}"`;
  390. }
  391. release() {}
  392. toString() {
  393. return this.model.value;
  394. }
  395. }
  396. class RichTextValue {
  397. constructor(cell, value) {
  398. this.model = {
  399. address: cell.address,
  400. type: Cell.Types.String,
  401. value
  402. };
  403. }
  404. get value() {
  405. return this.model.value;
  406. }
  407. set value(value) {
  408. this.model.value = value;
  409. }
  410. toString() {
  411. return this.model.value.richText.map(t => t.text).join('');
  412. }
  413. get type() {
  414. return Cell.Types.RichText;
  415. }
  416. get effectiveType() {
  417. return Cell.Types.RichText;
  418. }
  419. get address() {
  420. return this.model.address;
  421. }
  422. set address(value) {
  423. this.model.address = value;
  424. }
  425. toCsvString() {
  426. return `"${this.text.replace(/"/g, '""')}"`;
  427. }
  428. release() {}
  429. }
  430. class DateValue {
  431. constructor(cell, value) {
  432. this.model = {
  433. address: cell.address,
  434. type: Cell.Types.Date,
  435. value
  436. };
  437. }
  438. get value() {
  439. return this.model.value;
  440. }
  441. set value(value) {
  442. this.model.value = value;
  443. }
  444. get type() {
  445. return Cell.Types.Date;
  446. }
  447. get effectiveType() {
  448. return Cell.Types.Date;
  449. }
  450. get address() {
  451. return this.model.address;
  452. }
  453. set address(value) {
  454. this.model.address = value;
  455. }
  456. toCsvString() {
  457. return this.model.value.toISOString();
  458. }
  459. release() {}
  460. toString() {
  461. return this.model.value.toString();
  462. }
  463. }
  464. class HyperlinkValue {
  465. constructor(cell, value) {
  466. this.model = {
  467. address: cell.address,
  468. type: Cell.Types.Hyperlink,
  469. text: value ? value.text : undefined,
  470. hyperlink: value ? value.hyperlink : undefined
  471. };
  472. if (value && value.tooltip) {
  473. this.model.tooltip = value.tooltip;
  474. }
  475. }
  476. get value() {
  477. const v = {
  478. text: this.model.text,
  479. hyperlink: this.model.hyperlink
  480. };
  481. if (this.model.tooltip) {
  482. v.tooltip = this.model.tooltip;
  483. }
  484. return v;
  485. }
  486. set value(value) {
  487. this.model = {
  488. text: value.text,
  489. hyperlink: value.hyperlink
  490. };
  491. if (value.tooltip) {
  492. this.model.tooltip = value.tooltip;
  493. }
  494. }
  495. get text() {
  496. return this.model.text;
  497. }
  498. set text(value) {
  499. this.model.text = value;
  500. }
  501. /*
  502. get tooltip() {
  503. return this.model.tooltip;
  504. }
  505. set tooltip(value) {
  506. this.model.tooltip = value;
  507. } */
  508. get hyperlink() {
  509. return this.model.hyperlink;
  510. }
  511. set hyperlink(value) {
  512. this.model.hyperlink = value;
  513. }
  514. get type() {
  515. return Cell.Types.Hyperlink;
  516. }
  517. get effectiveType() {
  518. return Cell.Types.Hyperlink;
  519. }
  520. get address() {
  521. return this.model.address;
  522. }
  523. set address(value) {
  524. this.model.address = value;
  525. }
  526. toCsvString() {
  527. return this.model.hyperlink;
  528. }
  529. release() {}
  530. toString() {
  531. return this.model.text;
  532. }
  533. }
  534. class MergeValue {
  535. constructor(cell, master) {
  536. this.model = {
  537. address: cell.address,
  538. type: Cell.Types.Merge,
  539. master: master ? master.address : undefined
  540. };
  541. this._master = master;
  542. if (master) {
  543. master.addMergeRef();
  544. }
  545. }
  546. get value() {
  547. return this._master.value;
  548. }
  549. set value(value) {
  550. if (value instanceof Cell) {
  551. if (this._master) {
  552. this._master.releaseMergeRef();
  553. }
  554. value.addMergeRef();
  555. this._master = value;
  556. } else {
  557. this._master.value = value;
  558. }
  559. }
  560. isMergedTo(master) {
  561. return master === this._master;
  562. }
  563. get master() {
  564. return this._master;
  565. }
  566. get type() {
  567. return Cell.Types.Merge;
  568. }
  569. get effectiveType() {
  570. return this._master.effectiveType;
  571. }
  572. get address() {
  573. return this.model.address;
  574. }
  575. set address(value) {
  576. this.model.address = value;
  577. }
  578. toCsvString() {
  579. return '';
  580. }
  581. release() {
  582. this._master.releaseMergeRef();
  583. }
  584. toString() {
  585. return this.value.toString();
  586. }
  587. }
  588. class FormulaValue {
  589. constructor(cell, value) {
  590. this.cell = cell;
  591. this.model = {
  592. address: cell.address,
  593. type: Cell.Types.Formula,
  594. shareType: value ? value.shareType : undefined,
  595. ref: value ? value.ref : undefined,
  596. formula: value ? value.formula : undefined,
  597. sharedFormula: value ? value.sharedFormula : undefined,
  598. result: value ? value.result : undefined
  599. };
  600. }
  601. _copyModel(model) {
  602. const copy = {};
  603. const cp = name => {
  604. const value = model[name];
  605. if (value) {
  606. copy[name] = value;
  607. }
  608. };
  609. cp('formula');
  610. cp('result');
  611. cp('ref');
  612. cp('shareType');
  613. cp('sharedFormula');
  614. return copy;
  615. }
  616. get value() {
  617. return this._copyModel(this.model);
  618. }
  619. set value(value) {
  620. this.model = this._copyModel(value);
  621. }
  622. validate(value) {
  623. switch (Value.getType(value)) {
  624. case Cell.Types.Null:
  625. case Cell.Types.String:
  626. case Cell.Types.Number:
  627. case Cell.Types.Date:
  628. break;
  629. case Cell.Types.Hyperlink:
  630. case Cell.Types.Formula:
  631. default:
  632. throw new Error('Cannot process that type of result value');
  633. }
  634. }
  635. get dependencies() {
  636. // find all the ranges and cells mentioned in the formula
  637. const ranges = this.formula.match(/([a-zA-Z0-9]+!)?[A-Z]{1,3}\d{1,4}:[A-Z]{1,3}\d{1,4}/g);
  638. const cells = this.formula.replace(/([a-zA-Z0-9]+!)?[A-Z]{1,3}\d{1,4}:[A-Z]{1,3}\d{1,4}/g, '').match(/([a-zA-Z0-9]+!)?[A-Z]{1,3}\d{1,4}/g);
  639. return {
  640. ranges,
  641. cells
  642. };
  643. }
  644. get formula() {
  645. return this.model.formula || this._getTranslatedFormula();
  646. }
  647. set formula(value) {
  648. this.model.formula = value;
  649. }
  650. get formulaType() {
  651. if (this.model.formula) {
  652. return Enums.FormulaType.Master;
  653. }
  654. if (this.model.sharedFormula) {
  655. return Enums.FormulaType.Shared;
  656. }
  657. return Enums.FormulaType.None;
  658. }
  659. get result() {
  660. return this.model.result;
  661. }
  662. set result(value) {
  663. this.model.result = value;
  664. }
  665. get type() {
  666. return Cell.Types.Formula;
  667. }
  668. get effectiveType() {
  669. const v = this.model.result;
  670. if (v === null || v === undefined) {
  671. return Enums.ValueType.Null;
  672. }
  673. if (v instanceof String || typeof v === 'string') {
  674. return Enums.ValueType.String;
  675. }
  676. if (typeof v === 'number') {
  677. return Enums.ValueType.Number;
  678. }
  679. if (v instanceof Date) {
  680. return Enums.ValueType.Date;
  681. }
  682. if (v.text && v.hyperlink) {
  683. return Enums.ValueType.Hyperlink;
  684. }
  685. if (v.formula) {
  686. return Enums.ValueType.Formula;
  687. }
  688. return Enums.ValueType.Null;
  689. }
  690. get address() {
  691. return this.model.address;
  692. }
  693. set address(value) {
  694. this.model.address = value;
  695. }
  696. _getTranslatedFormula() {
  697. if (!this._translatedFormula && this.model.sharedFormula) {
  698. const {
  699. worksheet
  700. } = this.cell;
  701. const master = worksheet.findCell(this.model.sharedFormula);
  702. this._translatedFormula = master && slideFormula(master.formula, master.address, this.model.address);
  703. }
  704. return this._translatedFormula;
  705. }
  706. toCsvString() {
  707. return `${this.model.result || ''}`;
  708. }
  709. release() {}
  710. toString() {
  711. return this.model.result ? this.model.result.toString() : '';
  712. }
  713. }
  714. class SharedStringValue {
  715. constructor(cell, value) {
  716. this.model = {
  717. address: cell.address,
  718. type: Cell.Types.SharedString,
  719. value
  720. };
  721. }
  722. get value() {
  723. return this.model.value;
  724. }
  725. set value(value) {
  726. this.model.value = value;
  727. }
  728. get type() {
  729. return Cell.Types.SharedString;
  730. }
  731. get effectiveType() {
  732. return Cell.Types.SharedString;
  733. }
  734. get address() {
  735. return this.model.address;
  736. }
  737. set address(value) {
  738. this.model.address = value;
  739. }
  740. toCsvString() {
  741. return this.model.value.toString();
  742. }
  743. release() {}
  744. toString() {
  745. return this.model.value.toString();
  746. }
  747. }
  748. class BooleanValue {
  749. constructor(cell, value) {
  750. this.model = {
  751. address: cell.address,
  752. type: Cell.Types.Boolean,
  753. value
  754. };
  755. }
  756. get value() {
  757. return this.model.value;
  758. }
  759. set value(value) {
  760. this.model.value = value;
  761. }
  762. get type() {
  763. return Cell.Types.Boolean;
  764. }
  765. get effectiveType() {
  766. return Cell.Types.Boolean;
  767. }
  768. get address() {
  769. return this.model.address;
  770. }
  771. set address(value) {
  772. this.model.address = value;
  773. }
  774. toCsvString() {
  775. return this.model.value ? 1 : 0;
  776. }
  777. release() {}
  778. toString() {
  779. return this.model.value.toString();
  780. }
  781. }
  782. class ErrorValue {
  783. constructor(cell, value) {
  784. this.model = {
  785. address: cell.address,
  786. type: Cell.Types.Error,
  787. value
  788. };
  789. }
  790. get value() {
  791. return this.model.value;
  792. }
  793. set value(value) {
  794. this.model.value = value;
  795. }
  796. get type() {
  797. return Cell.Types.Error;
  798. }
  799. get effectiveType() {
  800. return Cell.Types.Error;
  801. }
  802. get address() {
  803. return this.model.address;
  804. }
  805. set address(value) {
  806. this.model.address = value;
  807. }
  808. toCsvString() {
  809. return this.toString();
  810. }
  811. release() {}
  812. toString() {
  813. return this.model.value.error.toString();
  814. }
  815. }
  816. class JSONValue {
  817. constructor(cell, value) {
  818. this.model = {
  819. address: cell.address,
  820. type: Cell.Types.String,
  821. value: JSON.stringify(value),
  822. rawValue: value
  823. };
  824. }
  825. get value() {
  826. return this.model.rawValue;
  827. }
  828. set value(value) {
  829. this.model.rawValue = value;
  830. this.model.value = JSON.stringify(value);
  831. }
  832. get type() {
  833. return Cell.Types.String;
  834. }
  835. get effectiveType() {
  836. return Cell.Types.String;
  837. }
  838. get address() {
  839. return this.model.address;
  840. }
  841. set address(value) {
  842. this.model.address = value;
  843. }
  844. toCsvString() {
  845. return this.model.value;
  846. }
  847. release() {}
  848. toString() {
  849. return this.model.value;
  850. }
  851. }
  852. // Value is a place to hold common static Value type functions
  853. const Value = {
  854. getType(value) {
  855. if (value === null || value === undefined) {
  856. return Cell.Types.Null;
  857. }
  858. if (value instanceof String || typeof value === 'string') {
  859. return Cell.Types.String;
  860. }
  861. if (typeof value === 'number') {
  862. return Cell.Types.Number;
  863. }
  864. if (typeof value === 'boolean') {
  865. return Cell.Types.Boolean;
  866. }
  867. if (value instanceof Date) {
  868. return Cell.Types.Date;
  869. }
  870. if (value.text && value.hyperlink) {
  871. return Cell.Types.Hyperlink;
  872. }
  873. if (value.formula || value.sharedFormula) {
  874. return Cell.Types.Formula;
  875. }
  876. if (value.richText) {
  877. return Cell.Types.RichText;
  878. }
  879. if (value.sharedString) {
  880. return Cell.Types.SharedString;
  881. }
  882. if (value.error) {
  883. return Cell.Types.Error;
  884. }
  885. return Cell.Types.JSON;
  886. },
  887. // map valueType to constructor
  888. types: [{
  889. t: Cell.Types.Null,
  890. f: NullValue
  891. }, {
  892. t: Cell.Types.Number,
  893. f: NumberValue
  894. }, {
  895. t: Cell.Types.String,
  896. f: StringValue
  897. }, {
  898. t: Cell.Types.Date,
  899. f: DateValue
  900. }, {
  901. t: Cell.Types.Hyperlink,
  902. f: HyperlinkValue
  903. }, {
  904. t: Cell.Types.Formula,
  905. f: FormulaValue
  906. }, {
  907. t: Cell.Types.Merge,
  908. f: MergeValue
  909. }, {
  910. t: Cell.Types.JSON,
  911. f: JSONValue
  912. }, {
  913. t: Cell.Types.SharedString,
  914. f: SharedStringValue
  915. }, {
  916. t: Cell.Types.RichText,
  917. f: RichTextValue
  918. }, {
  919. t: Cell.Types.Boolean,
  920. f: BooleanValue
  921. }, {
  922. t: Cell.Types.Error,
  923. f: ErrorValue
  924. }].reduce((p, t) => {
  925. p[t.t] = t.f;
  926. return p;
  927. }, []),
  928. create(type, cell, value) {
  929. const T = this.types[type];
  930. if (!T) {
  931. throw new Error(`Could not create Value of type ${type}`);
  932. }
  933. return new T(cell, value);
  934. }
  935. };
  936. module.exports = Cell;
  937. //# sourceMappingURL=cell.js.map