ブログ

【SAP】スプレッドシートからの貼り付け〜Clipboard APIを活用したデータインポート〜

この記事をSNSでシェア!

はじめに

SAP Fiori (SAPUI5) を使用したテーブル画面の実装において、データの追加は主に以下の2パターンで実装していました。

  • 1行ずつ追加: 「行追加」ボタンで空行を作り、1項目ずつ手入力する。
  • 一括アップロード: 指定フォーマットのCSVを作成し、一括で読み込む。

しかし、これらの方法には「大量データ登録時にCSVフォーマットを整える手間がかかる」「別フォーマットのExcelで作成した表の一部だけを即座に反映できない」という課題があります。 今回は、ブラウザの Clipboard API を活用し、Excelやスプレッドシートからコピーしたデータをボタン一つでテーブルへ反映させる実装方法と、開発時に直面した注意点をご紹介します。

前提条件

テーブルのツールバー領域に「クリップボードからペースト」ボタンを用意し、ボタン押下の処理でクリップボードの内容を文字列で読み込み、テーブルに追加します。

操作イメージ

Viewの定義

Tableextension 内に、ボタンを配置します。

<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() テキスト取得

クリップボードを読みに行くメソッド: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使用時の実行環境

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を活用した開発案件に携わっています。
この記事をSNSでシェア!