suchenge
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;
    }

}

 

分类:

技术点:

相关文章: