Angular Pegar cuadrícula de Excel

    The Ignite UI for Angular IgxGrid can read Excel data that is copied to the clipboard. In this section we will show you how to do this with some custom code.

    Angular Paste from Excel Example

    This sample demonstrates how to implement pasting from Excel into the igxGrid Material UI table. To work with the sample open up any Excel spreadsheet, copy some rows, and paste it into the grid using the keyboard (Ctrl + V, Shift + Insert, Command + V).

    En la parte superior hay un botón desplegable con 2 opciones:

    1. "Pegar datos como filas nuevas": en este modo, cualquier dato copiado de Excel se agregará a la cuadrícula como filas nuevas.
    2. "Pegar desde la celda activa": en este modo se sobrescribirán los datos de la cuadrícula.

    Los nuevos datos después del pegado están decorados en cursiva.

    Usage

    You should add the paste-handler directive (you can find its code in the next section) to the igxGrid and handle its onDataProcessed event. The onDataProcessed event has one parameter that gives you access to the Excel data in the form of an array. For reference see the addRecords and updateRecords methods.

    <igx-grid #grid1 [data]="data" [width]="'100%'" [height]="'505px'" [autoGenerate]="false" paste-handler (onDataProcessed)="dataPasted($event)" [primaryKey]="'ID'">
        <igx-column [field]="'Name'"></igx-column>
        <igx-column [field]="'Title'"></igx-column>
        <igx-column [field]="'Phone'"></igx-column>
        <igx-column [field]="'Country'"></igx-column>
    </igx-grid>
    
        public dataPasted(processedData) {
            if (this.pasteMode === "Paste data as new records") {
                this.addRecords(processedData);
            } else {
                this.updateRecords(processedData);
            }
        }
    
        public addRecords(processedData: any[]) {
            const columns = this.grid1.visibleColumns;
            const pk = this.grid1.primaryKey;
            const addedData = [];
            for (const curentDataRow of processedData) {
                const rowData = {};
                for (const col of columns) {
                    rowData[col.field] = curentDataRow[col.visibleIndex];
                }
                // generate PK
                rowData[pk] = this.grid1.data.length + 1;
                this.grid1.addRow(rowData);
                addedData.push(rowData);
                this.grid1.cdr.detectChanges();
            }
            // scroll to last added row
            this.grid1.verticalScrollContainer.scrollTo(this.grid1.data.length);
    
            this.grid1.verticalScrollContainer.chunkLoad.pipe(take(1)).subscribe(() => {
                this.clearStyles();
                for (const data of addedData) {
                    const row = this.grid1.getRowByKey(data[pk]);
                    if (row) {
                        row.nativeElement.style["font-style"] = "italic";
                        row.nativeElement.style.color = "gray";
                    }
                }
            });
        }
        public updateRecords(processedData: any[]) {
            const cell = this.grid1.selectedCells[0];
            const pk = this.grid1.primaryKey;
            if (!cell) { return; }
            const rowIndex = cell.row.index;
            // const rowPkValue = cell.row.data[pk];
            const cellIndex = cell.column.visibleIndex;
            const columns = this.grid1.visibleColumns;
            let index = 0;
            const updatedRecsPK = [];
            for (const curentDataRow of processedData) {
                const rowData = {};
                const dataRec = this.grid1.data[rowIndex + index];
                const rowPkValue = dataRec ? dataRec[pk] : this.grid1.data.length + 1;
                rowData[pk] = rowPkValue;
                for (let j = 0; j < columns.length; j++) {
                    let currentCell;
                    if (j >= cellIndex) {
                        currentCell = curentDataRow.shift();
                    }
                    const colKey = columns[j].field;
                    rowData[colKey] = currentCell || (!!dataRec ? dataRec[colKey] : null);
                }
                if (!dataRec) {
                    // no rec to update, add instead
                    rowData[pk] = rowPkValue;
                    this.grid1.addRow(rowData);
                    continue;
                }
                this.grid1.updateRow(rowData, rowPkValue);
                this.grid1.cdr.detectChanges();
                updatedRecsPK.push(rowPkValue);
                index++;
            }
    
            this.clearStyles();
            for (const pkVal of updatedRecsPK) {
                const row = this.grid1.getRowByKey(pkVal);
                if (row) {
                row.nativeElement.style["font-style"] = "italic";
                row.nativeElement.style.color = "gray";
                }
            }
        }
    
        protected clearStyles() {
            for (const row of this.grid1.rowList.toArray()) {
                row.nativeElement.style["font-style"] = "";
                row.nativeElement.style.color = "";
            }
        }
    

    Paste Handler Directive

    This is the paste-handler implementation. The code creates a DOM textarea element which is used to receive the pasted data from the clipboard. When the data is pasted in the textarea the directive parses it into an array and then emits a custom event onDataProcessed passing the parsed data.

    import { Directive, EventEmitter, HostListener, Output} from "@angular/core";
    
    @Directive({ selector: "[paste-handler]" })
    export class PasteHandler {
        public textArea;
    
        @Output()
        public onDataProcessed = new EventEmitter<any>();
    
        public ngOnInit(): void {
            const div = document.createElement("div");
            const divStyle = div.style;
            divStyle.position = "fixed";
            document.body.appendChild(div);
            this.textArea = document.createElement("textarea");
            const style = this.textArea.style;
            style.opacity = "0";
            style.height = "0px";
            style.width = "0px";
            style.overflow = "hidden";
            div.appendChild(this.textArea);
    
            this.textArea.addEventListener("paste", (eventArgs) => { this.onPaste(eventArgs); });
        }
    
        @HostListener("focusin", ["$event"])
        public focusIn(eventArgs) {
        }
    
        @HostListener("keydown", ["$event"])
        public ControlV(eventArgs) {
            const ctrl = eventArgs.ctrlKey;
            const key = eventArgs.keyCode;
            // Ctrl-V || Shift-Ins || Cmd-V
            if ((ctrl || eventArgs.metaKey) && key === 86 || eventArgs.shiftKey && key === 45) {
                this.textArea.focus();
            }
        }
    
        public onPaste(eventArgs) {
        let data;
        const clData = "clipboardData";
    
        // get clipboard data - from window.cliboardData for IE or from the original event's arguments.
        if (window[clData]) {
            window.event.returnValue = false;
            data = window[clData].getData("text");
        } else {
            data = eventArgs[clData].getData("text/plain");
        }
    
        // process the clipboard data
        const processedData = this.processData(data);
    
        this.onDataProcessed.emit(processedData);
        }
    
        public processData(data) {
            const pasteData = data.split("\n");
            for (let i = 0; i < pasteData.length; i++) {
                pasteData[i] = pasteData[i].split("\t");
                // Check if last row is a dummy row
                if (pasteData[pasteData.length - 1].length === 1 && pasteData[pasteData.length - 1][0] === "") {
                    pasteData.pop();
                }
                // remove empty data
                if (pasteData.length === 1 &&
                     pasteData[0].length === 1 &&
                      (pasteData[0][0] === "" || pasteData[0][0] === "\r")) {
                        pasteData.pop();
                }
            }
            return pasteData;
        }
    }
    
    

    API References

    Additional Resources

    • Exportador de Excel: utilice el servicio Exportador de Excel para exportar datos a Excel desde IgxGrid. También proporciona la opción de exportar solo los datos seleccionados desde IgxGrid. La funcionalidad de exportación está encapsulada en la clase IgxExcelExporterService y los datos se exportan en formato de tabla de MS Excel. Este formato permite funciones como filtrar, ordenar, etc. Para hacer esto, debe invocar el método de exportación de IgxExcelExporterService y pasar el componente IgxGrid como primer argumento.
    Nuestra comunidad es activa y siempre da la bienvenida a nuevas ideas.