
はじめに
SAP Fiori (SAPUI5) を使用したテーブル画面の実装において、データの追加は主に以下の2パターンで実装していました。
- 1行ずつ追加: 「行追加」ボタンで空行を作り、1項目ずつ手入力する。
- 一括アップロード: 指定フォーマットのCSVを作成し、一括で読み込む。
しかし、これらの方法には「大量データ登録時にCSVフォーマットを整える手間がかかる」「別フォーマットのExcelで作成した表の一部だけを即座に反映できない」という課題があります。 今回は、ブラウザの Clipboard API を活用し、Excelやスプレッドシートからコピーしたデータをボタン一つでテーブルへ反映させる実装方法と、開発時に直面した注意点をご紹介します。
前提条件
テーブルのツールバー領域に「クリップボードからペースト」ボタンを用意し、ボタン押下の処理でクリップボードの内容を文字列で読み込み、テーブルに追加します。
操作イメージ
Viewの定義
Table の extension 内に、ボタンを配置します。
<t:Table
id="demoTable"
rows="{tableModel>/Records}"
selectionMode="None"
width="60%">
<t:extension>
<OverflowToolbar id="toolbar">
<ToolbarSpacer id="spacer"/>
<Button id="idPasteButtton" text="クリップボードからペースト" press=".onCopy"/>
<Button id="idClearButtton" text="クリア" press=".onClear"/>
</OverflowToolbar>
</t:extension>
</t:Table> 処理内容
クリップボードを読みに行くメソッド:navigator.clipboard.readText() でクリップボードの内容を文字列として取得します。
ブラウザの設定で許可が必要な場合等を考慮し、try-catch または async/await によるエラーハンドリングを推奨します。
navigator.clipboard.readText().then(function(sText) {
// クリップボードにデータがコピーされていない場合
if(!sText) {
sap.m.MessageBox.error("コピー元が選択されていません");
return;
}
}).catch(function(error) {
sap.m.MessageBox.error("クリップボードへのアクセスが拒否されました。ブラウザの設定を確認してください。");
});navigator.clipboard APIは、「安全なコンテキスト(Secure Context)」でのみ動作します。
- 本番環境
https:// で配信されている必要があります。 - 開発環境
開発中のhttp://localhostは例外的に許可されますが、IPアドレス指定(例:http://192.168.x.x)だと動作しない場合が多いので注意が必要です。
【デバッグ時の罠】Document is not focused エラー
開発中、API呼び出しの直前にブレークポイントを張ると、NotAllowedError: Document is not focused というエラーが発生することがあります。
これは、デバッガー(DevTools)にフォーカスが移ったことで、セキュリティ保護が働くためです。
【対策】
ログ出力の活用: console.log を使い、処理を止めずにデータを確認する。
停止位置の工夫: API呼び出し(readText)の直後ではなく、その後のパース処理内にブレークポイントを張る。
OSごとの改行コードの違いを考慮した正規表現による行分割
Windows(\r\n)とMac/Linux(\n)の両方の改行コードに対応するため、正規表現(\r?\n)を用いて行単位に分割します。
const aLines = sText.split(/\r?\n/);区切り文字の判定
Excelからのコピー(タブ区切り)だけでなく、CSVファイル(カンマ区切り)からの読み取りも考慮し、1行目の内容から区切り文字を動的に判定します。
const sDelimiter = aLines[0].indexOf('\t') > -1 ? '\t' : ',';クリップボードデータの読み込みとテーブルへの反映
行ごとに分割した文字列をループ処理し、オブジェクト配列へ変換します。JSONModelに反映させる際は、変更を即座にUIへ反映させるため、setPropertyを使用してデータをセットします。
// 空の配列を用意して行データを格納していく
const aData = [];
// 文字列の内容と取り込み
aLines.forEach(function(sLine, iOffset) {
// 空行(末尾の改行コードなど)をスキップ
if(!sLine.trim()) {
return;
}
// 1行目がヘッダー行の場合、2行目から処理
if (iOffset > 0) {
// セルを区切る
const aCells = sLine.split(sDelimiter);
const oEntry = {
num: aCells[0] || "",
name: aCells[1] || "",
office: aCells[2] || "",
}
aData.push(oEntry);
}
});
oTableModel.setProperty("/Records", aData);実装上のポイントと注意点
- 空行のスキップ: Excel(およびGoogleスプレッドシートなどの表計算ソフト)からコピーすると、末尾に意図しない改行コードが含まれることが多いため、
trim()を用いた空行チェックは必須です。 - ヘッダー行有無判定: 1行目が項目名である場合、その行をスキップするロジックが必要です。ただし、コピー範囲の1行目がヘッダーかどうかの判定をする際には、判定方法の調整が必要です。
- 入力チェック(バリデーション):
JSONModelにセットする前に、必須項目の有無や型チェック(数値、日付など)を行うことを強く推奨します。不正な形式のデータがペーストされると、システム全体のエラーにつながる可能性があります。
さいごに
従来の『行追加』や『CSVアップロード』というお決まりのUIに対し、Clipboard APIによるデータ追加は、開発側としては正直なところ『考慮すべき事項が増えるな』という第一印象でした。
実際、列数が不足している場合の挙動や、まったく関係ないデータが追加された際のバリデーションなど、設計段階で議論すべき点は山積みです。そのため、今回のプロジェクトでは『手法の確立』に留め、システムへの統合は一旦保留となりました。
しかし、『いつものExcelをそのまま持っていける』という直感的な操作感は、やはり捨てがたい魅力があります。開発には慎重な設計が不可欠ですが、ユーザーの利便性を最優先に考えるなら、挑戦する価値は十分にあると思います。皆さんの現場でも、ぜひこの記事を一つのヒントにしてみてください。
投稿者プロフィール

-
BS事業部 BSグループの樋口です。
SAP BTP(Business Technology Platform)とSAP Fioriを活用した開発案件に携わっています。

