UNPKG

taktik-simple-spreadsheet-reader

Version:
478 lines 21.3 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; 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()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; import { Request, newHttpClient, Response, } from 'typescript-http-client'; /** * A simple reader for a Google spreadsheet publish on web. */ var SpreadsheetReader = /** @class */ (function () { function SpreadsheetReader(spreadsheetsUrlOrId, apiKey) { this._currentPage = 0; this.sheetsData = []; this.apiKey = apiKey; this.httpClient = newHttpClient(); try { var url = new URL(spreadsheetsUrlOrId); var parsed = /spreadsheets\/\w\/(.*)\//.exec(url.pathname); if (parsed) { this.spreadsheetsId = parsed[1]; } } catch (e) { this.spreadsheetsId = spreadsheetsUrlOrId; } } Object.defineProperty(SpreadsheetReader.prototype, "currentPage", { /** * gets the current page, indexed at 0 */ get: function () { return this._currentPage; }, /** * sets the current page, indexed at 0 */ set: function (page) { if (page >= 0 && page < this.numberOfPages) { this._currentPage = page; } else { throw Error("The new page value should be included in [0;" + this.numberOfPages + "["); } }, enumerable: true, configurable: true }); Object.defineProperty(SpreadsheetReader.prototype, "numberOfPages", { /** * get the total number of pages the sheet has */ get: function () { if (this.sheetsData.length > 0) { return this.sheetsData.length; } throw Error('No data, call loadSpreadsheetData first'); }, enumerable: true, configurable: true }); Object.defineProperty(SpreadsheetReader.prototype, "xmlError", { /** * XML string of the error message */ get: function () { return this._xmlError; }, enumerable: true, configurable: true }); Object.defineProperty(SpreadsheetReader.prototype, "parsedCells", { /** * get parsed cells */ get: function () { var parsedCells = this.sheetsData[this.currentPage].parsedCells; if (parsedCells) { return parsedCells; } throw Error('No data, call loadSpreadsheetData first'); }, enumerable: true, configurable: true }); Object.defineProperty(SpreadsheetReader.prototype, "cellsList", { /** * List od cells loaded from google spreadsheet */ get: function () { var cellsList = this.sheetsData[this.currentPage].cellsList; if (cellsList) { return cellsList; } throw Error('No data, call loadSpreadsheetData first'); }, enumerable: true, configurable: true }); Object.defineProperty(SpreadsheetReader.prototype, "maxRow", { /** * get the number of raw used in the spreadsheet */ get: function () { var maxRow = this.sheetsData[this.currentPage].maxRow; if (maxRow) { return maxRow; } throw Error('No data, call loadSpreadsheetData first'); }, enumerable: true, configurable: true }); Object.defineProperty(SpreadsheetReader.prototype, "maxColl", { /** * get the number of column used in the spreadsheet. */ get: function () { var maxColl = this.sheetsData[this.currentPage].maxColl; if (maxColl) { return maxColl; } throw Error('No data, call loadSpreadsheetData first'); }, enumerable: true, configurable: true }); SpreadsheetReader.prototype.processSpreadsheet = function (parsedCells) { var cellsList = parsedCells.map(function (elem) { var parcedCell = /([A-Z]+)([0-9]+)/.exec(elem.cell); if (parcedCell === null) throw Error('Error in spredsheet format'); var _a = __read(parcedCell, 3), cellId = _a[0], coll = _a[1], rows = _a[2]; return __assign({ rows: rows, coll: coll, cellId: cellId }, elem); }); var maxRow = cellsList.reduce(function (highestRow, nextValue) { var currentRow = Number(nextValue.rows); if (currentRow > highestRow) { return currentRow; } return highestRow; }, 0); var maxColl = cellsList.reduce(function (highestColl, _a) { var coll = _a.coll; // parseInt(coll, 36) parses the letters as a number, which can then be compared to each other to define which is the "highest" column letter if (parseInt(coll, 36) > parseInt(highestColl, 36)) { return coll; } return highestColl; }, 'A'); return { cellsList: cellsList, parsedCells: parsedCells, maxRow: maxRow, maxColl: maxColl }; }; SpreadsheetReader.getColumnLettersFromIndex = function (index) { // After the letter Z (index >= 26), the letter go back again from AA, AB, AC, ... if (index >= 26) { var firstLetterIndex = Math.floor(index / 26) - 1; var secondLetterIndex = index % 26; return "" + this.getColumnLettersFromIndex(firstLetterIndex) + this.getColumnLettersFromIndex(secondLetterIndex); } return String.fromCharCode(index + 65); }; /* * Function to parse the array we receive from google API into an array of objects containing the cell name alongside the cell value * [["cellValue1", "cellValue2"]] => [{cell: "A1", value: "cellValue1"}, {cell: "B2", value: "cellValue2"}] * This function is made to process results from a request using majorDimension=ROWS (default value for majorDimension on the get/value request) * If the request is made with another value for majorDimension, this function will break */ SpreadsheetReader.prototype.parseSheetValues = function (sheetValues) { var parsedValues = sheetValues.flatMap(function (row, rowIndex) { return row.map(function (cellValue, columnIndex) { return ({ cell: "" + SpreadsheetReader.getColumnLettersFromIndex(columnIndex) + (rowIndex + 1), value: cellValue, }); }); }); return this.processSpreadsheet(parsedValues); }; /** * Load spreadsheet cells values */ SpreadsheetReader.prototype.loadSpreadsheetData = function () { return __awaiter(this, void 0, void 0, function () { var sheetPropertiesUrl, sheetPropertiesRequest, _a, sheets, error_1; var _this = this; return __generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 4, , 5]); sheetPropertiesUrl = "https://sheets.googleapis.com/v4/spreadsheets/" + this.spreadsheetsId + "?key=" + this.apiKey; sheetPropertiesRequest = new Request(sheetPropertiesUrl, { method: 'GET', contentType: 'application/json', }); // We are interested in the sheetsProperties.sheets to know the number of sheets and their names as it is // necessary for the next request on /v4/spreadsheets/{sheetId}/values/{sheetName} _a = this; return [4 /*yield*/, this.httpClient.execute(sheetPropertiesRequest)]; case 1: // We are interested in the sheetsProperties.sheets to know the number of sheets and their names as it is // necessary for the next request on /v4/spreadsheets/{sheetId}/values/{sheetName} _a.sheetsProperties = _b.sent(); if (!this.sheetsProperties) return [3 /*break*/, 3]; return [4 /*yield*/, Promise.all(this.sheetsProperties.sheets.map(function (_a) { var title = _a.properties.title; return __awaiter(_this, void 0, void 0, function () { var valuesUrl, valuesRequest, sheet; return __generator(this, function (_b) { switch (_b.label) { case 0: valuesUrl = "https://sheets.googleapis.com/v4/spreadsheets/" + this.spreadsheetsId + "/values/" + title + "?majorDimension=ROWS&key=" + this.apiKey; valuesRequest = new Request(valuesUrl, { method: 'GET', contentType: 'application/json', }); return [4 /*yield*/, this.httpClient.execute(valuesRequest) // If sheet.value doesnt exists it means the sheet is empty, we should not display it. // We can't know before we fetch the sheets data, so the promise will resolve to undefined and we filter // that out after. ]; case 1: sheet = _b.sent(); // If sheet.value doesnt exists it means the sheet is empty, we should not display it. // We can't know before we fetch the sheets data, so the promise will resolve to undefined and we filter // that out after. if (!sheet.values) { return [2 /*return*/, undefined]; } return [2 /*return*/, this.parseSheetValues(sheet.values)]; } }); }); }))]; case 2: sheets = _b.sent(); this.sheetsData = sheets.filter(function (sheet) { return sheet !== undefined; }); _b.label = 3; case 3: return [3 /*break*/, 5]; case 4: error_1 = _b.sent(); this._xmlError = error_1 instanceof Response ? error_1.body : error_1 instanceof Error ? error_1.message : error_1; throw Error('Unable to load spreadsheets. For more info see xmlError attribute'); case 5: return [2 /*return*/]; } }); }); }; /** * get value of a cell * @param cellId * @param page */ SpreadsheetReader.prototype.getCellValue = function (cellId, page) { if (page === void 0) { page = 0; } this.currentPage = page; var matchingCell = this.parsedCells.find(function (_a) { var cell = _a.cell; return cell === cellId; }); if (matchingCell) { return matchingCell.value; } }; /** * 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> */ SpreadsheetReader.prototype.getTable = function () { if (this._xmlError) { var template = document.createElement('template'); template.innerHTML = this._xmlError.trim(); if (template.content && template.content.firstChild) return template.content.firstChild; throw Error('Unknow Error'); } var table = this.generateTable(this.maxRow, this.maxColl); this.cellsList.forEach(function (cell) { var cellContain = document.createTextNode(cell.value || ''); var cellElem = table.querySelector("#ssr-" + cell.cell); cellElem === null || cellElem === void 0 ? void 0 : cellElem.append(cellContain); }); return table; }; SpreadsheetReader.lettersGenerator = function (maxLetters) { var currentLetters, index; return __generator(this, function (_a) { switch (_a.label) { case 0: currentLetters = ''; index = 0; _a.label = 1; case 1: if (!(maxLetters !== currentLetters)) return [3 /*break*/, 3]; currentLetters = SpreadsheetReader.getColumnLettersFromIndex(index); return [4 /*yield*/, currentLetters]; case 2: _a.sent(); index++; return [3 /*break*/, 1]; case 3: return [2 /*return*/]; } }); }; SpreadsheetReader.numberGenerator = function (maxLines) { var i; if (maxLines === void 0) { maxLines = 100; } return __generator(this, function (_a) { switch (_a.label) { case 0: i = 1; _a.label = 1; case 1: if (!(i <= maxLines)) return [3 /*break*/, 4]; return [4 /*yield*/, i]; case 2: _a.sent(); _a.label = 3; case 3: i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/]; } }); }; SpreadsheetReader.prototype.createHeadCell = function (cellContaint) { var cell = document.createElement('td'); cell.classList.add('ssr-cell-head'); cell.appendChild(document.createTextNode(cellContaint || '')); return cell; }; SpreadsheetReader.prototype.generateTable = function (maxRow, maxCell) { var _this = this; var table = document.createElement('table'); table.classList.add('ssr-table'); var tableHead = document.createElement('thead'); var rowHead = document.createElement('tr'); rowHead.appendChild(this.createHeadCell('')); Array.from(SpreadsheetReader.lettersGenerator(maxCell)).forEach(function (collId) { rowHead.appendChild(_this.createHeadCell(collId)); }); tableHead.appendChild(rowHead); table.appendChild(tableHead); var tableBody = document.createElement('tbody'); Array.from(SpreadsheetReader.numberGenerator(maxRow)).forEach(function (rowId) { var row = document.createElement('tr'); row.appendChild(_this.createHeadCell("" + rowId)); Array.from(SpreadsheetReader.lettersGenerator(maxCell)).forEach(function (collId) { var cell = document.createElement('td'); var 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; }; return SpreadsheetReader; }()); export { SpreadsheetReader }; //# sourceMappingURL=SpreadsheetReader.js.map