Angular Grid - Excel から貼り付け
Ignite UI for Angular IgxGrid
は、クリップボードにコピーした Excel データを読み込むことができます。このトピックでは、カスタムコードを使用して実装する方法について説明します。
Angular Excel からデータを貼り付ける例
このサンプルでは、Excel から igxGrid
の貼り付けを実装する方法を紹介します。
サンプルは、Excel スプレッドシートを開いて行をコピーし、キーボード (Ctrl + V、Shift + Insert、Command + V) を使用してグリッドに貼り付けます。
上部に2 つのオプションとドロップダウン ボタンがあります。
- 新規行としてデータを貼り付け - このモードでは、Excel からコピーしたデータが新規行としてグリッドに追加されます。
- アクティブ セルから開始する貼り付け - このモードではグリッド データが上書きされます。
貼り付け後の新しいデータはイタリックになります。
使用方法
paste-handler
ディレクティブ (次のセクションにコードがあります) を IgxGrid
に追加して onDataProcessed
イベントを処理する必要があります。onDataProcessed
イベントに配列フォームの Excel データへアクセスを与えるパラメーターがあります。詳細については、addRecords
と updateRecords
メソッドを参照してください。
<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
実装です。クリップボードから張り付けたデータを受け取るために使用される DOM textarea
要素をコードで作成します。データを textarea
に張り付ける際にディレクティブはそれを配列へ解析し、解析データを渡すカスタム イベント onDataProcessed
を発生します。
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 argumets.
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 リファレンス
その他のリソース
- Excel エクスポーター - Excel エクスポーター サービスを使用して、IgxGrid から Excel にデータをエクスポートします。選択したデータのみを IgxGrid からエクスポートするオプションもあります。エクスポート機能は、IgxExcelExporterService クラスでカプセル化され、MS Excel テーブル形式でデータをエクスポートします。この形式はフィルタリングやソートなどの機能が使用でき、IgxExcelExporterService の export メソッドを呼び出して最初の引数として IgxGrid コンポーネントを渡します。
ページを開く:
GitHub