import * as XLSX from \'xlsx\'; export class ExcelSheet { public name: string; public headers: string[]; public data: any[]; } export class ExcelResolverService { private _fileReader = new FileReader(); private _rowRegex = new RegExp("^([A-Z])(\\d+)$"); private _errorCallback:any = null; private _successCallback:any = null; public set onError(errorCallback:(ex: any) => void) { this._errorCallback = errorCallback; } public set onSuccess(successCallback:(sheets: ExcelSheet[]) => void){ this._successCallback = successCallback; } private get reader(): {type:string, method:() => void}{ if (this.file.name.endsWith(".csv")){ return {type:"string", method: () => this._fileReader.readAsText(this.file)}; } return {type:"buffer", method: () => this._fileReader.readAsArrayBuffer(this.file)}; } constructor(private file: File, private resolverOption: any = {headerRowIndex : 1}){ this._fileReader.onload = fileEvent => { try { let result = fileEvent.target.result; let workbook = XLSX.read(result, {type: this.reader.type}); let sheets: ExcelSheet[] = new Array<ExcelSheet>(); for(let i = 0; i < workbook.SheetNames.length; i ++){ let [headers, data] = this.resolveSheet(workbook.Sheets["Sheet" + (i + 1)]); let sheet = new ExcelSheet(); sheet.name = workbook.SheetNames[i]; sheet.headers = headers; sheet.data = data; sheets.push(sheet); } if(this._successCallback != null) this._successCallback(sheets); } catch (e) { if(this._errorCallback != null) this._errorCallback(e); } }; this.reader.method(); } private resolveSheet(sheet: any): [string[], any[]]{ let columns = new Map<string, any[]>(); let headers = new Map<string, string>(); for(let row in sheet){ let match = this._rowRegex.exec(row); if (match != null && match.length == 3){ let [key, index, value] = [match[1], match[2], sheet[row].w === undefined || sheet[row].w === null ? sheet[row].v : sheet[row].w]; if (match[2] == this.resolverOption.headerRowIndex.toString()) headers.set(key, value); else { if (!columns.has(key)) columns.set(key, new Array()); columns.get(key).push({index, data:{[headers.has(key)?headers.get(key):key]:value}}); } } } if (headers.size > 0 || columns.size > 0){ let container = new Map<number, any>(); columns.forEach(columnValue => { columnValue.forEach(value => { if (container.has(value.index)) Object.assign(container.get(value.index), value.data); else container.set(value.index, Object.assign(this.buildDataStructure(headers), value.data)); }); }); return [Array.from(headers.values()), Array.from(container) .sort((left, right) => left[0] - right[0]) .map(value => value[1])]; } return [null, null]; } private buildDataStructure(headers: Map<string, string>){ let result = {}; headers.forEach(value => Object.assign(result, {[value]: null})); return result; } }