• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IgniteUI / igniteui-angular / 13331632524

14 Feb 2025 02:51PM CUT coverage: 22.015% (-69.6%) from 91.622%
13331632524

Pull #15372

github

web-flow
Merge d52d57714 into bcb78ae0a
Pull Request #15372: chore(*): test ci passing

1990 of 15592 branches covered (12.76%)

431 of 964 new or added lines in 18 files covered. (44.71%)

19956 existing lines in 307 files now uncovered.

6452 of 29307 relevant lines covered (22.02%)

249.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

5.77
/projects/igniteui-angular/src/lib/services/excel/excel-exporter.ts
1
import { zip } from 'fflate';
2

3
import { EventEmitter, Injectable } from '@angular/core';
4
import { ExcelElementsFactory } from './excel-elements-factory';
5
import { ExcelFolderTypes } from './excel-enums';
6
import { IgxExcelExporterOptions } from './excel-exporter-options';
7
import { IExcelFolder } from './excel-interfaces';
8
import { ExportRecordType, IExportRecord, IgxBaseExporter, DEFAULT_OWNER, ExportHeaderType, GRID_LEVEL_COL } from '../exporter-common/base-export-service';
9
import { ExportUtilities } from '../exporter-common/export-utilities';
10
import { WorksheetData } from './worksheet-data';
11
import { IBaseEventArgs } from '../../core/utils';
12
import { WorksheetFile } from './excel-files';
13

14
export interface IExcelExportEndedEventArgs extends IBaseEventArgs {
15
    xlsx?: Object
16
}
17

18
const EXCEL_MAX_ROWS = 1048576;
2✔
19
const EXCEL_MAX_COLS = 16384;
2✔
20

21
/**
22
 * **Ignite UI for Angular Excel Exporter Service** -
23
 * [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/exporter_excel.html)
24
 *
25
 * The Ignite UI for Angular Excel Exporter service can export data in Microsoft® Excel® format from both raw data
26
 * (array) or from an `IgxGrid`.
27
 *
28
 * Example:
29
 * ```typescript
30
 * public localData = [
31
 *   { Name: "Eric Ridley", Age: "26" },
32
 *   { Name: "Alanis Brook", Age: "22" },
33
 *   { Name: "Jonathan Morris", Age: "23" }
34
 * ];
35
 *
36
 * constructor(private excelExportService: IgxExcelExporterService) {
37
 * }
38
 *
39
 * this.excelExportService.exportData(this.localData, new IgxExcelExporterOptions("FileName"));
40
 * ```
41
 */
42
@Injectable({
43
    providedIn: 'root',
44
})
45
export class IgxExcelExporterService extends IgxBaseExporter {
2✔
46

47
    /**
48
     * This event is emitted when the export process finishes.
49
     * ```typescript
50
     * this.exporterService.exportEnded.subscribe((args: IExcelExportEndedEventArgs) => {
51
     * // put event handler code here
52
     * });
53
     * ```
54
     *
55
     * @memberof IgxExcelExporterService
56
     */
UNCOV
57
    public override exportEnded = new EventEmitter<IExcelExportEndedEventArgs>();
×
58

59
    private static async populateZipFileConfig(fileStructure: Object, folder: IExcelFolder, worksheetData: WorksheetData) {
UNCOV
60
        for (const childFolder of folder.childFolders(worksheetData)) {
×
UNCOV
61
            const folderInstance = ExcelElementsFactory.getExcelFolder(childFolder);
×
UNCOV
62
            const childStructure = fileStructure[folderInstance.folderName] = {};
×
UNCOV
63
            await IgxExcelExporterService.populateZipFileConfig(childStructure, folderInstance, worksheetData);
×
64
        }
65

UNCOV
66
        for (const childFile of folder.childFiles(worksheetData)) {
×
UNCOV
67
            const fileInstance = ExcelElementsFactory.getExcelFile(childFile);
×
UNCOV
68
            if (fileInstance instanceof WorksheetFile) {
×
UNCOV
69
                await (fileInstance as WorksheetFile).writeElementAsync(fileStructure, worksheetData);
×
70
            } else {
UNCOV
71
                fileInstance.writeElement(fileStructure, worksheetData);
×
72
            }
73
        }
74
    }
75

76
    protected exportDataImplementation(data: IExportRecord[], options: IgxExcelExporterOptions, done: () => void): void {
UNCOV
77
        const firstDataElement = data[0];
×
UNCOV
78
        const isHierarchicalGrid = firstDataElement?.type === ExportRecordType.HierarchicalGridRecord;
×
UNCOV
79
        const isPivotGrid = firstDataElement?.type === ExportRecordType.PivotGridRecord;
×
80

81
        let rootKeys;
82
        let columnCount;
83
        let columnWidths;
84
        let indexOfLastPinnedColumn;
85
        let defaultOwner;
86

UNCOV
87
        const columnsExceedLimit = typeof firstDataElement !== 'undefined' ?
×
88
            isHierarchicalGrid ?
×
UNCOV
89
                data.some(d => Object.keys(d.data).length > EXCEL_MAX_COLS) :
×
90
                Object.keys(firstDataElement.data).length > EXCEL_MAX_COLS :
91
            false;
92

UNCOV
93
        if (data.length > EXCEL_MAX_ROWS || columnsExceedLimit) {
×
94
            throw Error('The Excel file can contain up to 1,048,576 rows and 16,384 columns.');
×
95
        }
96

UNCOV
97
        if (typeof firstDataElement !== 'undefined') {
×
UNCOV
98
            let maxLevel = 0;
×
99

UNCOV
100
            data.forEach((r) => {
×
UNCOV
101
                maxLevel = Math.max(maxLevel, r.level);
×
102
            });
103

UNCOV
104
            if (maxLevel > 7) {
×
UNCOV
105
                throw Error('Can create an outline of up to eight levels!');
×
106
            }
107

UNCOV
108
            if (isHierarchicalGrid) {
×
UNCOV
109
                columnCount = data
×
UNCOV
110
                    .map(a => this._ownersMap.get(a.owner).columns.filter(c => !c.skip).length + a.level)
×
UNCOV
111
                    .sort((a, b) => b - a)[0];
×
112

UNCOV
113
                rootKeys = this._ownersMap.get(firstDataElement.owner).columns.filter(c => !c.skip).map(c => c.field);
×
UNCOV
114
                defaultOwner = this._ownersMap.get(firstDataElement.owner);
×
115
            } else {
UNCOV
116
                defaultOwner = this._ownersMap.get(DEFAULT_OWNER);
×
UNCOV
117
                const columns = defaultOwner.columns.filter(col => col.field !== GRID_LEVEL_COL && !col.skip && col.headerType === ExportHeaderType.ColumnHeader);
×
118

UNCOV
119
                columnWidths = defaultOwner.columnWidths;
×
UNCOV
120
                indexOfLastPinnedColumn = defaultOwner.indexOfLastPinnedColumn;
×
UNCOV
121
                columnCount = isPivotGrid ? columns.length + this.pivotGridFilterFieldsCount : columns.length;
×
UNCOV
122
                rootKeys = columns.map(c => c.field);
×
123
            }
124
        } else {
UNCOV
125
            const ownersKeys = Array.from(this._ownersMap.keys());
×
126

UNCOV
127
            defaultOwner = this._ownersMap.get(ownersKeys[0]);
×
UNCOV
128
            columnWidths = defaultOwner.columnWidths;
×
UNCOV
129
            columnCount = defaultOwner.columns.filter(col => col.field !== GRID_LEVEL_COL && !col.skip && col.headerType === ExportHeaderType.ColumnHeader).length;
×
130
        }
131

132
        const worksheetData =
UNCOV
133
            new WorksheetData(data, options, this._sort, columnCount, rootKeys, indexOfLastPinnedColumn,
×
134
                columnWidths, defaultOwner, this._ownersMap);
135

UNCOV
136
        const rootFolder = ExcelElementsFactory.getExcelFolder(ExcelFolderTypes.RootExcelFolder);
×
UNCOV
137
        const fileData = {};
×
UNCOV
138
        IgxExcelExporterService.populateZipFileConfig(fileData, rootFolder, worksheetData)
×
139
            .then(() => {
UNCOV
140
                zip(fileData, (_, result) => {
×
UNCOV
141
                    this.saveFile(result, options.fileName);
×
UNCOV
142
                    this.exportEnded.emit({ xlsx: fileData });
×
UNCOV
143
                    done();
×
144
                });
145
            });
146
    }
147

148
    private saveFile(data: Uint8Array, fileName: string): void {
UNCOV
149
        const blob = new Blob([data], {
×
150
            type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
151
        });
152

UNCOV
153
        ExportUtilities.saveBlobToFile(blob, fileName);
×
154
    }
155
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc