Skip to content

Commit 83af0f1

Browse files
authored
Merge pull request #14476 from IgniteUI/mkirova/pivot-horizontal-excel-export
Pivot horizontal excel export
2 parents d99b71b + 45dcd41 commit 83af0f1

File tree

5 files changed

+65
-15
lines changed

5 files changed

+65
-15
lines changed

projects/igniteui-angular/src/lib/services/excel/excel-exporter-grid.spec.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import { IgxHierarchicalGridComponent } from '../../grids/hierarchical-grid/publ
4343
import { IgxHierarchicalRowComponent } from '../../grids/hierarchical-grid/hierarchical-row.component';
4444
import { GridFunctions } from '../../test-utils/grid-functions.spec';
4545
import { IgxPivotGridMultipleRowComponent, IgxPivotGridTestComplexHierarchyComponent } from '../../test-utils/pivot-grid-samples.spec';
46-
import { IgxPivotGridComponent } from '../../grids/pivot-grid/public_api';
46+
import { IgxPivotGridComponent, PivotRowLayoutType } from '../../grids/pivot-grid/public_api';
4747

4848
describe('Excel Exporter', () => {
4949
configureTestSuite();
@@ -1396,6 +1396,33 @@ describe('Excel Exporter', () => {
13961396

13971397
await exportAndVerify(grid, options, actualData.exportPivotGridHierarchicalData, false);
13981398
});
1399+
1400+
it('should export pivot grid with horizontal row layout.', async () => {
1401+
fix = TestBed.createComponent(IgxPivotGridMultipleRowComponent);
1402+
fix.detectChanges();
1403+
1404+
grid = fix.componentInstance.pivotGrid;
1405+
grid.pivotUI.showRowHeaders = true;
1406+
grid.pivotUI.rowLayout = PivotRowLayoutType.Horizontal;
1407+
grid.pivotConfiguration.rows = [{
1408+
memberName: 'ProductCategory',
1409+
memberFunction: (data) => data.ProductCategory,
1410+
enabled: true,
1411+
childLevel:{
1412+
memberName: 'Country',
1413+
enabled: true,
1414+
childLevel: {
1415+
memberName: 'Date',
1416+
enabled: true
1417+
}
1418+
}
1419+
}],
1420+
fix.detectChanges();
1421+
await wait(300);
1422+
fix.detectChanges();
1423+
1424+
await exportAndVerify(grid, options, actualData.exportPivotGridDataHorizontal, false);
1425+
});
13991426
});
14001427

14011428
const getExportedData = (grid, exportOptions: IgxExcelExporterOptions) => {

projects/igniteui-angular/src/lib/services/excel/excel-files.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ export class WorksheetFile implements IExcelFile {
153153

154154
const allowedColumns = owner.columns.filter(c => c.headerType !== ExportHeaderType.RowHeader &&
155155
c.headerType !== ExportHeaderType.MultiRowHeader &&
156-
c.headerType !== ExportHeaderType.PivotRowHeader);
156+
c.headerType !== ExportHeaderType.PivotRowHeader &&
157+
c.headerType !== ExportHeaderType.PivotMergedHeader);
157158

158159
headersForLevel = hasMultiColumnHeader ?
159160
allowedColumns
@@ -607,7 +608,7 @@ export class WorksheetFile implements IExcelFile {
607608
for (const currentCol of headersForLevel) {
608609
const spanLength = isVertical ? currentCol.rowSpan : currentCol.columnSpan;
609610

610-
if (currentCol.level === i) {
611+
if (currentCol.level === i && currentCol.headerType !== ExportHeaderType.PivotMergedHeader) {
611612
let columnCoordinate;
612613
const column = isVertical
613614
? this.rowIndex
@@ -670,6 +671,10 @@ export class WorksheetFile implements IExcelFile {
670671
: this.sheetData += str
671672
}
672673
}
674+
if ((currentCol.headerType === ExportHeaderType.RowHeader || currentCol.headerType === ExportHeaderType.MultiRowHeader) &&
675+
currentCol.columnSpan && currentCol.columnSpan > 1 ) {
676+
columnCoordinate = ExcelStrings.getExcelColumn(column + currentCol.columnSpan - 1) + (rowCoordinate + spanLength - 1);
677+
}
673678

674679
this.mergeCellStr += `${columnCoordinate}" />`;
675680
}

projects/igniteui-angular/src/lib/services/excel/test-data.service.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,15 @@ export class FileContentData {
16401640
return this.createData();
16411641
}
16421642

1643+
public get exportPivotGridDataHorizontal() {
1644+
this._sharedStringsData =
1645+
`count="41" uniqueCount="26"><si><t>ProductCategory</t></si><si><t>Accessories</t></si><si><t>Bikes</t></si><si><t>Clothing</t></si><si><t>Components</t></si><si><t>Country</t></si><si><t>USA</t></si><si><t>Uruguay</t></si><si><t>Bulgaria</t></si><si><t>Date</t></si><si><t>04/07/2021</t></si><si><t>01/06/2020</t></si><si><t>01/05/2019</t></si><si><t>05/12/2020</t></si><si><t>01/01/2021</t></si><si><t>02/19/2020</t></si><si><t>12/08/2021</t></si><si><t>Stanley</t></si><si><t>Elisa</t></si><si><t>Lydia</t></si><si><t>David</t></si><si><t>John</t></si><si><t>Larry</t></si><si><t>Walter</t></si><si><t>UnitsSold</t></si><si><t>UnitPrice</t></si>`;
1646+
1647+
this._worksheetData =
1648+
`<sheetPr><outlinePrsummaryBelow="0"/></sheetPr><dimensionref="A1:Q9"/><sheetViews><sheetViewtabSelected="1"workbookViewId="0"><panexSplit="3"ySplit="0"topLeftCell="D1"activePane="topRight"state="frozen"/></sheetView></sheetViews><sheetFormatPrdefaultRowHeight="15"outlineLevelRow="2"x14ac:dyDescent="0.25"/><cols><colmin="1"max="17"width="15"customWidth="1"/></cols><sheetData><rowr="1"><cr="A1"s="4"t="s"><v>0</v></c><cr="B1"s="4"t="s"><v>5</v></c><cr="C1"s="4"t="s"><v>9</v></c><cr="D1"t="s"><v>17</v></c><cr="E1"/><cr="F1"t="s"><v>18</v></c><cr="G1"/><cr="H1"t="s"><v>19</v></c><cr="I1"/><cr="J1"t="s"><v>20</v></c><cr="K1"/><cr="L1"t="s"><v>21</v></c><cr="M1"/><cr="N1"t="s"><v>22</v></c><cr="O1"/><cr="P1"t="s"><v>23</v></c><cr="Q1"/></row><rowr="2"><cr="C2"s="4"/><cr="D2"t="s"><v>24</v></c><cr="E2"t="s"><v>25</v></c><cr="F2"t="s"><v>24</v></c><cr="G2"t="s"><v>25</v></c><cr="H2"t="s"><v>24</v></c><cr="I2"t="s"><v>25</v></c><cr="J2"t="s"><v>24</v></c><cr="K2"t="s"><v>25</v></c><cr="L2"t="s"><v>24</v></c><cr="M2"t="s"><v>25</v></c><cr="N2"t="s"><v>24</v></c><cr="O2"t="s"><v>25</v></c><cr="P2"t="s"><v>24</v></c><cr="Q2"t="s"><v>25</v></c></row><rowr="3"outlineLevel="2"><cr="A3"s="4"t="s"><v>1</v></c><cr="B3"s="4"t="s"><v>6</v></c><cr="C3"s="4"t="s"><v>10</v></c><cr="D3"s="1"/><cr="E3"s="1"/><cr="F3"s="1"/><cr="G3"s="1"/><cr="H3"s="1"/><cr="I3"s="1"/><cr="J3"s="1"><v>293</v></c><cr="K3"s="5"><v>85.58</v></c><cr="L3"s="1"/><cr="M3"s="1"/><cr="N3"s="1"/><cr="O3"s="1"/><cr="P3"s="1"/><cr="Q3"s="1"/></row><rowr="4"outlineLevel="2"><cr="A4"s="4"t="s"><v>2</v></c><cr="B4"s="4"t="s"><v>7</v></c><cr="C4"s="4"t="s"><v>11</v></c><cr="D4"s="1"/><cr="E4"s="1"/><cr="F4"s="1"/><cr="G4"s="1"/><cr="H4"s="1"><v>68</v></c><cr="I4"s="5"><v>3.56</v></c><cr="J4"s="1"/><cr="K4"s="1"/><cr="L4"s="1"/><cr="M4"s="1"/><cr="N4"s="1"/><cr="O4"s="1"/><cr="P4"s="1"/><cr="Q4"s="1"/></row><rowr="5"outlineLevel="2"><cr="A5"s="4"t="s"><v>3</v></c><cr="B5"s="4"t="s"><v>6</v></c><cr="C5"s="4"t="s"><v>12</v></c><cr="D5"s="1"><v>282</v></c><cr="E5"s="5"><v>12.81</v></c><cr="F5"s="1"/><cr="G5"s="1"/><cr="H5"s="1"/><cr="I5"s="1"/><cr="J5"s="1"/><cr="K5"s="1"/><cr="L5"s="1"/><cr="M5"s="1"/><cr="N5"s="1"/><cr="O5"s="1"/><cr="P5"s="1"/><cr="Q5"s="1"/></row><rowr="6"outlineLevel="2"><cr="A6"s="4"/><cr="B6"s="4"t="s"><v>7</v></c><cr="C6"s="4"t="s"><v>13</v></c><cr="D6"s="1"/><cr="E6"s="1"/><cr="F6"s="1"/><cr="G6"s="1"/><cr="H6"s="1"/><cr="I6"s="1"/><cr="J6"s="1"/><cr="K6"s="1"/><cr="L6"s="1"/><cr="M6"s="1"/><cr="N6"s="1"/><cr="O6"s="1"/><cr="P6"s="1"><v>492</v></c><cr="Q6"s="5"><v>16.05</v></c></row><rowr="7"outlineLevel="2"><cr="A7"s="4"/><cr="B7"s="4"t="s"><v>8</v></c><cr="C7"s="4"t="s"><v>14</v></c><cr="D7"s="1"/><cr="E7"s="1"/><cr="F7"s="1"><v>296</v></c><cr="G7"s="5"><v>49.57</v></c><cr="H7"s="1"/><cr="I7"s="1"/><cr="J7"s="1"/><cr="K7"s="1"/><cr="L7"s="1"/><cr="M7"s="1"/><cr="N7"s="1"/><cr="O7"s="1"/><cr="P7"s="1"/><cr="Q7"s="1"/></row><rowr="8"outlineLevel="2"><cr="B8"s="4"/><cr="C8"s="4"t="s"><v>15</v></c><cr="D8"s="1"/><cr="E8"s="1"/><cr="F8"s="1"/><cr="G8"s="1"/><cr="H8"s="1"/><cr="I8"s="1"/><cr="J8"s="1"/><cr="K8"s="1"/><cr="L8"s="1"/><cr="M8"s="1"/><cr="N8"s="1"><v>456</v></c><cr="O8"s="5"><v>68.33</v></c><cr="P8"s="1"/><cr="Q8"s="1"/></row><rowr="9"outlineLevel="2"><cr="A9"s="4"t="s"><v>4</v></c><cr="B9"s="4"t="s"><v>6</v></c><cr="C9"s="4"t="s"><v>16</v></c><cr="D9"s="1"/><cr="E9"s="1"/><cr="F9"s="1"/><cr="G9"s="1"/><cr="H9"s="1"/><cr="I9"s="1"/><cr="J9"s="1"/><cr="K9"s="1"/><cr="L9"s="1"><v>240</v></c><cr="M9"s="5"><v>18.13</v></c><cr="N9"s="1"/><cr="O9"s="1"/><cr="P9"s="1"/><cr="Q9"s="1"/></row></sheetData><mergeCellscount="27"><mergeCellref="A1:A2"/><mergeCellref="A3:A3"/><mergeCellref="A4:A4"/><mergeCellref="A5:A8"/><mergeCellref="A9:A9"/><mergeCellref="B1:B2"/><mergeCellref="B3:B3"/><mergeCellref="B4:B4"/><mergeCellref="B5:B5"/><mergeCellref="B6:B6"/><mergeCellref="B7:B8"/><mergeCellref="B9:B9"/><mergeCellref="C1:C2"/><mergeCellref="C3:C3"/><mergeCellref="C4:C4"/><mergeCellref="C5:C5"/><mergeCellref="C6:C6"/><mergeCellref="C7:C7"/><mergeCellref="C8:C8"/><mergeCellref="C9:C9"/><mergeCellref="D1:E1"/><mergeCellref="F1:G1"/><mergeCellref="H1:I1"/><mergeCellref="J1:K1"/><mergeCellref="L1:M1"/><mergeCellref="N1:O1"/><mergeCellref="P1:Q1"/></mergeCells>`;
1649+
return this.createData();
1650+
}
1651+
16431652
public get exportPivotGridHierarchicalData() {
16441653
this._sharedStringsData =
16451654
`count="40" uniqueCount="19"><si><t>All Cities</t></si><si><t>Ciudad de la Costa</t></si><si><t>London</t></si><si><t>New York</t></si><si><t>Plovdiv</t></si><si><t>Sofia</t></si><si><t>Yokohama</t></si><si><t>AllProducts</t></si><si><t>Bikes</t></si><si><t>Clothing</t></si><si><t>Accessories</t></si><si><t>Components</t></si><si><t>Bulgaria</t></si><si><t>US</t></si><si><t>Uruguay</t></si><si><t>UK</t></si><si><t>Japan</t></si><si><t>UnitsSold</t></si><si><t>Amount of Sale</t></si>`;

projects/igniteui-angular/src/lib/services/exporter-common/base-export-service.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export enum ExportHeaderType {
3232
MultiRowHeader = 'MultiRowHeader',
3333
MultiColumnHeader = 'MultiColumnHeader',
3434
PivotRowHeader = 'PivotRowHeader',
35+
PivotMergedHeader = 'PivotMergedHeader',
3536
}
3637

3738
export interface IExportRecord {
@@ -259,7 +260,7 @@ export abstract class IgxBaseExporter {
259260
this.pivotGridKeyValueMap = new Map<string, string>();
260261
this.pivotGridRowDimensionsMap = new Map<string, string>();
261262

262-
grid.pivotConfiguration.rows.filter(r => r.enabled).forEach(rowDimension => {
263+
grid.visibleRowDimensions.filter(r => r.enabled).forEach(rowDimension => {
263264
this.addToRowDimensionsMap(rowDimension, rowDimension.memberName);
264265
});
265266

@@ -1278,7 +1279,7 @@ export abstract class IgxBaseExporter {
12781279
private addPivotRowHeaders(grid: any) {
12791280
if (grid?.pivotUI?.showRowHeaders) {
12801281
const headersList = this._ownersMap.get(DEFAULT_OWNER);
1281-
const enabledRows = grid.pivotConfiguration.rows.filter(r => r.enabled).map((r, index) => ({ name: r.displayName || r.memberName, level: index }));
1282+
const enabledRows = grid.visibleRowDimensions.filter(r => r.enabled).map((r, index) => ({ name: r.displayName || r.memberName, level: index }));
12821283
let startIndex = 0;
12831284
enabledRows.forEach(x => {
12841285
headersList.columns.unshift({
@@ -1303,7 +1304,7 @@ export abstract class IgxBaseExporter {
13031304
return;
13041305
}
13051306

1306-
const enabledRows = grid.pivotConfiguration.rows.filter(r => r.enabled).map((r, i) => ({ name: r.memberName, level: i }));
1307+
const enabledRows = grid.visibleRowDimensions.map((r, i) => ({ name: r.memberName, level: i }));
13071308

13081309
this.preparePivotGridColumns(enabledRows);
13091310
this.pivotGridFilterFieldsCount = enabledRows.length;
@@ -1325,7 +1326,6 @@ export abstract class IgxBaseExporter {
13251326
const key = keys[0];
13261327
const records = this.flatRecords.map(r => r.data);
13271328
const groupedRecords = {};
1328-
13291329
records.forEach(obj => {
13301330
const keyValue = obj[key.name];
13311331
if (!groupedRecords[keyValue]) {
@@ -1349,32 +1349,41 @@ export abstract class IgxBaseExporter {
13491349
}
13501350

13511351
for (const k of Object.keys(groupedRecords)) {
1352+
let groupKey = k;
13521353
const rowSpan = groupedRecords[k].length;
13531354

1355+
13541356
const rowDimensionColumn: IColumnInfo = {
1357+
columnSpan: 1,
13551358
rowSpan,
1356-
field: k,
1357-
header: k,
1359+
field: groupKey,
1360+
header: groupKey,
13581361
startIndex,
13591362
skip: false,
13601363
pinnedIndex: 0,
13611364
level: key.level,
13621365
dataType: 'string',
1363-
headerType: groupedRecords[k].length > 1 ? ExportHeaderType.MultiRowHeader : ExportHeaderType.RowHeader,
1366+
headerType: groupedRecords[groupKey].length > 1 ? ExportHeaderType.MultiRowHeader : ExportHeaderType.RowHeader,
13641367
};
1365-
1368+
if (groupKey === 'undefined') {
1369+
this.pivotGridColumns[this.pivotGridColumns.length - 1].columnSpan += 1;
1370+
rowDimensionColumn.headerType = ExportHeaderType.PivotMergedHeader;
1371+
groupKey = columnGroupParent;
1372+
}
13661373
if (columnGroupParent) {
13671374
rowDimensionColumn.columnGroupParent = columnGroupParent;
13681375
} else {
1369-
rowDimensionColumn.columnGroup = k;
1376+
rowDimensionColumn.columnGroup = groupKey;
13701377
}
13711378

13721379
this.pivotGridColumns.push(rowDimensionColumn);
13731380

13741381
if (keys.length > 1) {
1375-
this.pivotGridKeyValueMap.set(key.name, k);
1382+
if (groupKey !== columnGroupParent) {
1383+
this.pivotGridKeyValueMap.set(key.name, groupKey);
1384+
}
13761385
const newKeys = keys.filter(kdd => kdd !== key);
1377-
this.preparePivotGridColumns(newKeys, k)
1386+
this.preparePivotGridColumns(newKeys, groupKey)
13781387
this.pivotGridKeyValueMap.delete(key.name);
13791388
}
13801389

src/app/pivot-grid-hierarchy/pivot-grid-hierarchy.sample.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88

99
<button (click)="exportButtonHandler()">Export To Excel</button><br />
1010
</div>
11-
<igx-pivot-grid [pivotUI]="{ showRowHeaders: true }" [superCompactMode]="true" #grid1 [data]="origData" [pivotConfiguration]="pivotConfigHierarchy" (dimensionsChange)="dimensionChange()" [defaultExpandState]="true">
11+
<igx-pivot-grid [pivotUI]="{ showRowHeaders: true, rowLayout: 'horizontal' }" [superCompactMode]="true" #grid1 [data]="origData" [pivotConfiguration]="pivotConfigHierarchy" (dimensionsChange)="dimensionChange()" [defaultExpandState]="true">
1212
</igx-pivot-grid>
1313

0 commit comments

Comments
 (0)