UNPKG

simple-spreadsheet-reader

Version:
255 lines 9.6 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { httpclient } from 'typescript-http-client'; import { search } from 'jmespath'; import { groupBy } from 'lodash'; var Request = httpclient.Request; /** * A simple reader for a Google spreadsheet publish on web. */ export class SpreadsheedReader { constructor(spreadsheetsUrlOrId) { this.httpClient = httpclient.newHttpClient(); try { const url = new URL(spreadsheetsUrlOrId); const parsed = /spreadsheets\/\w\/(.*)\//.exec(url.pathname); if (parsed) { this.spreadsheetsIs = parsed[1]; } } catch (e) { this.spreadsheetsIs = spreadsheetsUrlOrId; } } /** * XML string of the error message */ get xmlError() { return this._xmlError; } /** * get raw JSON loaded from google spreadsheet */ get rawJson() { if (this._rawJson) { return this._rawJson; } throw Error('No data, loadRawJson first'); } /** * List od cells loaded from google spreadsheet */ get cellsList() { if (this._cellsList) { return this._cellsList; } throw Error('No data, loadRawJson first'); } /** * get the number of raw used in the spreadsheet */ get maxRaw() { if (this._maxRaw) { return this._maxRaw; } throw Error('No data, loadRawJson first'); } /** * get the number of column used in the spreadsheet. */ get maxColl() { if (this._maxColl) { return this._maxColl; } throw Error('No data, loadRawJson first'); } processSpreadsheets(rawJson) { this._cellsList = search(rawJson, `feed.entry[*].{cell: title."$t", value: content."$t"}`) .map(elem => { const parcedCell = /([A-Z]+)([0-9]+)/.exec(elem.cell); if (parcedCell === null) throw Error('Error in spredsheet format'); const [cellId, coll, rows] = parcedCell; return Object.assign({ rows: Number(rows), coll, cellId, collNb: coll.charCodeAt(0) }, elem); }); this._rawJson = rawJson; this._maxRaw = Number(search(this.cellsList, 'max_by([*], &rows).rows')); this._maxColl = String.fromCharCode(search(this.cellsList, 'max_by([*], &collNb).collNb')); return this._rawJson; } /** * Load spreadsheet data */ loadSpreadsheetData() { return __awaiter(this, void 0, void 0, function* () { try { if (!this.spreadsheetsIs) { throw Error('Invalid spreadsheetsIs'); } const url = `https://spreadsheets.google.com/feeds/cells/${this.spreadsheetsIs}/1/public/full?alt=json`; const request = new Request(url, { method: 'GET', contentType: 'application/json' }); return this.processSpreadsheets(yield this.httpClient.execute(request)); } catch (error) { const requestError = error; this._xmlError = requestError.body || error.message; throw Error('Unable to load spreadsheets. For more info see xmlError attribute'); } }); } /** * get value of a cell * @param cellId */ getCellValue(cellId) { return search(this.rawJson, `feed.entry[*].{cell: title."$t", value: content."$t"}[?cell=='${cellId.toUpperCase()}'].value`)[0]; } /** * gel all lines of the spreadsheet in an array of array */ getAllLines() { const cellsByRaws = groupBy(this.cellsList, (cell) => cell.rows); const results = []; for (const i of SpreadsheedReader.numberGenerator(this.maxRaw)) { results.push(SpreadsheedReader.formatColl(cellsByRaws[i] || [], this.maxColl)); } return results; } /** * Compute Node elements of the table. * In case of errors the node will contains the error message. * * *classes* * - ssr-table: class of the root elements of the table * - ssr-cell-head: class of header cells * - ssr-cell-data: class of cells contains data * * *id* * - All data Element have id="ssr-${cellID}" * * *results HTML* * * ```html * <table class="ssr-table"> <thead> <tr> <td class="ssr-cell-head"></td> <td class="ssr-cell-head">A</td> <td class="ssr-cell-head">B</td> </tr> </thead> <tbody> <tr> <td class="ssr-cell-head">1</td> <td cell-id="A1" id="ssr-A1" class="ssr-cell-data">text</td> <td cell-id="B1" id="ssr-B1" class="ssr-cell-data">value</td> </tr> <tr> <td class="ssr-cell-head">2</td> <td cell-id="A2" id="ssr-A2" class="ssr-cell-data"></td> <td cell-id="B2" id="ssr-B2" class="ssr-cell-data">other</td> </tr> </tbody> </table> ``` * * <table class="ssr-table"> <thead> <tr> <td class="ssr-cell-head"></td> <td class="ssr-cell-head">A</td> <td class="ssr-cell-head">B</td> </tr> </thead> <tbody> <tr> <td class="ssr-cell-head">1</td> <td cell-id="A1" id="ssr-A1" class="ssr-cell-data">text</td> <td cell-id="B1" id="ssr-B1" class="ssr-cell-data">value</td> </tr> <tr> <td class="ssr-cell-head">2</td> <td cell-id="A2" id="ssr-A2" class="ssr-cell-data"></td> <td cell-id="B2" id="ssr-B2" class="ssr-cell-data">other</td> </tr> </tbody> </table> */ getTable() { if (this._xmlError) { const template = document.createElement('template'); template.innerHTML = this._xmlError.trim(); if (template.content && template.content.firstChild) return template.content.firstChild; throw Error('Unknow Error'); } const table = this.generateTable(this.maxRaw, this.maxColl); this.cellsList.forEach(cell => { const cellContain = document.createTextNode(cell.value || ''); const cellElem = table.querySelector(`#ssr-${cell.cell}`); cellElem === null || cellElem === void 0 ? void 0 : cellElem.append(cellContain); }); return table; } static formatColl(cells, maxColl) { const cellsByColl = groupBy(cells, (cell) => cell.coll); const results = []; for (const i of SpreadsheedReader.lettersGenerator(maxColl)) { const cell = (cellsByColl[i] || [{ value: undefined }])[0]; results.push(cell.value); } return results; } static *lettersGenerator(maxLetters) { for (let i = 65; i <= maxLetters.charCodeAt(0); i++) { yield String.fromCharCode(i); } } static *numberGenerator(maxLines = 100) { for (let i = 1; i <= maxLines; i++) { yield i; } } createHeadCell(cellContaint) { const cell = document.createElement('td'); cell.classList.add('ssr-cell-head'); cell.appendChild(document.createTextNode(cellContaint || '')); return cell; } generateTable(maxRaw, maxCell) { const table = document.createElement('table'); table.classList.add('ssr-table'); const tableHead = document.createElement('thead'); const rowHead = document.createElement('tr'); rowHead.appendChild(this.createHeadCell('')); Array.from(SpreadsheedReader.lettersGenerator(maxCell)).forEach((collId) => { rowHead.appendChild(this.createHeadCell(collId)); }); tableHead.appendChild(rowHead); table.appendChild(tableHead); const tableBody = document.createElement('tbody'); Array.from(SpreadsheedReader.numberGenerator(maxRaw)).forEach((rowId) => { const row = document.createElement('tr'); row.appendChild(this.createHeadCell(`${rowId}`)); Array.from(SpreadsheedReader.lettersGenerator(maxCell)).forEach((collId) => { const cell = document.createElement('td'); const cellId = collId + rowId; cell.id = `ssr-${cellId}`; cell.setAttribute('cell-id', cellId); cell.classList.add('ssr-cell-data'); row.appendChild(cell); }); tableBody.appendChild(row); }); table.appendChild(tableBody); return table; } } //# sourceMappingURL=spreadsheedReader.js.map