Angular Spreadsheet Component | ng-hub-ui-spreadsheet

Editable Angular spreadsheet with Excel's keyboard, rectangular selection, a clipboard that round-trips with Excel, frozen panes and merged cells. MIT, accessible, no paid tier.

API リファレンス

spreadsheet の完全な仕様をここにまとめました。バインド、リッスン、プロジェクション、テーマ設定ができるすべてが一か所に集約されています。必要なものを接続し、好きなようにスタイリングしてください — standalone で signal フレンドリーです。

インプット

31 個のインプットで spreadsheet を調整。通常の Angular @Input と同じようにバインドできます。

名前型デフォルト説明
rows必須readonly TRow[]—The rows, as you hold them. The sheet never writes to them.
columns必須readonly HubSpreadsheetColumn<TRow>[]—What each column shows and allows.
rowKey必須(row: TRow) => string—A stable name per row, so a save state follows its row across a reload.
errorsRecord<string, string>{}A validation message per cell, keyed like `states`. Owned by the host, because validation belongs to whoever knows what the data means.
statesRecord<string, HubSpreadsheetCellState>{}Save state per cell, keyed by the row key and the column alias joined by a tab.
decimalMark',' | '.'','The character this reader types decimals with. Only consulted when a pasted value carried no raw number.
emptyTextstring''What an empty sheet says.
pageSizenumber10How many rows Page Up and Page Down travel.
readonlybooleanfalseTurns off every editor, whatever the individual cells say.
frozenColumnsnumber0How many columns stay pinned to the leading edge, counted the way Excel freezes panes.
frozenRowsnumber0How many rows stay pinned below the header.
spansreadonly HubGridSpan[][]Merged blocks, each named by its top-left corner and its extent.
fillHandlebooleanfalseWhether the sheet offers the fill handle at the corner of the selection.
canUndobooleanfalseWhether undo is available. The sheet only asks; the owner keeps the history.
canRedobooleanfalseWhether redo is available.
resizableColumnsbooleanfalseWhether a reader may drag a column's trailing edge to widen or narrow it.
reorderableColumnsbooleanfalseWhether a reader may drag a header to put the column somewhere else.
columnWidthsRecord<string, number>{}The width of each column in pixels, keyed by alias. Two-way: the sheet writes it as the reader drags, and you may persist it.
minColumnWidthnumber48The narrowest a column may be dragged.
virtualbooleanfalse表示領域が覆う行だけを描き、残りの高さを確保します。数千行のシート向けです。既定では無効で、代償もあります。視界の外の行は文書に入っていないので、ブラウザの検索も印刷も描かれている分しか届かず、行の高さはそろっている必要があります。有効にするとシートに 24rem の高さも与えます。伸びるに任せたシートは中身と同じ高さになり、そうなると仮想化するものが残らないからです。
rowHeightnumber0仮想化中の行の高さ(ピクセル)。0 なら最初に描いた行を測ります。行がそろっている限りそれで正しく、隠れたまま組み立てるシートでは明示してください。一度も配置されていない行は 0 と測られ、0 から求めた窓はシート全体になります。
formulasbooleanfalse値が = で始まるセルを数式として読むかどうか。頼まれるまで無効です。テキストの列が =1+1 を「誰かが書いた文字列」として持っていて何もおかしくないからです。数式は列を別名で指せます — =[units] * [price]、=SUM([total:]) — 列を動かしても見出しを書き直しても意味は変わりません。表計算ソフトと同じ坐標でも指せます — =ROUND(SUM(E1:E4), 2) — その場合は「どの列か」でなく「どこにあったか」を言っているので、rewriteRowFormulas() がシートの形の変化に合わせて移し、消えたものへの参照は隣をこっそり読むのではなく #REF! になります。コロンは列全体を読み、尋ねているセルだけを外します。ほかの循環は追いかけずに #CYCLE! として見せます。
mergeablebooleanfalse読み手がセルを結合し、また解除できるかどうか。コンテキストメニューから提供するので contextMenu も必要です。構造を変えるものはすべてそうであるように、頼まれるまで無効です。
editOn'click' | 'double-click''double-click'ポインタで編集を開くきっかけ。既定はダブルクリックで、表計算の慣習です。クリックはセルを選ぶだけで値には触れず、最初に打った文字が編集を開いてそのまま入り、一覧や日付を持つセルには一度のクリックで開く印が出ます。書き込むためのシートなら click にすると最初のクリックで開きます。どちらでも編集はボタンを離したときに、しかもポインタが動かなかったときだけ開くので、範囲のドラッグはそのまま使えます。
contextMenubooleanfalseWhether a right-click offers the menu of structural changes. Each entry still has to pass the permissions, and the menu is never opened empty.
columns[].kind'text' | 'number' | 'currency' | 'date' | 'boolean' | 'select''text'How the column shows its values and reads back what is typed. A select column opens a list and refuses anything not on it; a boolean draws a checkbox that turns over in one click; a date opens a date field.
columns[].formulastring—この列のすべてのセルを導く数式。データに持たせるのではなくコードで宣言します。明細の合計、税、繰越残高などです。読み手が打つ数式とは逆で、あちらは行が持つ値であり、ほかの値と同じように変えられます。この列のセルはそもそも開けません。一つを置き換えるとその行だけ数式が消え、合計が合わなくなるまで誰も気づかないからです。シート側の formulas が必要です。
columns[].placeholderstring—A hint shown in an empty cell of this column while the pointer rests on it. Never in place of a value: a column of hints always on screen reads as a column of content.
columns[].optionsreadonly HubSpreadsheetOption[]—The answers a select column offers. A cell shows the matching label rather than the stored value, and falls back to the raw value when nothing matches, so a row holding a retired option stays readable.
structureHubSpreadsheetStructureOptions<TRow>{}Which structural changes the reader may ask for. Everything is refused until allowed.
retiredColumnKeysreadonly string[][]Aliases of columns that were deleted, so a new one never inherits a dead identity.

アウトプット

spreadsheet の動作に反応 — ロジックを接続できる 12 個のイベント。

名前型説明
commitHubSpreadsheetCommit<TRow>A cell took a new value, and it differs from the one it held.
pastedHubSpreadsheetPaste<TRow>A block was pasted, with counts of what fell outside the sheet and what was not a number.
clearedHubSpreadsheetCellRef<TRow>[]Delete was pressed over a selection; carries the editable cells it covered.
selectionChangeHubGridRange | nullThe selected rectangle changed.
filledHubSpreadsheetPaste<TRow>A drag of the fill handle finished, reported as one event for the whole gesture.
undoRequestedvoidThe reader asked to undo.
redoRequestedvoidThe reader asked to redo.
columnMoved{ from: number; to: number; key: string; keys: string[] }A column was dropped somewhere else. Reported, not applied: the payload carries the aliases already reordered.
mergeRequestedHubSpreadsheetMergeRequest選択範囲の結合が求められました。作る結合と、それが飲み込む結合の基点が渡されます。前者だけ足して後者を外さないと、同じセルを二つの結合が主張することになります。applySpanMerge() が一行で片づけます。
unmergeRequestedreadonly HubGridCoords[]選択範囲が触れている結合の解除が求められました。基点で示されます。applySpanUnmerge() で適用します。
insertRequestedHubSpreadsheetInsertRequestThe reader asked to add rows or columns.
deleteRequestedHubSpreadsheetDeleteRequestThe reader asked to remove rows or columns, naming the aliases at stake.

メソッド

spreadsheet をコードから操作 — プログラム操作のための 17 個のメソッドを備えています。

名前シグネチャ戻り値説明
sheetToXlsxsheetToXlsx<TRow>(rows, columns, options?: HubXlsxOptions): Uint8ArrayUint8Arrayシートを本物の .xlsx として、バイト列で返します。数値は数値のまま、日付列は日付になります。CSV では運べないものです。書き出すのはセルが見せている値で、リスト列はラベル、数式は結果です。行が持つ値そのものが要るときは values: 'stored' を渡します。
downloadXlsxdownloadXlsx(filename: string, bytes: Uint8Array): void—そのブックを保存用として読み手に渡します。名前に .xlsx がなければ付けます。どのホストも同じ六行を書き、object URL の解放を忘れるので、ここに置いてあります。
xlsxToRecordsxlsxToRecords<TRow>(bytes, columns, options?: HubXlsxReadOptions): Promise<Array<Record<string, string>>>Promise<Array<Record<string, string>>>ブックの最初のシートを、列の別名をキーにした行として読みます。CSV には無い二つのこと——共有文字列と、日数として保存された日付——を元に戻します。本物のブックは圧縮されており、展開はプラットフォームの機能を使うので非同期です。
sheetToCsvsheetToCsv<TRow>(rows, columns, options?: HubCsvOptions): stringstringシートを CSV として返します。区切り文字を指定しなければ小数点記号から決まります。小数点に使う文字で区切ることはできないので、1.234,56 と書く環境向けのファイルにはセミコロンを使います。
downloadTextdownloadText(filename: string, text: string, type?: string): void—テキストファイルを保存用として読み手に渡します。表計算ソフトが UTF-8 として開くためのバイト順マークを付けるので、文字化けしません。
csvToRecordscsvToRecords<TRow>(text, columns, options?: HubCsvOptions): Array<Record<string, string>>Array<Record<string, string>>CSV を、列の別名をキーにした行として読みます。区切り文字は決め打ちせず一行目から見分けます。見出しはまず見出しで、次に別名で突き合わせ、大文字小文字と前後の空白は無視します。
sheetValuessheetValues<TRow>(rows, columns, options?: HubSheetValuesOptions): HubSpreadsheetValue[][]HubSpreadsheetValue[][]各セルが持つ値。数式は計算済みで、失敗した数式は表計算ソフトと同じ綴りで入ります。二つの書き出しが読んでいるのはこれで、独自のファイルを書くホストのために公開しています。
evaluateSheetevaluateSheet<TRow>(input: HubFormulaSheetInput<TRow>): HubFormulaSheetHubFormulaSheetシートの数式をすべて、依存関係が要求する順で実行します。必要になった時に計算し、覚えておきます。循環は閉じた瞬間に捕まえ、追いかけません。描画せずに答えだけが欲しいホストのために公開しています。
rewriteRowFormulasrewriteRowFormulas<TRow extends object>(rows, change: HubFormulaShapeChange): TRow[]TRow[]シートの形が変わったとき——列が移動した、行や列を挿入した、削除した——行の中の座標をすべて動かします。消えたものへの参照は、隣をこっそり読むのではなく #REF! になります。行はホストのものなので、呼ぶのはホストです。
mergeRequestFormergeRequestFor(spans, range): HubSpreadsheetMergeRequest | nullHubSpreadsheetMergeRequest | null選択範囲がなるはずの結合ブロックと、それが飲み込むアンカー。単一セルなら null です。飲み込むアンカーはホストが自力でやると間違えるところで、外さずに追加すると二つのブロックが同じセルを主張します。
applySpanMergeapplySpanMerge(spans, request: HubSpreadsheetMergeRequest): HubGridSpan[]HubGridSpan[]その結合のあとのブロック一覧。飲み込まれたものは落ちます。
applySpanUnmergeapplySpanUnmerge(spans, anchors: readonly HubGridCoords[]): HubGridSpan[]HubGridSpan[]それらを分解したあとのブロック一覧。
spreadsheetRecordsspreadsheetRecords<TRow>(rows, columns): HubSpreadsheetRecord[]HubSpreadsheetRecord[]各行を、列の別名をキーにした素のデータとして返します。座標を位置で自分のフィールドに割り当てるのではなく、{ price: 12, units: 3 } を扱えます。
parseForColumnparseForColumn<TRow>(text, column, decimalMark: ',' | '.'): HubSpreadsheetValue | undefinedHubSpreadsheetValue | undefined打ち込まれた、あるいは貼り付けられた文字列が、その列でいくらになるか。値、空セルなら null、その列が持てないものなら undefined を返すので、呼ぶ側はゴミを保存せずに断れます。
nextColumnKeynextColumnKey(taken: Iterable<string>, prefix?: string): stringstringほかの列のものだったことが一度もない別名。新しい列が引退した名前を使い回さないので、保存済みの参照が別のものに解決されることがありません。
danglingColumnKeysdanglingColumnKeys<TRow>(referenced: Iterable<string>, columns): string[]string[]もうどの列にも解決しない参照。つまり削除が宙ぶらりんに残すもののことです。
provideHubSpreadsheetControlsprovideHubSpreadsheetControls(adapter: HubSpreadsheetControlsAdapter): EnvironmentProvidersEnvironmentProvidersコントロールのアダプターを登録します。以後すべてのリスト列がそれで開きます——検索付きで、すでに開いた状態で、セルを開いた文字を検索欄に入れて。アダプターが無ければシートはネイティブのリストを描き、それがこのライブラリ単体で入れられる理由です。

テンプレート

自分好みに — 2 個のテンプレートスロットでカスタムマークアップをプロジェクションできます。

名前説明サンプル
hubSpreadsheetEditor指定した別名の列の編集をテンプレートに差し替えます。テンプレートには値と commit・cancel の組、そして `seed`(読み手が入力して開いたときの最初の文字。ピッカーの検索欄に入れるもの)が渡されます。どちらかを呼ぶまで開いたままで、シートは中身に依存しません。<ng-template hubSpreadsheetEditor="assignee" let-value let-seed="seed" let-commit="commit"> <hub-select [items]="people" autoOpen [initialSearchTerm]="seed ?? null" [ngModel]="value" (ngModelChange)="commit($event)" /> </ng-template>
hubSpreadsheetCell編集していないあいだの列のセルを自分で描きます。状態のバッジ、名前の横のアバター、並んだアクションなど。セルのもう半分を受け持つ hubSpreadsheetEditor の対になるものです。クリップボードには描いたものではなく値が乗り、キーボードが立っているのは変わらずセルです。hubSpreadsheetCellRows で行を渡せば、コンパイラは `row` が何かを知ります。<ng-template hubSpreadsheetCell="state" let-value> <hub-badge variant="soft" [color]="colourOf(value)">{{ labelOf(value) }}</hub-badge> </ng-template>