diff --git a/cell/api.js b/cell/api.js index 5151838cec..ade9e932c1 100644 --- a/cell/api.js +++ b/cell/api.js @@ -7038,7 +7038,9 @@ var editor; if (!pivotTable) { return false; } - this._addWorksheets([this.asc_createSheetName()], this.wbModel.getActive(), function(worksheets){ + const indexes = pivotTable.getItemsIndexesByActiveCell(activeCell.row, activeCell.col); + const itemMapArray = pivotTable.getNoFilterItemFieldsMapArray(indexes.rowItemIndex, indexes.colItemIndex) + this._addWorksheets([pivotTable.getShowDetailsSheetName(itemMapArray)], this.wbModel.getActive(), function(worksheets){ let ws = worksheets[0]; if (!ws) { return; @@ -7046,7 +7048,7 @@ var editor; History.Create_NewPoint(); History.StartTransaction(); - let lengths = pivotTable.showDetails(ws, activeCell.row, activeCell.col); + let lengths = pivotTable.showDetails(ws, itemMapArray); let range = new Asc.Range(0, 0, lengths.colLength, lengths.rowLength); let ref = range.getAbsName(); diff --git a/cell/model/PivotTables.js b/cell/model/PivotTables.js index 694e9368b1..83587a4030 100644 --- a/cell/model/PivotTables.js +++ b/cell/model/PivotTables.js @@ -2598,7 +2598,7 @@ CT_PivotCacheRecords.prototype.updateCacheData = function() { }; /** * @param {Worksheet} ws - * @param {Map.} itemMap + * @param {PivotItemFieldsMap} itemMap * @param {CT_CacheFields} cacheFields * @return {boolean[]} */ @@ -2624,7 +2624,7 @@ CT_PivotCacheRecords.prototype.getRowMapByItemMap = function(itemMap, cacheField * @param {Worksheet} ws * @param {Map} rowMap rows to copy * @param {CT_CacheFields} cacheFields - * @return {Object} + * @return {FillPivotDetailsLengths} */ CT_PivotCacheRecords.prototype.copyRowsToWorksheet = function(ws, rowMap, cacheFields) { let rowsAddedByMap = 0; @@ -2658,11 +2658,16 @@ CT_PivotCacheRecords.prototype.copyRowsToWorksheet = function(ws, rowMap, cacheF colLength: this._cols.length - 1, }; }; +/** + * @typedef FillPivotDetailsLengths + * @property {number} rowLength + * @property {number} colLength + */ /** * @param {Worksheet} ws - * @param {Map.} itemMap + * @param {PivotItemFieldsMap} itemMap * @param {CT_CacheFields} cacheFields - * @return {Object} lengths + * @return {FillPivotDetailsLengths} lengths */ CT_PivotCacheRecords.prototype.fillPivotDetails = function(ws, itemMap, cacheFields) { let cacheFieldsWithoutGroups = cacheFields.filter(function(field, index) { @@ -3871,11 +3876,16 @@ CT_pivotTableDefinition.prototype.getPivotTableButtons = function (range, button } this._getPivotLabelButtons(range, buttons); }; +/** + * @typedef ItemsIndexesByActiveCell + * @property {number} rowItemIndex + * @property {number} colItemIndex + */ /** * Returns the rowItems and colItems indexes in the pivot table for the active cell (row, column) * @param {number} row cell's row in editor * @param {number} col cell's col in editor - * @return {Object} + * @return {ItemsIndexesByActiveCell | null} */ CT_pivotTableDefinition.prototype.getItemsIndexesByActiveCell = function(row, col) { let pivotRange = this.getRange(); @@ -6938,79 +6948,148 @@ CT_pivotTableDefinition.prototype._groupDiscreteAddFields = function(fld, parFld } } }; - +/** + * @typedef {[number, number][]} PivotItemFieldsMapArray + * [pivotFieldIndex, fieldItemIndex] array which describes the item by the all fields of the pivot table + */ /** - * Returns an array that stores the Map(Set-like map)>, - * which describes the values of this item in each field - * @param {number} rowItemIndex item index rowItems array. - * @param {number} colItemIndex item index colItems array. - * @return {Map.} + * @param {number} rowItemIndex + * @param {number} colItemIndex + * @return {PivotItemFieldsMapArray} [pivotFieldIndex, fieldItem.x] array */ -CT_pivotTableDefinition.prototype.getItemFieldsMap = function(rowItemIndex, colItemIndex) { - let rowItems = this.getRowItems(); - let colItems = this.getColItems(); - let rowFields = this.asc_getRowFields(); - let colFields = this.asc_getColumnFields(); - let filterMaps = this.getFilterMaps({}); - let searchRowItem = rowItems && rowItems[rowItemIndex]; - let searchColItem = colItems && colItems[colItemIndex]; - let pivotFields = this.asc_getPivotFields(); - let result = new Map(); - filterMaps.labelFilters.forEach(function (filter) { - result.set(filter.index, filter.map); - }); +CT_pivotTableDefinition.prototype.getNoFilterItemFieldsMapArray = function(rowItemIndex, colItemIndex) { + const rowItems = this.getRowItems(); + const colItems = this.getColItems(); + const rowFields = this.asc_getRowFields(); + const colFields = this.asc_getColumnFields(); + const searchRowItem = rowItems && rowItems[rowItemIndex]; + const searchColItem = colItems && colItems[colItemIndex]; + const pivotFields = this.asc_getPivotFields(); + const result = []; + function getRowColFieldsMap(searchItemIndex, rowColFields, items) { - let searchItem = items[searchItemIndex]; + const searchItem = items[searchItemIndex]; let r = null; function getIndexes(item, length) { - for (let i = 0; i < item.x.length && i < length; i+= 1) { - let x = item.x[i]; - let pivotFieldIndex = rowColFields[item.getR() + i].asc_getIndex(); + for (let i = length - 1; i >= 0; i -= 1) { + const x = item.x[i]; + const pivotFieldIndex = rowColFields[item.getR() + i].asc_getIndex(); if (pivotFieldIndex !== AscCommonExcel.st_VALUES) { - let res = new Map(); - let fieldItem = pivotFields[pivotFieldIndex].getItem(x.getV()); - res.set(fieldItem.x, 1); - result.set(pivotFieldIndex, res); + const fieldItem = pivotFields[pivotFieldIndex].getItem(x.getV()); + result.unshift([pivotFieldIndex, fieldItem.x]); } } r = item.getR() - 1; } getIndexes(searchItem, searchItem.x.length); for (let i = searchItemIndex - 1; i >= 0 && r >= 0; i-= 1) { - let item = items[i]; + const item = items[i]; if (item.getR() <= r) { getIndexes(item, r - item.getR() + 1); } } } + if (searchColItem && searchColItem.t !== Asc.c_oAscItemType.Grand) { + getRowColFieldsMap(colItemIndex, colFields, colItems); + } if (searchRowItem && searchRowItem.t !== Asc.c_oAscItemType.Grand) { getRowColFieldsMap(rowItemIndex, rowFields, rowItems); } - if (searchColItem && searchColItem.t !== Asc.c_oAscItemType.Grand) { - getRowColFieldsMap(colItemIndex, colFields, colItems); + return result; +} +/** @typedef {Map} PivotItemFieldsMap */ +/** + * Returns Map(Set-like map)>, + * which describes the values of this item in each field with filters. + * @param {PivotItemFieldsMapArray} itemFieldsMapArray + * @return {PivotItemFieldsMap} + */ +CT_pivotTableDefinition.prototype.getItemFieldsMap = function(itemFieldsMapArray) { + const filterMaps = this.getFilterMaps({}); + const result = new Map(); + filterMaps.labelFilters.forEach(function (filter) { + result.set(filter.index, filter.map); + }); + for(let i = 0; i < itemFieldsMapArray.length; i += 1) { + const value = itemFieldsMapArray[i]; + const pivotFieldIndex = value[0]; + const fieldItemIndex = value[1]; + const res = new Map(); + res.set(fieldItemIndex, 1); + result.set(pivotFieldIndex, res); } return result; }; /** * @param {Worksheet} ws - * @param {number} row - * @param {number} col + * @param {PivotItemFieldsMapArray} arrayFieldItemsMap * @return {Object} */ -CT_pivotTableDefinition.prototype.showDetails = function(ws, row, col) { - let rowItems = this.getRowItems(); - let colItems = this.getColItems(); - let indexes = this.getItemsIndexesByActiveCell(row, col); - if (indexes === null || rowItems[indexes.rowItemIndex].t === Asc.c_oAscItemType.Blank || colItems[indexes.colItemIndex].t === Asc.c_oAscItemType.Blank) { - return false; - } - let itemMap = this.getItemFieldsMap(indexes.rowItemIndex, indexes.colItemIndex); - let cacheFields = this.asc_getCacheFields(); - let records = this.getRecords(); +CT_pivotTableDefinition.prototype.showDetails = function(ws, arrayFieldItemsMap) { + const itemMap = this.getItemFieldsMap(arrayFieldItemsMap); + const cacheFields = this.asc_getCacheFields(); + const records = this.getRecords(); return records.fillPivotDetails(ws, itemMap, cacheFields); }; - +/** + * @param {PivotItemFieldsMapArray} arrayFieldItemsMap + * @return {string} sheetName + */ +CT_pivotTableDefinition.prototype.getShowDetailsSheetName = function(arrayFieldItemsMap) { + /** + * @param {RegExp} re + * @param {string[]} arr + * @return {number} + */ + function reIndexOf(re, arr) { + for(let i = 0; i < arr.length; i += 1) { + const str = arr[i]; + if (re.test(str)) { + return i; + } + } + return -1; + } + const cacheFields = this.asc_getCacheFields(); + const workbook = this.worksheet.workbook; + const api = workbook.oApi; + const translatedInfoString = AscCommon.translateManager.getValue('Info'); + let postfix = ''; + arrayFieldItemsMap.forEach(function(value) { + const fieldIndex = value[0]; + const itemIndex = value[1]; + const cacheField = cacheFields[fieldIndex]; + const sharedItem = cacheField.getGroupOrSharedItem(itemIndex); + if (sharedItem) { + const cellValue = sharedItem.getCellValue(); + const numFormat = cacheField.num && cacheField.num.getNumFormat(); + let res = cellValue.getTextValue(); + if (numFormat && cellValue.type === AscCommon.CellValueType.Number) { + res = numFormat.formatToMathInfo(cellValue.number, AscCommon.CellValueType.Number, AscCommon.gc_nMaxDigCountView); + } + postfix += '-' + res; + } + }); + const sheetNames = []; + const wc = api.asc_getWorksheetsCount(); + for(let i = 0; i < wc; i += 1) { + sheetNames.push(api.asc_getWorksheetName(i)); + } + let prefix; + for (let i = 1; ; i += 1) { + prefix = translatedInfoString + String(i); + const re = new RegExp('^' + prefix + '(-|$)'); + if (reIndexOf(re, sheetNames) === -1) { + break; + } + } + let result = prefix + postfix; + if (result.length > AscCommonExcel.g_nSheetNameMaxLength) { + result = result.substring(0, AscCommonExcel.g_nSheetNameMaxLength); + } + return result; +} CT_pivotTableDefinition.prototype.asc_canShowDetails = function(row, col) { let indexes = this.getItemsIndexesByActiveCell(row, col); if (indexes === null) { @@ -9859,9 +9938,15 @@ CT_CacheField.prototype.getSharedItem = function (index) { CT_CacheField.prototype.getSharedSize = function () { return this.sharedItems && this.sharedItems.Items.getSize() || 0; }; +/** + * @return {CT_SharedItems | CT_FieldGroup | null} + */ CT_CacheField.prototype.getGroupOrSharedItems = function () { return (this.fieldGroup && this.fieldGroup.groupItems) || this.sharedItems; }; +/** + * @return {PivotRecords | CT_FieldGroup | null} + */ CT_CacheField.prototype.getGroupOrSharedItem = function (index) { var sharedItems = this.getGroupOrSharedItems(); return sharedItems && sharedItems.Items.get(index); diff --git a/cell/model/Workbook.js b/cell/model/Workbook.js index 15c4a6f45b..2e1796084a 100644 --- a/cell/model/Workbook.js +++ b/cell/model/Workbook.js @@ -2809,7 +2809,7 @@ return -1; }; Workbook.prototype.checkValidSheetName=function(name){ - return (name && name.length < g_nSheetNameMaxLength); + return (name && name.length <= g_nSheetNameMaxLength); }; Workbook.prototype.getUniqueSheetNameFrom=function(name, bCopy){ var nIndex = 1; @@ -19114,6 +19114,7 @@ window['AscCommonExcel'] = window['AscCommonExcel'] || {}; window['AscCommonExcel'].g_nVerticalTextAngle = g_nVerticalTextAngle; + window['AscCommonExcel'].g_nSheetNameMaxLength = g_nSheetNameMaxLength; window['AscCommonExcel'].oDefaultMetrics = oDefaultMetrics; window['AscCommonExcel'].g_nAllColIndex = g_nAllColIndex; window['AscCommonExcel'].g_nAllRowIndex = g_nAllRowIndex; diff --git a/tests/cell/spreadsheet-calculation/PivotTests.js b/tests/cell/spreadsheet-calculation/PivotTests.js index 5ab76c736b..a83043fb14 100644 --- a/tests/cell/spreadsheet-calculation/PivotTests.js +++ b/tests/cell/spreadsheet-calculation/PivotTests.js @@ -5981,7 +5981,9 @@ var wb, ws, wsData, pivotStyle, tableName, defNameName, defNameLocalName, report undoStandard[i].fill(""); } let res = checkHistoryOperation2(assert, pivot, standard, message, undoStandard, function () { - pivot.showDetails(wsDetails, row, col); + const indexes = pivot.getItemsIndexesByActiveCell(row, col); + const arrayItemFieldsMap = pivot.getNoFilterItemFieldsMapArray(indexes.rowItemIndex, indexes.colItemIndex) + pivot.showDetails(wsDetails, arrayItemFieldsMap); }, function (assert, pivot, standard, message) { let cells = []; for (let i = 0; i < standard.length; i += 1) {