@syncfusion/ej2-spreadsheet
Version:
Feature-rich JavaScript Spreadsheet (Excel) control with built-in support for selection, editing, formatting, importing and exporting to Excel
1,045 lines (1,044 loc) • 131 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path='../../workbook/base/workbook-model.d.ts'/>
import { Property, NotifyPropertyChanges, Event, isUndefined, attributes } from '@syncfusion/ej2-base';
import { addClass, removeClass, Complex, formatUnit, L10n, isNullOrUndefined, Browser } from '@syncfusion/ej2-base';
import { detach, select, closest, setStyleAttribute, EventHandler } from '@syncfusion/ej2-base';
import { mouseDown, spreadsheetDestroyed, keyUp, clearViewer, refreshSheetTabs, positionAutoFillElement, readonlyAlert, deInitProperties, isColumnRange, isRowRange, findDlg } from '../common/index';
import { performUndoRedo, overlay, createImageElement, deleteImage, removeHyperlink } from '../common/index';
import { sheetNameUpdate, updateUndoRedoCollection, getUpdateUsingRaf, setAutoFit } from '../common/index';
import { actionEvents, keyDown, enableFileMenuItems, hideToolbarItems, updateAction } from '../common/index';
import { colWidthChanged, rowHeightChanged, hideRibbonTabs, addFileMenuItems, getSiblingsHeight } from '../common/index';
import { defaultLocale, locale, setResize, initiateFilterUI, clearFilter, focus, removeDesignChart } from '../common/index';
import { ribbon, formulaBar, sheetTabs, formulaOperation, addRibbonTabs } from '../common/index';
import { addContextMenuItems, removeContextMenuItems, enableContextMenuItems, selectRange, addToolbarItems } from '../common/index';
import { cut, copy, paste, dialog, editOperation, activeSheetChanged, refreshFormulaDatasource } from '../common/index';
import { Render } from '../renderer/render';
import { Scroll, VirtualScroll, Edit, CellFormat, Selection, KeyboardNavigation, KeyboardShortcut, WrapText } from '../actions/index';
import { Clipboard, ShowHide, UndoRedo, SpreadsheetHyperlink, Resize, Insert, Delete, FindAndReplace, Merge, AutoFill, SpreadsheetNote } from '../actions/index';
import { ProtectSheet } from '../actions/index';
import { click, hideFileMenuItems } from '../common/index';
import { Dialog, ActionEvents, Overlay } from '../services/index';
import { ServiceLocator } from '../../workbook/services/index';
import { getColumnsWidth, getSheetIndex, WorkbookHyperlink } from './../../workbook/index';
import { getCellAddress, getColumnHeaderText, getSwapRange, getSheetIndexFromAddress, isReadOnlyCells, updateSortCollection } from './../../workbook/common/index';
import { afterHyperlinkCreate, getColIndex, setLinkModel } from './../../workbook/index';
import { WorkbookInsert, WorkbookDelete, WorkbookMerge } from './../../workbook/index';
import { getSheetNameFromAddress, DataBind, beforeHyperlinkCreate } from './../../workbook/index';
import { sortComplete, dataSourceChanged, isHiddenRow, isHiddenCol } from './../../workbook/index';
import { getSheetIndexFromId, WorkbookEdit, WorkbookOpen, WorkbookSave, WorkbookCellFormat, WorkbookSort, getSheet } from './../../workbook/index';
import { findKeyUp, refreshRibbonIcons, hideShow } from './../../workbook/index';
import { Workbook } from '../../workbook/base/workbook';
import { getRequiredModules, ScrollSettings, enableToolbarItems } from '../common/index';
import { SelectionSettings, getStartEvent, enableRibbonTabs, getDPRValue } from '../common/index';
import { createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-popups';
import { setRowHeight, getRowsHeight, getColumnWidth, getRowHeight, getCell, setColumn, setCell, setRow } from './../../workbook/base/index';
import { getRangeIndexes, getIndexesFromAddress, getCellIndexes, WorkbookNumberFormat, WorkbookFormula } from '../../workbook/index';
import { Ribbon, FormulaBar, SheetTabs, Open, ContextMenu, Save, NumberFormat, Formula } from '../integrations/index';
import { Sort, Filter, SpreadsheetImage, SpreadsheetChart } from '../integrations/index';
import { getColumn, getRow, WorkbookFilter, refreshInsertDelete } from '../../workbook/index';
import { fltrPrevent } from '@syncfusion/ej2-grids';
import { DataValidation, spreadsheetCreated, showAggregate } from './../index';
import { WorkbookDataValidation, WorkbookConditionalFormat, WorkbookFindAndReplace, WorkbookAutoFill } from '../../workbook/actions/index';
import { findAllValues, getFormattedCellObject } from './../../workbook/common/index';
import { ConditionalFormatting } from '../actions/conditional-formatting';
import { WorkbookImage, WorkbookChart, updateView, focusChartBorder } from '../../workbook/index';
import { WorkbookProtectSheet, isImported } from '../../workbook/index';
import { contentLoaded, completeAction, freeze, refreshOverlayElem, insertDesignChart } from '../common/index';
import { beginAction, sheetsDestroyed, workbookFormulaOperation, getRangeAddress } from './../../workbook/common/index';
import { updateScroll, clearCopy, clearUndoRedoCollection, clearChartBorder, propertyChange } from '../common/index';
import { Print } from '../renderer/print';
/**
* Represents the Spreadsheet component.
*
* ```html
* <div id='spreadsheet'></div>
* <script>
* let spreadsheetObj = new Spreadsheet();
* spreadsheetObj.appendTo('#spreadsheet');
* </script>
* ```
*/
var Spreadsheet = /** @class */ (function (_super) {
__extends(Spreadsheet, _super);
/**
* Constructor for creating the widget.
*
* @param {SpreadsheetModel} options - Configures Spreadsheet options.
* @param {string|HTMLElement} element - Element to render Spreadsheet.
*/
function Spreadsheet(options, element) {
var _this = _super.call(this, options) || this;
/**
* Array to store multiple rafIds on intial rendering.
*
* @hidden */
_this.rafIds = [];
/** @hidden */
_this.viewport = {
rowCount: 0, colCount: 0, height: 0, topIndex: 0, leftIndex: 0, width: 0,
bottomIndex: 0, rightIndex: 0, beforeFreezeHeight: 0, beforeFreezeWidth: 0, scaleX: 1, scaleY: 1
};
_this.needsID = true;
Spreadsheet_1.Inject(Ribbon, FormulaBar, SheetTabs, Selection, Edit, KeyboardNavigation, KeyboardShortcut, Clipboard, DataBind, Open, ContextMenu, Save, NumberFormat, CellFormat, Formula, WrapText, WorkbookEdit, WorkbookOpen, WorkbookSave, WorkbookCellFormat, WorkbookNumberFormat, WorkbookFormula, Sort, WorkbookSort, Resize, UndoRedo, WorkbookFilter, Filter, SpreadsheetHyperlink, WorkbookHyperlink, Insert, Delete, WorkbookInsert, WorkbookDelete, DataValidation, WorkbookDataValidation, Print, ProtectSheet, WorkbookProtectSheet, FindAndReplace, WorkbookFindAndReplace, Merge, WorkbookMerge, SpreadsheetImage, ConditionalFormatting, WorkbookImage, WorkbookConditionalFormat, SpreadsheetChart, WorkbookChart, AutoFill, WorkbookAutoFill, SpreadsheetNote);
if (element) {
_this.appendTo(element);
}
return _this;
}
Spreadsheet_1 = Spreadsheet;
/**
* To get cell element.
*
* @param {number} rowIndex - specify the rowIndex.
* @param {number} colIndex - specify the colIndex.
* @param {HTMLTableElement} row - specify the row.
* @returns {HTMLElement} - Get cell element
* @hidden
*/
Spreadsheet.prototype.getCell = function (rowIndex, colIndex, row) {
var td;
if (this.insideViewport(rowIndex, colIndex)) {
if (!row) {
row = this.getRow(rowIndex, null, colIndex);
}
colIndex = this.getViewportIndex(colIndex, true);
td = row ? row.cells[colIndex] : row;
}
return td;
};
/**
* Get cell element.
*
* @param {number} index - specify the index.
* @param {HTMLTableElement} table - specify the table.
* @param {number} colIdx - specify the column index.
* @returns {HTMLTableRowElement} - Get cell element
* @hidden
*/
Spreadsheet.prototype.getRow = function (index, table, colIdx) {
if (!table) {
var sheet = this.getActiveSheet();
var frozenRow = this.frozenRowCount(sheet);
var frozenCol = this.frozenColCount(sheet);
if (isNullOrUndefined(colIdx) || index > frozenRow - 1 && colIdx > frozenCol - 1) {
table = this.getContentTable();
}
else {
table = index < frozenRow && colIdx < frozenCol ? this.sheetModule.getSelectAllTable() : (index < frozenRow ?
this.getColHeaderTable() : this.getRowHeaderTable());
}
}
index = this.getViewportIndex(index);
return table ? table.rows[index] : null;
};
/**
* To get hidden row/column count between two specified index.
*
* Set `layout` as `columns` if you want to get column hidden count.
*
* @param {number} startIndex - specify the startIndex.
* @param {number} endIndex - specify the endIndex.
* @param {string} layout - specify the layout.
* @param {SheetModel} sheet - specify the sheet.
* @returns {number} - To get hidden row/column count between two specified index.
* @hidden
*/
Spreadsheet.prototype.hiddenCount = function (startIndex, endIndex, layout, sheet) {
if (layout === void 0) { layout = 'rows'; }
if (sheet === void 0) { sheet = this.getActiveSheet(); }
var count = 0;
var rowColModel;
for (var i = startIndex; i <= endIndex; i++) {
rowColModel = sheet["" + layout][i];
if (rowColModel && rowColModel.hidden) {
count++;
}
}
return count;
};
/**
* To get row/column viewport index.
*
* @param {number} index - specify the index.
* @param {boolean} isCol - specify the bool value.
* @returns {number} - To get row/column viewport index.
* @hidden
*/
Spreadsheet.prototype.getViewportIndex = function (index, isCol) {
var sheet = this.getActiveSheet();
var frozenCol = this.frozenColCount(sheet);
var frozenRow = this.frozenRowCount(sheet);
if (isCol) {
if (frozenCol) {
var leftIndex = getCellIndexes(sheet.topLeftCell)[1];
if (index < frozenCol) {
index -= this.hiddenCount(leftIndex, index, 'columns');
index -= leftIndex;
return index + 1;
}
else {
index -= this.hiddenCount(this.viewport.leftIndex + frozenCol, index, 'columns');
index -= (this.viewport.leftIndex + frozenCol);
return index;
}
}
else {
index -= this.hiddenCount(this.viewport.leftIndex, index, 'columns');
index -= this.viewport.leftIndex;
}
}
else {
if (frozenRow) {
var topIndex = getCellIndexes(sheet.topLeftCell)[0];
if (index < frozenRow) {
index -= this.hiddenCount(topIndex, index);
index -= topIndex;
return index + 1;
}
else {
index -= this.hiddenCount(this.viewport.topIndex + frozenRow, index);
index -= (this.viewport.topIndex + frozenRow);
return index;
}
}
else {
index -= this.hiddenCount(this.viewport.topIndex, index);
index -= this.viewport.topIndex;
}
}
return index;
};
/**
* To initialize the services;
*
* @returns {void} - To initialize the services.
* @hidden
*/
Spreadsheet.prototype.preRender = function () {
_super.prototype.preRender.call(this);
this.serviceLocator = new ServiceLocator;
this.initServices();
};
Spreadsheet.prototype.initServices = function () {
this.serviceLocator.register(locale, new L10n(this.getModuleName(), defaultLocale, this.locale));
this.serviceLocator.register(dialog, new Dialog(this));
this.serviceLocator.register(actionEvents, new ActionEvents(this));
this.serviceLocator.register(overlay, new Overlay(this));
};
/**
* To Initialize the component rendering.
*
* @returns {void} - To Initialize the component rendering.
* @hidden
*/
Spreadsheet.prototype.render = function () {
_super.prototype.render.call(this);
this.element.setAttribute('tabindex', '0');
this.renderModule = new Render(this);
this.renderSpreadsheet();
this.wireEvents();
if (this.created && !this.refreshing) {
if (this.created.observers) {
if (this.created.observers.length > 0) {
var observerObject = { observers: this.created.observers };
if (this.isAngular) {
observerObject = { observers: this.created.observers,
currentObservers: this.created.observers };
this.created.currentObservers = [];
}
this.createdHandler = observerObject;
this.created.observers = [];
}
}
else {
this.createdHandler = this.created;
this.setProperties({ created: undefined }, true);
}
}
};
Spreadsheet.prototype.renderSpreadsheet = function () {
if (this.cssClass) {
addClass([this.element], this.cssClass.split(' '));
}
if (this.enableRtl) {
this.element.classList.add('e-rtl');
}
this.setHeight();
this.setWidth();
createSpinner({ target: this.element }, this.createElement);
if (this.cssClass && this.cssClass.indexOf('e-mobile-view') === -1 && this.isMobileView()) {
this.element.classList.add('e-mobile-view');
}
if (Browser.isDevice) {
this.element.classList.add('e-device');
}
this.sheetModule = this.serviceLocator.getService('sheet');
if (this.allowScrolling) {
this.scrollModule = new Scroll(this);
}
if (this.scrollSettings.enableVirtualization) {
new VirtualScroll(this);
}
this.renderModule.render();
new ShowHide(this);
};
/**
* By default, Spreadsheet shows the spinner for all its actions. To manually show spinner you this method at your needed time.
*
* {% codeBlock src='spreadsheet/showSpinner/index.md' %}{% endcodeBlock %}
*
* @returns {void} - shows spinner
*/
Spreadsheet.prototype.showSpinner = function () {
showSpinner(this.element);
};
/**
* To hide showed spinner manually.
*
* {% codeBlock src='spreadsheet/hideSpinner/index.md' %}{% endcodeBlock %}
*
* @returns {void} - To hide showed spinner manually.
*/
Spreadsheet.prototype.hideSpinner = function () {
hideSpinner(this.element);
};
/**
* To protect the particular sheet.
*
* {% codeBlock src='spreadsheet/protectSheet/index.md' %}{% endcodeBlock %}
*
* @param {number | string} sheet - Specifies the sheet to protect.
* @param {ProtectSettingsModel} protectSettings - Specifies the protect sheet options.
* @default { selectCells: 'false', formatCells: 'false', formatRows: 'false', formatColumns:'false', insertLink:'false' }
* @param {string} password - Specifies the password to protect.
* @returns {void} - To protect the particular sheet.
*/
Spreadsheet.prototype.protectSheet = function (sheet, protectSettings, password) {
_super.prototype.protectSheet.call(this, sheet, protectSettings, password);
};
/**
* To unprotect the particular sheet.
*
* {% codeBlock src='spreadsheet/unprotectSheet/index.md' %}{% endcodeBlock %}
*
* @param {number | string} sheet - Specifies the sheet name or index to Unprotect.
* @returns {void} - To unprotect the particular sheet.
*/
Spreadsheet.prototype.unprotectSheet = function (sheet) {
_super.prototype.unprotectSheet.call(this, sheet);
};
/**
* To find the specified cell value.
*
* {% codeBlock src='spreadsheet/find/index.md' %}{% endcodeBlock %}
*
* @param {FindOptions} args - Specifies the replace value with find args to replace specified cell value.
* @param {string} args.value - Specifies the value to be find.
* @param {string} args.mode - Specifies the value to be find within sheet or workbook.
* @param {string} args.searchBy - Specifies the value to be find by row or column.
* @param {boolean} args.isCSen - Specifies the find match with case sensitive or not.
* @param {boolean} args.isEMatch - Specifies the find match with entire match or not.
* @param {string} args.findOpt - Specifies the next or previous find match.
* @param {number} args.sheetIndex - Specifies the current sheet to find.
* @default { mode: 'Sheet', searchBy: 'By Row', isCSen: 'false', isEMatch:'false' }
* @returns {void} - To find the specified cell value.
*/
Spreadsheet.prototype.find = function (args) {
var activeCell = this.getActiveSheet().activeCell;
_super.prototype.findHandler.call(this, args);
if (!args.isAction) {
if (activeCell !== this.getActiveSheet().activeCell) {
return this.getActiveSheet().name + '!' + this.getActiveSheet().activeCell;
}
else {
return null;
}
}
};
/**
* To replace the specified cell value.
*
* {% codeBlock src='spreadsheet/replace/index.md' %}{% endcodeBlock %}
*
* @param {FindOptions} args - Specifies the replace value with find args to replace specified cell value.
* @param {string} args.replaceValue - Specifies the replacing value.
* @param {string} args.replaceBy - Specifies the value to be replaced for one or all.
* @param {string} args.value - Specifies the value to be replaced
* @returns {void} - To replace the specified cell value.
*/
Spreadsheet.prototype.replace = function (args) {
if (args.showDialog) {
this.notify(findDlg, args);
}
else {
args = {
value: args.value, mode: args.mode ? args.mode : 'Sheet', isCSen: args.isCSen ? args.isCSen : false,
isEMatch: args.isEMatch ? args.isEMatch : false, searchBy: args.searchBy ? args.searchBy : 'By Row',
replaceValue: args.replaceValue, replaceBy: args.replaceBy,
sheetIndex: isUndefined(args.sheetIndex) ? this.activeSheetIndex : args.sheetIndex, findOpt: args.findOpt ? args.findOpt : ''
};
_super.prototype.replaceHandler.call(this, args);
}
};
/**
* To Find All the Match values Address within Sheet or Workbook.
*
* {% codeBlock src='spreadsheet/findAll/index.md' %}{% endcodeBlock %}
*
* @param {string} value - Specifies the value to find.
* @param {string} mode - Specifies the value to be find within Sheet/Workbook.
* @param {boolean} isCSen - Specifies the find match with case sensitive or not.
* @param {boolean} isEMatch - Specifies the find match with entire match or not.
* @param {number} sheetIndex - Specifies the sheetIndex. If not specified, it will consider the active sheet.
* @returns {string[]} - To Find All the Match values Address within Sheet or Workbook.
*/
Spreadsheet.prototype.findAll = function (value, mode, isCSen, isEMatch, sheetIndex) {
mode = mode ? mode : 'Sheet';
sheetIndex = sheetIndex < this.sheets.length ? sheetIndex : this.activeSheetIndex;
isCSen = isCSen ? isCSen : false;
isEMatch = isEMatch ? isEMatch : false;
var findCollection = [];
var findAllArguments = {
value: value, mode: mode, sheetIndex: sheetIndex, isCSen: isCSen,
isEMatch: isEMatch, findCollection: findCollection
};
this.notify(findAllValues, findAllArguments);
return findCollection;
};
/**
* Used to navigate to cell address within workbook.
*
* {% codeBlock src='spreadsheet/goTo/index.md' %}{% endcodeBlock %}
*
* @param {string} address - Specifies the cell address you need to navigate.
* You can specify the address in two formats,
* `{sheet name}!{cell address}` - Switch to specified sheet and navigate to specified cell address.
* `{cell address}` - Navigate to specified cell address with in the active sheet.
* @returns {void} - Used to navigate to cell address within workbook.
*/
Spreadsheet.prototype.goTo = function (address) {
if (!this.allowScrolling) {
this.selectRange(address);
return;
}
if (address.includes('!')) {
var idx = getSheetIndex(this, getSheetNameFromAddress(address));
if (idx === undefined) {
return;
}
if (idx !== this.activeSheetIndex) {
var selectRange_1 = address.substring(address.lastIndexOf('!') + 1);
var activeCell = selectRange_1.split(':')[0];
var sheet_1 = this.sheets[idx];
this.setSheetPropertyOnMute(sheet_1, 'activeCell', activeCell);
this.setSheetPropertyOnMute(sheet_1, 'selectedRange', selectRange_1);
var cellIndex = getCellIndexes(activeCell);
if (sheet_1.frozenColumns || sheet_1.frozenRows) {
var topLeftCell = getCellIndexes(sheet_1.topLeftCell);
if (!((sheet_1.frozenRows && cellIndex[0] < topLeftCell[0]) || (sheet_1.frozenColumns && cellIndex[1] < topLeftCell[1]))) {
var frozenRow_1 = this.frozenRowCount(sheet_1);
var frozenCol_1 = this.frozenColCount(sheet_1);
var curCell = [];
var paneCell = [];
var paneTopLeftCell = getCellIndexes(sheet_1.paneTopLeftCell);
if (frozenRow_1) {
curCell.push(topLeftCell[0]);
if (cellIndex[0] >= frozenRow_1) {
paneCell.push(cellIndex[0]);
}
else {
paneCell.push(paneTopLeftCell[0]);
}
}
else {
curCell.push(cellIndex[0]);
paneCell.push(cellIndex[0]);
}
if (frozenCol_1) {
curCell.push(topLeftCell[1]);
if (cellIndex[1] >= frozenCol_1) {
paneCell.push(cellIndex[1]);
}
else {
paneCell.push(paneTopLeftCell[1]);
}
}
else {
curCell.push(cellIndex[1]);
paneCell.push(cellIndex[1]);
}
this.setSheetPropertyOnMute(sheet_1, 'topLeftCell', getCellAddress(curCell[0], curCell[1]));
this.setSheetPropertyOnMute(sheet_1, 'paneTopLeftCell', getCellAddress(paneCell[0], paneCell[1]));
}
}
else {
if (cellIndex[0] < this.viewport.rowCount) {
cellIndex[0] = 0;
}
if (cellIndex[1] < this.viewport.colCount) {
cellIndex[1] = 0;
}
this.updateTopLeftCell(cellIndex[0], cellIndex[1], null, sheet_1);
}
this.activeSheetIndex = idx;
this.dataBind();
return;
}
}
var indexes = getRangeIndexes(address);
var sheet = this.getActiveSheet();
var frozenRow = this.frozenRowCount(sheet);
var frozenCol = this.frozenColCount(sheet);
var insideDomCount = this.insideViewport(indexes[0], indexes[1]);
if (insideDomCount) {
this.selectRange(address);
var viewportIndexes = getCellIndexes(sheet.paneTopLeftCell);
var viewportSize = this.viewport.height;
if (this.allowScrolling) {
viewportSize -= this.getScrollElement().parentElement.getBoundingClientRect().height;
}
var threshold = 0;
var lastRowIdx = 0;
if (frozenRow) {
var topLeftIndexes = getCellIndexes(sheet.topLeftCell);
for (var i = topLeftIndexes[0]; i < frozenRow; i++) {
threshold += getRowHeight(sheet, i);
if (threshold > viewportSize) {
lastRowIdx = i;
break;
}
}
}
if (lastRowIdx === 0) {
for (var i = viewportIndexes[0]; i <= this.viewport.bottomIndex; i++) {
threshold += getRowHeight(sheet, i);
if (threshold > viewportSize) {
lastRowIdx = i;
break;
}
else if (i === this.viewport.bottomIndex) {
lastRowIdx = this.viewport.bottomIndex;
}
}
}
viewportIndexes[2] = lastRowIdx;
var lastColIdx = 0;
threshold = 0;
viewportSize = this.viewport.width - this.sheetModule.getScrollSize();
if (frozenCol) {
var topLeftIndexes = getCellIndexes(sheet.topLeftCell);
for (var i = topLeftIndexes[1]; i < frozenCol; i++) {
threshold += getColumnWidth(sheet, i);
if (threshold > viewportSize) {
lastColIdx = i;
break;
}
}
}
if (lastColIdx === 0) {
for (var i = viewportIndexes[1]; i <= this.viewport.rightIndex; i++) {
threshold += getColumnWidth(sheet, i);
if (threshold > viewportSize) {
lastColIdx = i;
break;
}
else if (i === this.viewport.rightIndex) {
lastColIdx = this.viewport.rightIndex;
}
}
}
viewportIndexes[3] = lastColIdx;
if (indexes[0] >= viewportIndexes[0] && indexes[0] < viewportIndexes[2] && indexes[1] >= viewportIndexes[1] &&
indexes[1] < viewportIndexes[3]) {
return;
}
if (frozenRow || frozenCol) {
viewportIndexes = [].concat(getCellIndexes(sheet.topLeftCell), [frozenRow, viewportIndexes[3]]);
if (indexes[0] >= viewportIndexes[0] && indexes[0] < viewportIndexes[2] && indexes[1] >= viewportIndexes[1] &&
indexes[1] < viewportIndexes[3]) {
return;
}
viewportIndexes[2] = lastRowIdx;
viewportIndexes[3] = frozenCol;
if (indexes[0] >= viewportIndexes[0] && indexes[0] < viewportIndexes[2] && indexes[1] >= viewportIndexes[1] &&
indexes[1] < viewportIndexes[3]) {
return;
}
}
}
var content = this.getMainContent().parentElement;
var vTrack;
var cVTrack;
var offset;
var vWidth;
var vHeight;
var scrollableSize;
if (indexes[0] === frozenRow) {
offset = 0;
}
else {
offset = getRowsHeight(sheet, frozenRow, indexes[0] - 1, true);
if (this.scrollSettings.enableVirtualization) {
scrollableSize = offset + this.getContentTable().getBoundingClientRect().height;
vHeight = parseFloat(content.querySelector('.e-virtualtrack').style.height);
if (scrollableSize > vHeight) {
scrollableSize += 10;
vTrack = content.querySelector('.e-virtualtrack');
vTrack.style.height = scrollableSize + "px";
getUpdateUsingRaf(function () { vTrack.style.height = vHeight + "px"; });
}
}
}
content.scrollTop = offset;
content = this.element.getElementsByClassName('e-scroller')[0];
if (indexes[1] === frozenCol) {
offset = 0;
}
else {
offset = getColumnsWidth(sheet, frozenCol, indexes[1] - 1, true);
if (this.scrollSettings.enableVirtualization) {
scrollableSize = offset + this.getContentTable().getBoundingClientRect().width;
vWidth = parseFloat(content.querySelector('.e-virtualtrack').style.width);
if (scrollableSize > vWidth) {
scrollableSize += 10;
vTrack = content.querySelector('.e-virtualtrack');
vTrack.style.width = scrollableSize + "px";
cVTrack = this.getColumnHeaderContent().querySelector('.e-virtualtrack');
cVTrack.style.width = scrollableSize + "px";
vTrack = this.getMainContent().querySelector('.e-virtualtrack');
vTrack.style.width = scrollableSize + "px";
getUpdateUsingRaf(function () {
vTrack.style.width = vWidth + "px";
cVTrack.style.width = vWidth + "px";
});
}
}
}
content.scrollLeft = offset;
if (!insideDomCount) {
this.selectRange(address);
}
};
/**
* @hidden
* @param {number} rowIndex - Specifies the row index.
* @param {number} colIndex - Specifies the column index.
* @returns {boolean} - Specifies the boolean value.
*/
Spreadsheet.prototype.insideViewport = function (rowIndex, colIndex) {
var sheet = this.getActiveSheet();
if (sheet.frozenRows || sheet.frozenColumns) {
var frozenRow = this.frozenRowCount(sheet);
var frozenCol = this.frozenColCount(sheet);
var indexes = getCellIndexes(sheet.topLeftCell);
return ((rowIndex >= indexes[0] && rowIndex < frozenRow) || (rowIndex >= this.viewport.topIndex + frozenRow && rowIndex <=
this.viewport.bottomIndex)) && ((colIndex >= indexes[1] && colIndex < frozenCol) || (colIndex >= this.viewport.leftIndex +
frozenCol && colIndex <= this.viewport.rightIndex));
}
else {
return rowIndex >= this.viewport.topIndex && rowIndex <= this.viewport.bottomIndex && colIndex >= this.viewport.leftIndex &&
colIndex <= this.viewport.rightIndex;
}
};
/**
* Used to resize the Spreadsheet.
*
* {% codeBlock src='spreadsheet/resize/index.md' %}{% endcodeBlock %}
*
* @returns {void} - Used to resize the Spreadsheet.
*/
Spreadsheet.prototype.resize = function () {
this.renderModule.setSheetPanelSize();
if (this.scrollSettings.enableVirtualization) {
this.renderModule.refreshSheet(false, true);
}
};
/**
* To cut the specified cell or cells properties such as value, format, style etc...
*
* {% codeBlock src='spreadsheet/cut/index.md' %}{% endcodeBlock %}
*
* @param {string} address - Specifies the range address to cut.
* @returns {Promise<Object>} - To cut the specified cell or cells properties such as value, format, style etc...
*/
Spreadsheet.prototype.cut = function (address) {
var promise = new Promise(function (resolve) { resolve((function () { })()); });
this.notify(cut, address ? {
range: getIndexesFromAddress(address),
sId: this.sheets[getSheetIndex(this, getSheetNameFromAddress(address))] ?
this.sheets[getSheetIndex(this, getSheetNameFromAddress(address))].id : this.getActiveSheet().id,
promise: promise, invokeCopy: true, isPublic: true
} : { promise: promise, invokeCopy: true, isPublic: true });
return promise;
};
/**
* To copy the specified cell or cells properties such as value, format, style etc...
*
* {% codeBlock src='spreadsheet/copy/index.md' %}{% endcodeBlock %}
*
* @param {string} address - Specifies the range address.
* @returns {Promise<Object>} - To copy the specified cell or cells properties such as value, format, style etc...
*/
Spreadsheet.prototype.copy = function (address) {
var promise = new Promise(function (resolve) { resolve((function () { })()); });
this.notify(copy, address ? {
range: getIndexesFromAddress(address),
sId: this.sheets[getSheetIndex(this, getSheetNameFromAddress(address))] ?
this.sheets[getSheetIndex(this, getSheetNameFromAddress(address))].id : this.getActiveSheet().id,
promise: promise, invokeCopy: true, isPublic: true
} : { promise: promise, invokeCopy: true, isPublic: true });
return promise;
};
/**
* This method is used to paste the cut or copied cells in to specified address.
*
* {% codeBlock src='spreadsheet/paste/index.md' %}{% endcodeBlock %}
*
* @param {string} address - Specifies the cell or range address.
* @param {PasteSpecialType} type - Specifies the type of paste.
* @returns {void} - used to paste the cut or copied cells in to specified address.
*/
Spreadsheet.prototype.paste = function (address, type) {
this.notify(paste, {
range: address ? getIndexesFromAddress(address) : address,
sIdx: address ? getSheetIndex(this, getSheetNameFromAddress(address)) : address,
type: type, isAction: true, isInternal: true
});
};
/**
* To update the action which need to perform.
*
* {% codeBlock src='spreadsheet/updateAction/index.md' %}{% endcodeBlock %}
*
* @param {string} options - It describes an action and event args to perform.
* @param {string} options.action - specifies an action.
* @param {string} options.eventArgs - specifies an args to perform an action.
* @returns {void} - To update the action which need to perform.
*/
Spreadsheet.prototype.updateAction = function (options) {
updateAction(options, this);
};
Spreadsheet.prototype.setHeight = function () {
if (this.height) {
if (this.height.toString().indexOf('%') > -1) {
this.element.style.minHeight = '400px';
}
this.element.style.height = formatUnit(this.height);
}
};
Spreadsheet.prototype.setWidth = function () {
if (this.width) {
if (this.width.toString().indexOf('%') > -1 || this.width === 'auto') {
this.element.style.minWidth = '300px';
}
this.element.style.width = formatUnit(this.width);
}
};
/**
* Set the width of column.
*
* {% codeBlock src='spreadsheet/setColWidth/index.md' %}{% endcodeBlock %}
*
* @param {number} width - To specify the width
* @param {number} colIndex - To specify the colIndex
* @param {number} sheetIndex - To specify the sheetIndex
* @returns {void} - Set the width of column.
*/
Spreadsheet.prototype.setColWidth = function (width, colIndex, sheetIndex) {
if (width === void 0) { width = 64; }
if (colIndex === void 0) { colIndex = 0; }
var sheet = isNullOrUndefined(sheetIndex) ? this.getActiveSheet() : this.sheets[sheetIndex];
if (sheet && (!sheet.isProtected || sheet.protectSettings.formatColumns)) {
var mIndex_1 = colIndex;
var colWidth_1 = (typeof width === 'number') ? width + 'px' : width;
colIndex = isNullOrUndefined(colIndex) ? getCellIndexes(sheet.activeCell)[1] : colIndex;
var setColModel = function () {
getColumn(sheet, mIndex_1).width = parseInt(colWidth_1, 10) > 0 ? parseInt(colWidth_1, 10) : 0;
sheet.columns[mIndex_1].customWidth = true;
};
var frozenCol = this.frozenColCount(sheet);
if (sheet.id === this.getActiveSheet().id) {
if ((colIndex >= this.viewport.leftIndex + frozenCol && colIndex <= this.viewport.rightIndex) ||
(frozenCol && colIndex < frozenCol)) {
colIndex = this.getViewportIndex(colIndex, true);
var eleWidth = getColumnWidth(sheet, mIndex_1, null, true);
var threshold = getDPRValue(parseInt(colWidth_1, 10)) - eleWidth;
if (threshold < 0 && eleWidth < -(threshold)) {
threshold = -eleWidth;
}
setColModel();
this.notify(colWidthChanged, { threshold: threshold, colIdx: mIndex_1, checkWrapCell: true });
setResize(mIndex_1, colIndex, colWidth_1, true, this);
}
else {
var oldWidth = getColumnWidth(sheet, colIndex);
var threshold = void 0;
if (parseInt(colWidth_1, 10) > 0) {
threshold = -(oldWidth - parseInt(colWidth_1, 10));
}
else {
threshold = -oldWidth;
}
setColModel();
this.notify(colWidthChanged, { threshold: threshold, colIdx: colIndex });
}
this.notify(positionAutoFillElement, null);
}
else {
setColModel();
}
}
};
/**
* Set the height of row.
*
* {% codeBlock src='spreadsheet/setRowHeight/index.md' %}{% endcodeBlock %}
*
* @param {number} height - Specifies height needs to be updated. If not specified, it will set the default height 20.
* @param {number} rowIndex - Specifies the row index. If not specified, it will consider the first row.
* @param {number} sheetIndex - Specifies the sheetIndex. If not specified, it will consider the active sheet.
* @param {boolean} edited - Specifies the boolean value.
* @param {boolean} skipCustomRow - When this parameter is enabled, the method will skip updating the row height if it has already been modified and its 'customHeight' property is set to true.
* @returns {void} - Set the height of row.
*/
Spreadsheet.prototype.setRowHeight = function (height, rowIndex, sheetIndex, edited, skipCustomRow) {
if (height === void 0) { height = 20; }
if (rowIndex === void 0) { rowIndex = 0; }
var sheet = isNullOrUndefined(sheetIndex) ? this.getActiveSheet() : this.sheets[sheetIndex];
if (sheet) {
var mIndex_2 = rowIndex;
rowIndex = isNullOrUndefined(rowIndex) ? getCellIndexes(sheet.activeCell)[0] : rowIndex;
if (skipCustomRow && sheet.rows[rowIndex] && sheet.rows[rowIndex].customHeight) {
return;
}
var rowHeight_1 = (typeof height === 'number') ? height + 'px' : height;
var setRowModel = function () {
setRowHeight(sheet, mIndex_2, parseInt(rowHeight_1, 10) > 0 ? parseInt(rowHeight_1, 10) : 0);
sheet.rows[mIndex_2].customHeight = true;
};
if (sheet.id === this.getActiveSheet().id) {
var frozenRow = this.frozenRowCount(sheet);
if ((rowIndex >= this.viewport.topIndex + frozenRow && rowIndex <= this.viewport.bottomIndex) ||
(frozenRow && rowIndex < frozenRow)) {
rowIndex = this.getViewportIndex(mIndex_2);
var eleHeight = getRowHeight(sheet, mIndex_2, true);
var threshold = getDPRValue(parseInt(rowHeight_1, 10)) - eleHeight;
if (threshold < 0 && eleHeight < -(threshold)) {
threshold = -eleHeight;
}
setRowModel();
this.notify(rowHeightChanged, { threshold: threshold, rowIdx: mIndex_2, isCustomHgt: true });
if (isNullOrUndefined(edited)) {
edited = false;
}
if (!edited) {
setResize(mIndex_2, rowIndex, rowHeight_1, false, this);
edited = false;
}
}
else {
var oldHeight = getRowHeight(sheet, rowIndex);
var threshold = void 0;
if (parseInt(rowHeight_1, 10) > 0) {
threshold = -(oldHeight - parseInt(rowHeight_1, 10));
}
else {
threshold = -oldHeight;
}
setRowModel();
this.notify(rowHeightChanged, { threshold: threshold, rowIdx: mIndex_2 });
}
this.notify(positionAutoFillElement, null);
}
else {
setRowModel();
}
}
};
/**
* Allows you to set the height to the single or multiple rows.
*
* @param {number} height - Specifies the height for row.
* @param {string[]} ranges - Specifies the row range to set the height. If the sheet name is not specified then height will apply to
* the rows in the active sheet. Possible values are
* * Single row range: ['2'] or ['2:2']
* * Multiple rows range: ['1:100']
* * Multiple rows with discontinuous range - ['1:10', '15:25', '30:40']
* * Multiple rows with different sheets - ['Sheet1!1:50', 'Sheet2!1:50', 'Sheet3!1:50'].
* @param {boolean} skipCustomRows - When this parameter is enabled, it will skip updating the heights of rows where the height has already been modified, and its 'customHeight' property is set to true.
* @returns {void}
*/
Spreadsheet.prototype.setRowsHeight = function (height, ranges, skipCustomRows) {
if (height === void 0) { height = 20; }
if (!ranges) {
ranges = [1 + ":" + (this.getActiveSheet().usedRange.rowIndex + 1)];
}
this.setSize(height, ranges, function (idx) { return Number(idx) - 1; }, this.setRowHeight.bind(this), skipCustomRows);
};
/**
* Allows you to set the width to the single or multiple columns.
*
* @param {number} width - Specifies the width for column.
* @param {string[]} ranges - Specifies the column range to set the width. If the sheet name is not specified then width will apply to
* the column in the active sheet. Possible values are
* * Single column range: ['F'] or ['F:F']
* * Multiple columns range: ['A:F']
* * Multiple columns with discontinuous range - ['A:C', 'G:I', 'K:M']
* * Multiple columns with different sheets - ['Sheet1!A:H', 'Sheet2!A:H', 'Sheet3!A:H'].
* @returns {void}
*/
Spreadsheet.prototype.setColumnsWidth = function (width, ranges) {
if (width === void 0) { width = 64; }
if (!ranges) {
ranges = ["A:" + getColumnHeaderText(this.getActiveSheet().usedRange.colIndex + 1)];
}
this.setSize(width, ranges, function (headerText) { return getColIndex(headerText); }, this.setColWidth.bind(this));
};
Spreadsheet.prototype.setSize = function (width, ranges, getIndex, updateSize, skipCustomRows) {
var _this = this;
var sheetIdx;
var rangeArr;
var sheetName;
var startIdx;
var endIdx;
ranges.forEach(function (range) {
if (range.includes('!')) {
sheetName = range.substring(0, range.lastIndexOf('!'));
sheetIdx = getSheetIndex(_this, sheetName);
range = range.substring(range.lastIndexOf('!') + 1);
}
else {
sheetIdx = _this.activeSheetIndex;
}
if (range.includes(':')) {
rangeArr = range.split(':');
startIdx = getIndex(rangeArr[0]);
endIdx = getIndex(rangeArr[1]);
}
else {
startIdx = endIdx = getIndex(range);
}
for (var idx = startIdx; idx <= endIdx; idx++) {
updateSize(width, idx, sheetIdx, false, skipCustomRows);
}
});
};
/**
* This method is used to autofit the range of rows or columns
*
* {% codeBlock src='spreadsheet/autoFit/index.md' %}{% endcodeBlock %}
*
* @param {string} range - range of rows or columns that needs to be autofit.
*
* @returns {void} - used to autofit the range of rows or columns
* ```html
* <div id='Spreadsheet'></div>
* ```
* ```typescript
* let spreadsheet = new Spreadsheet({
* allowResizing: true
* ...
* }, '#Spreadsheet');
* spreadsheet.autoFit('A:D'); // Auto fit from A to D columns
* Spreadsheet.autoFit('1:4'); // Auto fit from 1 to 4 rows
*
* ```
*/
Spreadsheet.prototype.autoFit = function (range) {
var sheetIdx;
if (range.indexOf('!') !== -1) {
sheetIdx = getSheetIndex(this, range.substring(0, range.lastIndexOf('!')));
range = range.substring(range.lastIndexOf('!') + 1);
}
var values = this.getIndexes(range);
var startIdx = values.startIdx;
var endIdx = values.endIdx;
var isCol = values.isCol;
var maximumColInx = isCol ? getColIndex('XFD') : 1048576;
if (startIdx <= maximumColInx) {
if (endIdx > maximumColInx) {
endIdx = maximumColInx;
}
}
else {
return;
}
for (startIdx; startIdx <= endIdx; startIdx++) {
this.notify(setAutoFit, { idx: startIdx, isCol: isCol, sheetIdx: sheetIdx });
}
};
/**
* @hidden
* @param {string} range - specify the range.
* @returns {number | boolean} - to get the index.
*
*/
Spreadsheet.prototype.getIndexes = function (range) {
var startIsCol;
var endIsCol;
var start;
var end;
if (range.indexOf(':') !== -1) {
var starttoend = range.split(':');
start = starttoend[0];
end = starttoend[1];
}
else {
start = range;
end = range;
}
if (!isNullOrUndefined(start)) {
var startValues = this.getAddress(start);
start = startValues.address;
startIsCol = startValues.isCol;
}
if (!isNullOrUndefined(end)) {
var endValues = this.getAddress(end);
end = endValues.address;
endIsCol = endValues.isCol;
}
var isCol = startIsCol === true && endIsCol === true ? true : false;
var startIdx = isCol ? getColIndex(start.toUpperCase()) : parseInt(start, 10);
var endIdx = isCol ? getColIndex(end.toUpperCase()) : parseInt(end, 10);
return { startIdx: startIdx, endIdx: endIdx, isCol: isCol };
};
Spreadsheet.prototype.getAddress = function (address) {
var isCol;
if (address.substring(0, 1).match(/\D/g)) {
isCol = true;
address = address.replace(/[0-9]/g, '');
return { address: address, isCol: isCol };
}
else if (address.substring(0, 1).match(/[0-9]/g) && address.match(/\D/g)) {
return { address: '', isCol: false };
}
else {
address = (parseInt(address, 10) - 1).toString();
return { address: address, isCol: isCol };
}
};
/**
* To add the hyperlink in the cell
*
* {% codeBlock src='spreadsheet/addHyperlink/index.md' %}{% endcodeBlock %}
*
* @param {string | HyperlinkModel} hyperlink - to specify the hyperlink