自動ルックアップで名入れレコードを作る

目次

はじめに

社内申請系のkintoneアプリでは、本人で申請することが多いため、レコードを追加する時から自分の名前をセットしたいと思うことはありませんか?

そこで今回は、レコード追加時に、社員情報マスターなどの他のアプリから自分の氏名をルックアップしてセットするカスタマイズを紹介します。

一言で表すと「自動ルックアップ」です!

まずルックアップのボタンを押して、次に[ユーザーを選択]画面で自分を選択して…という2アクションが一気に省けます。

完成イメージ

[+]ボタンを押して新しいレコードを追加する時、ルックアップフィールドに自分の名前がすでにセットされています。

実装イメージ

今回の実装のイメージです。
動作上は標準機能のルックアップと類似していますが、実際はJavaScriptでこのような処理を行っています。

実装の流れ

  1. レコード追加イベントで、REST APIを使用し、ログイン名をキーにルックアップ先のアプリのレコード情報をリクエスト
  2. キーに合致したレコード情報を1件取得
  3. 取得したレコードの値をルックアップフィールドにセット
  4. ルックアップフィールドのlookupプロパティにtrueを設定し、 ルックアップを自動で取得

アプリの準備

マスターアプリの設定

ルックアップ先のレコードが入るマスター用のアプリを用意します。
今回はログイン名をキーとして合致したレコード情報を取得します。
ログイン名の他にマスターから取得したいフィールドを設定しましょう。
今回は、[社員番号]と[氏名]を設定します。

フィールド名 フィールドタイプ フィールドコード 備考
社員番号 文字列(一行) 社員番号 「値の重複を禁止する」を設定
氏名 文字列(一行) 氏名
ログイン名
文字列(一行) ログイン名

今回のカスタマイズは、 ルックアップの取得を自動で行う ようにしています。
「コピー元のフィールド」で選択したフィールドについて、既存のレコードの値が重複する場合は自動取得できません。
そのため「コピー元のフィールド」で選択したフィールドについて、「値の重複を禁止する」に設定しています。

マスターができたら、ルックアップ先のレコードを追加するのをお忘れなく!
ログイン名がキーになるため、正確に記載しましょう。

フォームアプリの設定

フォーム用のアプリを用意します。
ルックアップフィールド[社員番号]で先ほどのマスターアプリとの関連付けを以下のキャプチャのように設定します。
なお、キーとなるログイン名についてはkintone APIで取得できるためアプリでのフィールド設定は不要です。

フィールド名 フィールドタイプ フィールドコード 備考
社員番号 ルックアップ 社員番号
[ほかのフィールドのコピー]で[氏名] < (マスターアプリ名の)[氏名]
氏名 文字列(一行) 氏名
(なし) スペース error_display_field エラーメッセージ表示用スペースフィールド

サンプルプログラム

プログラム(JavaScript)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
(() => {
  'use strict';
  const events1 = ['app.record.create.show'];
  kintone.events.on(events1, (event) => {
    const record = event.record;
    if (!record['社員番号'].value) {
      // ルックアップ先アプリIDを取得してリクエストボディにセット
      const appId = kintone.app.getLookupTargetAppId('社員番号');
      const user = kintone.getLoginUser();
      const params = {
        app: appId,
        // ログイン名をキーにしたクエリ
        query: 'ログイン名 = "' + user.code + '" order by $id desc limit 1'
      };
      // REST APIでルックアップ先のレコードを1件取得
      kintone.api(kintone.api.url('/k/v1/records', true), 'GET', params, (resp) => {
        if (resp.records.length === 1) {
          const setRecord = kintone.app.record.get();
          // 取得したレコードの値をルックアップ元にセット
          setRecord.record['社員番号'].value = resp.records[0]['社員番号'].value;
          // セットした値でルックアップ実行
          setRecord.record['社員番号'].lookup = true;
          kintone.app.record.set(setRecord);
          // マスタに該当レコードがなかった場合のエラー表示
        } else {
          const errorDisplayField = kintone.app.record.getSpaceElement('error_display_field');
          errorDisplayField.parentNode.style.width = '250px';
          // 文字列要素
          const errorDisplayDiv = document.createElement('div');
          errorDisplayDiv.style.backgroundColor = '#ffd78c';
          errorDisplayDiv.innerHTML = '該当データがありませんでした。';
          errorDisplayField.appendChild(errorDisplayDiv);
        }
      });
    }
  });
  // 手動ルックアップ時はエラー表示クリア
  const events2 = ['app.record.create.change.氏名'];
  kintone.events.on(events2, (event) => {
    const record = event.record;
    if (record['氏名'].value !== null) {
      const errorDisplayField = kintone.app.record.getSpaceElement('error_display_field');
      if (errorDisplayField !== null) {
        errorDisplayField.innerHTML = null;
      }
    }
    return event;
  });
})();

ポイント解説

ルックアップフィールドへの値セット
15
16
17
18
19
20
21
22
23
24
25
26
// REST APIでルックアップ先のレコードを1件取得
kintone.api(kintone.api.url('/k/v1/records', true), 'GET', params, (resp) => {
  if (resp.records.length === 1) {
    const setRecord = kintone.app.record.get();
    // 取得したレコードの値をルックアップ元にセット
    setRecord.record['社員番号'].value = resp.records[0]['社員番号'].value;
    // セットした値でルックアップ実行
    setRecord.record['社員番号'].lookup = true;
    kintone.app.record.set(setRecord);
    // ...
  }
});
  • REST APIで取得したルックアップ先のレコードの値(今回は社員番号)を、ルックアップ元にセットし、それでもってルックアップを実行しています。
  • それにより、申請者に社員番号を勝手に書き換えられることのないアプリ設計になっています。
エラー処理
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// マスタに該当レコードがなかった場合のエラー表示
}else {
    const errorDisplayField = kintone.app.record.getSpaceElement('error_display_field');
    errorDisplayField.parentNode.style.width = '250px';
    // 文字列要素
    const errorDisplayDiv = document.createElement('div');
    errorDisplayDiv.style.backgroundColor = '#ffd78c';
    errorDisplayDiv.innerHTML = '該当データがありませんでした。';
    errorDisplayField.appendChild(errorDisplayDiv);
}
  • マスターに該当のレコードが見つからない場合は、その旨を画面に表示します。

37
38
39
40
41
42
43
44
45
46
47
48
// 手動ルックアップ時はエラー表示クリア
const events2 = ['app.record.create.change.氏名'];
kintone.events.on(events2, (event) => {
  const record = event.record;
  if (record['氏名'].value !== null) {
    const errorDisplayField = kintone.app.record.getSpaceElement('error_display_field');
    if (errorDisplayField !== null) {
      errorDisplayField.innerHTML = null;
    }
  }
  return event;
});
  • エラー表示は、そのままだと、その後あらためて手動でルックアップに成功しても残ってしまいます。
  • そこでフィールド変更時イベントを利用して、ルックアップで値がコピーされた際はクリアするようにしています。

おわりに

このカスタマイズのメリットは2アクションが省けるだけでなく、他のアプリで同様にマスターを参照するアプリでも、同名のフィールドコードでルックアップを設定しておけば、同じコードのコピペで簡単に設定できるところです。

手近なところでは アプリストア (External link) にある ワークフロー(社内申請管理)パック (External link) (よく使う3つの社内申請管理のセット)と 社員名簿 (External link) の連携でも便利にお使いいただけるかと思います。ぜひ 開発ライセンス を申し込んで試してみてくださいね。

関連付けしたアプリのレコード情報を自在に取得できるため、たとえば休暇申請アプリに関連付けた有給休暇管理アプリから、自分の氏名と残りの有給休暇日数を同時に表示したレコードも作れることができそうです。
ご活用ください!

デモ環境

デモ環境で実際に動作を確認できます。
https://dev-demo.cybozu.com/k/229/ (External link)

ログイン情報は cybozu developer networkデモ環境 で確認してください。

information

このTipsは、2022年7月版kintoneで動作を確認しています。