Skip to content

Commit d6ea358

Browse files
authored
Merge pull request #6972 from IgniteUI/mkirova/row-pinning-export-to-excel
Row pinning + export to excel
2 parents 2548f43 + 6620240 commit d6ea358

File tree

9 files changed

+92
-18
lines changed

9 files changed

+92
-18
lines changed

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

+11
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,17 @@ describe('Excel Exporter', () => {
214214
await wrapper.verifyDataFilesContent(actualData.gridJobTitleIdFrozen, 'Not all pinned columns are frozen in the export!');
215215
});
216216

217+
it('should honor all pinned rows.', async() => {
218+
const result = await TestMethods.createGridAndPinRow(0, 2);
219+
const fix = result.fixture;
220+
const grid = result.grid;
221+
222+
const wrapper = await getExportedData(grid, options);
223+
wrapper.verifyStructure();
224+
await wrapper.verifyPinRowData('<pane ySplit="3" topLeftCell="A4" activePane="topRight" state="frozen"/>',
225+
'Not all pinned rows are frozen in the export!');
226+
});
227+
217228
it('should honor applied sorting.', async () => {
218229
const fix = TestBed.createComponent(GridIDNameJobTitleComponent);
219230
fix.detectChanges();

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ export class IgxExcelExporterService extends IgxBaseExporter {
7777
}
7878
}
7979

80-
const worksheetData = new WorksheetData(data, options, this._indexOfLastPinnedColumn, this._sort, this._isTreeGrid);
80+
const worksheetData = new WorksheetData(data, options, this._indexOfLastPinnedColumn,
81+
this._indexOfLastPinnedRow, this._sort, this._isTreeGrid);
8182
this._xlsx = new JSZip();
8283

8384
const rootFolder = ExcelElementsFactory.getExcelFolder(ExcelFolderTypes.RootExcelFolder);

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

+17-6
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,23 @@ export class WorksheetFile implements IExcelFile {
116116

117117
cols.push('</cols>');
118118

119-
if (worksheetData.indexOfLastPinnedColumn !== -1 &&
120-
!worksheetData.options.ignorePinning &&
121-
!worksheetData.options.ignoreColumnsOrder) {
122-
const frozenColumnCount = worksheetData.indexOfLastPinnedColumn + 1;
123-
const firstCell = ExcelStrings.getExcelColumn(frozenColumnCount) + '1';
124-
freezePane = `<pane xSplit="${frozenColumnCount}" topLeftCell="${firstCell}" activePane="topRight" state="frozen"/>`;
119+
const hasFrozenElements = !worksheetData.options.ignorePinning &&
120+
(worksheetData.indexOfLastPinnedColumn !== -1 || worksheetData.indexOfLastPinnedRow !== -1);
121+
122+
if (hasFrozenElements) {
123+
const hasFrozenCols = !worksheetData.options.ignoreColumnsOrder && worksheetData.indexOfLastPinnedColumn !== -1;
124+
const hasFrozenRows = worksheetData.indexOfLastPinnedRow !== -1;
125+
126+
const frozenColumnCount = hasFrozenCols ? worksheetData.indexOfLastPinnedColumn + 1 : null;
127+
const frozenRowCount = hasFrozenRows ? worksheetData.indexOfLastPinnedRow + 2 : null;
128+
129+
const frozenColumn = !hasFrozenCols ? 'A' : ExcelStrings.getExcelColumn(frozenColumnCount);
130+
const firstCell = frozenColumn + (frozenRowCount + 1);
131+
132+
const xSplit = hasFrozenCols ? `xSplit="${frozenColumnCount}" ` : '';
133+
const ySplit = hasFrozenRows ? `ySplit="${frozenRowCount}" ` : '';
134+
const xySplit = (xSplit + ySplit).trim();
135+
freezePane = `<pane ${xySplit} topLeftCell="${firstCell}" activePane="topRight" state="frozen"/>`;
125136
}
126137
}
127138
const hasTable = !worksheetData.isEmpty && worksheetData.options.exportAsTable;

projects/igniteui-angular/src/lib/services/excel/jszip-verification-wrapper.spec.ts

+8
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ export class JSZipWrapper {
141141
});
142142
}
143143

144+
public async verifyPinRowData(pinData: string, message = '') {
145+
let result;
146+
await this.readDataFiles().then(() => {
147+
result = this.dataFilesContent[1];
148+
expect(result.fileContent.indexOf(pinData) !== -1).toBeTruthy(message);
149+
});
150+
}
151+
144152
/* Verifies the contents of all files and asserts the result.
145153
Optionally, a message can be passed in, which, if specified, will be shown in the beginning of the comparison result. */
146154
public async verifyFilesContent(expectedData: IFileContent[], message = '') {

projects/igniteui-angular/src/lib/services/excel/worksheet-data.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export class WorksheetData {
1111
private _isSpecialData: boolean;
1212

1313
constructor(private _data: any[], public options: IgxExcelExporterOptions, public indexOfLastPinnedColumn,
14-
public sort: any, public isTreeGridData = false) {
14+
public indexOfLastPinnedRow, public sort: any, public isTreeGridData = false) {
1515
this.initializeData();
1616
}
1717

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

+10
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export abstract class IgxBaseExporter {
7272

7373
protected _isTreeGrid = false;
7474
protected _indexOfLastPinnedColumn = -1;
75+
protected _indexOfLastPinnedRow = -1;
7576
protected _sort = null;
7677

7778
/**
@@ -289,6 +290,14 @@ export abstract class IgxBaseExporter {
289290
}
290291
}
291292

293+
if (grid.hasPinnedRecords) {
294+
295+
const pinnedRecs = data.filter(x => grid.isRecordPinned(x));
296+
const unpinnedRecs = data.filter(x => !grid.isRecordPinned(x));
297+
data = [ ...pinnedRecs, ... unpinnedRecs];
298+
this._indexOfLastPinnedRow = pinnedRecs.length - 1;
299+
}
300+
292301
return data;
293302
}
294303

@@ -307,6 +316,7 @@ export abstract class IgxBaseExporter {
307316
private resetDefaults() {
308317
this._columnList = [];
309318
this._indexOfLastPinnedColumn = -1;
319+
this._indexOfLastPinnedRow = -1;
310320
this._sort = null;
311321
this.flatRecords = [];
312322
}

projects/igniteui-angular/src/lib/services/exporter-common/test-methods.spec.ts

+17
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,21 @@ export class TestMethods {
5050
return { fixture: fix, grid: myGrid };
5151
}
5252

53+
54+
/* Creates an instance of GridDeclarationComponent and pins the rows with the specified indices. */
55+
public static async createGridAndPinRow(...rowIndices: any[]) {
56+
const fix = TestBed.createComponent(GridIDNameJobTitleComponent);
57+
fix.detectChanges();
58+
await wait(16);
59+
60+
const myGrid = fix.componentInstance.grid;
61+
62+
// Pin columns
63+
rowIndices.forEach((i) => {
64+
myGrid.getRowByIndex(i).pin();
65+
});
66+
67+
return { fixture: fix, grid: myGrid };
68+
}
69+
5370
}

src/app/grid-row-pinning/grid-row-pinning.sample.html

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Allows rows to be pinned to the beginning/end of the grid.
44
</app-page-header>
55
<button (click)="grid1.addRow({'ID': 'TEST', 'CompanyName': 'Test'})">Add Row</button>
6+
<button (click)="exportButtonHandler()">Export</button>
67
<div class="sample-content">
78
<div class="sample-column">
89
<div class="sample-buttons">

src/app/grid-row-pinning/grid-row-pinning.sample.ts

+25-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
import { Component, OnInit, ViewChild } from '@angular/core';
2-
import { IgxGridComponent, ColumnPinningPosition, RowPinningPosition, IgxGridRowComponent, IgxTransactionService, IgxGridTransaction, IgxGridStateDirective } from 'igniteui-angular';
2+
import {
3+
IgxGridComponent,
4+
ColumnPinningPosition,
5+
RowPinningPosition, IgxGridRowComponent,
6+
IgxTransactionService,
7+
IgxGridTransaction,
8+
IgxGridStateDirective,
9+
IgxExcelExporterService,
10+
IgxExcelExporterOptions
11+
} from 'igniteui-angular';
312
import { IPinningConfig } from 'projects/igniteui-angular/src/lib/grids/common/grid.interface';
413

514
@Component({
@@ -23,13 +32,16 @@ export class GridRowPinningSampleComponent implements OnInit {
2332
columns: false,
2433
rowPinning: true,
2534
pinningConfig: true
26-
};
35+
};
2736

2837
@ViewChild('grid1', { static: true })
2938
grid1: IgxGridComponent;
3039

3140
@ViewChild(IgxGridStateDirective, { static: true }) public state: IgxGridStateDirective;
3241

42+
constructor(private excelExportService: IgxExcelExporterService) {
43+
}
44+
3345
onRowChange() {
3446
if (this.pinningConfig.rows === RowPinningPosition.Bottom) {
3547
this.pinningConfig = { columns: this.pinningConfig.columns, rows: RowPinningPosition.Top };
@@ -42,7 +54,7 @@ export class GridRowPinningSampleComponent implements OnInit {
4254
if (this.pinningConfig.columns === ColumnPinningPosition.End) {
4355
this.pinningConfig = { columns: ColumnPinningPosition.Start, rows: this.pinningConfig.rows };
4456
} else {
45-
this.pinningConfig = { columns: ColumnPinningPosition.End, rows: this.pinningConfig.rows };
57+
this.pinningConfig = { columns: ColumnPinningPosition.End, rows: this.pinningConfig.rows };
4658
}
4759
}
4860

@@ -53,7 +65,7 @@ export class GridRowPinningSampleComponent implements OnInit {
5365
this.columns = [
5466
{ field: 'ID', width: '200px', hidden: true },
5567
{ field: 'CompanyName', width: '200px', groupable: true },
56-
{ field: 'ContactName', width: '200px', pinned: false, groupable: true },
68+
{ field: 'ContactName', width: '200px', pinned: false, groupable: true },
5769
{ field: 'ContactTitle', width: '300px', pinned: false, groupable: true },
5870
{ field: 'Address', width: '250px' },
5971
{ field: 'City', width: '200px' },
@@ -98,28 +110,31 @@ export class GridRowPinningSampleComponent implements OnInit {
98110

99111
togglePinRow(index) {
100112
const rec = this.data[index];
101-
this.grid1.isRecordPinned(rec)?
102-
this.grid1.pinRow(this.data[index]) :
103-
this.grid1.unpinRow(this.data[index])
113+
this.grid1.isRecordPinned(rec) ?
114+
this.grid1.pinRow(this.data[index]) :
115+
this.grid1.unpinRow(this.data[index])
104116
}
105117

106118
togglePining(row: IgxGridRowComponent, event) {
107119
event.preventDefault();
108-
if(row.pinned) {
120+
if (row.pinned) {
109121
row.unpin();
110122
} else {
111123
row.pin();
112124
}
113125
}
114126

127+
public exportButtonHandler() {
128+
this.excelExportService.export(this.grid1, new IgxExcelExporterOptions("ExportFileFromGrid"));
129+
}
130+
115131
public saveGridState() {
116132
const state = this.state.getState() as string;
117133
window.localStorage.setItem("grid1-state", state);
118134
}
119-
135+
120136
public restoreGridState() {
121137
const state = window.localStorage.getItem("grid1-state");
122138
this.state.setState(state);
123139
}
124-
125140
}

0 commit comments

Comments
 (0)