[{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:168\"\u003e文字を入力するたびに候補を検索する画面では、「最後に完了した検索」が「最後に入力した文字の検索」とは限りません。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:369\"\u003e\u003ccode\u003eA\u003c/code\u003e の検索より後に始めた \u003ccode\u003eAB\u003c/code\u003e の検索が先に完了すると、遅れて届いた \u003ccode\u003eA\u003c/code\u003e の結果で候補が上書きされることがあります。対処の一つは、検索を始めるたびに番号を増やし、最新の番号に対応する結果だけを表示する方法です。ここでは、この番号を「世代番号」と呼びます。\u003c/p\u003e\n\u003cp data-sourcepos=\"5:1-5:305\"\u003eこの記事では、Kintacoの重複有無、サジェスト表示プラグインの実装で使っている考え方を、小さな独立した関数にして説明します。公開済みの表記ゆれ・候補の絞り込みの記事とは別に、\u003cstrong\u003e非同期処理の完了順序\u003c/strong\u003eを扱います。\u003c/p\u003e\n\u003cp data-sourcepos=\"7:1-7:224\"\u003eサンプルはJavaScript単体で動きます。kintoneへのアクセスやレコードの更新は行いません。プラグイン本体の全実装や、重複登録を防ぐ保存時チェックではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"9:1-9:64\"\u003e\n\u003cspan id=\"promiseの完了順序を入力順序として扱わない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#promise%E3%81%AE%E5%AE%8C%E4%BA%86%E9%A0%86%E5%BA%8F%E3%82%92%E5%85%A5%E5%8A%9B%E9%A0%86%E5%BA%8F%E3%81%A8%E3%81%97%E3%81%A6%E6%89%B1%E3%82%8F%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003ePromiseの完了順序を、入力順序として扱わない\u003c/h2\u003e\n\u003cp data-sourcepos=\"11:1-11:30\"\u003e次の順序を考えます。\u003c/p\u003e\n\u003col data-sourcepos=\"13:1-17:0\"\u003e\n\u003cli data-sourcepos=\"13:1-13:46\"\u003e\n\u003ccode\u003eA\u003c/code\u003e を入力し、検索を開始する。\u003c/li\u003e\n\u003cli data-sourcepos=\"14:1-14:63\"\u003e続けて \u003ccode\u003eAB\u003c/code\u003e を入力し、別の検索を開始する。\u003c/li\u003e\n\u003cli data-sourcepos=\"15:1-15:35\"\u003e\n\u003ccode\u003eAB\u003c/code\u003e の検索結果が届く。\u003c/li\u003e\n\u003cli data-sourcepos=\"16:1-17:0\"\u003e\n\u003ccode\u003eA\u003c/code\u003e の検索結果が届く。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp data-sourcepos=\"18:1-18:251\"\u003eどちらの結果も無条件に表示すると、最終的な画面は \u003ccode\u003eA\u003c/code\u003e の候補になります。問題は、検索結果そのものが誤っていることではなく、現在の入力に合わない結果を採用していることです。\u003c/p\u003e\n\u003cp data-sourcepos=\"20:1-20:400\"\u003ekintoneのREST API呼び出しも、コールバックを省略すればPromiseとして扱えます。実際のAPIの使い方は\u003ca href=\"https://cybozu.dev/ja/kintone/docs/js-api/api/kintone-rest-api-request/\" rel=\"nofollow noopener\" target=\"_blank\"\u003e公式のkintone.api()の説明\u003c/a\u003eを確認してください。以下ではAPI呼び出し部分を \u003ccode\u003eload\u003c/code\u003e 関数として外から渡し、表示するかどうかの判定だけに絞ります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"22:1-22:45\"\u003e\n\u003cspan id=\"最新の処理だけを採用する関数\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%9C%80%E6%96%B0%E3%81%AE%E5%87%A6%E7%90%86%E3%81%A0%E3%81%91%E3%82%92%E6%8E%A1%E7%94%A8%E3%81%99%E3%82%8B%E9%96%A2%E6%95%B0\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e最新の処理だけを採用する関数\u003c/h2\u003e\n\u003cp data-sourcepos=\"24:1-24:207\"\u003e\u003ccode\u003erun()\u003c/code\u003e は実行のたびに \u003ccode\u003eversion\u003c/code\u003e を増やします。完了したとき、開始時の番号 \u003ccode\u003emine\u003c/code\u003e が現在の番号と同じなら結果を渡します。失敗も同じ基準で判定します。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"26:1-48:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003ecreateLatestRunner\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e \u003cspan class=\"nx\"\u003eonValue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eonError\u003c/span\u003e \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003eversion\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003easync\u003c/span\u003e \u003cspan class=\"nf\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003emine\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"o\"\u003e++\u003c/span\u003e\u003cspan class=\"nx\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n        \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nf\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n      \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003ecatch \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n        \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003emine\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"nx\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n        \u003cspan class=\"nf\"\u003eonError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n        \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n      \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003emine\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"nx\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"nf\"\u003eonValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n    \u003cspan class=\"nf\"\u003einvalidate\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"nx\"\u003eversion\u003c/span\u003e \u003cspan class=\"o\"\u003e+=\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"50:1-50:186\"\u003e番号が古い場合は、成功結果だけでなく失敗通知も無視します。古い検索のエラーが、新しい候補の上に表示されることを防ぐためです。\u003c/p\u003e\n\u003cp data-sourcepos=\"52:1-52:195\"\u003e\u003ccode\u003eonValue\u003c/code\u003e と \u003ccode\u003eonError\u003c/code\u003e は同期的な表示処理を渡す前提です。表示関数自身の例外や非同期処理まで面倒を見る、汎用の例外処理関数ではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"54:1-54:63\"\u003e\n\u003cspan id=\"時間待ちに依存せず完了順序をテストする\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%99%82%E9%96%93%E5%BE%85%E3%81%A1%E3%81%AB%E4%BE%9D%E5%AD%98%E3%81%9B%E3%81%9A%E5%AE%8C%E4%BA%86%E9%A0%86%E5%BA%8F%E3%82%92%E3%83%86%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e時間待ちに依存せず、完了順序をテストする\u003c/h2\u003e\n\u003cp data-sourcepos=\"56:1-56:280\"\u003e実通信を使うと、いつも同じ順序で応答が届くとは限りません。そこで、解決・拒否するタイミングをテスト側で指定できるPromiseを用意します。次は上の関数も含む、単体で実行できるテストファイルです。\u003c/p\u003e\n\u003cp data-sourcepos=\"58:1-58:105\"\u003eファイル名を \u003ccode\u003elatest-result.test.cjs\u003c/code\u003e とし、Node.jsのテストランナーで実行します。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"61:1-119:3\"\u003e\n\u003cdiv class=\"code-lang\"\u003e\u003cspan class=\"bold\"\u003elatest-result.test.cjs\u003c/span\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003etest\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003erequire\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003enode:test\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003erequire\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003enode:assert/strict\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003ecreateLatestRunner\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e \u003cspan class=\"nx\"\u003eonValue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eonError\u003c/span\u003e \u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003eversion\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003easync\u003c/span\u003e \u003cspan class=\"nf\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003emine\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"o\"\u003e++\u003c/span\u003e\u003cspan class=\"nx\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n        \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nf\"\u003eload\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n      \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003ecatch \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n        \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003emine\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"nx\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n        \u003cspan class=\"nf\"\u003eonError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n        \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n      \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003emine\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"nx\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"nf\"\u003eonValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n    \u003cspan class=\"nf\"\u003einvalidate\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"nx\"\u003eversion\u003c/span\u003e \u003cspan class=\"o\"\u003e+=\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003edeferred\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003elet\u003c/span\u003e \u003cspan class=\"nx\"\u003eresolve\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ereject\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003epromise\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003ePromise\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003eres\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003erej\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003eresolve\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eres\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ereject\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erej\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003epromise\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eresolve\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ereject\u003c/span\u003e \u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"nf\"\u003etest\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003enew response is not overwritten by old response\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"k\"\u003easync \u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003evalues\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[],\u003c/span\u003e \u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003ecreateLatestRunner\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e \u003cspan class=\"na\"\u003eonValue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ex\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"na\"\u003eonError\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ee\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003emessage\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003edeferred\u003c/span\u003e\u003cspan class=\"p\"\u003e(),\u003c/span\u003e \u003cspan class=\"nx\"\u003eb\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003edeferred\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003epa\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e(()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epromise\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"nx\"\u003epb\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e(()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epromise\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eresolve\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eABの結果\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nx\"\u003epb\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eresolve\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eAの結果\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nx\"\u003epa\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003edeepEqual\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eABの結果\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003edeepEqual\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003cspan class=\"nf\"\u003etest\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eold rejection is ignored\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"k\"\u003easync \u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003evalues\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[],\u003c/span\u003e \u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003ecreateLatestRunner\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e \u003cspan class=\"na\"\u003eonValue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ex\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"na\"\u003eonError\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ee\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003emessage\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003edeferred\u003c/span\u003e\u003cspan class=\"p\"\u003e(),\u003c/span\u003e \u003cspan class=\"nx\"\u003eb\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003edeferred\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003epa\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e(()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epromise\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"nx\"\u003epb\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e(()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epromise\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eresolve\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e新結果\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nx\"\u003epb\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ereject\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e古い失敗\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nx\"\u003epa\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003edeepEqual\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e新結果\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003edeepEqual\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003cspan class=\"nf\"\u003etest\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003einvalidation prevents display after field is cleared\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"k\"\u003easync \u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003evalues\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[],\u003c/span\u003e \u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003ecreateLatestRunner\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e \u003cspan class=\"na\"\u003eonValue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ex\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"na\"\u003eonError\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ee\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003emessage\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003edeferred\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003epa\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e(()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epromise\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003einvalidate\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eresolve\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e消した検索語の結果\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nx\"\u003epa\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003edeepEqual\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]);\u003c/span\u003e \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003edeepEqual\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003cspan class=\"nf\"\u003etest\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003elatest error is reported\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"k\"\u003easync \u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003evalues\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[],\u003c/span\u003e \u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003ecreateLatestRunner\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e \u003cspan class=\"na\"\u003eonValue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ex\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"na\"\u003eonError\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ee\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003emessage\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nx\"\u003erunner\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003easync \u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e最新の失敗\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003edeepEqual\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]);\u003c/span\u003e \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003edeepEqual\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerrors\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e最新の失敗\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/div\u003e\n\u003cp data-sourcepos=\"121:1-121:74\"\u003e\u003ccode\u003enode --test latest-result.test.cjs\u003c/code\u003e で、次の4点を検証します。\u003c/p\u003e\n\u003cul data-sourcepos=\"123:1-127:0\"\u003e\n\u003cli data-sourcepos=\"123:1-123:98\"\u003e新しい検索が先に成功したあと、古い検索が成功しても上書きしない。\u003c/li\u003e\n\u003cli data-sourcepos=\"124:1-124:98\"\u003e新しい検索が成功したあと、古い検索が失敗してもエラーを出さない。\u003c/li\u003e\n\u003cli data-sourcepos=\"125:1-125:83\"\u003e入力のクリアで無効化したあと、以前の結果を表示しない。\u003c/li\u003e\n\u003cli data-sourcepos=\"126:1-127:0\"\u003e最新の検索が失敗した場合はエラーを渡す。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"128:1-128:239\"\u003eこのコードのローカル実行では4件すべて成功しました。確認したのは関数の順序判定であり、kintoneの実画面、権限やAPI通信、モバイルでの動作を確認した結果ではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"130:1-130:75\"\u003e\n\u003cspan id=\"入力を消したとき画面を離れるときにも無効化する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%85%A5%E5%8A%9B%E3%82%92%E6%B6%88%E3%81%97%E3%81%9F%E3%81%A8%E3%81%8D%E7%94%BB%E9%9D%A2%E3%82%92%E9%9B%A2%E3%82%8C%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AB%E3%82%82%E7%84%A1%E5%8A%B9%E5%8C%96%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e入力を消したとき・画面を離れるときにも無効化する\u003c/h2\u003e\n\u003cp data-sourcepos=\"132:1-132:284\"\u003e文字列が空になった場合、検索を実行しないだけでは不十分です。直前の検索が処理中なら、あとから候補が戻ってくるためです。入力を消す処理では \u003ccode\u003erunner.invalidate()\u003c/code\u003e を呼び、表示済みの候補も別に消します。\u003c/p\u003e\n\u003cp data-sourcepos=\"134:1-134:349\"\u003e画面を離れるときも同様です。このサンプルにはkintoneの画面イベントや入力要素への接続処理を含めていません。実装時は画面ごとに関数を作り、候補を消す操作・画面の破棄と対応させてください。複数の入力欄がある場合は、番号を欄ごとに管理します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"136:1-136:47\"\u003e\n\u003cspan id=\"debounceや通信中断とは役割が違う\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#debounce%E3%82%84%E9%80%9A%E4%BF%A1%E4%B8%AD%E6%96%AD%E3%81%A8%E3%81%AF%E5%BD%B9%E5%89%B2%E3%81%8C%E9%81%95%E3%81%86\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003edebounceや通信中断とは役割が違う\u003c/h2\u003e\n\u003cp data-sourcepos=\"138:1-138:301\"\u003e入力が落ち着くまで実行を待つdebounceは、主に検索を始める回数を抑える方法です。一方、世代番号は、すでに始まった処理のうち、どの結果を採用するかを決めます。debounceだけで応答順序の問題が消えるとは限りません。\u003c/p\u003e\n\u003cp data-sourcepos=\"140:1-140:355\"\u003eこのサンプルは古い結果を無視するだけで、通信自体は中断しません。リクエスト数やAPIの負荷を直接減らす仕組みでもありません。Promiseと非同期処理の基本は\u003ca href=\"https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise\" rel=\"nofollow noopener\" target=\"_blank\"\u003eMDNのPromiseの解説\u003c/a\u003eも参考になります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"142:1-142:42\"\u003e\n\u003cspan id=\"自社で実装する範囲を決める\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%87%AA%E7%A4%BE%E3%81%A7%E5%AE%9F%E8%A3%85%E3%81%99%E3%82%8B%E7%AF%84%E5%9B%B2%E3%82%92%E6%B1%BA%E3%82%81%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e自社で実装する範囲を決める\u003c/h2\u003e\n\u003cp data-sourcepos=\"144:1-144:294\"\u003e検索画面に組み込む場合は、クエリに使う文字列のエスケープ、取得権限、取得件数、キャッシュ、IME入力、候補選択時の値の扱いなども必要になります。表示上の重複候補と、保存時に重複を禁止する設計は別です。\u003c/p\u003e\n\u003cp data-sourcepos=\"146:1-146:615\"\u003e画面への組み込みを設定で行いたい場合は、Kintacoが提供する\u003ca href=\"https://kintaco.wisemap.biz/plugins/duplicate-suggest/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=20261029_async_generation\" rel=\"nofollow noopener\" target=\"_blank\"\u003e重複有無、サジェスト表示プラグイン\u003c/a\u003eも選択肢です。本記事は提供元による技術解説です。プラグイン本体には、サンプル以外に画面の有効性や入力状態を確認する処理もあります。無料利用時は有償プランの案内バナーが表示されるため、対応範囲と利用条件は詳細ページで確認してください。\u003c/p\u003e\n","body":"文字を入力するたびに候補を検索する画面では、「最後に完了した検索」が「最後に入力した文字の検索」とは限りません。\n\n`A` の検索より後に始めた `AB` の検索が先に完了すると、遅れて届いた `A` の結果で候補が上書きされることがあります。対処の一つは、検索を始めるたびに番号を増やし、最新の番号に対応する結果だけを表示する方法です。ここでは、この番号を「世代番号」と呼びます。\n\nこの記事では、Kintacoの重複有無、サジェスト表示プラグインの実装で使っている考え方を、小さな独立した関数にして説明します。公開済みの表記ゆれ・候補の絞り込みの記事とは別に、**非同期処理の完了順序**を扱います。\n\nサンプルはJavaScript単体で動きます。kintoneへのアクセスやレコードの更新は行いません。プラグイン本体の全実装や、重複登録を防ぐ保存時チェックではありません。\n\n## Promiseの完了順序を、入力順序として扱わない\n\n次の順序を考えます。\n\n1. `A` を入力し、検索を開始する。\n2. 続けて `AB` を入力し、別の検索を開始する。\n3. `AB` の検索結果が届く。\n4. `A` の検索結果が届く。\n\nどちらの結果も無条件に表示すると、最終的な画面は `A` の候補になります。問題は、検索結果そのものが誤っていることではなく、現在の入力に合わない結果を採用していることです。\n\nkintoneのREST API呼び出しも、コールバックを省略すればPromiseとして扱えます。実際のAPIの使い方は[公式のkintone.api()の説明](https://cybozu.dev/ja/kintone/docs/js-api/api/kintone-rest-api-request/)を確認してください。以下ではAPI呼び出し部分を `load` 関数として外から渡し、表示するかどうかの判定だけに絞ります。\n\n## 最新の処理だけを採用する関数\n\n`run()` は実行のたびに `version` を増やします。完了したとき、開始時の番号 `mine` が現在の番号と同じなら結果を渡します。失敗も同じ基準で判定します。\n\n```javascript\nfunction createLatestRunner({ onValue, onError }) {\n  let version = 0;\n  return {\n    async run(load) {\n      const mine = ++version;\n      let value;\n      try {\n        value = await load();\n      } catch (error) {\n        if (mine !== version) return;\n        onError(error);\n        return;\n      }\n      if (mine !== version) return;\n      onValue(value);\n    },\n    invalidate() {\n      version += 1;\n    }\n  };\n}\n```\n\n番号が古い場合は、成功結果だけでなく失敗通知も無視します。古い検索のエラーが、新しい候補の上に表示されることを防ぐためです。\n\n`onValue` と `onError` は同期的な表示処理を渡す前提です。表示関数自身の例外や非同期処理まで面倒を見る、汎用の例外処理関数ではありません。\n\n## 時間待ちに依存せず、完了順序をテストする\n\n実通信を使うと、いつも同じ順序で応答が届くとは限りません。そこで、解決・拒否するタイミングをテスト側で指定できるPromiseを用意します。次は上の関数も含む、単体で実行できるテストファイルです。\n\nファイル名を `latest-result.test.cjs` とし、Node.jsのテストランナーで実行します。\n\n\n```javascript:latest-result.test.cjs\nconst { test } = require('node:test');\nconst assert = require('node:assert/strict');\nfunction createLatestRunner({ onValue, onError }) {\n  let version = 0;\n  return {\n    async run(load) {\n      const mine = ++version;\n      let value;\n      try {\n        value = await load();\n      } catch (error) {\n        if (mine !== version) return;\n        onError(error);\n        return;\n      }\n      if (mine !== version) return;\n      onValue(value);\n    },\n    invalidate() {\n      version += 1;\n    }\n  };\n}\nfunction deferred() {\n  let resolve, reject;\n  const promise = new Promise((res, rej) =\u003e { resolve = res; reject = rej; });\n  return { promise, resolve, reject };\n}\ntest('new response is not overwritten by old response', async () =\u003e {\n  const values = [], errors = [];\n  const runner = createLatestRunner({ onValue: x =\u003e values.push(x), onError: e =\u003e errors.push(e.message) });\n  const a = deferred(), b = deferred();\n  const pa = runner.run(() =\u003e a.promise), pb = runner.run(() =\u003e b.promise);\n  b.resolve('ABの結果'); await pb; a.resolve('Aの結果'); await pa;\n  assert.deepEqual(values, ['ABの結果']); assert.deepEqual(errors, []);\n});\ntest('old rejection is ignored', async () =\u003e {\n  const values = [], errors = [];\n  const runner = createLatestRunner({ onValue: x =\u003e values.push(x), onError: e =\u003e errors.push(e.message) });\n  const a = deferred(), b = deferred();\n  const pa = runner.run(() =\u003e a.promise), pb = runner.run(() =\u003e b.promise);\n  b.resolve('新結果'); await pb; a.reject(new Error('古い失敗')); await pa;\n  assert.deepEqual(values, ['新結果']); assert.deepEqual(errors, []);\n});\ntest('invalidation prevents display after field is cleared', async () =\u003e {\n  const values = [], errors = [];\n  const runner = createLatestRunner({ onValue: x =\u003e values.push(x), onError: e =\u003e errors.push(e.message) });\n  const a = deferred(); const pa = runner.run(() =\u003e a.promise);\n  runner.invalidate(); a.resolve('消した検索語の結果'); await pa;\n  assert.deepEqual(values, []); assert.deepEqual(errors, []);\n});\ntest('latest error is reported', async () =\u003e {\n  const values = [], errors = [];\n  const runner = createLatestRunner({ onValue: x =\u003e values.push(x), onError: e =\u003e errors.push(e.message) });\n  await runner.run(async () =\u003e { throw new Error('最新の失敗'); });\n  assert.deepEqual(values, []); assert.deepEqual(errors, ['最新の失敗']);\n});\n```\n\n`node --test latest-result.test.cjs` で、次の4点を検証します。\n\n- 新しい検索が先に成功したあと、古い検索が成功しても上書きしない。\n- 新しい検索が成功したあと、古い検索が失敗してもエラーを出さない。\n- 入力のクリアで無効化したあと、以前の結果を表示しない。\n- 最新の検索が失敗した場合はエラーを渡す。\n\nこのコードのローカル実行では4件すべて成功しました。確認したのは関数の順序判定であり、kintoneの実画面、権限やAPI通信、モバイルでの動作を確認した結果ではありません。\n\n## 入力を消したとき・画面を離れるときにも無効化する\n\n文字列が空になった場合、検索を実行しないだけでは不十分です。直前の検索が処理中なら、あとから候補が戻ってくるためです。入力を消す処理では `runner.invalidate()` を呼び、表示済みの候補も別に消します。\n\n画面を離れるときも同様です。このサンプルにはkintoneの画面イベントや入力要素への接続処理を含めていません。実装時は画面ごとに関数を作り、候補を消す操作・画面の破棄と対応させてください。複数の入力欄がある場合は、番号を欄ごとに管理します。\n\n## debounceや通信中断とは役割が違う\n\n入力が落ち着くまで実行を待つdebounceは、主に検索を始める回数を抑える方法です。一方、世代番号は、すでに始まった処理のうち、どの結果を採用するかを決めます。debounceだけで応答順序の問題が消えるとは限りません。\n\nこのサンプルは古い結果を無視するだけで、通信自体は中断しません。リクエスト数やAPIの負荷を直接減らす仕組みでもありません。Promiseと非同期処理の基本は[MDNのPromiseの解説](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise)も参考になります。\n\n## 自社で実装する範囲を決める\n\n検索画面に組み込む場合は、クエリに使う文字列のエスケープ、取得権限、取得件数、キャッシュ、IME入力、候補選択時の値の扱いなども必要になります。表示上の重複候補と、保存時に重複を禁止する設計は別です。\n\n画面への組み込みを設定で行いたい場合は、Kintacoが提供する[重複有無、サジェスト表示プラグイン](https://kintaco.wisemap.biz/plugins/duplicate-suggest/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=20261029_async_generation)も選択肢です。本記事は提供元による技術解説です。プラグイン本体には、サンプル以外に画面の有効性や入力状態を確認する処理もあります。無料利用時は有償プランの案内バナーが表示されるため、対応範囲と利用条件は詳細ページで確認してください。\n","coediting":false,"comments_count":0,"created_at":"2026-10-29T11:14:42+09:00","group":null,"id":"cddc1c194806758d6249","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"非同期処理","versions":[]}],"title":"kintoneの検索候補で古い結果を表示しない｜非同期処理の世代番号をJavaScriptでテストする","updated_at":"2026-10-29T11:14:42+09:00","url":"https://qiita.com/kintaco/items/cddc1c194806758d6249","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:329\"\u003e「今日から7日以内」を実装するとき、今日と7日後を含めるのか、過去の日付を除外するのかで結果が変わります。この記事では、KintacoのテーブルIF計算プラグインで使っている日付判定を題材に、境界値を固定して確認する方法を説明します。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:150\"\u003e対象は日付（DATE）です。UTCの日時（DATETIME）をGoogleカレンダーへ渡す既存記事とは扱う値と目的が異なります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:51\"\u003e\n\u003cspan id=\"対象ソースとここで確認する範囲\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%AF%BE%E8%B1%A1%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%A8%E3%81%93%E3%81%93%E3%81%A7%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E7%AF%84%E5%9B%B2\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e対象ソースと、ここで確認する範囲\u003c/h2\u003e\n\u003cp data-sourcepos=\"7:1-7:409\"\u003eローカルの \u003ccode\u003eTableIfCalculation/src/js/desktop.js\u003c/code\u003e、manifestのバージョン1.0.4を確認しました。\u003ccode\u003ematchesCondition\u003c/code\u003e のDATE分岐から相対日付の処理を抜き出し、引数を持つ関数で包んでいます。製品コードを変更する記事ではありません。公開配布ZIPとの一致や、実際のkintone画面での動作まで検証したものではありません。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"9:1-19:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003ematchesRelativeDate\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etext\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ecriteria\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eoperator\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eparts\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"sr\"\u003e/^\u003c/span\u003e\u003cspan class=\"se\"\u003e([\u003c/span\u003e\u003cspan class=\"sr\"\u003e0-9\u003c/span\u003e\u003cspan class=\"se\"\u003e]{4})\u003c/span\u003e\u003cspan class=\"sr\"\u003e-\u003c/span\u003e\u003cspan class=\"se\"\u003e([\u003c/span\u003e\u003cspan class=\"sr\"\u003e0-9\u003c/span\u003e\u003cspan class=\"se\"\u003e]{2})\u003c/span\u003e\u003cspan class=\"sr\"\u003e-\u003c/span\u003e\u003cspan class=\"se\"\u003e([\u003c/span\u003e\u003cspan class=\"sr\"\u003e0-9\u003c/span\u003e\u003cspan class=\"se\"\u003e]{2})\u003c/span\u003e\u003cspan class=\"sr\"\u003e/\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eexec\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etext\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003edays\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nc\"\u003eNumber\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecriteria\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003eparts\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nb\"\u003eNumber\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisInteger\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003edays\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003edays\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eactual\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\"\u003eNumber\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eparts\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]),\u003c/span\u003e \u003cspan class=\"nc\"\u003eNumber\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eparts\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e])\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nc\"\u003eNumber\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eparts\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e]));\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003etoday\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e \u003cspan class=\"nx\"\u003etoday\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003esetHours\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003edifference\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eMath\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eround\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003eactual\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetTime\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"nx\"\u003etoday\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetTime\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e \u003cspan class=\"o\"\u003e/\u003c/span\u003e \u003cspan class=\"mi\"\u003e86400000\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eoperator\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_NEXT_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003edifference\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"nx\"\u003edifference\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan class=\"nx\"\u003edays\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003edifference\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"nx\"\u003edifference\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"nx\"\u003edays\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"21:1-21:181\"\u003eこの抜粋は \u003ccode\u003eWITHIN_NEXT_DAYS\u003c/code\u003e または \u003ccode\u003eWITHIN_PAST_DAYS\u003c/code\u003e を指定して呼ぶ前提です。それ以外の演算子を受け取る汎用関数としては使いません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"23:1-23:33\"\u003e\n\u003cspan id=\"日付と日時を混ぜない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%97%A5%E4%BB%98%E3%81%A8%E6%97%A5%E6%99%82%E3%82%92%E6%B7%B7%E3%81%9C%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e日付と日時を混ぜない\u003c/h2\u003e\n\u003cp data-sourcepos=\"25:1-25:369\"\u003ekintoneのフィールド形式では、DATEは \u003ccode\u003e2026-10-28\u003c/code\u003e、DATETIMEは \u003ccode\u003e2026-10-28T06:30:00Z\u003c/code\u003e のような文字列で表されます。公式の\u003ca href=\"https://cybozu.dev/ja/kintone/docs/overview/field-types/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eフィールド形式\u003c/a\u003eと\u003ca href=\"https://cybozu.dev/ja/kintone/docs/rest-api/overview/kintone-rest-api-overview/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eREST API共通仕様\u003c/a\u003eで形式を確認できます。\u003c/p\u003e\n\u003cp data-sourcepos=\"27:1-27:438\"\u003eこの処理は年月日を取り出し、ローカル時刻の午前0時を作ります。比較対象の今日もローカル時刻で午前0時にそろえています。DATEの日付を、UTC日時の文字列へ置き換える実装ではありません。「今日」は実行端末の時計とタイムゾーンに依存します。会社の基準日を固定したい場合は、基準日を別途決める設計が必要です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"29:1-29:33\"\u003e\n\u003cspan id=\"以内は両端を含む\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BB%A5%E5%86%85%E3%81%AF%E4%B8%A1%E7%AB%AF%E3%82%92%E5%90%AB%E3%82%80\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e「以内」は両端を含む\u003c/h2\u003e\n\u003cp data-sourcepos=\"31:1-31:220\"\u003e基準日を2026年10月28日、日数を7とすると、未来方向は10月28日から11月4日までを含みます。11月5日と10月27日は含みません。過去方向は10月21日から10月28日までです。\u003c/p\u003e\n\u003cp data-sourcepos=\"33:1-33:364\"\u003eつまり7日という差を許す場合、当日を入れると対象となるカレンダー日付は8日分あります。「直近7日」を当日を含む7日分にしたい業務とは、定義をすり合わせる必要があります。演算子の表示名だけで判断せず、開始日と終了日を例で合意すると取り違えを防げます。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"35:1-35:45\"\u003e\n\u003cspan id=\"現在日時を固定してテストする\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%8F%BE%E5%9C%A8%E6%97%A5%E6%99%82%E3%82%92%E5%9B%BA%E5%AE%9A%E3%81%97%E3%81%A6%E3%83%86%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e現在日時を固定してテストする\u003c/h2\u003e\n\u003cp data-sourcepos=\"37:1-37:290\"\u003e毎日の実行日で期待値が変わるテストは、失敗理由を追いにくくなります。次はNode.js用の独立した確認コードです。上の関数を同じファイルの先頭に置いて実行します。kintoneの本番カスタマイズには追加しません。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"39:1-71:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003erequire\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003enode:assert/strict\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eRealDate\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"kd\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eFixedDate\u003c/span\u003e \u003cspan class=\"kd\"\u003eextends\u003c/span\u003e \u003cspan class=\"nc\"\u003eRealDate\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"nf\"\u003econstructor\u003c/span\u003e\u003cspan class=\"p\"\u003e(...\u003c/span\u003e\u003cspan class=\"nx\"\u003eargs\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003esuper\u003c/span\u003e\u003cspan class=\"p\"\u003e(...(\u003c/span\u003e\u003cspan class=\"nx\"\u003eargs\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003eargs\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e2026\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e9\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e28\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e15\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e30\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e]));\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"nb\"\u003eglobal\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nb\"\u003eDate\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eFixedDate\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ecases\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-28\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e7\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_NEXT_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-11-04\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e7\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_NEXT_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-11-05\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e7\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_NEXT_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-27\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e7\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_NEXT_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-21\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e7\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_PAST_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-20\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e7\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_PAST_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-28\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e0\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_PAST_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-29\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e0\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_NEXT_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e7\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_NEXT_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-28\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e-1\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_NEXT_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-28\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e1.5\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_NEXT_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-28\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eabc\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eWITHIN_NEXT_DAYS\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e];\u003c/span\u003e\n  \u003cspan class=\"k\"\u003efor \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003edays\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eop\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eexpected\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"k\"\u003eof\u003c/span\u003e \u003cspan class=\"nx\"\u003ecases\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eequal\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003ematchesRelativeDate\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003edays\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eop\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"nx\"\u003eexpected\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n      \u003cspan class=\"nx\"\u003eJSON\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003estringify\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003edays\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eop\u003c/span\u003e\u003cspan class=\"p\"\u003e}));\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e`\u003c/span\u003e\u003cspan class=\"p\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003ecases\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"s2\"\u003e cases passed: \u003c/span\u003e\u003cspan class=\"p\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003eprocess\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eenv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eTZ\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"s2\"\u003e`\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003efinally\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"nb\"\u003eglobal\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nb\"\u003eDate\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eRealDate\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"73:1-73:310\"\u003e12ケースを \u003ccode\u003eTZ=Asia/Tokyo\u003c/code\u003e、\u003ccode\u003eTZ=UTC\u003c/code\u003e、\u003ccode\u003eTZ=America/New_York\u003c/code\u003e の3環境で確認し、36件の判定が通りました。各環境のローカル日付を同じ10月28日に固定したテストです。同一瞬間に世界中で同じ「今日」になることを示すテストではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"75:1-75:54\"\u003e\n\u003cspan id=\"この抜粋だけでは保証していないこと\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%93%E3%81%AE%E6%8A%9C%E7%B2%8B%E3%81%A0%E3%81%91%E3%81%A7%E3%81%AF%E4%BF%9D%E8%A8%BC%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eこの抜粋だけでは保証していないこと\u003c/h2\u003e\n\u003cp data-sourcepos=\"77:1-77:469\"\u003e空欄、不正な日数、小数の日数は判定から外れます。一方、正規表現は年月日の後ろに文字が続く入力も一致し、JavaScriptのDateは存在しない月日を繰り上げる場合があります。このコードは任意の文字列を厳密に検証するバリデーターではありません。kintoneのDATE値を渡す前提を外すなら、形式の完全一致と年月日の妥当性検証を追加してください。\u003c/p\u003e\n\u003cp data-sourcepos=\"79:1-79:436\"\u003eまた、1日を86400000ミリ秒として差を丸める実装です。今回の3環境・固定日付で通ったことだけで、全地域の夏時間や歴史的な時差変更を網羅したとはいえません。扱う地域・年と月末、うるう日、夏時間の切り替え日を追加ケースにします。画面を開いたまま日付をまたいだ場合に、いつ再計算するかも別の確認項目です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"81:1-81:60\"\u003e\n\u003cspan id=\"設定画面でテーブルの条件集計を使う場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%AD%E5%AE%9A%E7%94%BB%E9%9D%A2%E3%81%A7%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AE%E6%9D%A1%E4%BB%B6%E9%9B%86%E8%A8%88%E3%82%92%E4%BD%BF%E3%81%86%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e設定画面でテーブルの条件集計を使う場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"83:1-83:431\"\u003eコードを保守する代わりに設定画面から使いたい場合は、開発元であるKintacoの\u003ca href=\"https://kintaco.wisemap.biz/plugins/table-if-calculation/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=date_condition_boundaries\" rel=\"nofollow noopener\" target=\"_blank\"\u003eテーブルIF計算プラグイン\u003c/a\u003eで現在の対応範囲をご確認ください。無料利用時は有償プランの案内バナーが表示されます。\u003c/p\u003e\n\u003cp data-sourcepos=\"85:1-85:414\"\u003e設定全体の例は\u003ca href=\"https://kintaco.wisemap.biz/column/kintone-table-conditional-calculation/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=date_condition_boundaries\" rel=\"nofollow noopener\" target=\"_blank\"\u003e条件付き集計のコラム\u003c/a\u003eへまとめています。どちらの方法でも、業務で含めたい最初の日・最後の日を決めてから、実際の設定結果と照合することが大切です。\u003c/p\u003e\n","body":"「今日から7日以内」を実装するとき、今日と7日後を含めるのか、過去の日付を除外するのかで結果が変わります。この記事では、KintacoのテーブルIF計算プラグインで使っている日付判定を題材に、境界値を固定して確認する方法を説明します。\n\n対象は日付（DATE）です。UTCの日時（DATETIME）をGoogleカレンダーへ渡す既存記事とは扱う値と目的が異なります。\n\n## 対象ソースと、ここで確認する範囲\n\nローカルの `TableIfCalculation/src/js/desktop.js`、manifestのバージョン1.0.4を確認しました。`matchesCondition` のDATE分岐から相対日付の処理を抜き出し、引数を持つ関数で包んでいます。製品コードを変更する記事ではありません。公開配布ZIPとの一致や、実際のkintone画面での動作まで検証したものではありません。\n\n```javascript\nfunction matchesRelativeDate(text, criteria, operator) {\n  const parts = /^([0-9]{4})-([0-9]{2})-([0-9]{2})/.exec(text);\n  const days = Number(criteria);\n  if (!parts || !Number.isInteger(days) || days \u003c 0) return false;\n  const actual = new Date(Number(parts[1]), Number(parts[2]) - 1, Number(parts[3]));\n  const today = new Date(); today.setHours(0, 0, 0, 0);\n  const difference = Math.round((actual.getTime() - today.getTime()) / 86400000);\n  return operator === 'WITHIN_NEXT_DAYS' ? difference \u003e= 0 \u0026\u0026 difference \u003c= days : difference \u003c= 0 \u0026\u0026 difference \u003e= -days;\n}\n```\n\nこの抜粋は `WITHIN_NEXT_DAYS` または `WITHIN_PAST_DAYS` を指定して呼ぶ前提です。それ以外の演算子を受け取る汎用関数としては使いません。\n\n## 日付と日時を混ぜない\n\nkintoneのフィールド形式では、DATEは `2026-10-28`、DATETIMEは `2026-10-28T06:30:00Z` のような文字列で表されます。公式の[フィールド形式](https://cybozu.dev/ja/kintone/docs/overview/field-types/)と[REST API共通仕様](https://cybozu.dev/ja/kintone/docs/rest-api/overview/kintone-rest-api-overview/)で形式を確認できます。\n\nこの処理は年月日を取り出し、ローカル時刻の午前0時を作ります。比較対象の今日もローカル時刻で午前0時にそろえています。DATEの日付を、UTC日時の文字列へ置き換える実装ではありません。「今日」は実行端末の時計とタイムゾーンに依存します。会社の基準日を固定したい場合は、基準日を別途決める設計が必要です。\n\n## 「以内」は両端を含む\n\n基準日を2026年10月28日、日数を7とすると、未来方向は10月28日から11月4日までを含みます。11月5日と10月27日は含みません。過去方向は10月21日から10月28日までです。\n\nつまり7日という差を許す場合、当日を入れると対象となるカレンダー日付は8日分あります。「直近7日」を当日を含む7日分にしたい業務とは、定義をすり合わせる必要があります。演算子の表示名だけで判断せず、開始日と終了日を例で合意すると取り違えを防げます。\n\n## 現在日時を固定してテストする\n\n毎日の実行日で期待値が変わるテストは、失敗理由を追いにくくなります。次はNode.js用の独立した確認コードです。上の関数を同じファイルの先頭に置いて実行します。kintoneの本番カスタマイズには追加しません。\n\n```javascript\nconst assert = require('node:assert/strict');\nconst RealDate = Date;\nclass FixedDate extends RealDate {\n  constructor(...args) {\n    super(...(args.length ? args : [2026, 9, 28, 15, 30, 0]));\n  }\n}\nglobal.Date = FixedDate;\ntry {\n  const cases = [\n    ['2026-10-28', '7', 'WITHIN_NEXT_DAYS', true],\n    ['2026-11-04', '7', 'WITHIN_NEXT_DAYS', true],\n    ['2026-11-05', '7', 'WITHIN_NEXT_DAYS', false],\n    ['2026-10-27', '7', 'WITHIN_NEXT_DAYS', false],\n    ['2026-10-21', '7', 'WITHIN_PAST_DAYS', true],\n    ['2026-10-20', '7', 'WITHIN_PAST_DAYS', false],\n    ['2026-10-28', '0', 'WITHIN_PAST_DAYS', true],\n    ['2026-10-29', '0', 'WITHIN_NEXT_DAYS', false],\n    ['', '7', 'WITHIN_NEXT_DAYS', false],\n    ['2026-10-28', '-1', 'WITHIN_NEXT_DAYS', false],\n    ['2026-10-28', '1.5', 'WITHIN_NEXT_DAYS', false],\n    ['2026-10-28', 'abc', 'WITHIN_NEXT_DAYS', false]\n  ];\n  for (const [value, days, op, expected] of cases) {\n    assert.equal(matchesRelativeDate(value, days, op), expected,\n      JSON.stringify({value, days, op}));\n  }\n  console.log(`${cases.length} cases passed: ${process.env.TZ}`);\n} finally {\n  global.Date = RealDate;\n}\n```\n\n12ケースを `TZ=Asia/Tokyo`、`TZ=UTC`、`TZ=America/New_York` の3環境で確認し、36件の判定が通りました。各環境のローカル日付を同じ10月28日に固定したテストです。同一瞬間に世界中で同じ「今日」になることを示すテストではありません。\n\n## この抜粋だけでは保証していないこと\n\n空欄、不正な日数、小数の日数は判定から外れます。一方、正規表現は年月日の後ろに文字が続く入力も一致し、JavaScriptのDateは存在しない月日を繰り上げる場合があります。このコードは任意の文字列を厳密に検証するバリデーターではありません。kintoneのDATE値を渡す前提を外すなら、形式の完全一致と年月日の妥当性検証を追加してください。\n\nまた、1日を86400000ミリ秒として差を丸める実装です。今回の3環境・固定日付で通ったことだけで、全地域の夏時間や歴史的な時差変更を網羅したとはいえません。扱う地域・年と月末、うるう日、夏時間の切り替え日を追加ケースにします。画面を開いたまま日付をまたいだ場合に、いつ再計算するかも別の確認項目です。\n\n## 設定画面でテーブルの条件集計を使う場合\n\nコードを保守する代わりに設定画面から使いたい場合は、開発元であるKintacoの[テーブルIF計算プラグイン](https://kintaco.wisemap.biz/plugins/table-if-calculation/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=date_condition_boundaries)で現在の対応範囲をご確認ください。無料利用時は有償プランの案内バナーが表示されます。\n\n設定全体の例は[条件付き集計のコラム](https://kintaco.wisemap.biz/column/kintone-table-conditional-calculation/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=date_condition_boundaries)へまとめています。どちらの方法でも、業務で含めたい最初の日・最後の日を決めてから、実際の設定結果と照合することが大切です。\n","coediting":false,"comments_count":0,"created_at":"2026-10-28T14:20:00+09:00","group":null,"id":"d46e4c24d4e835426273","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"テスト","versions":[]}],"title":"kintoneの「今日から7日以内」をJavaScriptでテストする｜当日・最終日・日付と日時の違い","updated_at":"2026-10-28T14:20:00+09:00","url":"https://qiita.com/kintaco/items/d46e4c24d4e835426273","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:237\"\u003eフォーム上のラベルを \u003ccode\u003e[基本情報]\u003c/code\u003e のように書き、その間の項目をタブに分ける。こうした処理では、まず「どの文字列をタブの見出しと認めるか」を決める必要があります。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:351\"\u003eこの記事では、弊社kintacoのタブ表示プラグインのPC用コードから、ラベルを判定する関数を抜粋して読み解きます。対象はローカルソースのバージョン2.0.7です。公開ZIPとの一致や、実際のkintone画面での動作をこの記事のテストで保証するものではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:39\"\u003e\n\u003cspan id=\"ラベルを判定する実コード\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%A9%E3%83%99%E3%83%AB%E3%82%92%E5%88%A4%E5%AE%9A%E3%81%99%E3%82%8B%E5%AE%9F%E3%82%B3%E3%83%BC%E3%83%89\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eラベルを判定する実コード\u003c/h2\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"7:1-17:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003egetTabMarkers\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003efunction \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eindex\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003elabel\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003equerySelector\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e.control-label-field-gaia, [class*=\"label-field\"]\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n      \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ematch\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003elabel\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"sr\"\u003e/^\u003c/span\u003e\u003cspan class=\"se\"\u003e\\s\u003c/span\u003e\u003cspan class=\"sr\"\u003e*\u003c/span\u003e\u003cspan class=\"se\"\u003e\\[([^\\]]\u003c/span\u003e\u003cspan class=\"sr\"\u003e+\u003c/span\u003e\u003cspan class=\"se\"\u003e)\\]\\s\u003c/span\u003e\u003cspan class=\"sr\"\u003e*$/\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eexec\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003elabel\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etextContent\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n      \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003ematch\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ematch\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"nf\"\u003etrim\u003c/span\u003e\u003cspan class=\"p\"\u003e(),\u003c/span\u003e \u003cspan class=\"na\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003eindex\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003eindex\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}).\u003c/span\u003e\u003cspan class=\"nf\"\u003efilter\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003efunction \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003emarker\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003emarker\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"nx\"\u003emarker\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"19:1-19:398\"\u003e\u003ccode\u003erows\u003c/code\u003e はDOM要素の配列です。\u003ccode\u003emap\u003c/code\u003e は各行からラベル要素を探し、該当する場合にタブ名・行・元の位置を返します。最後の \u003ccode\u003efilter\u003c/code\u003e で、ラベルのない行と、名前が空のものを取り除きます。この関数だけではタブは表示されません。行の収集、表示切り替え、イベント登録は呼び出し側の処理です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"21:1-21:63\"\u003e\n\u003cspan id=\"部分一致ではなく行頭と行末まで確認する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E9%83%A8%E5%88%86%E4%B8%80%E8%87%B4%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%E8%A1%8C%E9%A0%AD%E3%81%A8%E8%A1%8C%E6%9C%AB%E3%81%BE%E3%81%A7%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e部分一致ではなく、行頭と行末まで確認する\u003c/h2\u003e\n\u003cp data-sourcepos=\"23:1-23:50\"\u003e正規表現は \u003ccode\u003e/^\\s*\\[([^\\]]+)\\]\\s*$/\u003c/code\u003e です。\u003c/p\u003e\n\u003cul data-sourcepos=\"25:1-29:0\"\u003e\n\u003cli data-sourcepos=\"25:1-25:124\"\u003e\n\u003ccode\u003e^\u003c/code\u003e と \u003ccode\u003e$\u003c/code\u003e：ラベル全体を判定し、\u003ccode\u003e[基本情報] の説明\u003c/code\u003e のような文字列を対象から外します。\u003c/li\u003e\n\u003cli data-sourcepos=\"26:1-26:64\"\u003e\n\u003ccode\u003e\\s*\u003c/code\u003e：角括弧の外側にある空白を許容します。\u003c/li\u003e\n\u003cli data-sourcepos=\"27:1-27:126\"\u003e\n\u003ccode\u003e\\[\u003c/code\u003e と \u003ccode\u003e\\]\u003c/code\u003e：半角の角括弧を使います。\u003ccode\u003e［基本情報］\u003c/code\u003e のような全角記号とは一致しません。\u003c/li\u003e\n\u003cli data-sourcepos=\"28:1-29:0\"\u003e\n\u003ccode\u003e([^\\]]+)\u003c/code\u003e：閉じ角括弧以外の文字を1文字以上取得します。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"30:1-30:390\"\u003e取得後に \u003ccode\u003etrim()\u003c/code\u003e してから空の名前を除外するため、\u003ccode\u003e[]\u003c/code\u003e だけでなく \u003ccode\u003e[   ]\u003c/code\u003e もタブになりません。一方、この正規表現はタブ名の重複を除外するものではありません。また、内側の開き括弧や改行を禁止する式でもありません。許容したい表記を厳密に制限するなら、別のルールが必要です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"32:1-32:53\"\u003e\n\u003cspan id=\"textcontentを使う範囲と使わない範囲\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#textcontent%E3%82%92%E4%BD%BF%E3%81%86%E7%AF%84%E5%9B%B2%E3%81%A8%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84%E7%AF%84%E5%9B%B2\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003etextContentを使う範囲と、使わない範囲\u003c/h2\u003e\n\u003cp data-sourcepos=\"34:1-34:317\"\u003e関数はラベルの \u003ccode\u003etextContent\u003c/code\u003e を読みます。文字の装飾を判定するのではなく、取得した文字列がルールに合うかを確認しています。ただし、PC用コードでは行全体の文字列ではなく、セレクターで見つかった最初のラベル要素が対象です。\u003c/p\u003e\n\u003cp data-sourcepos=\"36:1-36:221\"\u003e同じ製品のモバイル用コードは、文字列の取り出し方と空白処理が異なります。PC用関数のテスト結果を、そのままモバイル版の結果として扱わない点も大切です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"38:1-38:39\"\u003e\n\u003cspan id=\"ローカルで確認したケース\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%A7%E7%A2%BA%E8%AA%8D%E3%81%97%E3%81%9F%E3%82%B1%E3%83%BC%E3%82%B9\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eローカルで確認したケース\u003c/h2\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"40:1-62:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003erequire\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003enode:assert/strict\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erow\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003etext\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e({\u003c/span\u003e\n  \u003cspan class=\"na\"\u003equerySelector\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003etext\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etextContent\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003etext\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ecases\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e[基本情報]\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e基本情報\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e]],\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e  [ 商談内容 ]  \u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e商談内容\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e]],\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e[基本情報] の説明\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]],\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e［基本情報］\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]],\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e[]\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]],\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e[   ]\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]],\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e普通の説明ラベル\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]],\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"kc\"\u003enull\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[]]\u003c/span\u003e\n\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n\u003cspan class=\"k\"\u003efor \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003etext\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eexpected\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"k\"\u003eof\u003c/span\u003e \u003cspan class=\"nx\"\u003ecases\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003edeepEqual\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003egetTabMarkers\u003c/span\u003e\u003cspan class=\"p\"\u003e([\u003c/span\u003e\u003cspan class=\"nf\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etext\u003c/span\u003e\u003cspan class=\"p\"\u003e)]).\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ex\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"nx\"\u003eexpected\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erows\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nf\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e説明\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"nf\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e[基本]\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"nf\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e[基本]\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)];\u003c/span\u003e\n\u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003edeepEqual\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003egetTabMarkers\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ex\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003ex\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eindex\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eequal\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003egetTabMarkers\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e)[\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"nx\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e10 assertions passed\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"64:1-64:267\"\u003eこれはラベル抽出のためのスタブを使ったテストです。製品ソースの関数を実行して文字列判定を確認していますが、本物のDOM構造・表示切り替え・入力値の保存を確認したテストではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"66:1-66:51\"\u003e\n\u003cspan id=\"製品domに依存する部分を切り分ける\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A3%BD%E5%93%81dom%E3%81%AB%E4%BE%9D%E5%AD%98%E3%81%99%E3%82%8B%E9%83%A8%E5%88%86%E3%82%92%E5%88%87%E3%82%8A%E5%88%86%E3%81%91%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e製品DOMに依存する部分を切り分ける\u003c/h2\u003e\n\u003cp data-sourcepos=\"68:1-68:441\"\u003e抜粋の \u003ccode\u003e.control-label-field-gaia\u003c/code\u003e などは、kintoneの内部DOMに依存するセレクターです。新規実装の推奨方式として紹介しているものではありません。サイボウズの\u003ca href=\"https://cybozu.dev/ja/kintone/docs/guideline/coding-guideline/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eコーディングガイドライン\u003c/a\u003eは、内部のid・class・DOM構造への依存を避け、提供されるJavaScript APIを使うよう案内しています。\u003c/p\u003e\n\u003cp data-sourcepos=\"70:1-70:273\"\u003e文字列判定のテストが通っても、ラベル要素を取得できなければこの関数は動きません。「要素を取得する段階」と「取得した文字列を判定する段階」を分けて確認すると、原因を追いやすくなります。\u003c/p\u003e\n\u003cp data-sourcepos=\"72:1-72:218\"\u003eまた、タブによる表示切り替えとアクセス権は別です。情報を閲覧・編集できる相手の制限は、\u003ca href=\"https://jp.kintone.help/k/ja/app/rights\" rel=\"nofollow noopener\" target=\"_blank\"\u003ekintoneのアクセス権\u003c/a\u003eで設計します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"74:1-74:42\"\u003e\n\u003cspan id=\"設定画面から利用したい場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%AD%E5%AE%9A%E7%94%BB%E9%9D%A2%E3%81%8B%E3%82%89%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e設定画面から利用したい場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"76:1-76:294\"\u003e弊社の無料プラグインは、次のページで仕様・利用画面・制限を案内しています。無料利用時は有償プランの案内バナーが表示されます。上記のDOM依存も含め、自社の画面と利用端末で検証してから導入してください。\u003c/p\u003e\n\u003cp data-sourcepos=\"78:1-78:144\"\u003e\u003ciframe id=\"qiita-embed-content__26d1e59bfbd94d2e752f2cde42f04050\" src=\"https://qiita.com/embed-contents/link-card#qiita-embed-content__26d1e59bfbd94d2e752f2cde42f04050\" data-content=\"https%3A%2F%2Fkintaco.wisemap.biz%2Fplugins%2Ftab-display%2F%3Futm_source%3Dqiita%26utm_medium%3Dreferral%26utm_campaign%3Dexternal_howto%26utm_content%3Dtab_display_design\" frameborder=\"0\" scrolling=\"no\" loading=\"lazy\" style=\"width:100%;\" height=\"29\"\u003e\n\u003c/iframe\u003e\n\u003c/p\u003e\n\u003cp data-sourcepos=\"80:1-80:99\"\u003eラベルの置き方など、利用者向けの手順は次のコラムにまとめています。\u003c/p\u003e\n\u003cp data-sourcepos=\"82:1-82:149\"\u003e\u003ciframe id=\"qiita-embed-content__62dffe9088752caa330031065c8872f2\" src=\"https://qiita.com/embed-contents/link-card#qiita-embed-content__62dffe9088752caa330031065c8872f2\" data-content=\"https%3A%2F%2Fkintaco.wisemap.biz%2Fcolumn%2Fkintone-form-tabs%2F%3Futm_source%3Dqiita%26utm_medium%3Dreferral%26utm_campaign%3Dexternal_howto%26utm_content%3Dtab_display_design\" frameborder=\"0\" scrolling=\"no\" loading=\"lazy\" style=\"width:100%;\" height=\"29\"\u003e\n\u003c/iframe\u003e\n\u003c/p\u003e\n","body":"フォーム上のラベルを `[基本情報]` のように書き、その間の項目をタブに分ける。こうした処理では、まず「どの文字列をタブの見出しと認めるか」を決める必要があります。\n\nこの記事では、弊社kintacoのタブ表示プラグインのPC用コードから、ラベルを判定する関数を抜粋して読み解きます。対象はローカルソースのバージョン2.0.7です。公開ZIPとの一致や、実際のkintone画面での動作をこの記事のテストで保証するものではありません。\n\n## ラベルを判定する実コード\n\n```javascript\nfunction getTabMarkers(rows) {\n    return rows.map(function (row, index) {\n      const label = row.querySelector('.control-label-field-gaia, [class*=\"label-field\"]');\n      const match = label \u0026\u0026 /^\\s*\\[([^\\]]+)\\]\\s*$/.exec(label.textContent || '');\n      return match ? { name: match[1].trim(), row: row, index: index } : null;\n    }).filter(function (marker) {\n      return marker \u0026\u0026 marker.name;\n    });\n  }\n```\n\n`rows` はDOM要素の配列です。`map` は各行からラベル要素を探し、該当する場合にタブ名・行・元の位置を返します。最後の `filter` で、ラベルのない行と、名前が空のものを取り除きます。この関数だけではタブは表示されません。行の収集、表示切り替え、イベント登録は呼び出し側の処理です。\n\n## 部分一致ではなく、行頭と行末まで確認する\n\n正規表現は `/^\\s*\\[([^\\]]+)\\]\\s*$/` です。\n\n- `^` と `$`：ラベル全体を判定し、`[基本情報] の説明` のような文字列を対象から外します。\n- `\\s*`：角括弧の外側にある空白を許容します。\n- `\\[` と `\\]`：半角の角括弧を使います。`［基本情報］` のような全角記号とは一致しません。\n- `([^\\]]+)`：閉じ角括弧以外の文字を1文字以上取得します。\n\n取得後に `trim()` してから空の名前を除外するため、`[]` だけでなく `[   ]` もタブになりません。一方、この正規表現はタブ名の重複を除外するものではありません。また、内側の開き括弧や改行を禁止する式でもありません。許容したい表記を厳密に制限するなら、別のルールが必要です。\n\n## textContentを使う範囲と、使わない範囲\n\n関数はラベルの `textContent` を読みます。文字の装飾を判定するのではなく、取得した文字列がルールに合うかを確認しています。ただし、PC用コードでは行全体の文字列ではなく、セレクターで見つかった最初のラベル要素が対象です。\n\n同じ製品のモバイル用コードは、文字列の取り出し方と空白処理が異なります。PC用関数のテスト結果を、そのままモバイル版の結果として扱わない点も大切です。\n\n## ローカルで確認したケース\n\n```javascript\nconst assert = require('node:assert/strict');\nconst row = text =\u003e ({\n  querySelector: () =\u003e text === null ? null : { textContent: text }\n});\nconst cases = [\n  ['[基本情報]', ['基本情報']],\n  ['  [ 商談内容 ]  ', ['商談内容']],\n  ['[基本情報] の説明', []],\n  ['［基本情報］', []],\n  ['[]', []],\n  ['[   ]', []],\n  ['普通の説明ラベル', []],\n  [null, []]\n];\nfor (const [text, expected] of cases) {\n  assert.deepEqual(getTabMarkers([row(text)]).map(x =\u003e x.name), expected);\n}\nconst rows = [row('説明'), row('[基本]'), row('[基本]')];\nassert.deepEqual(getTabMarkers(rows).map(x =\u003e x.index), [1, 2]);\nassert.equal(getTabMarkers(rows)[0].row, rows[1]);\nconsole.log('10 assertions passed');\n```\n\nこれはラベル抽出のためのスタブを使ったテストです。製品ソースの関数を実行して文字列判定を確認していますが、本物のDOM構造・表示切り替え・入力値の保存を確認したテストではありません。\n\n## 製品DOMに依存する部分を切り分ける\n\n抜粋の `.control-label-field-gaia` などは、kintoneの内部DOMに依存するセレクターです。新規実装の推奨方式として紹介しているものではありません。サイボウズの[コーディングガイドライン](https://cybozu.dev/ja/kintone/docs/guideline/coding-guideline/)は、内部のid・class・DOM構造への依存を避け、提供されるJavaScript APIを使うよう案内しています。\n\n文字列判定のテストが通っても、ラベル要素を取得できなければこの関数は動きません。「要素を取得する段階」と「取得した文字列を判定する段階」を分けて確認すると、原因を追いやすくなります。\n\nまた、タブによる表示切り替えとアクセス権は別です。情報を閲覧・編集できる相手の制限は、[kintoneのアクセス権](https://jp.kintone.help/k/ja/app/rights)で設計します。\n\n## 設定画面から利用したい場合\n\n弊社の無料プラグインは、次のページで仕様・利用画面・制限を案内しています。無料利用時は有償プランの案内バナーが表示されます。上記のDOM依存も含め、自社の画面と利用端末で検証してから導入してください。\n\nhttps://kintaco.wisemap.biz/plugins/tab-display/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=tab_display_design\n\nラベルの置き方など、利用者向けの手順は次のコラムにまとめています。\n\nhttps://kintaco.wisemap.biz/column/kintone-form-tabs/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=tab_display_design\n","coediting":false,"comments_count":0,"created_at":"2026-10-27T16:00:48+09:00","group":null,"id":"15d119604b8b2c0afe0c","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"正規表現","versions":[]}],"title":"kintoneのタブラベルをJavaScriptで判定する｜正規表現・空白・DOM依存を分けて確認","updated_at":"2026-10-27T16:00:48+09:00","url":"https://qiita.com/kintaco/items/15d119604b8b2c0afe0c","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003ch2 data-sourcepos=\"1:1-1:15\"\u003e\n\u003cspan id=\"はじめに\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eはじめに\u003c/h2\u003e\n\u003cp data-sourcepos=\"3:1-4:106\"\u003ekintone のアプリの見た目を、スキンを選んで整える Chrome 拡張機能「EST キンスキン」を個人で作りました（無料。Chrome ウェブストアで公開しています）。\u003cbr\u003e\n運用の面で、\u003cstrong\u003e画面を色で分けられると便利そう\u003c/strong\u003eだと考えたのが出発点です。\u003c/p\u003e\n\u003cp data-sourcepos=\"6:1-6:189\"\u003eこの記事では、アプリの見た目をどういう仕組みで変えているかを中心に書きます。使い方の手順は、最後の note の記事にまとめています。\u003c/p\u003e\n\u003cp data-sourcepos=\"8:1-8:40\"\u003e作った目的は、次の3つです。\u003c/p\u003e\n\u003cul data-sourcepos=\"10:1-13:0\"\u003e\n\u003cli data-sourcepos=\"10:1-10:89\"\u003e業務別、機能別、運用別に、アプリの画面を区別する（スキン）\u003c/li\u003e\n\u003cli data-sourcepos=\"11:1-11:101\"\u003eカスタマイズで追加したボタンを、種類ごとに区別する（カスタム要素）\u003c/li\u003e\n\u003cli data-sourcepos=\"12:1-13:0\"\u003e関連するフィールドを、色で結び付けて見せる（フィールドの色。フィールドのグループ機能とは別の使い方です）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 data-sourcepos=\"14:1-14:18\"\u003e\n\u003cspan id=\"できること\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eできること\u003c/h2\u003e\n\u003cp data-sourcepos=\"16:1-16:64\"\u003eサイドパネルが、3つのタブに分かれています。\u003c/p\u003e\n\u003ctable data-sourcepos=\"18:1-22:166\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"18:1-18:67\"\u003e\n\u003cth data-sourcepos=\"18:2-18:9\"\u003eタブ\u003c/th\u003e\n\u003cth data-sourcepos=\"18:11-18:27\"\u003eできること\u003c/th\u003e\n\u003cth data-sourcepos=\"18:29-18:66\"\u003eアプリに登録するファイル\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"20:1-20:167\"\u003e\n\u003ctd data-sourcepos=\"20:2-20:12\"\u003eスキン\u003c/td\u003e\n\u003ctd data-sourcepos=\"20:14-20:146\"\u003e19種類のスキンから選び、メイン色・文字色、角丸、ボタンの形と高さ、文字の大きさを調整する\u003c/td\u003e\n\u003ctd data-sourcepos=\"20:148-20:166\"\u003e\u003ccode\u003eest-kinskin.css\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"21:1-21:169\"\u003e\n\u003ctd data-sourcepos=\"21:2-21:21\"\u003eカスタム要素\u003c/td\u003e\n\u003ctd data-sourcepos=\"21:23-21:141\"\u003eカスタマイズで追加したボタンなど（ID の付いた要素）の色・枠・角丸・余白を整える\u003c/td\u003e\n\u003ctd data-sourcepos=\"21:143-21:168\"\u003e\u003ccode\u003eest-kinskin-custom.css\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"22:1-22:166\"\u003e\n\u003ctd data-sourcepos=\"22:2-22:18\"\u003eフィールド\u003c/td\u003e\n\u003ctd data-sourcepos=\"22:20-22:139\"\u003eフィールド全体・内容・フィールド名の色や太さを、kintone 公式の \u003ccode\u003esetFieldStyle\u003c/code\u003e で付ける\u003c/td\u003e\n\u003ctd data-sourcepos=\"22:141-22:165\"\u003e\u003ccode\u003eest-kinskin-fields.js\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"24:1-24:140\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F4498380%2F4c5e81dc-04cf-4e80-834e-b8581c512a1a.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=f112f9b554151488829a54b00e34c878\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F4498380%2F4c5e81dc-04cf-4e80-834e-b8581c512a1a.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=f112f9b554151488829a54b00e34c878\" alt=\"n2-03-list-before-after.png\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F4498380%2F4c5e81dc-04cf-4e80-834e-b8581c512a1a.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=cdd98a2e427ac38b44116f21e5c0d451 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4498380/4c5e81dc-04cf-4e80-834e-b8581c512a1a.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"26:1-26:117\"\u003eスキン「オーシャン」をプレビューで確かめたときの一覧の画面です（上が変更前）。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"28:1-28:12\"\u003e\n\u003cspan id=\"仕組み\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BB%95%E7%B5%84%E3%81%BF\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e仕組み\u003c/h2\u003e\n\u003cp data-sourcepos=\"30:1-31:214\"\u003e全体の流れは、「パネルの値 → ファイルを生成 → プレビューで確かめる → REST API でアプリに登録」です。\u003cbr\u003e\nどのタブも、最後は「アプリの設定の『JavaScript / CSSでカスタマイズ』にファイルを登録する」だけで、拡張機能が画面を書き換え続けるわけではありません。\u003c/p\u003e\n\u003ch3 data-sourcepos=\"33:1-33:48\"\u003e\n\u003cspan id=\"1-スキン値から-css-を生成する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#1-%E3%82%B9%E3%82%AD%E3%83%B3%E5%80%A4%E3%81%8B%E3%82%89-css-%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e1. スキン：値から CSS を生成する\u003c/h3\u003e\n\u003cp data-sourcepos=\"35:1-35:187\"\u003ekintone の画面に付いているクラスを目印にして、パネルの値から CSS を生成します。たとえば、一覧の見出しは次のような規則になります。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"css\" data-sourcepos=\"37:1-44:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"nd\"\u003e:where\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nt\"\u003ehtml\u003c/span\u003e\u003cspan class=\"nd\"\u003e:not\u003c/span\u003e\u003cspan class=\"o\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\"\u003e.est-kinskin-preview\u003c/span\u003e\u003cspan class=\"o\"\u003e))\u003c/span\u003e \u003cspan class=\"nc\"\u003e.recordlist-header-cell-gaia\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"nl\"\u003ebackground-color\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003e#3498db\u003c/span\u003e \u003cspan class=\"cp\"\u003e!important\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"nl\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003e#ffffff\u003c/span\u003e \u003cspan class=\"cp\"\u003e!important\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"nl\"\u003eborder-color\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003e#2c81ba\u003c/span\u003e \u003cspan class=\"cp\"\u003e!important\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"nl\"\u003efont-size\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"m\"\u003e14px\u003c/span\u003e \u003cspan class=\"cp\"\u003e!important\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"46:1-46:228\"\u003e規則を \u003ccode\u003e:where(html:not(.est-kinskin-preview))\u003c/code\u003e の中に入れているのは、プレビューのためです（次の項で説明します）。\u003ccode\u003e:where\u003c/code\u003e は詳細度が 0 なので、規則の強さは変わりません。\u003c/p\u003e\n\u003ch3 data-sourcepos=\"48:1-48:79\"\u003e\n\u003cspan id=\"2-プレビュー開いている画面にだけ一時的に反映する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#2-%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E9%96%8B%E3%81%84%E3%81%A6%E3%81%84%E3%82%8B%E7%94%BB%E9%9D%A2%E3%81%AB%E3%81%A0%E3%81%91%E4%B8%80%E6%99%82%E7%9A%84%E3%81%AB%E5%8F%8D%E6%98%A0%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e2. プレビュー：開いている画面にだけ一時的に反映する\u003c/h3\u003e\n\u003cp data-sourcepos=\"50:1-50:173\"\u003eプレビューをオンにすると、パネルの内容から作った CSS を、開いている kintone の画面に一時的に注入します。保存はしません。\u003c/p\u003e\n\u003cul data-sourcepos=\"52:1-54:0\"\u003e\n\u003cli data-sourcepos=\"52:1-52:359\"\u003eプレビュー中は \u003ccode\u003e\u0026lt;html\u0026gt;\u003c/code\u003e に \u003ccode\u003eest-kinskin-preview\u003c/code\u003e のクラスを付けます。すると、アプリに登録済みの CSS は上の \u003ccode\u003e:where(...)\u003c/code\u003e の条件に当てはまらなくなり、効かなくなります。つまり、\u003cstrong\u003eパネルの内容だけで見える\u003c/strong\u003eので、「適用するとこうなる」がそのまま確かめられます。\u003c/li\u003e\n\u003cli data-sourcepos=\"53:1-54:0\"\u003e見た目を変える対象が、その画面にあるかも確かめます。見つからないものがあると、パネルに警告を出します（kintone の更新で画面の作りが変わったときに気づくためです）。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 data-sourcepos=\"55:1-55:73\"\u003e\n\u003cspan id=\"3-適用rest-api-でアプリのカスタマイズに登録する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#3-%E9%81%A9%E7%94%A8rest-api-%E3%81%A7%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA%E3%81%AB%E7%99%BB%E9%8C%B2%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e3. 適用：REST API でアプリのカスタマイズに登録する\u003c/h3\u003e\n\u003cp data-sourcepos=\"57:1-57:70\"\u003e「適用」を押すと、次の順番で REST API を呼びます。\u003c/p\u003e\n\u003col data-sourcepos=\"59:1-64:0\"\u003e\n\u003cli data-sourcepos=\"59:1-59:224\"\u003e\n\u003ccode\u003eGET /k/v1/preview/app/customize.json\u003c/code\u003e：動作テスト環境の設定を読む。運用環境の \u003ccode\u003eGET /k/v1/app/customize.json\u003c/code\u003e と revision を比べ、反映していない変更があれば確認画面で知らせる\u003c/li\u003e\n\u003cli data-sourcepos=\"60:1-60:97\"\u003e\n\u003ccode\u003ePOST /k/v1/file.json\u003c/code\u003e：生成したファイルをアップロードして fileKey を得る\u003c/li\u003e\n\u003cli data-sourcepos=\"61:1-61:255\"\u003e\n\u003ccode\u003ePUT /k/v1/preview/app/customize.json\u003c/code\u003e：前に登録した\u003cstrong\u003e同じ名前のファイルだけ\u003c/strong\u003eを外し、ほかのファイルは fileKey のまま残して、新しいファイルを加える（revision を指定して、同時の変更を防ぐ）\u003c/li\u003e\n\u003cli data-sourcepos=\"62:1-62:54\"\u003e\n\u003ccode\u003ePOST /k/v1/preview/app/deploy.json\u003c/code\u003e：反映する\u003c/li\u003e\n\u003cli data-sourcepos=\"63:1-64:0\"\u003e\n\u003ccode\u003eGET /k/v1/preview/app/deploy.json\u003c/code\u003e：\u003ccode\u003eSUCCESS\u003c/code\u003e になるまで待つ\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp data-sourcepos=\"65:1-65:311\"\u003e認証は、ログイン中のブラウザーのセッションです。アプリのカスタマイズを変更する API は、API トークンが使えません。そのため、適用できるのは、kintone のシステム管理権限と、そのアプリの管理権限の両方を持つ人だけです。\u003c/p\u003e\n\u003cp data-sourcepos=\"67:1-67:151\"\u003e適用の範囲（\u003ccode\u003escope\u003c/code\u003e）は変えません。ほかのファイルにも影響するためです。確認画面に今の範囲を表示します。\u003c/p\u003e\n\u003cp data-sourcepos=\"69:1-69:189\"\u003e「削除」は、拡張機能が登録したファイル（名前で見分けます）だけを外して、同じ手順で反映します。アプリの一般設定には触れません。\u003c/p\u003e\n\u003ch3 data-sourcepos=\"71:1-71:75\"\u003e\n\u003cspan id=\"4-フィールドの色setfieldstyle-を呼ぶ-js-を生成する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#4-%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%AE%E8%89%B2setfieldstyle-%E3%82%92%E5%91%BC%E3%81%B6-js-%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e4. フィールドの色：\u003ccode\u003esetFieldStyle\u003c/code\u003e を呼ぶ JS を生成する\u003c/h3\u003e\n\u003cp data-sourcepos=\"73:1-73:130\"\u003eフィールドの色は、CSS ではなく kintone 公式の \u003ccode\u003esetFieldStyle\u003c/code\u003e で付けます。生成する JS は、表示のイ\u003c/p\u003e\n\u003cp data-sourcepos=\"75:1-76:98\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F4498380%2F94befab6-9877-4f53-9e30-d30bf6190e59.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=f1e0babfd96309d8e54beaa664fc5057\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F4498380%2F94befab6-9877-4f53-9e30-d30bf6190e59.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=f1e0babfd96309d8e54beaa664fc5057\" alt=\"n3-05-record-colors.png\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F4498380%2F94befab6-9877-4f53-9e30-d30bf6190e59.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=a72c9090f0c99e0b1cd7f6c14a30513d 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4498380/94befab6-9877-4f53-9e30-d30bf6190e59.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003cbr\u003e\nベントで \u003ccode\u003esetFieldStyle\u003c/code\u003e を呼ぶだけです（要点だけを抜き出した例です）。\u003c/p\u003e\n\u003cp data-sourcepos=\"78:1-78:114\"\u003e単価、数量、金額に同じ背景色を付けた例です（プレビューで確かめた画面です）。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"80:1-90:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eevents\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eon\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eapp.record.create.show\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eapp.record.edit.show\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eapp.record.detail.show\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eapp.record.print.show\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eapp\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003esetFieldStyle\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ecustomer_name\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"na\"\u003ebackground\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003ebackgroundColor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e#ffd966\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"92:1-92:131\"\u003e\u003ccode\u003econtent\u003c/code\u003e が使えないフィールド（計算フィールドなど）では、\u003ccode\u003econtent\u003c/code\u003e を除いてもう一度呼びます。\u003c/p\u003e\n\u003ch3 data-sourcepos=\"94:1-94:64\"\u003e\n\u003cspan id=\"5-カスタム要素id-のある要素だけを選べる\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#5-%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E8%A6%81%E7%B4%A0id-%E3%81%AE%E3%81%82%E3%82%8B%E8%A6%81%E7%B4%A0%E3%81%A0%E3%81%91%E3%82%92%E9%81%B8%E3%81%B9%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e5. カスタム要素：ID のある要素だけを選べる\u003c/h3\u003e\n\u003cp data-sourcepos=\"96:1-96:205\"\u003eカスタマイズで追加したボタンなどは、kintone が API で用意している「カスタマイズ用の空白部分」の中の、ID のある要素だけを選べるようにしました。\u003c/p\u003e\n\u003cul data-sourcepos=\"98:1-100:0\"\u003e\n\u003cli data-sourcepos=\"98:1-98:92\"\u003e一覧：\u003ccode\u003ekintone.app.getHeaderMenuSpaceElement()\u003c/code\u003e、\u003ccode\u003ekintone.app.getHeaderSpaceElement()\u003c/code\u003e\n\u003c/li\u003e\n\u003cli data-sourcepos=\"99:1-100:0\"\u003eレコード：\u003ccode\u003ekintone.app.record.getHeaderMenuSpaceElement()\u003c/code\u003e、\u003ccode\u003ekintone.app.record.getSpaceElement()\u003c/code\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"101:1-101:230\"\u003e対象の指定は \u003ccode\u003e#ID\u003c/code\u003e になります。kintone の標準のクラスや、自動で作られるクラス（\u003ccode\u003esc-…\u003c/code\u003e など）は、kintone の更新で変わる可能性があるため、選べないようにしています。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"103:1-103:24\"\u003e\n\u003cspan id=\"ハマったところ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%8F%E3%83%9E%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%93%E3%82%8D\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eハマったところ\u003c/h2\u003e\n\u003ch3 data-sourcepos=\"105:1-105:65\"\u003e\n\u003cspan id=\"画面を移動しただけではcss-が反映されない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%94%BB%E9%9D%A2%E3%82%92%E7%A7%BB%E5%8B%95%E3%81%97%E3%81%9F%E3%81%A0%E3%81%91%E3%81%A7%E3%81%AFcss-%E3%81%8C%E5%8F%8D%E6%98%A0%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e画面を移動しただけでは、CSS が反映されない\u003c/h3\u003e\n\u003cp data-sourcepos=\"107:1-107:335\"\u003ekintone は、アプリのカスタマイズのファイルを、\u003cstrong\u003eブラウザーでページを読み込んだときにだけ\u003c/strong\u003e読みます。一覧からレコードへ移るなど、kintone の画面の中での移動では読み直されません。適用や削除のあとは、ブラウザーの再読み込みが必要です。\u003c/p\u003e\n\u003ch3 data-sourcepos=\"109:1-109:65\"\u003e\n\u003cspan id=\"setfieldstyle-は渡さなかった項目を変えない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#setfieldstyle-%E3%81%AF%E6%B8%A1%E3%81%95%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E9%A0%85%E7%9B%AE%E3%82%92%E5%A4%89%E3%81%88%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e\u003ccode\u003esetFieldStyle\u003c/code\u003e は、渡さなかった項目を変えない\u003c/h3\u003e\n\u003cp data-sourcepos=\"111:1-111:306\"\u003eパネルでチェックを外した項目を、config から外して呼ぶと、前の色が残ります。解除したい項目には、\u003ccode\u003e'DEFAULT'\u003c/code\u003e を渡す必要があります（公式のドキュメントにも、各項目に \u003ccode\u003eDEFAULT\u003c/code\u003e を指定すると個別に解除できるとあります）。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"113:1-118:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"c1\"\u003e// 背景だけ解除する\u003c/span\u003e\n\u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eapp\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003esetFieldStyle\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ecustomer_name\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"na\"\u003ebackground\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003ebackgroundColor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eDEFAULT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"120:1-120:124\"\u003eこの拡張機能のプレビューでは、パネルで外した項目に \u003ccode\u003e'DEFAULT'\u003c/code\u003e を送るようにしています。\u003c/p\u003e\n\u003ch3 data-sourcepos=\"122:1-122:82\"\u003e\n\u003cspan id=\"フィールドの背景色は値の要素ではなく外側の枠に付く\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%AE%E8%83%8C%E6%99%AF%E8%89%B2%E3%81%AF%E5%80%A4%E3%81%AE%E8%A6%81%E7%B4%A0%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%E5%A4%96%E5%81%B4%E3%81%AE%E6%9E%A0%E3%81%AB%E4%BB%98%E3%81%8F\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eフィールドの背景色は、値の要素ではなく外側の枠に付く\u003c/h3\u003e\n\u003cp data-sourcepos=\"124:1-124:269\"\u003e\u003ccode\u003egetFieldElement\u003c/code\u003e が返す値の要素の背景を見ても、反映されていないように見えます。背景色は、外側の \u003ccode\u003e.control-gaia\u003c/code\u003e の枠に付きます。動作確認のときに、最初は「反映されていない」と誤判定しました。\u003c/p\u003e\n\u003ch3 data-sourcepos=\"126:1-126:63\"\u003e\n\u003cspan id=\"ボタンの背景は-background-color-だけを変える\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%9C%E3%82%BF%E3%83%B3%E3%81%AE%E8%83%8C%E6%99%AF%E3%81%AF-background-color-%E3%81%A0%E3%81%91%E3%82%92%E5%A4%89%E3%81%88%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eボタンの背景は \u003ccode\u003ebackground-color\u003c/code\u003e だけを変える\u003c/h3\u003e\n\u003cp data-sourcepos=\"128:1-128:253\"\u003e\u003ccode\u003ebackground\u003c/code\u003e でまとめて指定すると、kintone がアイコンを描いている背景の画像まで消えてしまい、歯車などのボタンのアイコンが消えました。\u003ccode\u003ebackground-color\u003c/code\u003e だけを変えるようにしています。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"130:1-130:27\"\u003e\n\u003cspan id=\"注意していること\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%B3%A8%E6%84%8F%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e注意していること\u003c/h2\u003e\n\u003cul data-sourcepos=\"132:1-138:0\"\u003e\n\u003cli data-sourcepos=\"132:1-132:221\"\u003e適用の範囲が「すべてのユーザー」のアプリでは、ゲストユーザーを含むすべてのユーザーの画面に表示されます。適用の範囲は、この拡張機能では変えません。\u003c/li\u003e\n\u003cli data-sourcepos=\"133:1-133:94\"\u003ekintone の旧デザインの画面と、スマートフォンの画面は対象外です。\u003c/li\u003e\n\u003cli data-sourcepos=\"134:1-134:149\"\u003ekintone ライセンスのライトコースでは、JavaScript や CSS によるカスタマイズが使えないため、利用できません。\u003c/li\u003e\n\u003cli data-sourcepos=\"135:1-135:157\"\u003ekintone の定期メンテナンスで、画面に付いているクラス名が変わると、スキンが適用されなくなる場合があります。\u003c/li\u003e\n\u003cli data-sourcepos=\"136:1-136:166\"\u003e開発者のサーバーは使いません。レコードのデータは読みません。パスワードや API トークンは使わず、保存もしません。\u003c/li\u003e\n\u003cli data-sourcepos=\"137:1-138:0\"\u003e業務で使う前に、テスト用のアプリで確かめることをおすすめします。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 data-sourcepos=\"139:1-139:21\"\u003e\n\u003cspan id=\"詳しい使い方\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A9%B3%E3%81%97%E3%81%84%E4%BD%BF%E3%81%84%E6%96%B9\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e詳しい使い方\u003c/h2\u003e\n\u003cp data-sourcepos=\"141:1-141:71\"\u003e操作の手順や画面は、note の記事にまとめています。\u003c/p\u003e\n\u003cul data-sourcepos=\"143:1-145:0\"\u003e\n\u003cli data-sourcepos=\"143:1-143:153\"\u003e\u003ca href=\"https://note.com/cheeky_rat9295/n/n7055a60b1f6f\" rel=\"nofollow noopener\" target=\"_blank\"\u003eEST キンスキンの使い方。スキンを選び、プレビューしてから適用するまで\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"144:1-145:0\"\u003e\u003ca href=\"https://note.com/cheeky_rat9295/n/n1ce498927c2f\" rel=\"nofollow noopener\" target=\"_blank\"\u003eEST キンスキンの使い方（応用）。カスタマイズのボタンとフィールドの色を整える\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"146:1-146:192\"\u003e\u003ca href=\"https://chromewebstore.google.com/detail/ggbghgkahfaplgkbpehdlilfcobolonp?utm_source=qiita\u0026amp;utm_medium=article\u0026amp;utm_campaign=est_kinskin_launch\" rel=\"nofollow noopener\" target=\"_blank\"\u003eChrome ウェブストア：EST キンスキン\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"148:1-148:127\"\u003e※「kintone」はサイボウズ株式会社の登録商標です。個人で開発している非公式のツールです。\u003c/p\u003e\n","body":"## はじめに\n\nkintone のアプリの見た目を、スキンを選んで整える Chrome 拡張機能「EST キンスキン」を個人で作りました（無料。Chrome ウェブストアで公開しています）。\n運用の面で、**画面を色で分けられると便利そう**だと考えたのが出発点です。\n\nこの記事では、アプリの見た目をどういう仕組みで変えているかを中心に書きます。使い方の手順は、最後の note の記事にまとめています。\n\n作った目的は、次の3つです。\n\n- 業務別、機能別、運用別に、アプリの画面を区別する（スキン）\n- カスタマイズで追加したボタンを、種類ごとに区別する（カスタム要素）\n- 関連するフィールドを、色で結び付けて見せる（フィールドの色。フィールドのグループ機能とは別の使い方です）\n\n## できること\n\nサイドパネルが、3つのタブに分かれています。\n\n| タブ | できること | アプリに登録するファイル |\n| --- | --- | --- |\n| スキン | 19種類のスキンから選び、メイン色・文字色、角丸、ボタンの形と高さ、文字の大きさを調整する | `est-kinskin.css` |\n| カスタム要素 | カスタマイズで追加したボタンなど（ID の付いた要素）の色・枠・角丸・余白を整える | `est-kinskin-custom.css` |\n| フィールド | フィールド全体・内容・フィールド名の色や太さを、kintone 公式の `setFieldStyle` で付ける | `est-kinskin-fields.js` |\n\n![n2-03-list-before-after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4498380/4c5e81dc-04cf-4e80-834e-b8581c512a1a.png)\n\nスキン「オーシャン」をプレビューで確かめたときの一覧の画面です（上が変更前）。\n\n## 仕組み\n\n全体の流れは、「パネルの値 → ファイルを生成 → プレビューで確かめる → REST API でアプリに登録」です。\nどのタブも、最後は「アプリの設定の『JavaScript / CSSでカスタマイズ』にファイルを登録する」だけで、拡張機能が画面を書き換え続けるわけではありません。\n\n### 1. スキン：値から CSS を生成する\n\nkintone の画面に付いているクラスを目印にして、パネルの値から CSS を生成します。たとえば、一覧の見出しは次のような規則になります。\n\n```css\n:where(html:not(.est-kinskin-preview)) .recordlist-header-cell-gaia {\n  background-color: #3498db !important;\n  color: #ffffff !important;\n  border-color: #2c81ba !important;\n  font-size: 14px !important;\n}\n```\n\n規則を `:where(html:not(.est-kinskin-preview))` の中に入れているのは、プレビューのためです（次の項で説明します）。`:where` は詳細度が 0 なので、規則の強さは変わりません。\n\n### 2. プレビュー：開いている画面にだけ一時的に反映する\n\nプレビューをオンにすると、パネルの内容から作った CSS を、開いている kintone の画面に一時的に注入します。保存はしません。\n\n- プレビュー中は `\u003chtml\u003e` に `est-kinskin-preview` のクラスを付けます。すると、アプリに登録済みの CSS は上の `:where(...)` の条件に当てはまらなくなり、効かなくなります。つまり、**パネルの内容だけで見える**ので、「適用するとこうなる」がそのまま確かめられます。\n- 見た目を変える対象が、その画面にあるかも確かめます。見つからないものがあると、パネルに警告を出します（kintone の更新で画面の作りが変わったときに気づくためです）。\n\n### 3. 適用：REST API でアプリのカスタマイズに登録する\n\n「適用」を押すと、次の順番で REST API を呼びます。\n\n1. `GET /k/v1/preview/app/customize.json`：動作テスト環境の設定を読む。運用環境の `GET /k/v1/app/customize.json` と revision を比べ、反映していない変更があれば確認画面で知らせる\n2. `POST /k/v1/file.json`：生成したファイルをアップロードして fileKey を得る\n3. `PUT /k/v1/preview/app/customize.json`：前に登録した**同じ名前のファイルだけ**を外し、ほかのファイルは fileKey のまま残して、新しいファイルを加える（revision を指定して、同時の変更を防ぐ）\n4. `POST /k/v1/preview/app/deploy.json`：反映する\n5. `GET /k/v1/preview/app/deploy.json`：`SUCCESS` になるまで待つ\n\n認証は、ログイン中のブラウザーのセッションです。アプリのカスタマイズを変更する API は、API トークンが使えません。そのため、適用できるのは、kintone のシステム管理権限と、そのアプリの管理権限の両方を持つ人だけです。\n\n適用の範囲（`scope`）は変えません。ほかのファイルにも影響するためです。確認画面に今の範囲を表示します。\n\n「削除」は、拡張機能が登録したファイル（名前で見分けます）だけを外して、同じ手順で反映します。アプリの一般設定には触れません。\n\n### 4. フィールドの色：`setFieldStyle` を呼ぶ JS を生成する\n\nフィールドの色は、CSS ではなく kintone 公式の `setFieldStyle` で付けます。生成する JS は、表示のイ\n\n![n3-05-record-colors.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4498380/94befab6-9877-4f53-9e30-d30bf6190e59.png)\nベントで `setFieldStyle` を呼ぶだけです（要点だけを抜き出した例です）。\n\n単価、数量、金額に同じ背景色を付けた例です（プレビューで確かめた画面です）。\n\n```javascript\nkintone.events.on(\n  ['app.record.create.show', 'app.record.edit.show', 'app.record.detail.show', 'app.record.print.show'],\n  (event) =\u003e {\n    kintone.app.record.setFieldStyle('customer_name', {\n      background: { backgroundColor: '#ffd966' },\n    });\n    return event;\n  }\n);\n```\n\n`content` が使えないフィールド（計算フィールドなど）では、`content` を除いてもう一度呼びます。\n\n### 5. カスタム要素：ID のある要素だけを選べる\n\nカスタマイズで追加したボタンなどは、kintone が API で用意している「カスタマイズ用の空白部分」の中の、ID のある要素だけを選べるようにしました。\n\n- 一覧：`kintone.app.getHeaderMenuSpaceElement()`、`kintone.app.getHeaderSpaceElement()`\n- レコード：`kintone.app.record.getHeaderMenuSpaceElement()`、`kintone.app.record.getSpaceElement()`\n\n対象の指定は `#ID` になります。kintone の標準のクラスや、自動で作られるクラス（`sc-…` など）は、kintone の更新で変わる可能性があるため、選べないようにしています。\n\n## ハマったところ\n\n### 画面を移動しただけでは、CSS が反映されない\n\nkintone は、アプリのカスタマイズのファイルを、**ブラウザーでページを読み込んだときにだけ**読みます。一覧からレコードへ移るなど、kintone の画面の中での移動では読み直されません。適用や削除のあとは、ブラウザーの再読み込みが必要です。\n\n### `setFieldStyle` は、渡さなかった項目を変えない\n\nパネルでチェックを外した項目を、config から外して呼ぶと、前の色が残ります。解除したい項目には、`'DEFAULT'` を渡す必要があります（公式のドキュメントにも、各項目に `DEFAULT` を指定すると個別に解除できるとあります）。\n\n```javascript\n// 背景だけ解除する\nawait kintone.app.record.setFieldStyle('customer_name', {\n  background: { backgroundColor: 'DEFAULT' },\n});\n```\n\nこの拡張機能のプレビューでは、パネルで外した項目に `'DEFAULT'` を送るようにしています。\n\n### フィールドの背景色は、値の要素ではなく外側の枠に付く\n\n`getFieldElement` が返す値の要素の背景を見ても、反映されていないように見えます。背景色は、外側の `.control-gaia` の枠に付きます。動作確認のときに、最初は「反映されていない」と誤判定しました。\n\n### ボタンの背景は `background-color` だけを変える\n\n`background` でまとめて指定すると、kintone がアイコンを描いている背景の画像まで消えてしまい、歯車などのボタンのアイコンが消えました。`background-color` だけを変えるようにしています。\n\n## 注意していること\n\n- 適用の範囲が「すべてのユーザー」のアプリでは、ゲストユーザーを含むすべてのユーザーの画面に表示されます。適用の範囲は、この拡張機能では変えません。\n- kintone の旧デザインの画面と、スマートフォンの画面は対象外です。\n- kintone ライセンスのライトコースでは、JavaScript や CSS によるカスタマイズが使えないため、利用できません。\n- kintone の定期メンテナンスで、画面に付いているクラス名が変わると、スキンが適用されなくなる場合があります。\n- 開発者のサーバーは使いません。レコードのデータは読みません。パスワードや API トークンは使わず、保存もしません。\n- 業務で使う前に、テスト用のアプリで確かめることをおすすめします。\n\n## 詳しい使い方\n\n操作の手順や画面は、note の記事にまとめています。\n\n- [EST キンスキンの使い方。スキンを選び、プレビューしてから適用するまで](https://note.com/cheeky_rat9295/n/n7055a60b1f6f)\n- [EST キンスキンの使い方（応用）。カスタマイズのボタンとフィールドの色を整える](https://note.com/cheeky_rat9295/n/n1ce498927c2f)\n\n[Chrome ウェブストア：EST キンスキン](https://chromewebstore.google.com/detail/ggbghgkahfaplgkbpehdlilfcobolonp?utm_source=qiita\u0026utm_medium=article\u0026utm_campaign=est_kinskin_launch)\n\n※「kintone」はサイボウズ株式会社の登録商標です。個人で開発している非公式のツールです。\n","coediting":false,"comments_count":0,"created_at":"2026-10-27T11:07:48+09:00","group":null,"id":"0cc291641e4fa8f8621d","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"Chrome拡張","versions":[]},{"name":"CSS","versions":[]},{"name":"JavaScript","versions":[]}],"title":"kintone の画面を色で見分けやすくする Chrome 拡張を作った。CSS と setFieldStyle をアプリに登録する仕組み","updated_at":"2026-10-27T11:07:48+09:00","url":"https://qiita.com/goldgearloom/items/0cc291641e4fa8f8621d","user":{"description":null,"facebook_id":null,"followees_count":1,"followers_count":0,"github_login_name":null,"id":"goldgearloom","items_count":3,"linkedin_id":null,"location":null,"name":"","organization":null,"permanent_id":4498380,"profile_image_url":"https://secure.gravatar.com/avatar/7c4dc48bb02e8ad6a36501b681486cad","team_only":false,"twitter_screen_name":null,"website_url":null},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:239\"\u003ekintoneの案件数は3件なのに、担当者別グラフの件数を足すと4件になる。こんな場合は、集計の誤りと決めつける前に、\u003cstrong\u003e1つのレコードが複数の分類に入る設計か\u003c/strong\u003eを確認します。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:338\"\u003eこの記事では、自社開発のダッシュボードプラグインの公開版1.1.4のコードを題材に、ユーザー選択フィールドを担当者別に分類する考え方を解説します。APIでレコードを取得する部分やグラフ描画は省き、取得済みの配列をどう数えるかに絞ります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:38\"\u003e\n\u003cspan id=\"ユーザー選択のvalueは配列\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E9%81%B8%E6%8A%9E%E3%81%AEvalue%E3%81%AF%E9%85%8D%E5%88%97\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eユーザー選択のvalueは配列\u003c/h2\u003e\n\u003cp data-sourcepos=\"7:1-7:213\"\u003eユーザー選択フィールドには、複数のユーザーを設定できます。値の形は\u003ca href=\"https://cybozu.dev/ja/kintone/docs/overview/field-types/\" rel=\"nofollow noopener\" target=\"_blank\"\u003e公式のフィールド形式\u003c/a\u003eで確認できます。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"9:1-20:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erecords\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003e担当\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ea\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e担当A\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eb\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e担当B\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003e担当\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ea\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e担当A\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003e担当\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[]\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"22:1-22:221\"\u003eこの3レコードを「各担当者が関わる案件の件数」として数えると、担当Aが2件、担当Bが1件、未入力が1件です。分類ごとの合計は4件ですが、元レコードは3件です。\u003c/p\u003e\n\u003cp data-sourcepos=\"24:1-24:181\"\u003eここで4件を「ユニークな案件数」と呼ぶと混乱します。指標名を「担当者別の関与件数」とするなど、何を数えた値かを明示します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"26:1-26:66\"\u003e\n\u003cspan id=\"mapのキーは名前ではなくユーザーコードにする\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#map%E3%81%AE%E3%82%AD%E3%83%BC%E3%81%AF%E5%90%8D%E5%89%8D%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AB%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eMapのキーは名前ではなくユーザーコードにする\u003c/h2\u003e\n\u003cp data-sourcepos=\"28:1-28:177\"\u003e名前だけをキーにすると、同名の別ユーザーを同じ分類へまとめてしまいます。ここでは\u003ccode\u003ecode\u003c/code\u003eをキー、\u003ccode\u003ename\u003c/code\u003eを表示ラベルにします。\u003c/p\u003e\n\u003cp data-sourcepos=\"30:1-30:299\"\u003eまた、1つのレコード内で同じコードを複数回処理しないように、行ごとに\u003ccode\u003eSet\u003c/code\u003eを作ります。レコード全体で1つの\u003ccode\u003eSet\u003c/code\u003eを共有すると、担当Aが複数案件に関与していても1件にしか数えられなくなるため、作る場所が重要です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"32:1-32:69\"\u003e\n\u003cspan id=\"教材コード元の件数と分類の件数を分けて返す\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%95%99%E6%9D%90%E3%82%B3%E3%83%BC%E3%83%89%E5%85%83%E3%81%AE%E4%BB%B6%E6%95%B0%E3%81%A8%E5%88%86%E9%A1%9E%E3%81%AE%E4%BB%B6%E6%95%B0%E3%82%92%E5%88%86%E3%81%91%E3%81%A6%E8%BF%94%E3%81%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e教材コード：元の件数と分類の件数を分けて返す\u003c/h2\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"34:1-67:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"c1\"\u003e// 教材用：取得済みのレコードを担当者別の関与件数に分類する。\u003c/span\u003e\n\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003ecountByUser\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erecords\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003efieldCode\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003egroups\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eMap\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n  \u003cspan class=\"k\"\u003efor \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e \u003cspan class=\"k\"\u003eof\u003c/span\u003e \u003cspan class=\"nx\"\u003erecords\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003efieldCode\u003c/span\u003e\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e`ユーザー選択を確認してください: \u003c/span\u003e\u003cspan class=\"p\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003efieldCode\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"s2\"\u003e`\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eusers\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ekeys\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eSet\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eusers\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003eusers\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003euser\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003euser\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e\n    \u003cspan class=\"k\"\u003efor \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"k\"\u003eof\u003c/span\u003e \u003cspan class=\"nx\"\u003ekeys\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003estring\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eusers\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n        \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eユーザーコードを取得できません\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n      \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n      \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003euser\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eusers\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003efind\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003euser\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003euser\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n      \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003egroups\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ehas\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n        \u003cspan class=\"nx\"\u003egroups\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eset\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n          \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n          \u003cspan class=\"na\"\u003elabel\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003euser\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ename\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e（未入力）\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n          \u003cspan class=\"na\"\u003ecount\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\n        \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n      \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n      \u003cspan class=\"nx\"\u003egroups\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eget\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nx\"\u003ecount\u003c/span\u003e \u003cspan class=\"o\"\u003e+=\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erows\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[...\u003c/span\u003e\u003cspan class=\"nx\"\u003egroups\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e()];\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"na\"\u003erecordCount\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003erecords\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n    \u003cspan class=\"na\"\u003eassignmentCount\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ereduce\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003esum\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003egroup\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003esum\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"nx\"\u003egroup\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ecount\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\n    \u003cspan class=\"na\"\u003egroups\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003erows\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"69:1-69:84\"\u003e上の例の\u003ccode\u003erecords\u003c/code\u003eと合わせて実行すると、次の結果になります。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"71:1-81:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eresult\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003ecountByUser\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erecords\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e担当\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eresult\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erecordCount\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e     \u003cspan class=\"c1\"\u003e// 3\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eresult\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eassignmentCount\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e \u003cspan class=\"c1\"\u003e// 4\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eresult\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003egroups\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e// [\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e//   { code: 'a', label: '担当A', count: 2 },\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e//   { code: 'b', label: '担当B', count: 1 },\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e//   { code: '', label: '（未入力）', count: 1 }\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e// ]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"83:1-83:210\"\u003e\u003ccode\u003erecordCount\u003c/code\u003eは入力配列の長さです。同じレコードを重複して取得していない前提で使います。このコードがレコードIDの重複を取り除くわけではありません。\u003c/p\u003e\n\u003cp data-sourcepos=\"85:1-85:230\"\u003e\u003ccode\u003eassignmentCount\u003c/code\u003eは、未入力の分類も含む分類件数の合計です。案件の総数とは分けて扱います。未入力を集計対象から除くかどうかも、業務のルールとして決めてください。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"87:1-87:45\"\u003e\n\u003cspan id=\"未入力と未取得を同じにしない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%9C%AA%E5%85%A5%E5%8A%9B%E3%81%A8%E6%9C%AA%E5%8F%96%E5%BE%97%E3%82%92%E5%90%8C%E3%81%98%E3%81%AB%E3%81%97%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e未入力と未取得を同じにしない\u003c/h2\u003e\n\u003cp data-sourcepos=\"89:1-89:269\"\u003e\u003ccode\u003evalue: []\u003c/code\u003eは、ユーザー選択フィールドを取得できているが、誰も選ばれていない状態として扱います。一方、フィールド自体が存在しない場合は、コード・取得対象・閲覧権限などの確認が必要です。\u003c/p\u003e\n\u003cp data-sourcepos=\"91:1-91:279\"\u003e教材では、フィールドがない場合や型が違う場合は停止します。未取得を「未入力」に混ぜると、権限や取得条件の問題を、未割り当て案件として数えてしまうためです。コード未取得も同様に停止します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"93:1-93:78\"\u003e\n\u003cspan id=\"売上を担当者別に合計するときは配分のルールも必要\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%A3%B2%E4%B8%8A%E3%82%92%E6%8B%85%E5%BD%93%E8%80%85%E5%88%A5%E3%81%AB%E5%90%88%E8%A8%88%E3%81%99%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AF%E9%85%8D%E5%88%86%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%AB%E3%82%82%E5%BF%85%E8%A6%81\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e売上を担当者別に合計するときは、配分のルールも必要\u003c/h2\u003e\n\u003cp data-sourcepos=\"95:1-95:164\"\u003e件数だけでなく、1件100,000円の案件を担当A・担当Bの両方にそのまま集計すれば、担当別合計を足すと200,000円になります。\u003c/p\u003e\n\u003cp data-sourcepos=\"97:1-97:277\"\u003eこれは担当別の関与金額を見たいのか、会社の売上総額を見たいのかで意味が変わります。会社全体の売上総額を出したい場合は、担当者別の棒の合計ではなく、対象レコードの金額を1回ずつ集計します。\u003c/p\u003e\n\u003cp data-sourcepos=\"99:1-99:334\"\u003e担当者ごとの売上配分が必要なら、主担当を1人に決める、明細や別フィールドへ配分額を持たせるなど、先にデータ設計を決めます。担当者の数で自動的に均等配分される機能を、この教材や紹介するプラグインが持つという説明ではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"101:1-101:48\"\u003e\n\u003cspan id=\"公開製品のコードと照合した範囲\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%85%AC%E9%96%8B%E8%A3%BD%E5%93%81%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%89%E3%81%A8%E7%85%A7%E5%90%88%E3%81%97%E3%81%9F%E7%AF%84%E5%9B%B2\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e公開製品のコードと照合した範囲\u003c/h2\u003e\n\u003cp data-sourcepos=\"103:1-103:291\"\u003e公開配布中のZIPから\u003ccode\u003ejs/core.js\u003c/code\u003eを取り出し、ローカルの対象ファイルと一致することを確認しました。製品の\u003ccode\u003eaggregate()\u003c/code\u003eも、ユーザー選択の各要素を分類へ入れ、同じレコード内の分類キーを\u003ccode\u003eSet\u003c/code\u003eで重複除外しています。\u003c/p\u003e\n\u003cp data-sourcepos=\"105:1-105:395\"\u003e教材コードと公開製品コードに対し、元3件と分類4件の違い、同一レコード内の同じコード、同名・別コード、空配列、未取得など、計10項目をNode.jsで確認しました。入力が不正な場合の停止処理は教材で追加した範囲もあり、製品と教材のすべての振る舞いが同一という意味ではありません。\u003c/p\u003e\n\u003cp data-sourcepos=\"107:1-107:316\"\u003eこの検証には実機kintoneへの変更やグラフ画面の試験は含みません。また、取得範囲・期間・権限・取得上限が違えば、分類以前に対象レコードの件数が変わります。比較するときは、対象レコードをそろえてから分類の違いを見ます。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"109:1-109:33\"\u003e\n\u003cspan id=\"画面で確認したい場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%94%BB%E9%9D%A2%E3%81%A7%E7%A2%BA%E8%AA%8D%E3%81%97%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e画面で確認したい場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"111:1-111:228\"\u003e自社で開発・提供しているダッシュボードプラグインでは、指標カード・グラフ・表を一覧画面上部へ配置できます。設定・利用画面と対応範囲は以下で確認できます。\u003c/p\u003e\n\u003cp data-sourcepos=\"113:1-113:214\"\u003e\u003ca href=\"https://kintaco.wisemap.biz/plugins/dashboard/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=dashboard_multi_user\" rel=\"nofollow noopener\" target=\"_blank\"\u003eダッシュボードプラグインの画面・無料ZIPを見る\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"115:1-115:269\"\u003e無料利用では、有償プランの案内バナーがPC・モバイルの一覧画面に30%の確率で表示されます。契約済みドメインには表示されません。利用前に、対応する項目・画面・取得上限を確認してください。\u003c/p\u003e\n","body":"kintoneの案件数は3件なのに、担当者別グラフの件数を足すと4件になる。こんな場合は、集計の誤りと決めつける前に、**1つのレコードが複数の分類に入る設計か**を確認します。\n\nこの記事では、自社開発のダッシュボードプラグインの公開版1.1.4のコードを題材に、ユーザー選択フィールドを担当者別に分類する考え方を解説します。APIでレコードを取得する部分やグラフ描画は省き、取得済みの配列をどう数えるかに絞ります。\n\n## ユーザー選択のvalueは配列\n\nユーザー選択フィールドには、複数のユーザーを設定できます。値の形は[公式のフィールド形式](https://cybozu.dev/ja/kintone/docs/overview/field-types/)で確認できます。\n\n```javascript\nconst records = [\n  { 担当: { type: 'USER_SELECT', value: [\n    { code: 'a', name: '担当A' },\n    { code: 'b', name: '担当B' }\n  ] } },\n  { 担当: { type: 'USER_SELECT', value: [\n    { code: 'a', name: '担当A' }\n  ] } },\n  { 担当: { type: 'USER_SELECT', value: [] } }\n];\n```\n\nこの3レコードを「各担当者が関わる案件の件数」として数えると、担当Aが2件、担当Bが1件、未入力が1件です。分類ごとの合計は4件ですが、元レコードは3件です。\n\nここで4件を「ユニークな案件数」と呼ぶと混乱します。指標名を「担当者別の関与件数」とするなど、何を数えた値かを明示します。\n\n## Mapのキーは名前ではなくユーザーコードにする\n\n名前だけをキーにすると、同名の別ユーザーを同じ分類へまとめてしまいます。ここでは`code`をキー、`name`を表示ラベルにします。\n\nまた、1つのレコード内で同じコードを複数回処理しないように、行ごとに`Set`を作ります。レコード全体で1つの`Set`を共有すると、担当Aが複数案件に関与していても1件にしか数えられなくなるため、作る場所が重要です。\n\n## 教材コード：元の件数と分類の件数を分けて返す\n\n```javascript\n// 教材用：取得済みのレコードを担当者別の関与件数に分類する。\nfunction countByUser(records, fieldCode) {\n  const groups = new Map();\n  for (const record of records) {\n    const field = record[fieldCode];\n    if (!field || field.type !== 'USER_SELECT' || !Array.isArray(field.value)) {\n      throw new Error(`ユーザー選択を確認してください: ${fieldCode}`);\n    }\n    const users = field.value;\n    const keys = new Set(users.length ? users.map(user =\u003e user.code) : ['']);\n    for (const code of keys) {\n      if (typeof code !== 'string' || (users.length \u0026\u0026 !code)) {\n        throw new Error('ユーザーコードを取得できません');\n      }\n      const user = users.find(user =\u003e user.code === code);\n      if (!groups.has(code)) {\n        groups.set(code, {\n          code,\n          label: code ? user.name || code : '（未入力）',\n          count: 0\n        });\n      }\n      groups.get(code).count += 1;\n    }\n  }\n  const rows = [...groups.values()];\n  return {\n    recordCount: records.length,\n    assignmentCount: rows.reduce((sum, group) =\u003e sum + group.count, 0),\n    groups: rows\n  };\n}\n```\n\n上の例の`records`と合わせて実行すると、次の結果になります。\n\n```javascript\nconst result = countByUser(records, '担当');\nconsole.log(result.recordCount);     // 3\nconsole.log(result.assignmentCount); // 4\nconsole.log(result.groups);\n// [\n//   { code: 'a', label: '担当A', count: 2 },\n//   { code: 'b', label: '担当B', count: 1 },\n//   { code: '', label: '（未入力）', count: 1 }\n// ]\n```\n\n`recordCount`は入力配列の長さです。同じレコードを重複して取得していない前提で使います。このコードがレコードIDの重複を取り除くわけではありません。\n\n`assignmentCount`は、未入力の分類も含む分類件数の合計です。案件の総数とは分けて扱います。未入力を集計対象から除くかどうかも、業務のルールとして決めてください。\n\n## 未入力と未取得を同じにしない\n\n`value: []`は、ユーザー選択フィールドを取得できているが、誰も選ばれていない状態として扱います。一方、フィールド自体が存在しない場合は、コード・取得対象・閲覧権限などの確認が必要です。\n\n教材では、フィールドがない場合や型が違う場合は停止します。未取得を「未入力」に混ぜると、権限や取得条件の問題を、未割り当て案件として数えてしまうためです。コード未取得も同様に停止します。\n\n## 売上を担当者別に合計するときは、配分のルールも必要\n\n件数だけでなく、1件100,000円の案件を担当A・担当Bの両方にそのまま集計すれば、担当別合計を足すと200,000円になります。\n\nこれは担当別の関与金額を見たいのか、会社の売上総額を見たいのかで意味が変わります。会社全体の売上総額を出したい場合は、担当者別の棒の合計ではなく、対象レコードの金額を1回ずつ集計します。\n\n担当者ごとの売上配分が必要なら、主担当を1人に決める、明細や別フィールドへ配分額を持たせるなど、先にデータ設計を決めます。担当者の数で自動的に均等配分される機能を、この教材や紹介するプラグインが持つという説明ではありません。\n\n## 公開製品のコードと照合した範囲\n\n公開配布中のZIPから`js/core.js`を取り出し、ローカルの対象ファイルと一致することを確認しました。製品の`aggregate()`も、ユーザー選択の各要素を分類へ入れ、同じレコード内の分類キーを`Set`で重複除外しています。\n\n教材コードと公開製品コードに対し、元3件と分類4件の違い、同一レコード内の同じコード、同名・別コード、空配列、未取得など、計10項目をNode.jsで確認しました。入力が不正な場合の停止処理は教材で追加した範囲もあり、製品と教材のすべての振る舞いが同一という意味ではありません。\n\nこの検証には実機kintoneへの変更やグラフ画面の試験は含みません。また、取得範囲・期間・権限・取得上限が違えば、分類以前に対象レコードの件数が変わります。比較するときは、対象レコードをそろえてから分類の違いを見ます。\n\n## 画面で確認したい場合\n\n自社で開発・提供しているダッシュボードプラグインでは、指標カード・グラフ・表を一覧画面上部へ配置できます。設定・利用画面と対応範囲は以下で確認できます。\n\n[ダッシュボードプラグインの画面・無料ZIPを見る](https://kintaco.wisemap.biz/plugins/dashboard/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=dashboard_multi_user)\n\n無料利用では、有償プランの案内バナーがPC・モバイルの一覧画面に30%の確率で表示されます。契約済みドメインには表示されません。利用前に、対応する項目・画面・取得上限を確認してください。\n","coediting":false,"comments_count":0,"created_at":"2026-10-26T21:26:32+09:00","group":null,"id":"46249c7d2e6b7f9d4175","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"データ分析","versions":[]}],"title":"kintoneの担当者別集計で件数が合わない理由｜複数選択をJavaScriptで数える","updated_at":"2026-10-26T21:26:32+09:00","url":"https://qiita.com/kintaco/items/46249c7d2e6b7f9d4175","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:265\"\u003ekintoneの数値をExcel帳票へ差し込む際、値をすべて文字列にすると、後続の計算に使いづらくなることがあります。一方、何でも数値へ変換すると、商品コードの先頭の0や未入力の意味を失います。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:265\"\u003eこの記事では、自社開発の帳票出力プラグイン1.0.6で使っている値の扱いを題材に、\u003cstrong\u003e「0」「空欄」「未取得」を区別し、セル全体への差し込みと文章中の差し込みを分ける\u003c/strong\u003e考え方を解説します。\u003c/p\u003e\n\u003cp data-sourcepos=\"5:1-5:179\"\u003e以下の教材コードは文字列・数値フィールドに範囲を絞ったものです。Excelファイルを書き出す処理や、PDF生成の処理は含みません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"7:1-7:58\"\u003e\n\u003cspan id=\"最初にkintoneのフィールド型を確認する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%9C%80%E5%88%9D%E3%81%ABkintone%E3%81%AE%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E5%9E%8B%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e最初に、kintoneのフィールド型を確認する\u003c/h2\u003e\n\u003cp data-sourcepos=\"9:1-9:357\"\u003ekintoneのレコードは、フィールドコードごとのオブジェクトに値が入ります。数値フィールドも、取得した\u003ccode\u003evalue\u003c/code\u003eをそのままJavaScriptの数値と考えず、型と値を確認します。形式は\u003ca href=\"https://cybozu.dev/ja/kintone/docs/overview/field-types/\" rel=\"nofollow noopener\" target=\"_blank\"\u003e公式のフィールド形式\u003c/a\u003eを参照してください。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"11:1-17:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"na\"\u003e数量\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eNUMBER\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e0\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n  \u003cspan class=\"na\"\u003e備考\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSINGLE_LINE_TEXT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n  \u003cspan class=\"na\"\u003e商品コード\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSINGLE_LINE_TEXT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e00123\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"19:1-19:49\"\u003eここで残したい意味は次の3つです。\u003c/p\u003e\n\u003cul data-sourcepos=\"21:1-24:0\"\u003e\n\u003cli data-sourcepos=\"21:1-21:59\"\u003e数量の\u003ccode\u003e'0'\u003c/code\u003e：金額計算などで使う数値の0。\u003c/li\u003e\n\u003cli data-sourcepos=\"22:1-22:61\"\u003e備考の\u003ccode\u003e''\u003c/code\u003e：未入力。数値の0へ変換しない。\u003c/li\u003e\n\u003cli data-sourcepos=\"23:1-24:0\"\u003e商品コードの\u003ccode\u003e'00123'\u003c/code\u003e：識別子。文字列として先頭の0を残す。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"25:1-25:216\"\u003e\u003ccode\u003evalue || ''\u003c/code\u003eという書き方は、JavaScriptの数値\u003ccode\u003e0\u003c/code\u003eまで空文字にしてしまいます。また、\u003ccode\u003eNumber('')\u003c/code\u003eは0になるため、未入力判定より先に数値変換しないことも大切です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"27:1-27:60\"\u003e\n\u003cspan id=\"セル全体の記号と文章中の記号を分ける\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%82%BB%E3%83%AB%E5%85%A8%E4%BD%93%E3%81%AE%E8%A8%98%E5%8F%B7%E3%81%A8%E6%96%87%E7%AB%A0%E4%B8%AD%E3%81%AE%E8%A8%98%E5%8F%B7%E3%82%92%E5%88%86%E3%81%91%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eセル全体の記号と、文章中の記号を分ける\u003c/h2\u003e\n\u003cp data-sourcepos=\"29:1-29:135\"\u003e例えば、テンプレートのセルに\u003ccode\u003e$(数量)\u003c/code\u003eだけがある場合は、差し込み結果を数値の0として返せます。\u003c/p\u003e\n\u003cp data-sourcepos=\"31:1-31:193\"\u003e一方、\u003ccode\u003e数量：$(数量)\u003c/code\u003eというセルなら、結果は\u003ccode\u003e'数量：0'\u003c/code\u003eという文章です。同じ項目でも、テンプレートの置き方によって返す型が異なります。\u003c/p\u003e\n\u003cp data-sourcepos=\"33:1-33:229\"\u003e製品の\u003ccode\u003ereport-engine.js\u003c/code\u003eでも、セルの値全体が1つの差し込み記号に一致する場合と、文章中に記号を含む場合を分けています。教材では、次のように関数を小さく分けます。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"35:1-35:57\"\u003e\n\u003cspan id=\"教材コード値の変換と記号の置き換え\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%95%99%E6%9D%90%E3%82%B3%E3%83%BC%E3%83%89%E5%80%A4%E3%81%AE%E5%A4%89%E6%8F%9B%E3%81%A8%E8%A8%98%E5%8F%B7%E3%81%AE%E7%BD%AE%E3%81%8D%E6%8F%9B%E3%81%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e教材コード：値の変換と記号の置き換え\u003c/h2\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"37:1-64:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"c1\"\u003e// 教材用：NUMBER/CALCと文字列だけを扱う、差し込み値の変換例。\u003c/span\u003e\n\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003ecellValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eフィールドを取得できません\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003estring\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003enumber\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eこのサンプルの対象外の型です\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003etext\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/\u003c/span\u003e\u003cspan class=\"se\"\u003e\\r\\n?\u003c/span\u003e\u003cspan class=\"sr\"\u003e/g\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"se\"\u003e\\n\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003edigits\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003etext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/\u003c/span\u003e\u003cspan class=\"se\"\u003e[^\u003c/span\u003e\u003cspan class=\"sr\"\u003e0-9\u003c/span\u003e\u003cspan class=\"se\"\u003e]\u003c/span\u003e\u003cspan class=\"sr\"\u003e/g\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/^0+/\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e([\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eNUMBER\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eCALC\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"nf\"\u003eincludes\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n      \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"nb\"\u003eNumber\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisFinite\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\"\u003eNumber\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etext\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"nx\"\u003edigits\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan class=\"mi\"\u003e15\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nc\"\u003eNumber\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etext\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003etext\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\n\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003efillText\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etemplate\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"kd\"\u003eget\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nb\"\u003eObject\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ehasOwn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e`未取得の項目: \u003c/span\u003e\u003cspan class=\"p\"\u003e${\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"s2\"\u003e`\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nf\"\u003ecellValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e};\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eexact\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"sr\"\u003e/^\u003c/span\u003e\u003cspan class=\"se\"\u003e\\$\\(([^\u003c/span\u003e\u003cspan class=\"sr\"\u003e)\u003c/span\u003e\u003cspan class=\"se\"\u003e]\u003c/span\u003e\u003cspan class=\"sr\"\u003e+\u003c/span\u003e\u003cspan class=\"se\"\u003e)\\)\u003c/span\u003e\u003cspan class=\"sr\"\u003e$/\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eexec\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etemplate\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eexact\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nf\"\u003eget\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eexact\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003etemplate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/\u003c/span\u003e\u003cspan class=\"se\"\u003e\\$\\(([^\u003c/span\u003e\u003cspan class=\"sr\"\u003e)\u003c/span\u003e\u003cspan class=\"se\"\u003e]\u003c/span\u003e\u003cspan class=\"sr\"\u003e+\u003c/span\u003e\u003cspan class=\"se\"\u003e)\\)\u003c/span\u003e\u003cspan class=\"sr\"\u003e/g\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003e_\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003eget\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e)));\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"66:1-66:235\"\u003e\u003ccode\u003ecellValue()\u003c/code\u003eで値の意味を決め、\u003ccode\u003efillText()\u003c/code\u003eでテンプレートの記号を置き換えます。テンプレートの項目名は、表示ラベルではなく、実際のフィールドコードへ合わせてください。\u003c/p\u003e\n\u003cp data-sourcepos=\"68:1-68:457\"\u003eこの例は\u003ccode\u003eNUMBER\u003c/code\u003e・\u003ccode\u003eCALC\u003c/code\u003eのうち、有限の数値へ変換でき、数値表現中の数字を数えた条件が15桁以下のものを数値にします。長い番号を安易に数値化しないための方針であり、あらゆる小数や数式の精度を保証する判定ではありません。商品コード・口座番号など、桁の見た目が重要な識別子は、そもそも文字列で管理する設計を検討します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"70:1-70:51\"\u003e\n\u003cspan id=\"動かして値と型の両方を確かめる\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E5%80%A4%E3%81%A8%E5%9E%8B%E3%81%AE%E4%B8%A1%E6%96%B9%E3%82%92%E7%A2%BA%E3%81%8B%E3%82%81%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e動かして、値と型の両方を確かめる\u003c/h2\u003e\n\u003cp data-sourcepos=\"72:1-72:72\"\u003e上の関数と、次のコードを同じ環境で実行できます。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"74:1-87:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"na\"\u003e数量\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eNUMBER\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e0\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n  \u003cspan class=\"na\"\u003e備考\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSINGLE_LINE_TEXT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n  \u003cspan class=\"na\"\u003e商品コード\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSINGLE_LINE_TEXT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e00123\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003enumberCell\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003efillText\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e$(数量)\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003enumberCell\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003enumberCell\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003enumber\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003efillText\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e$(備考)\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003efillText\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e$(商品コード)\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e00123\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eassert\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003efillText\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e数量：$(数量)\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e数量：0\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"89:1-89:184\"\u003e確認するのは画面に「0」と見えるかだけではありません。数値の0と文字列の\u003ccode\u003e'0'\u003c/code\u003eは表示が似ていても、後続の処理で扱いが変わります。\u003c/p\u003e\n\u003cp data-sourcepos=\"91:1-91:391\"\u003eなお、\u003cstrong\u003eJavaScript側で数値を返しただけで、Excelのセル型が決まるわけではありません\u003c/strong\u003e。実際に\u003ccode\u003e.xlsx\u003c/code\u003eへ書く側でも、数値セルと文字列セルを分ける必要があります。製品側では値の変換の後に、Excel内部のセルを書き換える処理を行っています。この教材は、その手前の確認に絞っています。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"93:1-93:63\"\u003e\n\u003cspan id=\"空欄と取得できていないを同じにしない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%A9%BA%E6%AC%84%E3%81%A8%E5%8F%96%E5%BE%97%E3%81%A7%E3%81%8D%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%82%92%E5%90%8C%E3%81%98%E3%81%AB%E3%81%97%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e空欄と「取得できていない」を同じにしない\u003c/h2\u003e\n\u003cp data-sourcepos=\"95:1-95:284\"\u003e\u003ccode\u003e備考\u003c/code\u003eがレコード内に存在し、その\u003ccode\u003evalue\u003c/code\u003eが空なら未入力として扱えます。一方、\u003ccode\u003erecord\u003c/code\u003e内にそのフィールド自体がない場合は、フィールドコードの取り違え・取得対象・閲覧権限などを確認する必要があります。\u003c/p\u003e\n\u003cp data-sourcepos=\"97:1-97:183\"\u003e教材では、項目がなければエラーで止めます。未取得を空欄として埋めると、空欄だらけの帳票が正常な出力に見えてしまうためです。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"99:1-106:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"c1\"\u003e// 「備考」という項目自体がないので停止する\u003c/span\u003e\n\u003cspan class=\"k\"\u003etry\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"nf\"\u003efillText\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e$(備考)\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{});\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003ecatch \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003emessage\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e \u003cspan class=\"c1\"\u003e// 未取得の項目: 備考\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"108:1-108:117\"\u003eエラーだけで権限不足と断定せず、まずアプリ更新・コード・取得経路を確認します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"110:1-110:59\"\u003e\n\u003cspan id=\"テーブルは行のvalueを取り出して考える\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AF%E8%A1%8C%E3%81%AEvalue%E3%82%92%E5%8F%96%E3%82%8A%E5%87%BA%E3%81%97%E3%81%A6%E8%80%83%E3%81%88%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eテーブルは、行のvalueを取り出して考える\u003c/h2\u003e\n\u003cp data-sourcepos=\"112:1-112:142\"\u003eテーブル内の項目は、外側のレコードから直接読む構造ではありません。行ごとの\u003ccode\u003evalue\u003c/code\u003eを取り出します。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"114:1-129:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"na\"\u003e見積明細\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSUBTABLE\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n    \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\n      \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e1\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003e数量\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eNUMBER\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n      \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003e数量\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eNUMBER\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e0\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e]\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e};\u003c/span\u003e\n\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003equantities\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003e見積明細\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erow\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e\n  \u003cspan class=\"nf\"\u003efillText\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e$(数量)\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003equantities\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e \u003cspan class=\"c1\"\u003e// [2, 0]\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"131:1-131:338\"\u003eこのコードは行ごとの値を得る例です。Excel行の複製、数式参照の調整、結合セルや明細0件の処理までは行いません。また、教材の\u003ccode\u003efillText()\u003c/code\u003eは\u003ccode\u003e$(見積明細.数量)\u003c/code\u003eという修飾付きコードを解釈しません。行を選んで\u003ccode\u003erow.value\u003c/code\u003eを渡す設計に限定しています。\u003c/p\u003e\n\u003cp data-sourcepos=\"133:1-133:298\"\u003e製品では、フィールド定義と行のコンテキストを使って、どのテーブルのどの行を出力するかを解決しています。値の変換と、行を繰り返す処理を分けておくと、0が消えた問題と、行数が違う問題を別々に調べられます。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"135:1-135:27\"\u003e\n\u003cspan id=\"今回確認した範囲\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BB%8A%E5%9B%9E%E7%A2%BA%E8%AA%8D%E3%81%97%E3%81%9F%E7%AF%84%E5%9B%B2\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e今回確認した範囲\u003c/h2\u003e\n\u003cp data-sourcepos=\"137:1-137:271\"\u003eNode.jsで、教材コードとローカルの製品コードに対して計18項目の値変換テストを行いました。0、空欄、文章中の記号、文字列の先頭0、16桁の値、未取得項目、テーブル行の指定などを確認しています。\u003c/p\u003e\n\u003cp data-sourcepos=\"139:1-139:303\"\u003eこの結果は、実機kintoneでの操作試験や、完成したExcel・PDFファイルの検証を代替するものではありません。最終的には、実際のテンプレート・レコード・利用者で、セルの型、計算結果、明細件数、印刷結果まで確認します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"141:1-141:45\"\u003e\n\u003cspan id=\"設定画面で帳票を作りたい場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%AD%E5%AE%9A%E7%94%BB%E9%9D%A2%E3%81%A7%E5%B8%B3%E7%A5%A8%E3%82%92%E4%BD%9C%E3%82%8A%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e設定画面で帳票を作りたい場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"143:1-143:301\"\u003eここまでの考え方を含め、Excelテンプレートから帳票を作るために開発しているのが、自社の帳票出力プラグインです。公開中の設定・利用画面をまとめた33秒の解説動画と、対応範囲・無料ZIPを製品ページで確認できます。\u003c/p\u003e\n\u003cp data-sourcepos=\"145:1-145:239\"\u003e\u003ca href=\"https://kintaco.wisemap.biz/plugins/excel-report/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=excel_field_types#excel-report-intro-video\" rel=\"nofollow noopener\" target=\"_blank\"\u003e帳票出力プラグインの画面解説・対応範囲を見る\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"147:1-147:278\"\u003e無料利用では、有償プランの案内バナーがPC・モバイルの一覧画面に30%の確率で表示されます。契約済みドメインには表示されません。PDFの再現範囲なども含め、最新の仕様は製品ページをご確認ください。\u003c/p\u003e\n","body":"kintoneの数値をExcel帳票へ差し込む際、値をすべて文字列にすると、後続の計算に使いづらくなることがあります。一方、何でも数値へ変換すると、商品コードの先頭の0や未入力の意味を失います。\n\nこの記事では、自社開発の帳票出力プラグイン1.0.6で使っている値の扱いを題材に、**「0」「空欄」「未取得」を区別し、セル全体への差し込みと文章中の差し込みを分ける**考え方を解説します。\n\n以下の教材コードは文字列・数値フィールドに範囲を絞ったものです。Excelファイルを書き出す処理や、PDF生成の処理は含みません。\n\n## 最初に、kintoneのフィールド型を確認する\n\nkintoneのレコードは、フィールドコードごとのオブジェクトに値が入ります。数値フィールドも、取得した`value`をそのままJavaScriptの数値と考えず、型と値を確認します。形式は[公式のフィールド形式](https://cybozu.dev/ja/kintone/docs/overview/field-types/)を参照してください。\n\n```javascript\nconst record = {\n  数量: { type: 'NUMBER', value: '0' },\n  備考: { type: 'SINGLE_LINE_TEXT', value: '' },\n  商品コード: { type: 'SINGLE_LINE_TEXT', value: '00123' }\n};\n```\n\nここで残したい意味は次の3つです。\n\n- 数量の`'0'`：金額計算などで使う数値の0。\n- 備考の`''`：未入力。数値の0へ変換しない。\n- 商品コードの`'00123'`：識別子。文字列として先頭の0を残す。\n\n`value || ''`という書き方は、JavaScriptの数値`0`まで空文字にしてしまいます。また、`Number('')`は0になるため、未入力判定より先に数値変換しないことも大切です。\n\n## セル全体の記号と、文章中の記号を分ける\n\n例えば、テンプレートのセルに`$(数量)`だけがある場合は、差し込み結果を数値の0として返せます。\n\n一方、`数量：$(数量)`というセルなら、結果は`'数量：0'`という文章です。同じ項目でも、テンプレートの置き方によって返す型が異なります。\n\n製品の`report-engine.js`でも、セルの値全体が1つの差し込み記号に一致する場合と、文章中に記号を含む場合を分けています。教材では、次のように関数を小さく分けます。\n\n## 教材コード：値の変換と記号の置き換え\n\n```javascript\n// 教材用：NUMBER/CALCと文字列だけを扱う、差し込み値の変換例。\nfunction cellValue(field) {\n  if (field == null) throw new Error('フィールドを取得できません');\n  const value = field.value;\n  if (value == null || value === '') return '';\n  if (typeof value !== 'string' \u0026\u0026 typeof value !== 'number') {\n    throw new Error('このサンプルの対象外の型です');\n  }\n  const text = String(value).replace(/\\r\\n?/g, '\\n');\n  const digits = text.replace(/[^0-9]/g, '').replace(/^0+/, '').length;\n  if (['NUMBER', 'CALC'].includes(field.type)\n      \u0026\u0026 Number.isFinite(Number(text)) \u0026\u0026 digits \u003c= 15) {\n    return Number(text);\n  }\n  return text;\n}\n\nfunction fillText(template, record) {\n  const get = code =\u003e {\n    if (!Object.hasOwn(record, code)) throw new Error(`未取得の項目: ${code}`);\n    return cellValue(record[code]);\n  };\n  const exact = /^\\$\\(([^)]+)\\)$/.exec(template);\n  if (exact) return get(exact[1]);\n  return template.replace(/\\$\\(([^)]+)\\)/g, (_, code) =\u003e String(get(code)));\n}\n```\n\n`cellValue()`で値の意味を決め、`fillText()`でテンプレートの記号を置き換えます。テンプレートの項目名は、表示ラベルではなく、実際のフィールドコードへ合わせてください。\n\nこの例は`NUMBER`・`CALC`のうち、有限の数値へ変換でき、数値表現中の数字を数えた条件が15桁以下のものを数値にします。長い番号を安易に数値化しないための方針であり、あらゆる小数や数式の精度を保証する判定ではありません。商品コード・口座番号など、桁の見た目が重要な識別子は、そもそも文字列で管理する設計を検討します。\n\n## 動かして、値と型の両方を確かめる\n\n上の関数と、次のコードを同じ環境で実行できます。\n\n```javascript\nconst record = {\n  数量: { type: 'NUMBER', value: '0' },\n  備考: { type: 'SINGLE_LINE_TEXT', value: '' },\n  商品コード: { type: 'SINGLE_LINE_TEXT', value: '00123' }\n};\n\nconst numberCell = fillText('$(数量)', record);\nconsole.assert(numberCell === 0);\nconsole.assert(typeof numberCell === 'number');\nconsole.assert(fillText('$(備考)', record) === '');\nconsole.assert(fillText('$(商品コード)', record) === '00123');\nconsole.assert(fillText('数量：$(数量)', record) === '数量：0');\n```\n\n確認するのは画面に「0」と見えるかだけではありません。数値の0と文字列の`'0'`は表示が似ていても、後続の処理で扱いが変わります。\n\nなお、**JavaScript側で数値を返しただけで、Excelのセル型が決まるわけではありません**。実際に`.xlsx`へ書く側でも、数値セルと文字列セルを分ける必要があります。製品側では値の変換の後に、Excel内部のセルを書き換える処理を行っています。この教材は、その手前の確認に絞っています。\n\n## 空欄と「取得できていない」を同じにしない\n\n`備考`がレコード内に存在し、その`value`が空なら未入力として扱えます。一方、`record`内にそのフィールド自体がない場合は、フィールドコードの取り違え・取得対象・閲覧権限などを確認する必要があります。\n\n教材では、項目がなければエラーで止めます。未取得を空欄として埋めると、空欄だらけの帳票が正常な出力に見えてしまうためです。\n\n```javascript\n// 「備考」という項目自体がないので停止する\ntry {\n  fillText('$(備考)', {});\n} catch (error) {\n  console.log(error.message); // 未取得の項目: 備考\n}\n```\n\nエラーだけで権限不足と断定せず、まずアプリ更新・コード・取得経路を確認します。\n\n## テーブルは、行のvalueを取り出して考える\n\nテーブル内の項目は、外側のレコードから直接読む構造ではありません。行ごとの`value`を取り出します。\n\n```javascript\nconst record = {\n  見積明細: {\n    type: 'SUBTABLE',\n    value: [\n      { id: '1', value: { 数量: { type: 'NUMBER', value: '2' } } },\n      { id: '2', value: { 数量: { type: 'NUMBER', value: '0' } } }\n    ]\n  }\n};\n\nconst quantities = record.見積明細.value.map(row =\u003e\n  fillText('$(数量)', row.value)\n);\nconsole.log(quantities); // [2, 0]\n```\n\nこのコードは行ごとの値を得る例です。Excel行の複製、数式参照の調整、結合セルや明細0件の処理までは行いません。また、教材の`fillText()`は`$(見積明細.数量)`という修飾付きコードを解釈しません。行を選んで`row.value`を渡す設計に限定しています。\n\n製品では、フィールド定義と行のコンテキストを使って、どのテーブルのどの行を出力するかを解決しています。値の変換と、行を繰り返す処理を分けておくと、0が消えた問題と、行数が違う問題を別々に調べられます。\n\n## 今回確認した範囲\n\nNode.jsで、教材コードとローカルの製品コードに対して計18項目の値変換テストを行いました。0、空欄、文章中の記号、文字列の先頭0、16桁の値、未取得項目、テーブル行の指定などを確認しています。\n\nこの結果は、実機kintoneでの操作試験や、完成したExcel・PDFファイルの検証を代替するものではありません。最終的には、実際のテンプレート・レコード・利用者で、セルの型、計算結果、明細件数、印刷結果まで確認します。\n\n## 設定画面で帳票を作りたい場合\n\nここまでの考え方を含め、Excelテンプレートから帳票を作るために開発しているのが、自社の帳票出力プラグインです。公開中の設定・利用画面をまとめた33秒の解説動画と、対応範囲・無料ZIPを製品ページで確認できます。\n\n[帳票出力プラグインの画面解説・対応範囲を見る](https://kintaco.wisemap.biz/plugins/excel-report/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=excel_field_types#excel-report-intro-video)\n\n無料利用では、有償プランの案内バナーがPC・モバイルの一覧画面に30%の確率で表示されます。契約済みドメインには表示されません。PDFの再現範囲なども含め、最新の仕様は製品ページをご確認ください。\n","coediting":false,"comments_count":0,"created_at":"2026-10-26T20:12:08+09:00","group":null,"id":"0ec7af87d6eff26e501c","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"Excel","versions":[]}],"title":"kintoneの値をExcel帳票へ差し込む前に｜0・空欄・数値型を保つJavaScript","updated_at":"2026-10-26T20:12:08+09:00","url":"https://qiita.com/kintaco/items/0ec7af87d6eff26e501c","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:157\"\u003e「\u003ca href=\"https://qiita.com/rex0220/items/ad08bb138a052c6bdff7\" id=\"reference-93e6f0887eb622c8c900\"\u003erex0220 一覧編集プラグイン - 導入編（追加から編集まで）\u003c/a\u003e」の続きです。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:389\"\u003e一覧編集では、複数の人が同じアプリのレコードを同時に編集できます。この記事では、自分が表を開いた後に、ほかの人が同じレコードを先に更新していたときの動き（排他制御）を説明します。競合したときは、行の ⇄ から、自分の変更を残すか、最新の値を取り込むかを選べます。\u003c/p\u003e\n\u003cp data-sourcepos=\"5:1-5:249\"\u003e例のアプリは導入編と同じ「問合せ管理（顧客サポートパック）」、保存方式は自動保存です。ほかの人の更新は、表を開いた後で同じレコードを別の画面から更新して作っています。\u003c/p\u003e\n\u003ch1 data-sourcepos=\"7:1-7:11\"\u003e\n\u003cspan id=\"仕組み\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BB%95%E7%B5%84%E3%81%BF\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e仕組み\u003c/h1\u003e\n\u003cul data-sourcepos=\"9:1-13:0\"\u003e\n\u003cli data-sourcepos=\"9:1-9:124\"\u003e一覧編集は、表を開いたときに、レコードごとの版（kintone のリビジョン番号）を覚えます\u003c/li\u003e\n\u003cli data-sourcepos=\"10:1-10:160\"\u003e保存するときに、その版を一緒に送ります。kintone は、その間にほかの人が更新していて版が違えば、保存を断ります\u003c/li\u003e\n\u003cli data-sourcepos=\"11:1-11:151\"\u003e断られたレコードは保存せず、行の左端に ⇄ の印を付けます。ほかの人の変更を上書きすることはありません\u003c/li\u003e\n\u003cli data-sourcepos=\"12:1-13:0\"\u003e判断はレコード単位です。ほかの人が変えたのが別の項目でも、⇄ になります\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"14:1-14:52\"\u003e⇄ を押すと、次の 2 つから選べます。\u003c/p\u003e\n\u003ctable data-sourcepos=\"16:1-19:109\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"16:1-16:58\"\u003e\n\u003cth data-sourcepos=\"16:2-16:15\"\u003e選ぶもの\u003c/th\u003e\n\u003cth data-sourcepos=\"16:17-16:33\"\u003e自分の変更\u003c/th\u003e\n\u003cth data-sourcepos=\"16:35-16:57\"\u003eほかの人の変更\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"18:1-18:157\"\u003e\n\u003ctd data-sourcepos=\"18:2-18:66\"\u003e自分の変更を残して、ほかの項目を最新にする\u003c/td\u003e\n\u003ctd data-sourcepos=\"18:68-18:105\"\u003e残して、もう一度保存する\u003c/td\u003e\n\u003ctd data-sourcepos=\"18:107-18:156\"\u003e自分が変えていない項目に取り込む\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"19:1-19:109\"\u003e\n\u003ctd data-sourcepos=\"19:2-19:63\"\u003e最新の値を取り込む（自分の変更を捨てる）\u003c/td\u003e\n\u003ctd data-sourcepos=\"19:65-19:75\"\u003e捨てる\u003c/td\u003e\n\u003ctd data-sourcepos=\"19:77-19:108\"\u003e全部の項目に取り込む\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch1 data-sourcepos=\"21:1-21:33\"\u003e\n\u003cspan id=\"例-1-自分の変更を残す\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BE%8B-1-%E8%87%AA%E5%88%86%E3%81%AE%E5%A4%89%E6%9B%B4%E3%82%92%E6%AE%8B%E3%81%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e例 1: 自分の変更を残す\u003c/h1\u003e\n\u003cp data-sourcepos=\"23:1-23:205\"\u003e表を開いた後に、ほかの人がレコード 14 の対応状況を「未対応」から「対応中」に変えて保存しました。自分の表には、まだ「未対応」と出ています。\u003c/p\u003e\n\u003cp data-sourcepos=\"25:1-25:261\"\u003eこの状態で、自分はレコード 14 の期限を 2018-09-07 に変えました。保存のときに kintone に断られ、行に ⇄ が付きます。下にも「ほかの人が先に更新したレコードが 1 件あります。…」と出ます。\u003c/p\u003e\n\u003cp data-sourcepos=\"27:1-27:179\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F12266e44-9bb7-4efc-8a3f-05ecc6515f1a.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=3a0495e7c2072cb8d1d89194bbd8779e\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F12266e44-9bb7-4efc-8a3f-05ecc6515f1a.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=3a0495e7c2072cb8d1d89194bbd8779e\" alt=\"期限を変えた行に ⇄（ほかの人が先に更新した）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F12266e44-9bb7-4efc-8a3f-05ecc6515f1a.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=f7b5662a02284b29cf6d34955d666e9d 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/12266e44-9bb7-4efc-8a3f-05ecc6515f1a.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"29:1-29:67\"\u003e⇄ を押すと、取り込み方を選ぶ画面が開きます。\u003c/p\u003e\n\u003cp data-sourcepos=\"31:1-31:142\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F9eed7475-4b77-45f1-b237-ed6541504b1d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=b8225a2e832ee3dcf468d85e067a974c\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F9eed7475-4b77-45f1-b237-ed6541504b1d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=b8225a2e832ee3dcf468d85e067a974c\" alt=\"取り込み方を選ぶ画面\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F9eed7475-4b77-45f1-b237-ed6541504b1d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=e7573e8d33312d8edff6a4785877d961 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/9eed7475-4b77-45f1-b237-ed6541504b1d.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"33:1-33:240\"\u003e「自分の変更を残して、ほかの項目を最新にする」を押すと、期限は自分の値（2018-09-07）のまま、対応状況はほかの人の値（対応中）になり、もう一度保存して ✓ になります。\u003c/p\u003e\n\u003cp data-sourcepos=\"35:1-35:199\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4ee04e7e-6dcc-4f23-8a96-9f0681efaf54.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=6aa638d9f3b518dcc85bd1b9ab84d19b\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4ee04e7e-6dcc-4f23-8a96-9f0681efaf54.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=6aa638d9f3b518dcc85bd1b9ab84d19b\" alt=\"自分の期限と、ほかの人の対応状況がそろって保存された（✓）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4ee04e7e-6dcc-4f23-8a96-9f0681efaf54.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=6f97b110e002ab7e4defefcfb3b48cbc 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4ee04e7e-6dcc-4f23-8a96-9f0681efaf54.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"37:1-37:272\"\u003e\u003cstrong\u003e自分とほかの人が同じ項目を変えていたときは、その項目は自分の値で保存し直します（ほかの人の値は残りません）。\u003c/strong\u003e ほかの人の値を残したいときは、例 2 の「最新の値を取り込む」を選びます。\u003c/p\u003e\n\u003ch1 data-sourcepos=\"39:1-39:69\"\u003e\n\u003cspan id=\"例-2-最新の値を取り込む自分の変更を捨てる\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BE%8B-2-%E6%9C%80%E6%96%B0%E3%81%AE%E5%80%A4%E3%82%92%E5%8F%96%E3%82%8A%E8%BE%BC%E3%82%80%E8%87%AA%E5%88%86%E3%81%AE%E5%A4%89%E6%9B%B4%E3%82%92%E6%8D%A8%E3%81%A6%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e例 2: 最新の値を取り込む（自分の変更を捨てる）\u003c/h1\u003e\n\u003cp data-sourcepos=\"41:1-41:220\"\u003e表を開いた後に、ほかの人がレコード 4 の対応状況を「対応中」に変えて保存しました。自分は同じレコードの対応状況を「完了」にしたので、⇄ が付きました。\u003c/p\u003e\n\u003cp data-sourcepos=\"43:1-43:151\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7e2555f2-ab20-4007-be13-bf560228a9d5.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=c5bf7e2adc1f09d1373bbdc75130b01b\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7e2555f2-ab20-4007-be13-bf560228a9d5.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=c5bf7e2adc1f09d1373bbdc75130b01b\" alt=\"自分は「完了」にした（⇄）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7e2555f2-ab20-4007-be13-bf560228a9d5.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=f90b0a8ed4e8e2c583ad6f50988c960f 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7e2555f2-ab20-4007-be13-bf560228a9d5.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"45:1-45:244\"\u003e⇄ を押して「最新の値を取り込む（自分の変更を捨てる）」を選ぶと、自分の「完了」は捨てて、ほかの人の「対応中」になります。自分の変更は残らないので、保存はしません。\u003c/p\u003e\n\u003cp data-sourcepos=\"47:1-47:163\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc56336d5-1cf1-43ca-81aa-bd6144d512ed.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=acc2935c1330fd2da7fa7235adf191ae\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc56336d5-1cf1-43ca-81aa-bd6144d512ed.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=acc2935c1330fd2da7fa7235adf191ae\" alt=\"ほかの人の値（対応中）を取り込んだ\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc56336d5-1cf1-43ca-81aa-bd6144d512ed.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=93f562978bef7d7e6118f2b04acfa4c7 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c56336d5-1cf1-43ca-81aa-bd6144d512ed.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"49:1-49:83\"\u003e取り込んだ後は、その行の自分の変更を Ctrl+Z で戻せません。\u003c/p\u003e\n\u003ch1 data-sourcepos=\"51:1-51:45\"\u003e\n\u003cspan id=\"例-3-複数の行に貼り付けたとき\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BE%8B-3-%E8%A4%87%E6%95%B0%E3%81%AE%E8%A1%8C%E3%81%AB%E8%B2%BC%E3%82%8A%E4%BB%98%E3%81%91%E3%81%9F%E3%81%A8%E3%81%8D\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e例 3: 複数の行に貼り付けたとき\u003c/h1\u003e\n\u003cp data-sourcepos=\"53:1-53:411\"\u003e自動保存で、複数の行への貼り付けは 1 回にまとめて保存します。この保存は、1 行でもほかの人が先に更新していると、その回の更新はすべて保存されません（kintone のまとめた更新は、全部保存するか全部保存しないかのどちらかです）。競合した行には ⇄ が付き、ほかの行も保存されずに残ります。\u003c/p\u003e\n\u003cp data-sourcepos=\"55:1-55:66\"\u003e3 行の期限に貼り付けました（● は保存の前）。\u003c/p\u003e\n\u003cp data-sourcepos=\"57:1-57:135\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc87885a3-d37c-4015-bd9e-d507f1ccc412.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=3f86763abbe04ad6d8f75fecc9dc32e2\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc87885a3-d37c-4015-bd9e-d507f1ccc412.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=3f86763abbe04ad6d8f75fecc9dc32e2\" alt=\"3 行に貼り付けた\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc87885a3-d37c-4015-bd9e-d507f1ccc412.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=12705e3264c084df24fc2a5f2759c43f 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c87885a3-d37c-4015-bd9e-d507f1ccc412.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"59:1-59:283\"\u003eこのうちレコード 15 は、ほかの人が先に更新していました。レコード 15 に ⇄ が付き、ほかの 2 行も保存されずに ● のままです。下の［未保存 2 件を保存］を押すと、⇄ の行を除いた 2 行を保存し直します。\u003c/p\u003e\n\u003cp data-sourcepos=\"61:1-61:182\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F40a53311-586d-444d-b542-6e45b5a31404.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=f3a88b28dc72b9e73a88ff280e14b081\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F40a53311-586d-444d-b542-6e45b5a31404.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=f3a88b28dc72b9e73a88ff280e14b081\" alt=\"1 行の ⇄ で、ほかの 2 行も保存されていない（●）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F40a53311-586d-444d-b542-6e45b5a31404.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=f616209bbade809405cc3f0460bbd0e3 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/40a53311-586d-444d-b542-6e45b5a31404.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"63:1-63:214\"\u003e⇄ を押して「自分の変更を残して、ほかの項目を最新にする」を選ぶと、同じ貼り付けの 3 行をまとめて保存し直しました（「更新 3 件を保存しました」）。\u003c/p\u003e\n\u003cp data-sourcepos=\"65:1-65:147\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5579dc4c-396e-41d1-82bc-df289d4314ef.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=dd50bbae45de4c4ed6098c0268eb29e8\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5579dc4c-396e-41d1-82bc-df289d4314ef.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=dd50bbae45de4c4ed6098c0268eb29e8\" alt=\"3 行とも保存された（✓）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5579dc4c-396e-41d1-82bc-df289d4314ef.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=879ee6bb20be15a71fca2be3ff9db122 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5579dc4c-396e-41d1-82bc-df289d4314ef.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"67:1-67:23\"\u003e\n\u003cspan id=\"覚えておくこと\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A6%9A%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8F%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e覚えておくこと\u003c/h1\u003e\n\u003cul data-sourcepos=\"69:1-73:0\"\u003e\n\u003cli data-sourcepos=\"69:1-69:144\"\u003e⇄ の行は、取り込み方を選ぶまで保存しません（自動保存でも）。ほかの行の編集と保存は続けられます\u003c/li\u003e\n\u003cli data-sourcepos=\"70:1-70:100\"\u003e明示保存の一覧でも、［保存］を押したときに同じように ⇄ が付きます\u003c/li\u003e\n\u003cli data-sourcepos=\"71:1-71:266\"\u003e表を開いたままにしておくほど、ほかの人の更新と重なりやすくなります。タイトル行の右端の再読込のアイコンで、最新の値で表を作り直せます（保存していない変更があるときは確かめます）\u003c/li\u003e\n\u003cli data-sourcepos=\"72:1-73:0\"\u003e「自分の変更を残す」は、同じ項目をほかの人が変えていても自分の値で保存します。テーブルを変えていれば、子行を含めてテーブル全体が自分の値になります\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 data-sourcepos=\"74:1-74:14\"\u003e\n\u003cspan id=\"関連記事\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E9%96%A2%E9%80%A3%E8%A8%98%E4%BA%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e関連記事\u003c/h1\u003e\n\u003cul data-sourcepos=\"76:1-77:129\"\u003e\n\u003cli data-sourcepos=\"76:1-76:135\"\u003e\u003ca href=\"https://qiita.com/rex0220/items/ad08bb138a052c6bdff7\"\u003erex0220 一覧編集プラグイン - 導入編（追加から編集まで）\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"77:1-77:129\"\u003e\n\u003ca href=\"https://qiita.com/rex0220/items/ad4705f630e97c605f54\" id=\"reference-cc32c8cea9224472c7d9\"\u003erex0220 一覧編集プラグイン\u003c/a\u003e（機能ごとの詳しい説明）\u003c/li\u003e\n\u003c/ul\u003e\n","body":"「[rex0220 一覧編集プラグイン - 導入編（追加から編集まで）](https://qiita.com/rex0220/items/ad08bb138a052c6bdff7)」の続きです。\n\n一覧編集では、複数の人が同じアプリのレコードを同時に編集できます。この記事では、自分が表を開いた後に、ほかの人が同じレコードを先に更新していたときの動き（排他制御）を説明します。競合したときは、行の ⇄ から、自分の変更を残すか、最新の値を取り込むかを選べます。\n\n例のアプリは導入編と同じ「問合せ管理（顧客サポートパック）」、保存方式は自動保存です。ほかの人の更新は、表を開いた後で同じレコードを別の画面から更新して作っています。\n\n# 仕組み\n\n- 一覧編集は、表を開いたときに、レコードごとの版（kintone のリビジョン番号）を覚えます\n- 保存するときに、その版を一緒に送ります。kintone は、その間にほかの人が更新していて版が違えば、保存を断ります\n- 断られたレコードは保存せず、行の左端に ⇄ の印を付けます。ほかの人の変更を上書きすることはありません\n- 判断はレコード単位です。ほかの人が変えたのが別の項目でも、⇄ になります\n\n⇄ を押すと、次の 2 つから選べます。\n\n| 選ぶもの | 自分の変更 | ほかの人の変更 |\n|---|---|---|\n| 自分の変更を残して、ほかの項目を最新にする | 残して、もう一度保存する | 自分が変えていない項目に取り込む |\n| 最新の値を取り込む（自分の変更を捨てる） | 捨てる | 全部の項目に取り込む |\n\n# 例 1: 自分の変更を残す\n\n表を開いた後に、ほかの人がレコード 14 の対応状況を「未対応」から「対応中」に変えて保存しました。自分の表には、まだ「未対応」と出ています。\n\nこの状態で、自分はレコード 14 の期限を 2018-09-07 に変えました。保存のときに kintone に断られ、行に ⇄ が付きます。下にも「ほかの人が先に更新したレコードが 1 件あります。…」と出ます。\n\n![期限を変えた行に ⇄（ほかの人が先に更新した）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/12266e44-9bb7-4efc-8a3f-05ecc6515f1a.png)\n\n⇄ を押すと、取り込み方を選ぶ画面が開きます。\n\n![取り込み方を選ぶ画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/9eed7475-4b77-45f1-b237-ed6541504b1d.png)\n\n「自分の変更を残して、ほかの項目を最新にする」を押すと、期限は自分の値（2018-09-07）のまま、対応状況はほかの人の値（対応中）になり、もう一度保存して ✓ になります。\n\n![自分の期限と、ほかの人の対応状況がそろって保存された（✓）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4ee04e7e-6dcc-4f23-8a96-9f0681efaf54.png)\n\n**自分とほかの人が同じ項目を変えていたときは、その項目は自分の値で保存し直します（ほかの人の値は残りません）。** ほかの人の値を残したいときは、例 2 の「最新の値を取り込む」を選びます。\n\n# 例 2: 最新の値を取り込む（自分の変更を捨てる）\n\n表を開いた後に、ほかの人がレコード 4 の対応状況を「対応中」に変えて保存しました。自分は同じレコードの対応状況を「完了」にしたので、⇄ が付きました。\n\n![自分は「完了」にした（⇄）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7e2555f2-ab20-4007-be13-bf560228a9d5.png)\n\n⇄ を押して「最新の値を取り込む（自分の変更を捨てる）」を選ぶと、自分の「完了」は捨てて、ほかの人の「対応中」になります。自分の変更は残らないので、保存はしません。\n\n![ほかの人の値（対応中）を取り込んだ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c56336d5-1cf1-43ca-81aa-bd6144d512ed.png)\n\n取り込んだ後は、その行の自分の変更を Ctrl+Z で戻せません。\n\n# 例 3: 複数の行に貼り付けたとき\n\n自動保存で、複数の行への貼り付けは 1 回にまとめて保存します。この保存は、1 行でもほかの人が先に更新していると、その回の更新はすべて保存されません（kintone のまとめた更新は、全部保存するか全部保存しないかのどちらかです）。競合した行には ⇄ が付き、ほかの行も保存されずに残ります。\n\n3 行の期限に貼り付けました（● は保存の前）。\n\n![3 行に貼り付けた](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c87885a3-d37c-4015-bd9e-d507f1ccc412.png)\n\nこのうちレコード 15 は、ほかの人が先に更新していました。レコード 15 に ⇄ が付き、ほかの 2 行も保存されずに ● のままです。下の［未保存 2 件を保存］を押すと、⇄ の行を除いた 2 行を保存し直します。\n\n![1 行の ⇄ で、ほかの 2 行も保存されていない（●）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/40a53311-586d-444d-b542-6e45b5a31404.png)\n\n⇄ を押して「自分の変更を残して、ほかの項目を最新にする」を選ぶと、同じ貼り付けの 3 行をまとめて保存し直しました（「更新 3 件を保存しました」）。\n\n![3 行とも保存された（✓）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5579dc4c-396e-41d1-82bc-df289d4314ef.png)\n\n# 覚えておくこと\n\n- ⇄ の行は、取り込み方を選ぶまで保存しません（自動保存でも）。ほかの行の編集と保存は続けられます\n- 明示保存の一覧でも、［保存］を押したときに同じように ⇄ が付きます\n- 表を開いたままにしておくほど、ほかの人の更新と重なりやすくなります。タイトル行の右端の再読込のアイコンで、最新の値で表を作り直せます（保存していない変更があるときは確かめます）\n- 「自分の変更を残す」は、同じ項目をほかの人が変えていても自分の値で保存します。テーブルを変えていれば、子行を含めてテーブル全体が自分の値になります\n\n# 関連記事\n\n- [rex0220 一覧編集プラグイン - 導入編（追加から編集まで）](https://qiita.com/rex0220/items/ad08bb138a052c6bdff7)\n- [rex0220 一覧編集プラグイン](https://qiita.com/rex0220/items/ad4705f630e97c605f54)（機能ごとの詳しい説明）\n","coediting":false,"comments_count":0,"created_at":"2026-10-26T12:32:19+09:00","group":null,"id":"d334c123f22e27e09065","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]}],"title":"rex0220 一覧編集プラグイン - 排他制御編（ほかの人が先に更新したとき）","updated_at":"2026-10-26T12:33:21+09:00","url":"https://qiita.com/rex0220/items/d334c123f22e27e09065","user":{"description":"","facebook_id":"","followees_count":0,"followers_count":155,"github_login_name":"rex0220","id":"rex0220","items_count":756,"linkedin_id":"","location":"","name":"","organization":"","permanent_id":100572,"profile_image_url":"https://qiita-image-store.s3.amazonaws.com/0/100572/profile-images/1473708137","team_only":false,"twitter_screen_name":"rex02201","website_url":"https://rex0220.stores.jp/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:305\"\u003ekintoneでPDFなどをレコードへ添付するとき、「ファイルのアップロードが成功した」だけでは、まだレコードへの保存は終わっていません。また、添付先へ新しいfileKeyだけを書き込むと、既存ファイルを残す意図になりません。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:338\"\u003eこの記事では、弊社kintacoの帳票出力プラグインで使っている添付保存処理を抜粋し、\u003cstrong\u003e既存ファイルの保持と同時更新の検知\u003c/strong\u003eを読み解きます。帳票生成やボタン設置までを含む完成サンプルではなく、生成済みのバイト列を保存する部分の解説です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:18\"\u003e\n\u003cspan id=\"対象と前提\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%AF%BE%E8%B1%A1%E3%81%A8%E5%89%8D%E6%8F%90\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e対象と前提\u003c/h2\u003e\n\u003cul data-sourcepos=\"7:1-12:0\"\u003e\n\u003cli data-sourcepos=\"7:1-7:105\"\u003e対象は保存済みの1レコードと、テーブル外の添付ファイルフィールドです。\u003c/li\u003e\n\u003cli data-sourcepos=\"8:1-8:144\"\u003ekintone内でログイン済みのブラウザーから実行する処理です。APIトークンをブラウザーへ埋め込みません。\u003c/li\u003e\n\u003cli data-sourcepos=\"9:1-9:89\"\u003e対象レコードとフィールドを閲覧・編集できる権限が必要です。\u003c/li\u003e\n\u003cli data-sourcepos=\"10:1-10:166\"\u003e\n\u003ccode\u003esource.revision\u003c/code\u003eには、帳票の元データを取得した時点のリビジョンを渡します。保存直前の番号に無条件で差し替えません。\u003c/li\u003e\n\u003cli data-sourcepos=\"11:1-12:0\"\u003e以下はExcelReport 1.0.6のローカルソースにある処理を確認したものです。既存添付の保持・競合時の停止をローカルのモックで検証し、この記事のための実環境への書き込みは行っていません。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 data-sourcepos=\"13:1-13:58\"\u003e\n\u003cspan id=\"処理はgetファイルpostレコードputの順\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%87%A6%E7%90%86%E3%81%AFget%E3%83%95%E3%82%A1%E3%82%A4%E3%83%ABpost%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89put%E3%81%AE%E9%A0%86\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e処理はGET、ファイルPOST、レコードPUTの順\u003c/h2\u003e\n\u003col data-sourcepos=\"15:1-19:0\"\u003e\n\u003cli data-sourcepos=\"15:1-15:108\"\u003e最新レコードを取得し、帳票の元データとリビジョンが一致するか確認する。\u003c/li\u003e\n\u003cli data-sourcepos=\"16:1-16:80\"\u003e保存先がFILE型で、既存のfileKeyを取得できるか確認する。\u003c/li\u003e\n\u003cli data-sourcepos=\"17:1-17:88\"\u003e生成済みファイルをアップロードし、新しいfileKeyを受け取る。\u003c/li\u003e\n\u003cli data-sourcepos=\"18:1-19:0\"\u003e既存のfileKeyと新しいfileKeyをまとめ、同じリビジョンを指定してレコードを更新する。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp data-sourcepos=\"20:1-20:468\"\u003eアップロードとレコード更新は別のAPIです。\u003ca href=\"https://cybozu.dev/ja/kintone/docs/rest-api/files/upload-file/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eファイルをアップロードするAPI\u003c/a\u003eで得たキーを、\u003ca href=\"https://cybozu.dev/ja/kintone/docs/rest-api/records/update-record/\" rel=\"nofollow noopener\" target=\"_blank\"\u003e1件のレコードを更新するAPI\u003c/a\u003eへ渡します。後者の公式ドキュメントでも、既存ファイルを残して追加するときは既存のfileKeyを含めるよう案内されています。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"22:1-22:36\"\u003e\n\u003cspan id=\"添付保存部分の実コード\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%B7%BB%E4%BB%98%E4%BF%9D%E5%AD%98%E9%83%A8%E5%88%86%E3%81%AE%E5%AE%9F%E3%82%B3%E3%83%BC%E3%83%89\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e添付保存部分の実コード\u003c/h2\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"24:1-46:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"k\"\u003easync\u003c/span\u003e \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003esaveAttachment\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003edata\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003efilename\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003emime\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003efieldCode\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eapp\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eid\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"sr\"\u003e/^\u003c/span\u003e\u003cspan class=\"se\"\u003e\\d\u003c/span\u003e\u003cspan class=\"sr\"\u003e+$/\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003etest\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erevision\u003c/span\u003e\u003cspan class=\"p\"\u003e)))\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eレコード情報を確認できません。詳細画面を再読み込みしてください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003efieldCode\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e保存先の添付ファイルフィールドを設定してください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eurl\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eapi\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eurl\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e/k/v1/record.json\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003elatest\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eapi\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eurl\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eGET\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003eapp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eapp\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eid\u003c/span\u003e\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003elatest\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e?.\u003c/span\u003e\u003cspan class=\"nx\"\u003e$revision\u003c/span\u003e\u003cspan class=\"p\"\u003e?.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erevision\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eレコードが更新されています。詳細画面を再読み込みしてから帳票を出力してください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003elatest\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003efieldCode\u003c/span\u003e\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eFILE\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e保存先の添付ファイルフィールドを取得できません。フィールド設定・閲覧権限を確認してください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eexisting\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efile\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003efile\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003efileKey\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e既存の添付情報を確認できません。保存を中止しました。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n      \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003efileKey\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003efile\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003efileKey\u003c/span\u003e\u003cspan class=\"p\"\u003e};\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eform\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eFormData\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n    \u003cspan class=\"nx\"\u003eform\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eappend\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e__REQUEST_TOKEN__\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetRequestToken\u003c/span\u003e\u003cspan class=\"p\"\u003e());\u003c/span\u003e\n    \u003cspan class=\"nx\"\u003eform\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eappend\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003efile\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eBlob\u003c/span\u003e\u003cspan class=\"p\"\u003e([\u003c/span\u003e\u003cspan class=\"nx\"\u003edata\u003c/span\u003e\u003cspan class=\"p\"\u003e],\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003emime\u003c/span\u003e\u003cspan class=\"p\"\u003e}),\u003c/span\u003e \u003cspan class=\"nx\"\u003efilename\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eresponse\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nb\"\u003ewindow\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003efetch\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eapi\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eurl\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e/k/v1/file.json\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ePOST\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"na\"\u003ecredentials\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003esame-origin\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"p\"\u003e:{\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eX-Requested-With\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eXMLHttpRequest\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e},\u003c/span\u003e\u003cspan class=\"na\"\u003ebody\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003eform\u003c/span\u003e\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003euploaded\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nx\"\u003eresponse\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ejson\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003eresponse\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eok\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003euploaded\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003efileKey\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003estring\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003euploaded\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003efileKey\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003euploaded\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003emessage\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e帳票ファイルのアップロードに失敗しました。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"c1\"\u003e// Preserve all existing files and reject concurrent changes; never retry a write automatically.\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eapi\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eurl\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ePUT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003eapp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eapp\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eid\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"na\"\u003erevision\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erevision\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"na\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e:{[\u003c/span\u003e\u003cspan class=\"nx\"\u003efieldCode\u003c/span\u003e\u003cspan class=\"p\"\u003e]:{\u003c/span\u003e\u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:[...\u003c/span\u003e\u003cspan class=\"nx\"\u003eexisting\u003c/span\u003e\u003cspan class=\"p\"\u003e,{\u003c/span\u003e\u003cspan class=\"na\"\u003efileKey\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003euploaded\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003efileKey\u003c/span\u003e\u003cspan class=\"p\"\u003e}]}}});\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"48:1-48:361\"\u003e引数の\u003ccode\u003edata\u003c/code\u003eは生成済みのバイト列、\u003ccode\u003efilename\u003c/code\u003eは保存名、\u003ccode\u003emime\u003c/code\u003eはMIMEタイプ、\u003ccode\u003efieldCode\u003c/code\u003eは保存先の実際のフィールドコードです。\u003ccode\u003esource\u003c/code\u003eには\u003ccode\u003eapp\u003c/code\u003e、\u003ccode\u003eid\u003c/code\u003e、\u003ccode\u003erevision\u003c/code\u003eを渡します。帳票生成処理やイベントハンドラー、二重クリック防止は、この関数を呼ぶ側で扱う必要があります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"50:1-50:28\"\u003e\n\u003cspan id=\"既存のfilekeyを残す\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%97%A2%E5%AD%98%E3%81%AEfilekey%E3%82%92%E6%AE%8B%E3%81%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e既存のfileKeyを残す\u003c/h2\u003e\n\u003cp data-sourcepos=\"52:1-52:242\"\u003e更新値の\u003ccode\u003evalue\u003c/code\u003eには、既存添付を\u003ccode\u003e{fileKey: ...}\u003c/code\u003eへ整形した配列と、アップロードで得たキーを入れています。現在のファイルがA・B、新しいファイルがCなら、送るキーはA・B・Cです。\u003c/p\u003e\n\u003cp data-sourcepos=\"54:1-54:327\"\u003eこの関数は同名ファイルを探して置き換える処理を持ちません。再実行すると追加になるため、同名判定や版管理が必要なら別途設計します。ファイル名が同じという理由だけで既存添付を自動削除しない点も、意識しておきたいところです。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"56:1-56:56\"\u003e\n\u003cspan id=\"getで確認してもputにrevisionを付ける理由\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#get%E3%81%A7%E7%A2%BA%E8%AA%8D%E3%81%97%E3%81%A6%E3%82%82put%E3%81%ABrevision%E3%82%92%E4%BB%98%E3%81%91%E3%82%8B%E7%90%86%E7%94%B1\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eGETで確認してもPUTにrevisionを付ける理由\u003c/h2\u003e\n\u003cp data-sourcepos=\"58:1-58:323\"\u003eGET直後に番号が一致していても、その後のアップロード中に他の利用者がレコードを更新する可能性があります。そこで、最終PUTにも元の\u003ccode\u003esource.revision\u003c/code\u003eを渡します。チェック後から保存までの間に起きた更新も、競合として止めるためです。\u003c/p\u003e\n\u003cp data-sourcepos=\"60:1-60:273\"\u003e競合エラーの後で最新リビジョンを取り直し、同じ帳票を自動でPUTし直す処理は入れていません。帳票が古い値から生成されていないか、既存添付がどう変わったかを人が確認する必要があるからです。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"62:1-62:47\"\u003e\n\u003cspan id=\"formdataにcontent-typeを手で付けない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#formdata%E3%81%ABcontent-type%E3%82%92%E6%89%8B%E3%81%A7%E4%BB%98%E3%81%91%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eFormDataにContent-Typeを手で付けない\u003c/h2\u003e\n\u003cp data-sourcepos=\"64:1-64:398\"\u003eファイルのPOSTでは\u003ccode\u003eFormData\u003c/code\u003eを使い、リクエストトークンを含めています。\u003ccode\u003eContent-Type: multipart/form-data\u003c/code\u003eを自分で固定せず、境界文字列をブラウザーに設定させます。\u003ccode\u003ekintone.api.url(..., true)\u003c/code\u003eはゲストスペースを考慮したURL生成のために使用していますが、権限や配置する画面の動作確認は別途必要です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"66:1-66:48\"\u003e\n\u003cspan id=\"自動リトライしない境界を決める\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%87%AA%E5%8B%95%E3%83%AA%E3%83%88%E3%83%A9%E3%82%A4%E3%81%97%E3%81%AA%E3%81%84%E5%A2%83%E7%95%8C%E3%82%92%E6%B1%BA%E3%82%81%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e自動リトライしない境界を決める\u003c/h2\u003e\n\u003cp data-sourcepos=\"68:1-68:294\"\u003eこの関数はエラーを呼び出し元へ返します。権限不足、アップロード失敗、PUT失敗を無視して成功扱いにはしません。アップロード後にPUTが失敗した場合、そのファイルはレコードへ紐付いていない可能性があります。\u003c/p\u003e\n\u003cp data-sourcepos=\"70:1-70:397\"\u003e通信が切れたときは「保存されなかった」と断定できない場合もあります。画面側でエラーを表示し、レコードの値・添付を確認してから再実行する運用にします。レコードを更新すると更新者・更新日時や通知・Webhook等に影響する場合もあるため、帳票以外の処理を含めて検証してください。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"72:1-72:72\"\u003e\n\u003cspan id=\"ローカルで確認したことと実環境で確認すること\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%A7%E7%A2%BA%E8%AA%8D%E3%81%97%E3%81%9F%E3%81%93%E3%81%A8%E3%81%A8%E5%AE%9F%E7%92%B0%E5%A2%83%E3%81%A7%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eローカルで確認したことと、実環境で確認すること\u003c/h2\u003e\n\u003cp data-sourcepos=\"74:1-74:299\"\u003eモックでは、既存添付2件への追加、空の添付先への追加、事前のリビジョン不一致、FILE型以外、既存キー欠落、アップロード失敗、PUT時の競合を確認します。失敗時に後続処理や自動再試行へ進まないことも確認します。\u003c/p\u003e\n\u003cp data-sourcepos=\"76:1-76:319\"\u003e実環境では、実際の利用者の権限、生成ファイルが開けること、保存後の表示更新、通知・Webhook、モバイル、二重クリックや再発行の扱いを別途確認してください。ローカルの成功は、これらの実機動作を保証するものではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"78:1-78:60\"\u003e\n\u003cspan id=\"帳票生成と保存先設定をまとめて使う場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%B8%B3%E7%A5%A8%E7%94%9F%E6%88%90%E3%81%A8%E4%BF%9D%E5%AD%98%E5%85%88%E8%A8%AD%E5%AE%9A%E3%82%92%E3%81%BE%E3%81%A8%E3%82%81%E3%81%A6%E4%BD%BF%E3%81%86%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e帳票生成と保存先設定をまとめて使う場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"80:1-80:399\"\u003eこの記事の処理を題材にした自社製品は、\u003ca href=\"https://kintaco.wisemap.biz/plugins/excel-report/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=report_attachment_20261026\" rel=\"nofollow noopener\" target=\"_blank\"\u003eExcel・PDF帳票出力プラグイン\u003c/a\u003eです。テンプレートから生成し、帳票ごとにダウンロード・添付保存・両方を選べます。機能と制約はリンク先で確認できます。\u003c/p\u003e\n\u003cp data-sourcepos=\"82:1-82:318\"\u003e無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プラン案内が30%の確率で表示されます。契約済みドメインには表示されません。一度閉じると、同じブラウザー・同じkintoneドメインの全Kintacoプラグインで24時間非表示です。\u003c/p\u003e\n\u003cp data-sourcepos=\"84:1-84:276\"\u003e設定画面を使った運用手順は、\u003ca href=\"https://kintaco.wisemap.biz/column/kintone-report-attachment-save/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=report_attachment_20261026\" rel=\"nofollow noopener\" target=\"_blank\"\u003e作成した帳票をレコードへ添付保存するコラム\u003c/a\u003eに分けています。\u003c/p\u003e\n","body":"kintoneでPDFなどをレコードへ添付するとき、「ファイルのアップロードが成功した」だけでは、まだレコードへの保存は終わっていません。また、添付先へ新しいfileKeyだけを書き込むと、既存ファイルを残す意図になりません。\n\nこの記事では、弊社kintacoの帳票出力プラグインで使っている添付保存処理を抜粋し、**既存ファイルの保持と同時更新の検知**を読み解きます。帳票生成やボタン設置までを含む完成サンプルではなく、生成済みのバイト列を保存する部分の解説です。\n\n## 対象と前提\n\n- 対象は保存済みの1レコードと、テーブル外の添付ファイルフィールドです。\n- kintone内でログイン済みのブラウザーから実行する処理です。APIトークンをブラウザーへ埋め込みません。\n- 対象レコードとフィールドを閲覧・編集できる権限が必要です。\n- `source.revision`には、帳票の元データを取得した時点のリビジョンを渡します。保存直前の番号に無条件で差し替えません。\n- 以下はExcelReport 1.0.6のローカルソースにある処理を確認したものです。既存添付の保持・競合時の停止をローカルのモックで検証し、この記事のための実環境への書き込みは行っていません。\n\n## 処理はGET、ファイルPOST、レコードPUTの順\n\n1. 最新レコードを取得し、帳票の元データとリビジョンが一致するか確認する。\n2. 保存先がFILE型で、既存のfileKeyを取得できるか確認する。\n3. 生成済みファイルをアップロードし、新しいfileKeyを受け取る。\n4. 既存のfileKeyと新しいfileKeyをまとめ、同じリビジョンを指定してレコードを更新する。\n\nアップロードとレコード更新は別のAPIです。[ファイルをアップロードするAPI](https://cybozu.dev/ja/kintone/docs/rest-api/files/upload-file/)で得たキーを、[1件のレコードを更新するAPI](https://cybozu.dev/ja/kintone/docs/rest-api/records/update-record/)へ渡します。後者の公式ドキュメントでも、既存ファイルを残して追加するときは既存のfileKeyを含めるよう案内されています。\n\n## 添付保存部分の実コード\n\n```javascript\nasync function saveAttachment(data, filename, mime, fieldCode, source) {\n    if (!source.app || !source.id || !/^\\d+$/.test(String(source.revision))) throw new Error('レコード情報を確認できません。詳細画面を再読み込みしてください。');\n    if (!fieldCode) throw new Error('保存先の添付ファイルフィールドを設定してください。');\n    const url = kintone.api.url('/k/v1/record.json', true);\n    const latest = await kintone.api(url, 'GET', {app:source.app,id:source.id});\n    if (String(latest.record?.$revision?.value) !== String(source.revision)) throw new Error('レコードが更新されています。詳細画面を再読み込みしてから帳票を出力してください。');\n    const field = latest.record[fieldCode];\n    if (!field || field.type !== 'FILE' || !Array.isArray(field.value)) throw new Error('保存先の添付ファイルフィールドを取得できません。フィールド設定・閲覧権限を確認してください。');\n    const existing = field.value.map(file =\u003e {\n      if (!file.fileKey) throw new Error('既存の添付情報を確認できません。保存を中止しました。');\n      return {fileKey:file.fileKey};\n    });\n    const form = new FormData();\n    form.append('__REQUEST_TOKEN__', kintone.getRequestToken());\n    form.append('file', new Blob([data], {type:mime}), filename);\n    const response = await window.fetch(kintone.api.url('/k/v1/file.json', true), {method:'POST',credentials:'same-origin',headers:{'X-Requested-With':'XMLHttpRequest'},body:form});\n    const uploaded = await response.json();\n    if (!response.ok || typeof uploaded.fileKey !== 'string' || !uploaded.fileKey) throw new Error(uploaded.message || '帳票ファイルのアップロードに失敗しました。');\n    // Preserve all existing files and reject concurrent changes; never retry a write automatically.\n    return kintone.api(url, 'PUT', {app:source.app,id:source.id,revision:source.revision,record:{[fieldCode]:{value:[...existing,{fileKey:uploaded.fileKey}]}}});\n  }\n```\n\n引数の`data`は生成済みのバイト列、`filename`は保存名、`mime`はMIMEタイプ、`fieldCode`は保存先の実際のフィールドコードです。`source`には`app`、`id`、`revision`を渡します。帳票生成処理やイベントハンドラー、二重クリック防止は、この関数を呼ぶ側で扱う必要があります。\n\n## 既存のfileKeyを残す\n\n更新値の`value`には、既存添付を`{fileKey: ...}`へ整形した配列と、アップロードで得たキーを入れています。現在のファイルがA・B、新しいファイルがCなら、送るキーはA・B・Cです。\n\nこの関数は同名ファイルを探して置き換える処理を持ちません。再実行すると追加になるため、同名判定や版管理が必要なら別途設計します。ファイル名が同じという理由だけで既存添付を自動削除しない点も、意識しておきたいところです。\n\n## GETで確認してもPUTにrevisionを付ける理由\n\nGET直後に番号が一致していても、その後のアップロード中に他の利用者がレコードを更新する可能性があります。そこで、最終PUTにも元の`source.revision`を渡します。チェック後から保存までの間に起きた更新も、競合として止めるためです。\n\n競合エラーの後で最新リビジョンを取り直し、同じ帳票を自動でPUTし直す処理は入れていません。帳票が古い値から生成されていないか、既存添付がどう変わったかを人が確認する必要があるからです。\n\n## FormDataにContent-Typeを手で付けない\n\nファイルのPOSTでは`FormData`を使い、リクエストトークンを含めています。`Content-Type: multipart/form-data`を自分で固定せず、境界文字列をブラウザーに設定させます。`kintone.api.url(..., true)`はゲストスペースを考慮したURL生成のために使用していますが、権限や配置する画面の動作確認は別途必要です。\n\n## 自動リトライしない境界を決める\n\nこの関数はエラーを呼び出し元へ返します。権限不足、アップロード失敗、PUT失敗を無視して成功扱いにはしません。アップロード後にPUTが失敗した場合、そのファイルはレコードへ紐付いていない可能性があります。\n\n通信が切れたときは「保存されなかった」と断定できない場合もあります。画面側でエラーを表示し、レコードの値・添付を確認してから再実行する運用にします。レコードを更新すると更新者・更新日時や通知・Webhook等に影響する場合もあるため、帳票以外の処理を含めて検証してください。\n\n## ローカルで確認したことと、実環境で確認すること\n\nモックでは、既存添付2件への追加、空の添付先への追加、事前のリビジョン不一致、FILE型以外、既存キー欠落、アップロード失敗、PUT時の競合を確認します。失敗時に後続処理や自動再試行へ進まないことも確認します。\n\n実環境では、実際の利用者の権限、生成ファイルが開けること、保存後の表示更新、通知・Webhook、モバイル、二重クリックや再発行の扱いを別途確認してください。ローカルの成功は、これらの実機動作を保証するものではありません。\n\n## 帳票生成と保存先設定をまとめて使う場合\n\nこの記事の処理を題材にした自社製品は、[Excel・PDF帳票出力プラグイン](https://kintaco.wisemap.biz/plugins/excel-report/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=report_attachment_20261026)です。テンプレートから生成し、帳票ごとにダウンロード・添付保存・両方を選べます。機能と制約はリンク先で確認できます。\n\n無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プラン案内が30%の確率で表示されます。契約済みドメインには表示されません。一度閉じると、同じブラウザー・同じkintoneドメインの全Kintacoプラグインで24時間非表示です。\n\n設定画面を使った運用手順は、[作成した帳票をレコードへ添付保存するコラム](https://kintaco.wisemap.biz/column/kintone-report-attachment-save/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=report_attachment_20261026)に分けています。\n","coediting":false,"comments_count":0,"created_at":"2026-10-26T11:03:42+09:00","group":null,"id":"5c1f66586d0adea9a2c7","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"REST-API","versions":[]}],"title":"kintoneで添付ファイルを追加保存するJavaScript｜既存fileKeyとrevisionで上書きを防ぐ","updated_at":"2026-10-26T11:03:42+09:00","url":"https://qiita.com/kintaco/items/5c1f66586d0adea9a2c7","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-2:168\"\u003ekintone の一覧画面のレコードを、表のまま編集できるようにするプラグインです。\u003cbr\u003e\nこの記事では、プラグインをアプリに追加して、全部の一覧で全部の項目を編集できるようにするまでを、順に説明します。\u003c/p\u003e\n\u003cp data-sourcepos=\"4:1-4:151\"\u003e機能の詳しい説明は「\u003ca href=\"https://qiita.com/rex0220/items/ad4705f630e97c605f54\" id=\"reference-ed65e3a6054a9a57866f\"\u003erex0220 一覧編集プラグイン\u003c/a\u003e」の記事にあります。\u003c/p\u003e\n\u003cp data-sourcepos=\"6:1-6:185\"\u003e例のアプリは、kintone のサンプルアプリ「問合せ管理（顧客サポートパック）」です。一覧は「対応一覧」と「未対応一覧」の 2 つです。\u003c/p\u003e\n\u003ch1 data-sourcepos=\"8:1-8:17\"\u003e\n\u003cspan id=\"設定の流れ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%AD%E5%AE%9A%E3%81%AE%E6%B5%81%E3%82%8C\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e設定の流れ\u003c/h1\u003e\n\u003col data-sourcepos=\"10:1-17:0\"\u003e\n\u003cli data-sourcepos=\"10:1-10:45\"\u003eアプリにプラグインを追加する\u003c/li\u003e\n\u003cli data-sourcepos=\"11:1-11:36\"\u003eプラグインの設定を開く\u003c/li\u003e\n\u003cli data-sourcepos=\"12:1-12:39\"\u003e保存方式を自動保存にする\u003c/li\u003e\n\u003cli data-sourcepos=\"13:1-13:56\"\u003e1 つの一覧で、編集する項目を全部選ぶ\u003c/li\u003e\n\u003cli data-sourcepos=\"14:1-14:45\"\u003eほかの一覧に設定をコピーする\u003c/li\u003e\n\u003cli data-sourcepos=\"15:1-15:42\"\u003e保存して運用環境に反映する\u003c/li\u003e\n\u003cli data-sourcepos=\"16:1-17:0\"\u003e一覧で編集する\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp data-sourcepos=\"18:1-18:183\"\u003e前もって、プラグインの zip を「kintone システム管理 \u0026gt; プラグイン」で読み込んでおきます（kintone のシステム管理の権限が要ります）。\u003c/p\u003e\n\u003ch1 data-sourcepos=\"20:1-20:47\"\u003e\n\u003cspan id=\"1-アプリにプラグインを追加する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#1-%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AB%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e1. アプリにプラグインを追加する\u003c/h1\u003e\n\u003cp data-sourcepos=\"22:1-22:81\"\u003e「アプリの設定 \u0026gt; プラグイン」で［追加する］を押します。\u003c/p\u003e\n\u003cp data-sourcepos=\"24:1-24:187\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5a698975-af8b-4458-a158-f392ea02f814.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=d97961507f28efe98caab3870d6ae6cc\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5a698975-af8b-4458-a158-f392ea02f814.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=d97961507f28efe98caab3870d6ae6cc\" alt=\"アプリの設定のプラグイン（まだ何も追加していない）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5a698975-af8b-4458-a158-f392ea02f814.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=3ff947ffd8413c218b2a743364536eec 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5a698975-af8b-4458-a158-f392ea02f814.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"26:1-26:87\"\u003e「一覧編集」にチェックを入れて、右下の［追加］を押します。\u003c/p\u003e\n\u003cp data-sourcepos=\"28:1-28:169\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F39bc827e-60bd-4bdd-bf5b-f8f82994dbef.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=a555f602d809edc8a669310ab15bf747\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F39bc827e-60bd-4bdd-bf5b-f8f82994dbef.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=a555f602d809edc8a669310ab15bf747\" alt=\"プラグインの追加（一覧編集にチェック）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F39bc827e-60bd-4bdd-bf5b-f8f82994dbef.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=7c447cb281eed8fdfaae0bd26aa75ade 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/39bc827e-60bd-4bdd-bf5b-f8f82994dbef.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"30:1-30:156\"\u003eプラグインの一覧に「一覧編集」が出ます。「必須項目が設定されていません」は、まだ設定していないためです。\u003c/p\u003e\n\u003ch1 data-sourcepos=\"32:1-32:38\"\u003e\n\u003cspan id=\"2-プラグインの設定を開く\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#2-%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E9%96%8B%E3%81%8F\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e2. プラグインの設定を開く\u003c/h1\u003e\n\u003cp data-sourcepos=\"34:1-34:78\"\u003e「一覧編集」の行の歯車を押すと、設定画面が開きます。\u003c/p\u003e\n\u003cp data-sourcepos=\"36:1-36:166\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fa7b929b3-ee77-4cc8-86eb-4f890a7a083d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=981495858ab8bf4782fec6b8d5b509f4\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fa7b929b3-ee77-4cc8-86eb-4f890a7a083d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=981495858ab8bf4782fec6b8d5b509f4\" alt=\"追加した一覧編集（歯車で設定画面へ）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fa7b929b3-ee77-4cc8-86eb-4f890a7a083d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=5392d25987d7bb3741122492f158cc7e 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a7b929b3-ee77-4cc8-86eb-4f890a7a083d.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"38:1-38:96\"\u003eアプリの一覧が並びます。「（すべて）」は kintone の全件の一覧です。\u003c/p\u003e\n\u003cp data-sourcepos=\"40:1-40:145\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4cb53063-da91-4655-995a-9ed050518de2.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=a1e6d98dbb36a04a3adce41853605b4c\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4cb53063-da91-4655-995a-9ed050518de2.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=a1e6d98dbb36a04a3adce41853605b4c\" alt=\"設定画面を開いたところ\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4cb53063-da91-4655-995a-9ed050518de2.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=171017f40a8c7a8f676ec41953c844f2 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4cb53063-da91-4655-995a-9ed050518de2.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"42:1-42:41\"\u003e\n\u003cspan id=\"3-保存方式を自動保存にする\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#3-%E4%BF%9D%E5%AD%98%E6%96%B9%E5%BC%8F%E3%82%92%E8%87%AA%E5%8B%95%E4%BF%9D%E5%AD%98%E3%81%AB%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e3. 保存方式を自動保存にする\u003c/h1\u003e\n\u003cp data-sourcepos=\"44:1-44:180\"\u003eツールバーの［詳細設定］を押し、保存方式の「自動保存」を選びます（初めから自動保存です）。［保存］で設定画面に戻ります。\u003c/p\u003e\n\u003cul data-sourcepos=\"46:1-48:0\"\u003e\n\u003cli data-sourcepos=\"46:1-46:82\"\u003e自動保存: セルを確定して少し待つと、その行を保存します\u003c/li\u003e\n\u003cli data-sourcepos=\"47:1-48:0\"\u003e明示保存: 一覧画面の［保存］を押したときに、変更をまとめて保存します\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"49:1-49:157\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F9172a1f8-0387-4a5f-a6b2-3793577ff03c.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=3210aff51521f4db7c090f3434c827fd\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F9172a1f8-0387-4a5f-a6b2-3793577ff03c.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=3210aff51521f4db7c090f3434c827fd\" alt=\"詳細設定（保存方式は自動保存）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F9172a1f8-0387-4a5f-a6b2-3793577ff03c.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=097f26c4ae3f0eb2159c5af4a5e112ef 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/9172a1f8-0387-4a5f-a6b2-3793577ff03c.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"51:1-51:58\"\u003e\n\u003cspan id=\"4-1-つの一覧で編集する項目を全部選ぶ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#4-1-%E3%81%A4%E3%81%AE%E4%B8%80%E8%A6%A7%E3%81%A7%E7%B7%A8%E9%9B%86%E3%81%99%E3%82%8B%E9%A0%85%E7%9B%AE%E3%82%92%E5%85%A8%E9%83%A8%E9%81%B8%E3%81%B6\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e4. 1 つの一覧で、編集する項目を全部選ぶ\u003c/h1\u003e\n\u003cp data-sourcepos=\"53:1-53:171\"\u003e「対応一覧」の行の「編集を許可する項目」のセルを押します。見出しのチェックで全部の項目を選び、［保存］を押します。\u003c/p\u003e\n\u003cul data-sourcepos=\"55:1-58:0\"\u003e\n\u003cli data-sourcepos=\"55:1-55:83\"\u003eテーブルの子の項目（対応詳細の対応日時など）も選べます\u003c/li\u003e\n\u003cli data-sourcepos=\"56:1-56:122\"\u003e計算、ルックアップのコピー先、レコード番号などは、編集できないので候補に出ません\u003c/li\u003e\n\u003cli data-sourcepos=\"57:1-58:0\"\u003eアクセス権は一覧編集では確かめません。権限の無いレコード・項目の変更は、保存のときに kintone がエラーにします\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"59:1-59:178\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc727e76d-a96a-44dd-bc7b-74c548719cf6.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=1d7edf8cc0c52c6f0a81059305bd0ef1\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc727e76d-a96a-44dd-bc7b-74c548719cf6.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=1d7edf8cc0c52c6f0a81059305bd0ef1\" alt=\"編集を許可する項目（見出しのチェックで全部）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc727e76d-a96a-44dd-bc7b-74c548719cf6.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=a300950302fff23832bd030d8953bcb8 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c727e76d-a96a-44dd-bc7b-74c548719cf6.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"61:1-61:132\"\u003e「対応一覧」の左端のチェックを入れます。左端のチェックは、プラグインを使う一覧の印です。\u003c/p\u003e\n\u003cp data-sourcepos=\"63:1-63:151\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Feff0a7fe-631e-461e-82b3-9f915127eea0.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=77b6ef264c93718a0f1250a78b961673\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Feff0a7fe-631e-461e-82b3-9f915127eea0.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=77b6ef264c93718a0f1250a78b961673\" alt=\"対応一覧だけ設定したところ\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Feff0a7fe-631e-461e-82b3-9f915127eea0.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=1aa6f6a47f2cb75032c583d8702f2217 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/eff0a7fe-631e-461e-82b3-9f915127eea0.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"65:1-65:47\"\u003e\n\u003cspan id=\"5-ほかの一覧に設定をコピーする\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#5-%E3%81%BB%E3%81%8B%E3%81%AE%E4%B8%80%E8%A6%A7%E3%81%AB%E8%A8%AD%E5%AE%9A%E3%82%92%E3%82%B3%E3%83%94%E3%83%BC%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e5. ほかの一覧に設定をコピーする\u003c/h1\u003e\n\u003cp data-sourcepos=\"67:1-67:69\"\u003eツールバーの［一覧の設定をコピー］を押します。\u003c/p\u003e\n\u003cul data-sourcepos=\"69:1-72:0\"\u003e\n\u003cli data-sourcepos=\"69:1-69:103\"\u003eコピー元の一覧: 「対応一覧」（最後に押した行が初めに選ばれています）\u003c/li\u003e\n\u003cli data-sourcepos=\"70:1-70:37\"\u003e写す設定: 初めは全部です\u003c/li\u003e\n\u003cli data-sourcepos=\"71:1-72:0\"\u003eコピー先の一覧: 「すべて」をチェックします\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"73:1-73:189\"\u003e「コピー先の一覧で使う（左端のチェック）」がチェックされているので、コピー先の左端のチェックも付きます。［コピー］を押します。\u003c/p\u003e\n\u003cp data-sourcepos=\"75:1-75:169\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fe80dfc0e-7fe5-49ef-98cc-b9db464b70b9.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=84996998249f673cb876f786c169ed61\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fe80dfc0e-7fe5-49ef-98cc-b9db464b70b9.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=84996998249f673cb876f786c169ed61\" alt=\"一覧の設定をコピー（コピー先はすべて）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fe80dfc0e-7fe5-49ef-98cc-b9db464b70b9.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=1d65a9aef6e858649cf705d584483c5b 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/e80dfc0e-7fe5-49ef-98cc-b9db464b70b9.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"77:1-77:114\"\u003e全部の一覧に、同じ「編集を許可する項目」が入り、左端のチェックも付きました。\u003c/p\u003e\n\u003ch1 data-sourcepos=\"79:1-79:44\"\u003e\n\u003cspan id=\"6-保存して運用環境に反映する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#6-%E4%BF%9D%E5%AD%98%E3%81%97%E3%81%A6%E9%81%8B%E7%94%A8%E7%92%B0%E5%A2%83%E3%81%AB%E5%8F%8D%E6%98%A0%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e6. 保存して運用環境に反映する\u003c/h1\u003e\n\u003cp data-sourcepos=\"81:1-81:195\"\u003e画面の下の「運用環境に反映」にチェックを入れて、［保存する］を押します。確かめる画面で［保存する］を押すと、アプリに反映されます。\u003c/p\u003e\n\u003cp data-sourcepos=\"83:1-83:193\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F3af59049-4e37-4d08-b840-bd2d21661781.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=dce68724ca027ae6f4e12b26e5dbf9de\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F3af59049-4e37-4d08-b840-bd2d21661781.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=dce68724ca027ae6f4e12b26e5dbf9de\" alt=\"全部の一覧を設定したところ（運用環境に反映にチェック）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F3af59049-4e37-4d08-b840-bd2d21661781.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=ec67071e3ad4dea4539536493486c4c5 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3af59049-4e37-4d08-b840-bd2d21661781.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"85:1-85:145\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F3ae66772-5750-42b3-8e06-9efdf4a87582.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=580d640af0773f75e4ea1f7c2c070b3e\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F3ae66772-5750-42b3-8e06-9efdf4a87582.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=580d640af0773f75e4ea1f7c2c070b3e\" alt=\"運用環境に反映しました\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F3ae66772-5750-42b3-8e06-9efdf4a87582.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=911c359507b6a480670b1c7e017fd010 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3ae66772-5750-42b3-8e06-9efdf4a87582.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"87:1-87:26\"\u003e\n\u003cspan id=\"7-一覧で編集する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#7-%E4%B8%80%E8%A6%A7%E3%81%A7%E7%B7%A8%E9%9B%86%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e7. 一覧で編集する\u003c/h1\u003e\n\u003cp data-sourcepos=\"89:1-89:152\"\u003e一覧画面のヘッダーの［一覧編集］を押すと、表に切り替わります。もう一度押すと、kintone の一覧に戻ります。\u003c/p\u003e\n\u003cp data-sourcepos=\"91:1-91:160\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F84c2b714-7c76-49c6-b420-ff8e5058c512.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=b9283266265df2c7ddcb98f26c690d35\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F84c2b714-7c76-49c6-b420-ff8e5058c512.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=b9283266265df2c7ddcb98f26c690d35\" alt=\"一覧画面のヘッダーの［一覧編集］\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F84c2b714-7c76-49c6-b420-ff8e5058c512.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=d48a0a6a1afe9c8de140f63c19e9484f 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/84c2b714-7c76-49c6-b420-ff8e5058c512.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"93:1-93:54\"\u003e編集できるセルは薄い色で表示します。\u003c/p\u003e\n\u003cp data-sourcepos=\"95:1-95:130\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F48f4895f-be4b-48f1-bfd4-3c0d670b2941.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=6e3c0845312f4c78c3478f9816950659\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F48f4895f-be4b-48f1-bfd4-3c0d670b2941.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=6e3c0845312f4c78c3478f9816950659\" alt=\"一覧編集の表\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F48f4895f-be4b-48f1-bfd4-3c0d670b2941.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=43a0afaeb39bb5f0da3c0dd83f799801 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/48f4895f-be4b-48f1-bfd4-3c0d670b2941.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"97:1-97:135\"\u003eセルをダブルクリック（または Enter）すると編集を始めます。ドロップダウンは候補から選びます。\u003c/p\u003e\n\u003cp data-sourcepos=\"99:1-99:172\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb5d683f7-77f6-46c4-a3d7-cfedf4c6a1c3.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=c8eec3b6e25cd072abde8e34bb689905\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb5d683f7-77f6-46c4-a3d7-cfedf4c6a1c3.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=c8eec3b6e25cd072abde8e34bb689905\" alt=\"ドロップダウンのセルを編集しているところ\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb5d683f7-77f6-46c4-a3d7-cfedf4c6a1c3.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=d6a4aa1ff00fae3195491fcfa92ac3e9 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/b5d683f7-77f6-46c4-a3d7-cfedf4c6a1c3.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"101:1-101:124\"\u003e確定すると、行の左端に ● が付きます。少し待つと保存して ✓ になります（自動保存）。\u003c/p\u003e\n\u003cp data-sourcepos=\"103:1-103:156\"\u003e※自動保存では、セルを確定すると kintone のレコードに保存されます。初めは試験用のレコードで試してください。\u003c/p\u003e\n\u003cp data-sourcepos=\"105:1-105:155\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fbcc13040-f701-416b-9d7c-febd42af7721.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=94a03bfb2cca49cef664379d7f46f244\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fbcc13040-f701-416b-9d7c-febd42af7721.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=94a03bfb2cca49cef664379d7f46f244\" alt=\"確定した直後（● は保存の前）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fbcc13040-f701-416b-9d7c-febd42af7721.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=3b8f0961d5bc4417d3a8c187d5a6e446 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/bcc13040-f701-416b-9d7c-febd42af7721.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"107:1-107:136\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F95861a10-ccb2-49bf-9a55-703a651cb0dd.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=c624a092e1e926bb1b31e6a2d3392d83\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F95861a10-ccb2-49bf-9a55-703a651cb0dd.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=c624a092e1e926bb1b31e6a2d3392d83\" alt=\"保存した後（✓）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F95861a10-ccb2-49bf-9a55-703a651cb0dd.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=5a613a5ae5e22f0554292c692f95239e 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/95861a10-ccb2-49bf-9a55-703a651cb0dd.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"109:1-109:201\"\u003eテーブルのある行は、左端の ▸ でテーブルを開きます。子行も同じように編集でき、↑ ↓ ＋ 複製 × で行を並べ替え・追加・複製・削除できます。\u003c/p\u003e\n\u003cp data-sourcepos=\"111:1-111:163\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fa5e29d7c-9d6a-4034-8c51-431344cb4c97.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=a25effd1e3e9c8c53229d599edff7c46\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fa5e29d7c-9d6a-4034-8c51-431344cb4c97.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=a25effd1e3e9c8c53229d599edff7c46\" alt=\"テーブル（対応詳細）を開いたところ\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fa5e29d7c-9d6a-4034-8c51-431344cb4c97.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=13f1e3d80c6b755ffbc27c8dda1df985 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a5e29d7c-9d6a-4034-8c51-431344cb4c97.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"113:1-113:81\"\u003eほかの一覧（未対応一覧）でも、同じように編集できます。\u003c/p\u003e\n\u003cp data-sourcepos=\"115:1-115:148\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5259a891-f968-4df7-adbf-67d32c4249ff.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=35aaf6a0ff6cb0adb1c3ebbe1c097d1d\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5259a891-f968-4df7-adbf-67d32c4249ff.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=35aaf6a0ff6cb0adb1c3ebbe1c097d1d\" alt=\"未対応一覧でも編集できる\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5259a891-f968-4df7-adbf-67d32c4249ff.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=2f55e12e91b2fa9554cf4aef808b6114 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5259a891-f968-4df7-adbf-67d32c4249ff.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"117:1-117:8\"\u003e\n\u003cspan id=\"次に\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%AC%A1%E3%81%AB\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e次に\u003c/h1\u003e\n\u003cul data-sourcepos=\"119:1-122:179\"\u003e\n\u003cli data-sourcepos=\"119:1-119:294\"\u003e複数の人で同じアプリを編集するときの動き（ほかの人が先に更新したレコード）は、「\u003ca href=\"https://qiita.com/rex0220/items/d334c123f22e27e09065\" id=\"reference-8c4c7c8e3dd1f0101443\"\u003erex0220 一覧編集プラグイン - 排他制御編（ほかの人が先に更新したとき）\u003c/a\u003e」にあります\u003c/li\u003e\n\u003cli data-sourcepos=\"120:1-120:162\"\u003eコピー・貼り付け（Excel と同じタブ区切り）、範囲を Delete で空にする、Ctrl+D で下へ埋める、Ctrl+Z で戻す、も使えます\u003c/li\u003e\n\u003cli data-sourcepos=\"121:1-121:261\"\u003e行の追加・削除、選択行の複写、追加行の初期値、表示する項目、計算式プラグインとの連携などは、「\u003ca href=\"https://qiita.com/rex0220/items/ad4705f630e97c605f54\"\u003erex0220 一覧編集プラグイン\u003c/a\u003e」の記事にあります\u003c/li\u003e\n\u003cli data-sourcepos=\"122:1-122:179\"\u003e削除したレコードは元に戻せません。アクセス権は一覧編集では確かめず、権限の無い変更は保存のときに kintone がエラーにします\u003c/li\u003e\n\u003c/ul\u003e\n","body":"kintone の一覧画面のレコードを、表のまま編集できるようにするプラグインです。\nこの記事では、プラグインをアプリに追加して、全部の一覧で全部の項目を編集できるようにするまでを、順に説明します。\n\n機能の詳しい説明は「[rex0220 一覧編集プラグイン](https://qiita.com/rex0220/items/ad4705f630e97c605f54)」の記事にあります。\n\n例のアプリは、kintone のサンプルアプリ「問合せ管理（顧客サポートパック）」です。一覧は「対応一覧」と「未対応一覧」の 2 つです。\n\n# 設定の流れ\n\n1. アプリにプラグインを追加する\n2. プラグインの設定を開く\n3. 保存方式を自動保存にする\n4. 1 つの一覧で、編集する項目を全部選ぶ\n5. ほかの一覧に設定をコピーする\n6. 保存して運用環境に反映する\n7. 一覧で編集する\n\n前もって、プラグインの zip を「kintone システム管理 \u003e プラグイン」で読み込んでおきます（kintone のシステム管理の権限が要ります）。\n\n# 1. アプリにプラグインを追加する\n\n「アプリの設定 \u003e プラグイン」で［追加する］を押します。\n\n![アプリの設定のプラグイン（まだ何も追加していない）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5a698975-af8b-4458-a158-f392ea02f814.png)\n\n「一覧編集」にチェックを入れて、右下の［追加］を押します。\n\n![プラグインの追加（一覧編集にチェック）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/39bc827e-60bd-4bdd-bf5b-f8f82994dbef.png)\n\nプラグインの一覧に「一覧編集」が出ます。「必須項目が設定されていません」は、まだ設定していないためです。\n\n# 2. プラグインの設定を開く\n\n「一覧編集」の行の歯車を押すと、設定画面が開きます。\n\n![追加した一覧編集（歯車で設定画面へ）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a7b929b3-ee77-4cc8-86eb-4f890a7a083d.png)\n\nアプリの一覧が並びます。「（すべて）」は kintone の全件の一覧です。\n\n![設定画面を開いたところ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4cb53063-da91-4655-995a-9ed050518de2.png)\n\n# 3. 保存方式を自動保存にする\n\nツールバーの［詳細設定］を押し、保存方式の「自動保存」を選びます（初めから自動保存です）。［保存］で設定画面に戻ります。\n\n- 自動保存: セルを確定して少し待つと、その行を保存します\n- 明示保存: 一覧画面の［保存］を押したときに、変更をまとめて保存します\n\n![詳細設定（保存方式は自動保存）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/9172a1f8-0387-4a5f-a6b2-3793577ff03c.png)\n\n# 4. 1 つの一覧で、編集する項目を全部選ぶ\n\n「対応一覧」の行の「編集を許可する項目」のセルを押します。見出しのチェックで全部の項目を選び、［保存］を押します。\n\n- テーブルの子の項目（対応詳細の対応日時など）も選べます\n- 計算、ルックアップのコピー先、レコード番号などは、編集できないので候補に出ません\n- アクセス権は一覧編集では確かめません。権限の無いレコード・項目の変更は、保存のときに kintone がエラーにします\n\n![編集を許可する項目（見出しのチェックで全部）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c727e76d-a96a-44dd-bc7b-74c548719cf6.png)\n\n「対応一覧」の左端のチェックを入れます。左端のチェックは、プラグインを使う一覧の印です。\n\n![対応一覧だけ設定したところ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/eff0a7fe-631e-461e-82b3-9f915127eea0.png)\n\n# 5. ほかの一覧に設定をコピーする\n\nツールバーの［一覧の設定をコピー］を押します。\n\n- コピー元の一覧: 「対応一覧」（最後に押した行が初めに選ばれています）\n- 写す設定: 初めは全部です\n- コピー先の一覧: 「すべて」をチェックします\n\n「コピー先の一覧で使う（左端のチェック）」がチェックされているので、コピー先の左端のチェックも付きます。［コピー］を押します。\n\n![一覧の設定をコピー（コピー先はすべて）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/e80dfc0e-7fe5-49ef-98cc-b9db464b70b9.png)\n\n全部の一覧に、同じ「編集を許可する項目」が入り、左端のチェックも付きました。\n\n# 6. 保存して運用環境に反映する\n\n画面の下の「運用環境に反映」にチェックを入れて、［保存する］を押します。確かめる画面で［保存する］を押すと、アプリに反映されます。\n\n![全部の一覧を設定したところ（運用環境に反映にチェック）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3af59049-4e37-4d08-b840-bd2d21661781.png)\n\n![運用環境に反映しました](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3ae66772-5750-42b3-8e06-9efdf4a87582.png)\n\n# 7. 一覧で編集する\n\n一覧画面のヘッダーの［一覧編集］を押すと、表に切り替わります。もう一度押すと、kintone の一覧に戻ります。\n\n![一覧画面のヘッダーの［一覧編集］](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/84c2b714-7c76-49c6-b420-ff8e5058c512.png)\n\n編集できるセルは薄い色で表示します。\n\n![一覧編集の表](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/48f4895f-be4b-48f1-bfd4-3c0d670b2941.png)\n\nセルをダブルクリック（または Enter）すると編集を始めます。ドロップダウンは候補から選びます。\n\n![ドロップダウンのセルを編集しているところ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/b5d683f7-77f6-46c4-a3d7-cfedf4c6a1c3.png)\n\n確定すると、行の左端に ● が付きます。少し待つと保存して ✓ になります（自動保存）。\n\n※自動保存では、セルを確定すると kintone のレコードに保存されます。初めは試験用のレコードで試してください。\n\n![確定した直後（● は保存の前）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/bcc13040-f701-416b-9d7c-febd42af7721.png)\n\n![保存した後（✓）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/95861a10-ccb2-49bf-9a55-703a651cb0dd.png)\n\nテーブルのある行は、左端の ▸ でテーブルを開きます。子行も同じように編集でき、↑ ↓ ＋ 複製 × で行を並べ替え・追加・複製・削除できます。\n\n![テーブル（対応詳細）を開いたところ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a5e29d7c-9d6a-4034-8c51-431344cb4c97.png)\n\nほかの一覧（未対応一覧）でも、同じように編集できます。\n\n![未対応一覧でも編集できる](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5259a891-f968-4df7-adbf-67d32c4249ff.png)\n\n# 次に\n\n- 複数の人で同じアプリを編集するときの動き（ほかの人が先に更新したレコード）は、「[rex0220 一覧編集プラグイン - 排他制御編（ほかの人が先に更新したとき）](https://qiita.com/rex0220/items/d334c123f22e27e09065)」にあります\n- コピー・貼り付け（Excel と同じタブ区切り）、範囲を Delete で空にする、Ctrl+D で下へ埋める、Ctrl+Z で戻す、も使えます\n- 行の追加・削除、選択行の複写、追加行の初期値、表示する項目、計算式プラグインとの連携などは、「[rex0220 一覧編集プラグイン](https://qiita.com/rex0220/items/ad4705f630e97c605f54)」の記事にあります\n- 削除したレコードは元に戻せません。アクセス権は一覧編集では確かめず、権限の無い変更は保存のときに kintone がエラーにします\n","coediting":false,"comments_count":0,"created_at":"2026-10-26T08:41:05+09:00","group":null,"id":"ad08bb138a052c6bdff7","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]}],"title":"rex0220 一覧編集プラグイン - 導入編（追加から編集まで）","updated_at":"2026-10-26T12:34:15+09:00","url":"https://qiita.com/rex0220/items/ad08bb138a052c6bdff7","user":{"description":"","facebook_id":"","followees_count":0,"followers_count":155,"github_login_name":"rex0220","id":"rex0220","items_count":756,"linkedin_id":"","location":"","name":"","organization":"","permanent_id":100572,"profile_image_url":"https://qiita-image-store.s3.amazonaws.com/0/100572/profile-images/1473708137","team_only":false,"twitter_screen_name":"rex02201","website_url":"https://rex0220.stores.jp/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:191\"\u003ekintone アプリの一覧編集プラグインです。一覧画面のレコードをグリッドに表示し、セルの編集、行の追加・削除をして kintone に保存します。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:286\"\u003eプラグインの追加から、一覧で編集するまでの手順は「\u003ca href=\"https://qiita.com/rex0220/items/ad08bb138a052c6bdff7\" id=\"reference-51613eb421a9f107d414\"\u003erex0220 一覧編集プラグイン - 導入編（追加から編集まで）\u003c/a\u003e」にあります。この記事は、機能ごとの詳しい説明です。\u003c/p\u003e\n\u003cp data-sourcepos=\"5:1-5:12\"\u003e主な機能\u003c/p\u003e\n\u003cul data-sourcepos=\"7:1-11:0\"\u003e\n\u003cli data-sourcepos=\"7:1-7:193\"\u003e複数のレコードをまとめて編集: 範囲の選択、Excel と同じタブ区切りのコピー・貼り付け、Delete で空にする、Ctrl+D で下へ埋める、Ctrl+Z で戻す\u003c/li\u003e\n\u003cli data-sourcepos=\"8:1-8:160\"\u003eテーブルの子行も一覧の中で編集: 行の展開部に子のグリッドを出し、子行の編集・追加・並べ替え・削除ができます\u003c/li\u003e\n\u003cli data-sourcepos=\"9:1-9:158\"\u003e自動保存と明示保存を選べます。ほかの人が先に更新したレコードは上書きせず、最新の値の取り込み方を選べます\u003c/li\u003e\n\u003cli data-sourcepos=\"10:1-11:0\"\u003e計算式プラグインと連携: 一覧で編集したときも、詳細画面と同じ式で計算して保存します\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"12:1-12:15\"\u003e使い方の例\u003c/p\u003e\n\u003cul data-sourcepos=\"14:1-18:0\"\u003e\n\u003cli data-sourcepos=\"14:1-14:68\"\u003e商品マスターの価格や区分を、一覧で並べて直す\u003c/li\u003e\n\u003cli data-sourcepos=\"15:1-15:74\"\u003e案件の一覧で、期日や進捗の項目をまとめて更新する\u003c/li\u003e\n\u003cli data-sourcepos=\"16:1-16:104\"\u003e受注レコードの明細（テーブル）の数量や単価を、詳細画面を開かずに直す\u003c/li\u003e\n\u003cli data-sourcepos=\"17:1-18:0\"\u003eExcel の表の値を、範囲を選んで貼り付ける\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"19:1-19:33\"\u003e※動作環境は、PC です。\u003c/p\u003e\n\u003cp data-sourcepos=\"21:1-21:22\"\u003e※ Ver.1（2026/10）\u003c/p\u003e\n\u003cul data-sourcepos=\"22:1-23:0\"\u003e\n\u003cli data-sourcepos=\"22:1-23:0\"\u003e初版\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 data-sourcepos=\"24:1-24:41\"\u003e\n\u003cspan id=\"文字検索プラグインとの関係\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%96%87%E5%AD%97%E6%A4%9C%E7%B4%A2%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%A8%E3%81%AE%E9%96%A2%E4%BF%82\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e文字検索プラグインとの関係\u003c/h1\u003e\n\u003cp data-sourcepos=\"26:1-26:153\"\u003e文字検索プラグインとは別の製品です。文字検索は閲覧用（編集の機能はありません）、一覧編集は編集用です。\u003c/p\u003e\n\u003cul data-sourcepos=\"28:1-30:0\"\u003e\n\u003cli data-sourcepos=\"28:1-28:95\"\u003e検索欄の書き方は文字検索と同じです（「検索文字の書き方」参照）\u003c/li\u003e\n\u003cli data-sourcepos=\"29:1-30:0\"\u003e同じ一覧を両方のプラグインの設定で選ぶと、画面の部品が重なります。別々の一覧を選んでください\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 data-sourcepos=\"31:1-31:26\"\u003e\n\u003cspan id=\"一覧編集の表示例\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%B8%80%E8%A6%A7%E7%B7%A8%E9%9B%86%E3%81%AE%E8%A1%A8%E7%A4%BA%E4%BE%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e一覧編集の表示例\u003c/h1\u003e\n\u003cul data-sourcepos=\"33:1-37:0\"\u003e\n\u003cli data-sourcepos=\"33:1-33:116\"\u003eプラグイン設定で「初期表示」にした一覧は、開いた直後からグリッドを表示します\u003c/li\u003e\n\u003cli data-sourcepos=\"34:1-34:167\"\u003eそれ以外の一覧は、ヘッダーの［一覧編集］を押すとグリッドに切り替わります。もう一度押すと kintone の一覧に戻ります\u003c/li\u003e\n\u003cli data-sourcepos=\"35:1-35:173\"\u003e絞り込みと並び順は kintone の一覧の条件を使います。取得するレコード数の上限は、ツールバーの「取得件数」で変えられます\u003c/li\u003e\n\u003cli data-sourcepos=\"36:1-37:0\"\u003e編集できるセルは薄い色で表示します。どの項目を編集できるかは、プラグイン設定の「編集を許可する項目」で決まります（アクセス権は「権限」参照）\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"38:1-38:162\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb8c0544c-7597-4c08-825e-711d4eaa1759.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=7e2f23d8b6392a06c443933a5f95781d\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb8c0544c-7597-4c08-825e-711d4eaa1759.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=7e2f23d8b6392a06c443933a5f95781d\" alt=\"一覧画面 — ヘッダーの［一覧編集］\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb8c0544c-7597-4c08-825e-711d4eaa1759.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=b8b042ad4b8f72cc1e8c0a46fa42a3e9 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/b8c0544c-7597-4c08-825e-711d4eaa1759.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"40:1-40:202\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Faaf67166-b50e-4628-b6f7-6fbdf7a0e492.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=5a8ccd206bf466d8c4246fd4907ff6f8\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Faaf67166-b50e-4628-b6f7-6fbdf7a0e492.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=5a8ccd206bf466d8c4246fd4907ff6f8\" alt=\"一覧編集の画面（タイトル行、ツールバー、編集できるセルの色）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Faaf67166-b50e-4628-b6f7-6fbdf7a0e492.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=22098dc6acfaad99dfd4e02845ff990a 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/aaf67166-b50e-4628-b6f7-6fbdf7a0e492.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"42:1-42:17\"\u003e\n\u003cspan id=\"セルの編集\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%82%BB%E3%83%AB%E3%81%AE%E7%B7%A8%E9%9B%86\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eセルの編集\u003c/h1\u003e\n\u003ctable data-sourcepos=\"44:1-53:188\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"44:1-44:19\"\u003e\n\u003cth data-sourcepos=\"44:2-44:9\"\u003e操作\u003c/th\u003e\n\u003cth data-sourcepos=\"44:11-44:18\"\u003e動き\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"46:1-46:61\"\u003e\n\u003ctd data-sourcepos=\"46:2-46:15\"\u003eクリック\u003c/td\u003e\n\u003ctd data-sourcepos=\"46:17-46:60\"\u003eセルを選ぶ（編集は始めない）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"47:1-47:113\"\u003e\n\u003ctd data-sourcepos=\"47:2-47:52\"\u003eダブルクリック / Enter / F2 / 文字キー\u003c/td\u003e\n\u003ctd data-sourcepos=\"47:54-47:112\"\u003e編集を始める（文字キーはその文字から）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"48:1-48:39\"\u003e\n\u003ctd data-sourcepos=\"48:2-48:14\"\u003eEnter / Esc\u003c/td\u003e\n\u003ctd data-sourcepos=\"48:16-48:38\"\u003e確定 / 取り消し\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"49:1-49:110\"\u003e\n\u003ctd data-sourcepos=\"49:2-49:31\"\u003eTab / ↑ ↓（編集中）\u003c/td\u003e\n\u003ctd data-sourcepos=\"49:33-49:109\"\u003e確定して隣のセルへ移る（移った先の編集は始めない）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"50:1-50:337\"\u003e\n\u003ctd data-sourcepos=\"50:2-50:27\"\u003e日付・日時のセル\u003c/td\u003e\n\u003ctd data-sourcepos=\"50:29-50:336\"\u003e表示と同じ 2026-10-24（日時は 2026-10-24 09:30）で入力する。2026/10/24 も読む。右のボタンか Alt+↓（Mac は Option+↓）でカレンダー（見出しの年・月を押すと年・月を選べる。矢印で日、PageUp / PageDown で月、Enter で選ぶ、Esc で閉じる）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"51:1-51:206\"\u003e\n\u003ctd data-sourcepos=\"51:2-51:27\"\u003e日時のカレンダー\u003c/td\u003e\n\u003ctd data-sourcepos=\"51:29-51:205\"\u003e日を押すと時・分の表に進み、分を押すと時刻も入って確定する。下端の時刻のボタンで時刻だけ選べる。Esc で一つ前の表に戻る\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"52:1-52:214\"\u003e\n\u003ctd data-sourcepos=\"52:2-52:18\"\u003e時刻のセル\u003c/td\u003e\n\u003ctd data-sourcepos=\"52:20-52:213\"\u003e表示と同じ 09:30 で入力する（9:30 も読む）。右の時計のボタンか Alt+↓ で時・分の表（分を押すと確定。「現在」で今の時刻、「削除」で空）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"53:1-53:188\"\u003e\n\u003ctd data-sourcepos=\"53:2-53:28\"\u003e分の表の 1分 / 15分\u003c/td\u003e\n\u003ctd data-sourcepos=\"53:30-53:187\"\u003e分の刻みを切り替える（このブラウザーに記憶し、ほかの時刻・日時のセルも同じ刻み）。刻みに無い分は欄に入力\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cul data-sourcepos=\"55:1-58:0\"\u003e\n\u003cli data-sourcepos=\"55:1-55:287\"\u003e編集できる項目: 文字列（1行・複数行）、数値、日付・時刻・日時、ドロップダウン、ラジオボタン、チェックボックス、複数選択、ユーザー・組織・グループ選択、リンク、ルックアップ、テーブルの子の項目\u003c/li\u003e\n\u003cli data-sourcepos=\"56:1-56:204\"\u003e計算、ルックアップのコピー先、「自動計算する」を設定した文字列（1行）、リッチエディター、レコード番号、作成者・更新者などは表示のみです\u003c/li\u003e\n\u003cli data-sourcepos=\"57:1-58:0\"\u003e「$id」欄のレコード番号を押すと、詳細画面を新しいタブで開きます\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"59:1-59:159\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F352d6ae6-4114-44ae-bbd4-e7d6aeb6aecf.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=82aa2ecc13e48a8d258270de3dcdbbb3\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F352d6ae6-4114-44ae-bbd4-e7d6aeb6aecf.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=82aa2ecc13e48a8d258270de3dcdbbb3\" alt=\"日付のセルの編集中 — カレンダー\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F352d6ae6-4114-44ae-bbd4-e7d6aeb6aecf.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=e25db3e5c95495c2867278e125df44f5 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/352d6ae6-4114-44ae-bbd4-e7d6aeb6aecf.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"61:1-61:165\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fda5fcf41-38cc-44b6-a720-987508d522df.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=63620ee69e29741c686616f178a13bc3\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fda5fcf41-38cc-44b6-a720-987508d522df.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=63620ee69e29741c686616f178a13bc3\" alt=\"ドロップダウンのセルの編集中 — 候補\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fda5fcf41-38cc-44b6-a720-987508d522df.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=7460ab93307880898ca449d1d63cd4ab 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/da5fcf41-38cc-44b6-a720-987508d522df.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 data-sourcepos=\"63:1-63:33\"\u003e\n\u003cspan id=\"範囲とクリップボード\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%AF%84%E5%9B%B2%E3%81%A8%E3%82%AF%E3%83%AA%E3%83%83%E3%83%97%E3%83%9C%E3%83%BC%E3%83%89\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e範囲とクリップボード\u003c/h2\u003e\n\u003ctable data-sourcepos=\"65:1-72:80\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"65:1-65:19\"\u003e\n\u003cth data-sourcepos=\"65:2-65:9\"\u003e操作\u003c/th\u003e\n\u003cth data-sourcepos=\"65:11-65:18\"\u003e動き\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"67:1-67:70\"\u003e\n\u003ctd data-sourcepos=\"67:2-67:51\"\u003eドラッグ / Shift+クリック / Shift+矢印\u003c/td\u003e\n\u003ctd data-sourcepos=\"67:53-67:69\"\u003e範囲を選ぶ\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"68:1-68:55\"\u003e\n\u003ctd data-sourcepos=\"68:2-68:9\"\u003eCtrl+A\u003c/td\u003e\n\u003ctd data-sourcepos=\"68:11-68:54\"\u003e表に出ている全部のセルを選ぶ\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"69:1-69:225\"\u003e\n\u003ctd data-sourcepos=\"69:2-69:18\"\u003eCtrl+C / Ctrl+V\u003c/td\u003e\n\u003ctd data-sourcepos=\"69:20-69:224\"\u003e範囲をコピー / 貼り付け（Excel と同じタブ区切り）。1 つのセルのコピーは選んだ範囲の全部に入る（範囲がコピーの行数・列数の倍数なら繰り返す）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"70:1-70:43\"\u003e\n\u003ctd data-sourcepos=\"70:2-70:9\"\u003eDelete\u003c/td\u003e\n\u003ctd data-sourcepos=\"70:11-70:42\"\u003e範囲のセルを空にする\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"71:1-71:58\"\u003e\n\u003ctd data-sourcepos=\"71:2-71:9\"\u003eCtrl+D\u003c/td\u003e\n\u003ctd data-sourcepos=\"71:11-71:57\"\u003e範囲の先頭の行の値で下を埋める\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"72:1-72:80\"\u003e\n\u003ctd data-sourcepos=\"72:2-72:9\"\u003eCtrl+Z\u003c/td\u003e\n\u003ctd data-sourcepos=\"72:11-72:79\"\u003eその行の直前の変更を戻す（行ごとに 10 回まで）\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cul data-sourcepos=\"74:1-77:0\"\u003e\n\u003cli data-sourcepos=\"74:1-74:53\"\u003eMac では Ctrl の代わりに ⌘ を使います\u003c/li\u003e\n\u003cli data-sourcepos=\"75:1-75:173\"\u003e貼り付けで、変換できない値（日付でない文字、選択肢に無い値など）が 1 つでもあれば何も書かず、理由を一覧で表示します\u003c/li\u003e\n\u003cli data-sourcepos=\"76:1-77:0\"\u003e編集できないセルは飛ばします\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"78:1-78:196\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5fd924af-e628-4e0c-8408-b8d85b65f540.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=a01e2e74b2de5c228d4e715be4c0501d\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5fd924af-e628-4e0c-8408-b8d85b65f540.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=a01e2e74b2de5c228d4e715be4c0501d\" alt=\"貼り付けで変換できなかったときの一覧（何も書き込まない）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F5fd924af-e628-4e0c-8408-b8d85b65f540.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=5f32fe4ba9487ccf26302eec09e9430d 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5fd924af-e628-4e0c-8408-b8d85b65f540.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 data-sourcepos=\"80:1-80:21\"\u003e\n\u003cspan id=\"ルックアップ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%AB%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eルックアップ\u003c/h2\u003e\n\u003cul data-sourcepos=\"82:1-87:0\"\u003e\n\u003cli data-sourcepos=\"82:1-82:187\"\u003eルックアップのセルの編集を始めると、取得画面が開きます。表示する列と絞り込み・並び順は、kintone のルックアップの設定に従います\u003c/li\u003e\n\u003cli data-sourcepos=\"83:1-83:134\"\u003e選ぶと、コピー先の項目に仮の値を表示します。保存した後に kintone が入れた値で表示し直します\u003c/li\u003e\n\u003cli data-sourcepos=\"84:1-84:146\"\u003eREST API の制限で、参照先のキーの項目が重複禁止（またはレコード番号）のルックアップだけ編集できます\u003c/li\u003e\n\u003cli data-sourcepos=\"85:1-85:455\"\u003e取得画面の検索欄をダブルクリック（または ↓ キー）すると、直近 20 件の検索文字と、名前を付けて保存した検索条件（★）を選べます。検索欄の右の ☆ で、いまの検索文字に名前を付けて保存します（最大 20 件）。履歴と保存した条件は、このアプリで同じアプリを参照するルックアップと共有し、このブラウザーにだけ残ります\u003c/li\u003e\n\u003cli data-sourcepos=\"86:1-87:0\"\u003e検索の行の右端のツールのアイコンで、取得件数の切り替え、列の状態を初期化、表示する項目を出します。手で変えた列幅・並び・表示する項目は、ルックアップの項目ごとにブラウザーに記憶します\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"88:1-88:186\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fba77a8e5-37fb-4956-84c2-d4b7203b5b42.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=6e7febd17f8cecef34dcfd761b6011a6\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fba77a8e5-37fb-4956-84c2-d4b7203b5b42.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=6e7febd17f8cecef34dcfd761b6011a6\" alt=\"ルックアップの取得画面 — 検索欄の履歴とツールバー\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fba77a8e5-37fb-4956-84c2-d4b7203b5b42.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=7e5312f49cb1616c86813dd5928a0dd0 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ba77a8e5-37fb-4956-84c2-d4b7203b5b42.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"90:1-90:8\"\u003e\n\u003cspan id=\"保存\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BF%9D%E5%AD%98\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e保存\u003c/h1\u003e\n\u003cp data-sourcepos=\"92:1-92:93\"\u003eプラグイン設定の「保存方式」で、自動保存と明示保存を選びます。\u003c/p\u003e\n\u003cul data-sourcepos=\"94:1-98:0\"\u003e\n\u003cli data-sourcepos=\"94:1-94:259\"\u003e自動保存: セルを確定して少し待つと、その行を保存します。保存中にその行を続けて変えると、保存が終わってからもう一度保存します。複数の行への貼り付けは 1 回でまとめて保存します\u003c/li\u003e\n\u003cli data-sourcepos=\"95:1-95:211\"\u003e明示保存: ツールバーの［保存］で、変更をまとめて保存します（設定で、件数を確かめる画面を出せます）。［すべて取り消す］で全部の変更を戻します\u003c/li\u003e\n\u003cli data-sourcepos=\"96:1-96:156\"\u003e検索で隠れている行の変更も保存の対象です（「保存前の確認」が on なら、確かめる画面にその件数も出します）\u003c/li\u003e\n\u003cli data-sourcepos=\"97:1-98:0\"\u003e2,000 件を超える変更は分けて保存します。途中で失敗すると、それより前の回の分だけが保存されます\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"99:1-99:12\"\u003e左端の印\u003c/p\u003e\n\u003ctable data-sourcepos=\"101:1-109:21\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"101:1-101:16\"\u003e\n\u003cth data-sourcepos=\"101:2-101:6\"\u003e印\u003c/th\u003e\n\u003cth data-sourcepos=\"101:8-101:15\"\u003e意味\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"103:1-103:22\"\u003e\n\u003ctd data-sourcepos=\"103:2-103:6\"\u003e●\u003c/td\u003e\n\u003ctd data-sourcepos=\"103:8-103:21\"\u003e変更あり\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"104:1-104:19\"\u003e\n\u003ctd data-sourcepos=\"104:2-104:6\"\u003e⟳\u003c/td\u003e\n\u003ctd data-sourcepos=\"104:8-104:18\"\u003e保存中\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"105:1-105:22\"\u003e\n\u003ctd data-sourcepos=\"105:2-105:6\"\u003e✓\u003c/td\u003e\n\u003ctd data-sourcepos=\"105:8-105:21\"\u003e保存した\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"106:1-106:68\"\u003e\n\u003ctd data-sourcepos=\"106:2-106:4\"\u003e!\u003c/td\u003e\n\u003ctd data-sourcepos=\"106:6-106:67\"\u003e保存できなかった（セルは赤枠。印に理由）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"107:1-107:43\"\u003e\n\u003ctd data-sourcepos=\"107:2-107:6\"\u003e⇄\u003c/td\u003e\n\u003ctd data-sourcepos=\"107:8-107:42\"\u003eほかの人が先に更新した\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"108:1-108:25\"\u003e\n\u003ctd data-sourcepos=\"108:2-108:6\"\u003e＋\u003c/td\u003e\n\u003ctd data-sourcepos=\"108:8-108:24\"\u003e追加した行\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"109:1-109:21\"\u003e\n\u003ctd data-sourcepos=\"109:2-109:5\"\u003e×\u003c/td\u003e\n\u003ctd data-sourcepos=\"109:7-109:20\"\u003e削除の印\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cul data-sourcepos=\"111:1-114:0\"\u003e\n\u003cli data-sourcepos=\"111:1-111:101\"\u003e● ! を押すと、その行の変更を取り消して、取得したときの値に戻します\u003c/li\u003e\n\u003cli data-sourcepos=\"112:1-112:131\"\u003e自動保存で保存できなかった行は、フッターの［未保存 n 件を保存］でまとめて保存し直せます\u003c/li\u003e\n\u003cli data-sourcepos=\"113:1-114:0\"\u003e保存していない変更があるときに、ページを離れる・一覧に戻す・取得件数を変える・再読込のアイコンを押すと確かめます\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"115:1-115:180\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F1381212e-9e80-4995-b84b-e4816fd53245.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=66413a16e4462ec64421e602cf68f6c0\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F1381212e-9e80-4995-b84b-e4816fd53245.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=66413a16e4462ec64421e602cf68f6c0\" alt=\"保存できなかったセル — 赤枠と ! の印、下に理由\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F1381212e-9e80-4995-b84b-e4816fd53245.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=711cbf80848fee5ba3a311b12e0e4bf1 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/1381212e-9e80-4995-b84b-e4816fd53245.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 data-sourcepos=\"117:1-117:42\"\u003e\n\u003cspan id=\"ほかの人が先に更新したとき\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%BB%E3%81%8B%E3%81%AE%E4%BA%BA%E3%81%8C%E5%85%88%E3%81%AB%E6%9B%B4%E6%96%B0%E3%81%97%E3%81%9F%E3%81%A8%E3%81%8D\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eほかの人が先に更新したとき\u003c/h2\u003e\n\u003cp data-sourcepos=\"119:1-119:201\"\u003e取得した後にほかの人がレコードを更新していると、そのレコードは保存せず ⇄ の印を付けます。⇄ を押すと、最新の値の取り込み方を選べます。\u003c/p\u003e\n\u003cul data-sourcepos=\"121:1-123:0\"\u003e\n\u003cli data-sourcepos=\"121:1-121:62\"\u003e最新の値を取り込む（自分の変更を捨てる）\u003c/li\u003e\n\u003cli data-sourcepos=\"122:1-123:0\"\u003e自分の変更を残して、ほかの項目を最新にする: 自分が変えた項目は、ほかの人が同じ項目を変えていても自分の値で保存し直します。テーブルを変えていれば、子行を含めてテーブル全体が自分の値になります\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"124:1-124:187\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fac2665aa-345d-4830-9b0e-8394930a497d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=6d3f21aba5e134ad4e392dc28050133d\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fac2665aa-345d-4830-9b0e-8394930a497d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=6d3f21aba5e134ad4e392dc28050133d\" alt=\"⇄ を押したときの画面 — 最新の値の取り込み方を選ぶ\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fac2665aa-345d-4830-9b0e-8394930a497d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=ab483ad0264bbdadc279cd3c457ac5fe 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ac2665aa-345d-4830-9b0e-8394930a497d.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"126:1-126:23\"\u003e\n\u003cspan id=\"行の追加と削除\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A1%8C%E3%81%AE%E8%BF%BD%E5%8A%A0%E3%81%A8%E5%89%8A%E9%99%A4\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e行の追加と削除\u003c/h1\u003e\n\u003cp data-sourcepos=\"128:1-128:84\"\u003eプラグイン設定で一覧ごとに「追加」「削除」を許可します。\u003c/p\u003e\n\u003cul data-sourcepos=\"130:1-136:0\"\u003e\n\u003cli data-sourcepos=\"130:1-130:171\"\u003eタイトル行の ＋（行を追加）で末尾に行を足します。プラグイン設定の「追加行の初期値」と、フォームの初期値が入ります\u003c/li\u003e\n\u003cli data-sourcepos=\"131:1-131:293\"\u003e自動保存の一覧では、［追加を確定 (n)］か行の ＋ を押すと追加行を保存します（それまでは kintone に何も送りません）。［追加を確定 (n)］は確定していない追加行があるときだけタイトル行に出ます（n はその数）\u003c/li\u003e\n\u003cli data-sourcepos=\"132:1-132:401\"\u003e左の列のチェックで行を選び、タイトル行の複写のアイコン（選択行を複写）を押すと、選んだ行を写した新しい行を末尾に足します。写すのはプラグイン設定の「選択行の複写」で選んだ項目だけで、ほかの項目は追加行の初期値です（テーブルは子行ごと写します）。保存は追加行と同じです\u003c/li\u003e\n\u003cli data-sourcepos=\"133:1-133:276\"\u003e左の列のチェックで行を選び、タイトル行のゴミ箱（選択行を削除）を押します。自動保存の一覧はすぐに削除します（確かめる画面が出ます）。明示保存の一覧は × の印を付け、［保存］で削除します\u003c/li\u003e\n\u003cli data-sourcepos=\"134:1-134:50\"\u003e削除したレコードは元に戻せません\u003c/li\u003e\n\u003cli data-sourcepos=\"135:1-136:0\"\u003e＋（行を追加）は、レコードの追加の権限がある利用者にだけ表示します\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"137:1-137:186\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F8005c1d4-1a8f-46ed-8cfe-d01c96618147.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=870d99f6b48e67a962ed28581c163fcf\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F8005c1d4-1a8f-46ed-8cfe-d01c96618147.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=870d99f6b48e67a962ed28581c163fcf\" alt=\"行を追加した状態 — 行の ＋ の印と［追加を確定 (1)］\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F8005c1d4-1a8f-46ed-8cfe-d01c96618147.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=fcceb475abaff3a78894d5e7ceefea7d 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/8005c1d4-1a8f-46ed-8cfe-d01c96618147.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"139:1-139:14\"\u003e\n\u003cspan id=\"テーブル\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eテーブル\u003c/h1\u003e\n\u003cul data-sourcepos=\"141:1-149:0\"\u003e\n\u003cli data-sourcepos=\"141:1-141:219\"\u003eテーブルの列（「n 行」の表示）か、行の左端の ▸ を押すと、行の下にテーブルを開きます。もう一度押すと閉じます。テーブルが複数ならタブで切り替えます\u003c/li\u003e\n\u003cli data-sourcepos=\"142:1-142:111\"\u003e子のセルは、一番上の表と同じ操作で編集できます（範囲・貼り付け・Ctrl+Z も）\u003c/li\u003e\n\u003cli data-sourcepos=\"143:1-143:350\"\u003e子行の右端の ＋ はその行のすぐ下に新しい行（初期値入り）を、複製のアイコンはその行の値を写した行を足します。↑ ↓ で並べ替え、× で削除の印（もう一度押すと外します）。子行が無いテーブルでは、子の表の右端の見出しの ＋ で 1 行目を足します\u003c/li\u003e\n\u003cli data-sourcepos=\"144:1-144:173\"\u003e子の列見出しの右端をドラッグすると列幅を変えられます。一番上の表と同じく、ブラウザーにアプリと一覧ごとに記憶します\u003c/li\u003e\n\u003cli data-sourcepos=\"145:1-145:398\"\u003e展開部の［表示する項目］を押すと、今のテーブルの子の項目のタグの欄が出ます。タグを外すと列を隠し、足すと出し、ドラッグで並びを変えます。初めはプラグイン設定の「テーブルの表示項目」の並びで、変えた状態はブラウザーに記憶し、ツールバーの［列の状態を初期化］で戻ります\u003c/li\u003e\n\u003cli data-sourcepos=\"146:1-146:102\"\u003e子行の変更は親のレコードの変更として保存します（テーブルの列に ●）\u003c/li\u003e\n\u003cli data-sourcepos=\"147:1-147:432\"\u003e表の左上（▸ の列の見出し）の ▸ で、表に出ている行のテーブルを全部開きます（表の並びで先頭から 300 行まで。取得件数とは別です）。開いている間は ▾ になり、押すと全部閉じます。検索や取得し直しの後も開きます。プラグイン設定の「テーブルの全展開」をチェックすると、開いたときに全展開にできます\u003c/li\u003e\n\u003cli data-sourcepos=\"148:1-149:0\"\u003eテーブルの子の項目を「編集を許可する項目」で 1 つでも選ぶと、そのテーブルの子行の追加・並べ替え・削除ができます\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"150:1-150:214\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7bf01882-85a9-43bd-b2fa-e97e60a67106.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=ff521429365513a2477c535fcfdf8544\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7bf01882-85a9-43bd-b2fa-e97e60a67106.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=ff521429365513a2477c535fcfdf8544\" alt=\"テーブルを開いた状態 — タブ、［表示する項目］、子行の ↑ ↓ ＋ 複製 ×\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7bf01882-85a9-43bd-b2fa-e97e60a67106.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=456cf26d4706423e594e012854c7b595 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7bf01882-85a9-43bd-b2fa-e97e60a67106.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"152:1-152:32\"\u003e\n\u003cspan id=\"計算式プラグイン連携\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%88%E7%AE%97%E5%BC%8F%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E9%80%A3%E6%90%BA\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e計算式プラグイン連携\u003c/h1\u003e\n\u003cp data-sourcepos=\"154:1-154:358\"\u003e計算式プラグインが入っているアプリで、プラグイン設定の［詳細設定］の「計算式連携」を on にすると、プラグインを使う一覧で、セルを確定するたびに計算式プラグインの式で計算して画面に入れ、保存します。詳細画面で編集したときと同じ式で計算します。\u003c/p\u003e\n\u003cul data-sourcepos=\"156:1-163:0\"\u003e\n\u003cli data-sourcepos=\"156:1-156:86\"\u003eテーブルの子行を確定したときも、レコード全体で計算します\u003c/li\u003e\n\u003cli data-sourcepos=\"157:1-157:110\"\u003e計算に失敗した行は ! の印を付け、保存しません。入力した値は画面に残ります\u003c/li\u003e\n\u003cli data-sourcepos=\"158:1-158:168\"\u003e計算式連携が on なら、プラグインを使う一覧はどれもレコードを全項目で取得します（式が参照する項目をそろえるため）\u003c/li\u003e\n\u003cli data-sourcepos=\"159:1-159:321\"\u003e計算式プラグインで「編集」を off にした項目は、一覧編集でも編集できません。テーブルを off にしたときは、子行の追加・削除・並べ替え・複製ができません（子の項目の入力はそれぞれの指定どおり。計算式プラグイン Ver.102 以降）\u003c/li\u003e\n\u003cli data-sourcepos=\"160:1-160:92\"\u003eほかの計算する項目を手で入力しても、次の計算で上書きされます\u003c/li\u003e\n\u003cli data-sourcepos=\"161:1-161:410\"\u003e計算式でレコード番号・作成者・作成日時・更新者・更新日時を使うと、保存の前の値で計算します（追加行ではどれも空、更新では前の保存の値）。添付ファイルを足したときの fileKey も、アップロードしたときの一時的な値で計算します。保存で kintone が入れた値は、その保存の計算には入りません\u003c/li\u003e\n\u003cli data-sourcepos=\"162:1-163:0\"\u003eプラグイン設定の［詳細設定］に、このアプリに計算式プラグインが追加されているか（有効 / 無効 / 未追加）を表示します\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"164:1-164:205\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7dc5d265-5ed4-49bf-aede-57e5dbd19430.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=ffb671643804755e3fa3b2a07ff0dc98\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7dc5d265-5ed4-49bf-aede-57e5dbd19430.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=ffb671643804755e3fa3b2a07ff0dc98\" alt=\"計算式連携 — 数値を確定すると計算式の列も変わる（● は保存前）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7dc5d265-5ed4-49bf-aede-57e5dbd19430.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=d3307bde53680f5e6de8f57c820e5eab 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7dc5d265-5ed4-49bf-aede-57e5dbd19430.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"166:1-166:8\"\u003e\n\u003cspan id=\"権限\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%A8%A9%E9%99%90\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e権限\u003c/h1\u003e\n\u003cul data-sourcepos=\"168:1-172:0\"\u003e\n\u003cli data-sourcepos=\"168:1-168:140\"\u003e一覧編集はアクセス権を確かめません（確かめる API の分だけ、kintone の 1 日の API の回数を使うため）\u003c/li\u003e\n\u003cli data-sourcepos=\"169:1-169:188\"\u003e権限の無いレコード・項目の変更や削除は、保存のときに kintone がエラーにします。行に ! の印を付け、セルを赤枠にして理由を出します\u003c/li\u003e\n\u003cli data-sourcepos=\"170:1-170:185\"\u003e貼り付けなどで複数の行をまとめて保存するとき、権限の無い行が 1 行でもあると、その回（2,000 件まで）の保存は全部取り消されます\u003c/li\u003e\n\u003cli data-sourcepos=\"171:1-172:0\"\u003e＋（行を追加）と選択行の複写は、レコードの追加の権限がある利用者にだけ表示します\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 data-sourcepos=\"173:1-173:26\"\u003e\n\u003cspan id=\"検索文字の書き方\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%A4%9C%E7%B4%A2%E6%96%87%E5%AD%97%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e検索文字の書き方\u003c/h1\u003e\n\u003cp data-sourcepos=\"175:1-175:297\"\u003eタイトル行の検索欄では、取得したレコードを画面の上で絞り込みます（kintone への再取得はしません）。書き方は文字検索プラグインと同じで、一覧は右端の「?」で開く操作の説明の「検索の書き方」タブにあります。\u003c/p\u003e\n\u003ctable data-sourcepos=\"177:1-187:59\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"177:1-177:22\"\u003e\n\u003cth data-sourcepos=\"177:2-177:12\"\u003e書き方\u003c/th\u003e\n\u003cth data-sourcepos=\"177:14-177:21\"\u003e意味\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"179:1-179:57\"\u003e\n\u003ctd data-sourcepos=\"179:2-179:6\"\u003eA B\u003c/td\u003e\n\u003ctd data-sourcepos=\"179:8-179:56\"\u003eスペース区切り: すべて含む（AND）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"180:1-180:59\"\u003e\n\u003ctd data-sourcepos=\"180:2-180:9\"\u003eA | B\u003c/td\u003e\n\u003ctd data-sourcepos=\"180:11-180:58\"\u003e| か , 区切り: どれかを含む（OR）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"181:1-181:23\"\u003e\n\u003ctd data-sourcepos=\"181:2-181:7\"\u003e-語\u003c/td\u003e\n\u003ctd data-sourcepos=\"181:9-181:22\"\u003e含まない\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"182:1-182:33\"\u003e\n\u003ctd data-sourcepos=\"182:2-182:8\"\u003e\"A B\"\u003c/td\u003e\n\u003ctd data-sourcepos=\"182:10-182:32\"\u003e語句をそのまま\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"183:1-183:65\"\u003e\n\u003ctd data-sourcepos=\"183:2-183:16\"\u003e分類:飲料\u003c/td\u003e\n\u003ctd data-sourcepos=\"183:18-183:64\"\u003e列名を付けてその列だけ（文字）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"184:1-184:62\"\u003e\n\u003ctd data-sourcepos=\"184:2-184:13\"\u003e=400 !=400\u003c/td\u003e\n\u003ctd data-sourcepos=\"184:15-184:61\"\u003e数値・日付が等しい / 等しくない\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"185:1-185:52\"\u003e\n\u003ctd data-sourcepos=\"185:2-185:24\"\u003e\u0026gt;300 \u0026gt;=300 \u0026lt;300 \u0026lt;=300\u003c/td\u003e\n\u003ctd data-sourcepos=\"185:26-185:51\"\u003e数値・日付の大小\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"186:1-186:48\"\u003e\n\u003ctd data-sourcepos=\"186:2-186:11\"\u003e300..500\u003c/td\u003e\n\u003ctd data-sourcepos=\"186:13-186:47\"\u003e範囲（300 以上 500 以下）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"187:1-187:59\"\u003e\n\u003ctd data-sourcepos=\"187:2-187:13\"\u003e価格\u0026gt;300\u003c/td\u003e\n\u003ctd data-sourcepos=\"187:15-187:58\"\u003e数値・日付の列に条件を付ける\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"189:1-189:167\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb30ed9f1-2651-4f05-b49a-69bbb00b7418.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=4d8eb8dd8d6ae41ad99a5e15b470da44\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb30ed9f1-2651-4f05-b49a-69bbb00b7418.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=4d8eb8dd8d6ae41ad99a5e15b470da44\" alt=\"操作の説明（?）の「検索の書き方」タブ\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb30ed9f1-2651-4f05-b49a-69bbb00b7418.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=f2a4e77a9b815d41e807dfa4d915a762 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/b30ed9f1-2651-4f05-b49a-69bbb00b7418.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 data-sourcepos=\"191:1-191:51\"\u003e\n\u003cspan id=\"検索文字の履歴と保存した検索条件\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%A4%9C%E7%B4%A2%E6%96%87%E5%AD%97%E3%81%AE%E5%B1%A5%E6%AD%B4%E3%81%A8%E4%BF%9D%E5%AD%98%E3%81%97%E3%81%9F%E6%A4%9C%E7%B4%A2%E6%9D%A1%E4%BB%B6\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e検索文字の履歴と保存した検索条件\u003c/h2\u003e\n\u003cul data-sourcepos=\"193:1-198:0\"\u003e\n\u003cli data-sourcepos=\"193:1-193:315\"\u003e検索欄をダブルクリック（または ↓ キー）すると、直近 20 件の検索文字と、名前を付けて保存した検索条件（★）を選べます。選ぶとその文字で絞り込みます。履歴は Enter を押したときと、入力した検索欄を離れたときに残ります\u003c/li\u003e\n\u003cli data-sourcepos=\"194:1-194:265\"\u003e検索欄の右の ☆ を押すと、いまの検索文字に名前を付けて保存できます（最大 20 件）。保存した条件は候補の上段に「★ 名前 — 検索文字」で出て、左端の ≡ をドラッグして並べ替えられます\u003c/li\u003e\n\u003cli data-sourcepos=\"195:1-195:91\"\u003e各行の × （または Shift+Delete）で履歴や保存した条件から消せます\u003c/li\u003e\n\u003cli data-sourcepos=\"196:1-196:201\"\u003e列見出しを検索欄にドラッグ＆ドロップするか、列見出しを Ctrl+クリック（Mac は ⌘+クリック）すると「列名:」が入るので、続けて語を入力します\u003c/li\u003e\n\u003cli data-sourcepos=\"197:1-198:0\"\u003e履歴と保存した条件はブラウザーにアプリごとに保存されます。別のブラウザーや PC には引き継がれません\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"199:1-199:163\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc4e017ef-4fb8-4e2c-b43b-0fbb01ef233d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=803e27961f68871a1b0e5e16eb12334a\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc4e017ef-4fb8-4e2c-b43b-0fbb01ef233d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=803e27961f68871a1b0e5e16eb12334a\" alt=\"検索文字の履歴と保存した条件（☆）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc4e017ef-4fb8-4e2c-b43b-0fbb01ef233d.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=7cd93466284f1d0045afa180f09727c6 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c4e017ef-4fb8-4e2c-b43b-0fbb01ef233d.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"201:1-201:32\"\u003e\n\u003cspan id=\"ツールバーと列の操作\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%84%E3%83%BC%E3%83%AB%E3%83%90%E3%83%BC%E3%81%A8%E5%88%97%E3%81%AE%E6%93%8D%E4%BD%9C\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eツールバーと列の操作\u003c/h1\u003e\n\u003cul data-sourcepos=\"203:1-218:0\"\u003e\n\u003cli data-sourcepos=\"203:1-203:333\"\u003eタイトル行（検索欄の右）に、＋（行を追加）・ゴミ箱（選択行を削除）のアイコンと、［追加を確定 (n)］（自動保存で確定していない追加行があるとき）または［保存］［すべて取り消す］（明示保存）を、設定と保存方式に合わせて出します\u003c/li\u003e\n\u003cli data-sourcepos=\"204:1-204:113\"\u003eタイトル行の右端の再読込のアイコン（回る矢印）で、レコードを取得し直します\u003c/li\u003e\n\u003cli data-sourcepos=\"205:1-207:172\"\u003e件数の左の ⧉ を押すと、表に出ているレコード（検索で絞り込んだ分）を kintone の一覧で新しいタブに開きます。その一覧から一括更新プラグインなどで一括の処理ができます（一括更新プラグインは一覧の絞り込み条件を対象にします）。処理した後は、こちらの再読込のアイコンで取り直してください\n\u003cul data-sourcepos=\"206:3-207:172\"\u003e\n\u003cli data-sourcepos=\"206:3-206:256\"\u003e一覧の URL にレコード番号を並べる仕組みのため、URL の長さの制限に収まる先頭の件数までになります（超えるときは確認が出ます）。カスタム一覧では「（すべて）」の一覧で開きます\u003c/li\u003e\n\u003cli data-sourcepos=\"207:3-207:172\"\u003e保存していない変更があるときは確認が出ます（開く一覧には保存済みの値が出ます。確定していない追加行は入りません）\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli data-sourcepos=\"208:1-213:324\"\u003eタイトル行の右端のツールのアイコン（? の左）を押すと、ツールバーが出ます（押している間はアイコンが青）。ツールバーには次のものがあります\n\u003cul data-sourcepos=\"209:3-213:324\"\u003e\n\u003cli data-sourcepos=\"209:3-209:92\"\u003e取得件数: 取得するレコード数の上限（500 / 1,000 / 5,000 / 10,000 件）\u003c/li\u003e\n\u003cli data-sourcepos=\"210:3-210:63\"\u003e固定カラム数: 横に送っても左に残す列の数\u003c/li\u003e\n\u003cli data-sourcepos=\"211:3-211:264\"\u003e画像サイズ: 添付ファイルの縮小画像の大きさ（なし / 100〜500）。表か展開部に添付ファイルの列があるときだけ出ます。この画面だけの切り替えで、次に開くとプラグイン設定の値に戻ります\u003c/li\u003e\n\u003cli data-sourcepos=\"212:3-212:249\"\u003e列の状態を初期化: 覚えている列幅・並び・表示する項目・固定カラム数を消して、プラグイン設定の初期値に戻します（レコードは取得し直さず、保存していない変更は残ります）\u003c/li\u003e\n\u003cli data-sourcepos=\"213:3-213:324\"\u003e表示する項目: 押すと項目のタグの欄が出ます。タグを外すと列を隠し、足すと出します。タグをドラッグすると列の並びが変わります（列見出しのドラッグと同じ）。テーブルのタグを外すと、行の展開部にもそのテーブルを出しません\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli data-sourcepos=\"214:1-214:169\"\u003e文字列（複数行）は改行して出します。4 行まで出し、続きはセルの中でスクロールします（行の高さが行数で伸びません）\u003c/li\u003e\n\u003cli data-sourcepos=\"215:1-215:119\"\u003e列見出しの右端をドラッグすると列幅、列見出しをドラッグすると列の順番を変えます\u003c/li\u003e\n\u003cli data-sourcepos=\"216:1-216:259\"\u003e右上の全画面のアイコンで、全画面表示・通常表示を切り替えます。その左の「?」で操作の説明（検索の書き方、検索の操作、編集、保存、追加と削除、テーブル、表示 のタブ）が開きます\u003c/li\u003e\n\u003cli data-sourcepos=\"217:1-218:0\"\u003e列幅、列の並び、表示する項目、固定カラム数は、ブラウザーにアプリと一覧ごとに記憶し、次に開いたときに戻します\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"219:1-219:145\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fd71cc880-fb32-415e-93c6-d18c35ff29e2.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=181d6af67ebe93de3f26f4f1acf5d1b6\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fd71cc880-fb32-415e-93c6-d18c35ff29e2.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=181d6af67ebe93de3f26f4f1acf5d1b6\" alt=\"タイトル行とツールバー\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fd71cc880-fb32-415e-93c6-d18c35ff29e2.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=28546c2b3c0eb9c76187e300290ed587 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d71cc880-fb32-415e-93c6-d18c35ff29e2.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"221:1-221:20\"\u003e\n\u003cspan id=\"添付ファイル\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%B7%BB%E4%BB%98%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e添付ファイル\u003c/h1\u003e\n\u003ch2 data-sourcepos=\"223:1-223:15\"\u003e\n\u003cspan id=\"縮小画像\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%B8%AE%E5%B0%8F%E7%94%BB%E5%83%8F\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e縮小画像\u003c/h2\u003e\n\u003cp data-sourcepos=\"225:1-225:216\"\u003eプラグイン設定の［詳細設定］の「画像サイズ」を選ぶと、添付ファイルの列に縮小画像を出します（なしを選ぶと出しません。文字検索プラグインと同じ）。\u003c/p\u003e\n\u003cul data-sourcepos=\"227:1-231:0\"\u003e\n\u003cli data-sourcepos=\"227:1-227:89\"\u003e画像の枠は画像サイズの正方形です。画像は枠に収めて出します\u003c/li\u003e\n\u003cli data-sourcepos=\"228:1-228:235\"\u003e縮小画像は 1 段分の高さまで出し、ファイルが多いときはセルの中でスクロールします（行の高さが画像の数で伸びません）。ファイル名と ✎ はスクロールしても見えます\u003c/li\u003e\n\u003cli data-sourcepos=\"229:1-229:90\"\u003e画像 / pdf のファイル名と縮小画像を押すと、ビューワで開きます\u003c/li\u003e\n\u003cli data-sourcepos=\"230:1-231:0\"\u003eテーブルの子の添付ファイルも同じです\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"232:1-232:170\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4e1392e0-a6e7-4ded-bc86-938b5fdd1ef4.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=19f6929bb88395b44b86fa7ee9f542f6\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4e1392e0-a6e7-4ded-bc86-938b5fdd1ef4.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=19f6929bb88395b44b86fa7ee9f542f6\" alt=\"添付ファイルの縮小画像（画像サイズ 100）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4e1392e0-a6e7-4ded-bc86-938b5fdd1ef4.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=2c3199aa76735f3d39319779567e7141 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4e1392e0-a6e7-4ded-bc86-938b5fdd1ef4.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 data-sourcepos=\"234:1-234:33\"\u003e\n\u003cspan id=\"追加削除並べ替え\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%BF%BD%E5%8A%A0%E5%89%8A%E9%99%A4%E4%B8%A6%E3%81%B9%E6%9B%BF%E3%81%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e追加・削除・並べ替え\u003c/h2\u003e\n\u003cp data-sourcepos=\"236:1-236:209\"\u003e「編集を許可する項目」で添付ファイルを選ぶと、セルの先頭に ✎ が出ます。✎ を押すと（Enter・ダブルクリックでも）添付ファイルの画面が開きます。\u003c/p\u003e\n\u003cul data-sourcepos=\"238:1-246:0\"\u003e\n\u003cli data-sourcepos=\"238:1-238:164\"\u003e［ファイルを追加］（複数選べます）か、画面へのドロップで足します。足したファイルはその場でアップロードします\u003c/li\u003e\n\u003cli data-sourcepos=\"239:1-239:46\"\u003e↑ ↓ で並べ替え、× で外します\u003c/li\u003e\n\u003cli data-sourcepos=\"240:1-240:170\"\u003eOK でセルに入れます。保存はほかの項目と同じです（自動保存 / 明示保存）。外したファイルは、保存すると元に戻せません\u003c/li\u003e\n\u003cli data-sourcepos=\"241:1-241:325\"\u003e保存済みのファイルを並べ替えると、OK で、動かしたファイルから後ろのファイルを上げ直します。kintone は保存済みのファイルの並びを変えないためです（足したファイルは後ろに付きます）。ファイルが大きいとその分時間がかかります\u003c/li\u003e\n\u003cli data-sourcepos=\"242:1-242:212\"\u003e足したファイルと上げ直したファイルは、保存するまで kintone の一時保管領域に置かれます。保存しなければ 3 日で消えます（ディスク使用量に入ります）\u003c/li\u003e\n\u003cli data-sourcepos=\"243:1-243:56\"\u003eテーブルの子の添付ファイルも同じです\u003c/li\u003e\n\u003cli data-sourcepos=\"244:1-244:104\"\u003e貼り付け・Delete・下へ埋める（Ctrl+D）は、添付ファイルのセルを変えません\u003c/li\u003e\n\u003cli data-sourcepos=\"245:1-246:0\"\u003e選択行の複写と子行の複製では、添付ファイルは写しません（ほかの行のファイルはそのまま送れないため）\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"247:1-247:180\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fcf9ce233-b16e-4631-bc22-af18984be220.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=11fa8015855f2c58e5ca902e2094dc62\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fcf9ce233-b16e-4631-bc22-af18984be220.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=11fa8015855f2c58e5ca902e2094dc62\" alt=\"添付ファイルの画面 — 足したファイルに「追加」\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fcf9ce233-b16e-4631-bc22-af18984be220.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=bbb59575ede2cc06e6278e7894270ae4 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/cf9ce233-b16e-4631-bc22-af18984be220.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"249:1-249:155\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F806e5944-9740-405d-8d1c-e8f8788d25f8.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=ad9e90e2095d277bb2222f6941d199ac\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F806e5944-9740-405d-8d1c-e8f8788d25f8.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=ad9e90e2095d277bb2222f6941d199ac\" alt=\"操作の説明（?）の「編集」タブ\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F806e5944-9740-405d-8d1c-e8f8788d25f8.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=158a39d526ba13be47e37556fd8ea891 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/806e5944-9740-405d-8d1c-e8f8788d25f8.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"251:1-251:20\"\u003e\n\u003cspan id=\"カスタム一覧\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E4%B8%80%E8%A6%A7\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eカスタム一覧\u003c/h1\u003e\n\u003cp data-sourcepos=\"253:1-253:300\"\u003eプラグイン設定でカスタム一覧を選ぶと、カスタム一覧の画面でグリッドを表示します（初期表示は固定で on）。表示する項目はプラグイン設定の「表示する項目」で指定します。指定しない場合はフォームの全項目です。\u003c/p\u003e\n\u003ch1 data-sourcepos=\"255:1-255:26\"\u003e\n\u003cspan id=\"プラグインの追加\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%AE%E8%BF%BD%E5%8A%A0\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eプラグインの追加\u003c/h1\u003e\n\u003cul data-sourcepos=\"257:1-259:0\"\u003e\n\u003cli data-sourcepos=\"257:1-257:70\"\u003e「kintone システム管理 \u0026gt; プラグイン」で追加します\u003c/li\u003e\n\u003cli data-sourcepos=\"258:1-259:0\"\u003e「アプリの設定 \u0026gt; プラグイン」で、アプリに追加します\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"260:1-260:195\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4e56ad9a-162e-4350-b65c-8f383398d8ad.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=9135dbf868031efe06e68c7f95520e59\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4e56ad9a-162e-4350-b65c-8f383398d8ad.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=9135dbf868031efe06e68c7f95520e59\" alt=\"アプリの設定のプラグイン — 一覧編集の歯車から設定画面へ\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F4e56ad9a-162e-4350-b65c-8f383398d8ad.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=d1cfb898adc9601b4cc0bc552a7b2eb3 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4e56ad9a-162e-4350-b65c-8f383398d8ad.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch1 data-sourcepos=\"262:1-262:26\"\u003e\n\u003cspan id=\"プラグインの設定\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%AE%E8%A8%AD%E5%AE%9A\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eプラグインの設定\u003c/h1\u003e\n\u003cp data-sourcepos=\"264:1-264:142\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Febfc50c5-0329-4acd-a1b4-1e7e2ea2681a.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=fb6675565d5bb49ffbe76aa5887e2f32\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Febfc50c5-0329-4acd-a1b4-1e7e2ea2681a.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=fb6675565d5bb49ffbe76aa5887e2f32\" alt=\"プラグインの設定画面\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Febfc50c5-0329-4acd-a1b4-1e7e2ea2681a.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=26f663b3a01e5c179d4be9c0db38b396 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ebfc50c5-0329-4acd-a1b4-1e7e2ea2681a.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"266:1-266:36\"\u003e共通の設定（ツールバー）\u003c/p\u003e\n\u003cul data-sourcepos=\"268:1-270:0\"\u003e\n\u003cli data-sourcepos=\"268:1-268:82\"\u003eプラグインを使う: プラグインを有効にする場合、チェック\u003c/li\u003e\n\u003cli data-sourcepos=\"269:1-270:0\"\u003e［詳細設定］: 全部の一覧に共通の設定を開きます。ボタンの右に、今の保存方式・計算式連携（画像を出すときは画像サイズも）を表示します\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"271:1-271:12\"\u003e詳細設定\u003c/p\u003e\n\u003cul data-sourcepos=\"273:1-280:0\"\u003e\n\u003cli data-sourcepos=\"273:1-273:43\"\u003e保存方式: 自動保存 / 明示保存\u003c/li\u003e\n\u003cli data-sourcepos=\"274:1-274:133\"\u003e保存前の確認: 明示保存の［保存］で件数を確かめる画面を出します（自動保存では使いません）\u003c/li\u003e\n\u003cli data-sourcepos=\"275:1-275:100\"\u003e分割保存の確認: 2,000 件を超える変更を分けて保存するときに確かめます\u003c/li\u003e\n\u003cli data-sourcepos=\"276:1-276:148\"\u003e計算式プラグイン: このアプリに計算式プラグインが追加されているかを表示します（設定ではありません）\u003c/li\u003e\n\u003cli data-sourcepos=\"277:1-277:61\"\u003e計算式連携: 「計算式プラグイン連携」参照\u003c/li\u003e\n\u003cli data-sourcepos=\"278:1-278:142\"\u003e画像サイズ: 添付ファイルの縮小画像の大きさの初期値。なしなら出しません（「添付ファイル」参照）\u003c/li\u003e\n\u003cli data-sourcepos=\"279:1-280:0\"\u003e［保存］は設定画面に入れるだけです。設定画面の「保存する」で保存します\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"281:1-281:133\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F643bc506-f303-43f0-afd9-133fe4450d4b.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=ecaee1e8985b78f6af71c068ce4ece3b\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F643bc506-f303-43f0-afd9-133fe4450d4b.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=ecaee1e8985b78f6af71c068ce4ece3b\" alt=\"詳細設定の画面\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F643bc506-f303-43f0-afd9-133fe4450d4b.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=f367ec3f63be73d2ecc766538ccf7988 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/643bc506-f303-43f0-afd9-133fe4450d4b.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"283:1-283:108\"\u003e一覧ごとの設定（対象の一覧にチェックを入れます。カスタム一覧も選べます）\u003c/p\u003e\n\u003cul data-sourcepos=\"285:1-296:0\"\u003e\n\u003cli data-sourcepos=\"285:1-285:115\"\u003e初期表示: 一覧を開いた直後からグリッドを表示します（カスタム一覧は固定で on）\u003c/li\u003e\n\u003cli data-sourcepos=\"286:1-286:67\"\u003e取得件数、固定カラム数: 一覧画面の初期値です\u003c/li\u003e\n\u003cli data-sourcepos=\"287:1-287:145\"\u003e表示する項目: グリッドに出す項目と並び。選ばなければ一覧の項目（カスタム一覧はフォームの全項目）\u003c/li\u003e\n\u003cli data-sourcepos=\"288:1-288:136\"\u003e表示するテーブル: 行の展開部に出すテーブル。選ばなければ、表示する項目に入っているテーブル\u003c/li\u003e\n\u003cli data-sourcepos=\"289:1-289:153\"\u003eテーブルの表示項目: 展開部のテーブルに出す子の項目と並び。テーブルごとに、1 つも選ばなければ全部の項目\u003c/li\u003e\n\u003cli data-sourcepos=\"290:1-290:235\"\u003e編集を許可する項目: グリッドで編集できる項目。計算・ルックアップのコピー先・自動計算の文字列・レコード番号などは候補に出ません。テーブルの子の項目も選べます\u003c/li\u003e\n\u003cli data-sourcepos=\"291:1-291:125\"\u003e追加 / 削除: 一覧画面のタイトル行に ＋（行を追加）とゴミ箱（選択行を削除）を出します\u003c/li\u003e\n\u003cli data-sourcepos=\"292:1-292:232\"\u003e選択行の複写: 写す項目を選ぶと、一覧画面のタイトル行に複写のアイコンを出します。何も選ばなければ出しません（レコードの追加の権限がある利用者だけ使えます）\u003c/li\u003e\n\u003cli data-sourcepos=\"293:1-293:783\"\u003e追加行の初期値: ＋（行を追加）で入れる値。ドロップダウン・ラジオボタン・チェックボックス・複数選択は、セルを押して選択肢の一覧から選びます（言語ごとの名称を付けた選択肢も、保存されるのはデフォルトの名称なので、どの言語の利用者にも入ります）。ほかの項目の書き方は貼り付けと同じです（日付は 2026-10-24、複数の値はカンマ区切り、ユーザー・組織・グループはコードか名前）。ログインユーザーにしたいときは、kintone のフォームでユーザー選択の初期値を「ログインユーザー」にします。種別ごとの書き方は設定の説明（?）の「編集」タブにあります\u003c/li\u003e\n\u003cli data-sourcepos=\"294:1-294:165\"\u003eテーブルの全展開: チェックすると、一覧を開いたときにテーブルのある行を開きます（表の並びで先頭から 300 行まで）\u003c/li\u003e\n\u003cli data-sourcepos=\"295:1-296:0\"\u003e「保存する」をクリックします\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"297:1-297:558\"\u003eツールバーの［一覧の設定をコピー］で、ある一覧の設定をほかの一覧に写せます。コピー元の一覧（初めは最後に押した行）、写す設定（初期表示・取得件数・表示する項目など。初めは全部。［すべて選択］［すべて解除］でまとめて選べます）、コピー先の一覧を選んで［コピー］を押します。「コピー先の一覧で使う」をチェックすると、コピー先の左端のチェックも付けます。保存は「保存する」です。\u003c/p\u003e\n\u003cp data-sourcepos=\"299:1-299:148\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fa032968e-a4b1-4e16-a8c6-12a0c5764a78.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=9c532335dc5ed85febf4aab1b4283103\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fa032968e-a4b1-4e16-a8c6-12a0c5764a78.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=9c532335dc5ed85febf4aab1b4283103\" alt=\"一覧の設定をコピーの画面\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fa032968e-a4b1-4e16-a8c6-12a0c5764a78.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=8022d1fced449317068dbbcc04246022 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a032968e-a4b1-4e16-a8c6-12a0c5764a78.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"301:1-301:447\"\u003e「表示する項目」「表示するテーブル」「テーブルの表示項目」「編集を許可する項目」「追加行の初期値」の列は、セルを押すと選ぶ画面が開きます。候補はフォームの配置の順に並びます。「表示する項目」「表示するテーブル」「テーブルの表示項目」は、チェックした項目を上から順に使い、ドラッグで並べ替えられます。\u003c/p\u003e\n\u003cp data-sourcepos=\"303:1-303:192\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fd71fadb8-c86a-4a8b-b3f6-17a4db12251c.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=f793d5eb41f8ba158ce8db013851164a\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fd71fadb8-c86a-4a8b-b3f6-17a4db12251c.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=f793d5eb41f8ba158ce8db013851164a\" alt=\"編集を許可する項目の選択 — テーブルの子の項目も選べる\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fd71fadb8-c86a-4a8b-b3f6-17a4db12251c.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=3387e9267d5133bb9e80dacf71436f71 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d71fadb8-c86a-4a8b-b3f6-17a4db12251c.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"305:1-305:183\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb0648c11-b291-4fab-9f38-6cb1f243c632.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=4754eb2b3b68bc41d9c44cd3fa33c12c\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb0648c11-b291-4fab-9f38-6cb1f243c632.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=4754eb2b3b68bc41d9c44cd3fa33c12c\" alt=\"追加行の初期値 — ドロップダウンは選択肢から選ぶ\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fb0648c11-b291-4fab-9f38-6cb1f243c632.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=63118c0ca56cf95c8f7087c40492372f 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/b0648c11-b291-4fab-9f38-6cb1f243c632.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 data-sourcepos=\"307:1-307:59\"\u003e\n\u003cspan id=\"設定の説明とプラグインの概要i\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%AD%E5%AE%9A%E3%81%AE%E8%AA%AC%E6%98%8E%E3%81%A8%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%AE%E6%A6%82%E8%A6%81i\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e設定の説明（?）とプラグインの概要（i）\u003c/h2\u003e\n\u003cp data-sourcepos=\"309:1-309:93\"\u003e「一覧画面情報」の右端のアイコンで、次の 2 つの画面が開きます。\u003c/p\u003e\n\u003cul data-sourcepos=\"311:1-313:0\"\u003e\n\u003cli data-sourcepos=\"311:1-311:197\"\u003e「?」（全画面の左）: 設定の説明です。「一覧画面情報」「編集」「保存」「一覧画面との関係」のタブで、設定画面の各欄の意味を説明します\u003c/li\u003e\n\u003cli data-sourcepos=\"312:1-313:0\"\u003e「i」（? の左）: プラグインの概要です\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"314:1-314:134\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F3af878f3-bf42-44cb-94b5-88fc388c62f6.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=b1b345efd023d6ee9ca521475cde4fa6\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F3af878f3-bf42-44cb-94b5-88fc388c62f6.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=b1b345efd023d6ee9ca521475cde4fa6\" alt=\"設定の説明（?）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F3af878f3-bf42-44cb-94b5-88fc388c62f6.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=aa5442715c118a7aec3bcfbda50fc6d2 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3af878f3-bf42-44cb-94b5-88fc388c62f6.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 data-sourcepos=\"316:1-316:39\"\u003e\n\u003cspan id=\"設定の保存とバックアップ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%AD%E5%AE%9A%E3%81%AE%E4%BF%9D%E5%AD%98%E3%81%A8%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e設定の保存とバックアップ\u003c/h2\u003e\n\u003cp data-sourcepos=\"318:1-318:185\"\u003e設定画面の下端のボタンで、設定のダウンロード（JSON）とアップロード、設定の Markdown 形式でのクリップボードへのコピーができます。\u003c/p\u003e\n\u003cp data-sourcepos=\"320:1-320:132\"\u003e※フォーム変更時は、本番環境にフォーム変更を反映後に、本プラグイン設定を行ってください。\u003c/p\u003e\n\u003ch1 data-sourcepos=\"322:1-322:14\"\u003e\n\u003cspan id=\"注意事項\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e注意事項\u003c/h1\u003e\n\u003cul data-sourcepos=\"323:1-327:257\"\u003e\n\u003cli data-sourcepos=\"323:1-323:247\"\u003e既に、JavaScript によるカスタマイズを行っているアプリの場合、処理が競合して、エラーになる場合があります。その場合は、該当するアプリでプラグインの使用を中止してください\u003c/li\u003e\n\u003cli data-sourcepos=\"324:1-324:50\"\u003e削除したレコードは元に戻せません\u003c/li\u003e\n\u003cli data-sourcepos=\"325:1-325:434\"\u003e計算式プラグイン連携で、計算式がレコード番号・作成者・作成日時・更新者・更新日時や、添付ファイルの fileKey を使っているときは、保存の前の値で計算します（足したファイルの fileKey はアップロードしたときの一時的な値）。追加・更新で kintone が入れた値は計算に入りません（「計算式プラグイン連携」参照）\u003c/li\u003e\n\u003cli data-sourcepos=\"326:1-326:191\"\u003e検索文字の履歴、保存した検索条件、列の状態はブラウザー（localStorage）に保存されます。ブラウザーのサイトデータを消すと無くなります\u003c/li\u003e\n\u003cli data-sourcepos=\"327:1-327:257\"\u003e表示項目が多くかつレコード数が多い場合、ブラウザーで大量のメモリを使用し動作が遅くなります。その場合は、標準のフィルター機能や取得件数でレコード数を絞って使用してください\u003c/li\u003e\n\u003c/ul\u003e\n","body":"kintone アプリの一覧編集プラグインです。一覧画面のレコードをグリッドに表示し、セルの編集、行の追加・削除をして kintone に保存します。\n\nプラグインの追加から、一覧で編集するまでの手順は「[rex0220 一覧編集プラグイン - 導入編（追加から編集まで）](https://qiita.com/rex0220/items/ad08bb138a052c6bdff7)」にあります。この記事は、機能ごとの詳しい説明です。\n\n主な機能\n\n- 複数のレコードをまとめて編集: 範囲の選択、Excel と同じタブ区切りのコピー・貼り付け、Delete で空にする、Ctrl+D で下へ埋める、Ctrl+Z で戻す\n- テーブルの子行も一覧の中で編集: 行の展開部に子のグリッドを出し、子行の編集・追加・並べ替え・削除ができます\n- 自動保存と明示保存を選べます。ほかの人が先に更新したレコードは上書きせず、最新の値の取り込み方を選べます\n- 計算式プラグインと連携: 一覧で編集したときも、詳細画面と同じ式で計算して保存します\n\n使い方の例\n\n- 商品マスターの価格や区分を、一覧で並べて直す\n- 案件の一覧で、期日や進捗の項目をまとめて更新する\n- 受注レコードの明細（テーブル）の数量や単価を、詳細画面を開かずに直す\n- Excel の表の値を、範囲を選んで貼り付ける\n\n※動作環境は、PC です。\n\n※ Ver.1（2026/10）\n- 初版\n\n# 文字検索プラグインとの関係\n\n文字検索プラグインとは別の製品です。文字検索は閲覧用（編集の機能はありません）、一覧編集は編集用です。\n\n- 検索欄の書き方は文字検索と同じです（「検索文字の書き方」参照）\n- 同じ一覧を両方のプラグインの設定で選ぶと、画面の部品が重なります。別々の一覧を選んでください\n\n# 一覧編集の表示例\n\n- プラグイン設定で「初期表示」にした一覧は、開いた直後からグリッドを表示します\n- それ以外の一覧は、ヘッダーの［一覧編集］を押すとグリッドに切り替わります。もう一度押すと kintone の一覧に戻ります\n- 絞り込みと並び順は kintone の一覧の条件を使います。取得するレコード数の上限は、ツールバーの「取得件数」で変えられます\n- 編集できるセルは薄い色で表示します。どの項目を編集できるかは、プラグイン設定の「編集を許可する項目」で決まります（アクセス権は「権限」参照）\n\n![一覧画面 — ヘッダーの［一覧編集］](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/b8c0544c-7597-4c08-825e-711d4eaa1759.png)\n\n![一覧編集の画面（タイトル行、ツールバー、編集できるセルの色）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/aaf67166-b50e-4628-b6f7-6fbdf7a0e492.png)\n\n# セルの編集\n\n| 操作 | 動き |\n|---|---|\n| クリック | セルを選ぶ（編集は始めない） |\n| ダブルクリック / Enter / F2 / 文字キー | 編集を始める（文字キーはその文字から） |\n| Enter / Esc | 確定 / 取り消し |\n| Tab / ↑ ↓（編集中） | 確定して隣のセルへ移る（移った先の編集は始めない） |\n| 日付・日時のセル | 表示と同じ 2026-10-24（日時は 2026-10-24 09:30）で入力する。2026/10/24 も読む。右のボタンか Alt+↓（Mac は Option+↓）でカレンダー（見出しの年・月を押すと年・月を選べる。矢印で日、PageUp / PageDown で月、Enter で選ぶ、Esc で閉じる） |\n| 日時のカレンダー | 日を押すと時・分の表に進み、分を押すと時刻も入って確定する。下端の時刻のボタンで時刻だけ選べる。Esc で一つ前の表に戻る |\n| 時刻のセル | 表示と同じ 09:30 で入力する（9:30 も読む）。右の時計のボタンか Alt+↓ で時・分の表（分を押すと確定。「現在」で今の時刻、「削除」で空） |\n| 分の表の 1分 / 15分 | 分の刻みを切り替える（このブラウザーに記憶し、ほかの時刻・日時のセルも同じ刻み）。刻みに無い分は欄に入力 |\n\n- 編集できる項目: 文字列（1行・複数行）、数値、日付・時刻・日時、ドロップダウン、ラジオボタン、チェックボックス、複数選択、ユーザー・組織・グループ選択、リンク、ルックアップ、テーブルの子の項目\n- 計算、ルックアップのコピー先、「自動計算する」を設定した文字列（1行）、リッチエディター、レコード番号、作成者・更新者などは表示のみです\n- 「$id」欄のレコード番号を押すと、詳細画面を新しいタブで開きます\n\n![日付のセルの編集中 — カレンダー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/352d6ae6-4114-44ae-bbd4-e7d6aeb6aecf.png)\n\n![ドロップダウンのセルの編集中 — 候補](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/da5fcf41-38cc-44b6-a720-987508d522df.png)\n\n## 範囲とクリップボード\n\n| 操作 | 動き |\n|---|---|\n| ドラッグ / Shift+クリック / Shift+矢印 | 範囲を選ぶ |\n| Ctrl+A | 表に出ている全部のセルを選ぶ |\n| Ctrl+C / Ctrl+V | 範囲をコピー / 貼り付け（Excel と同じタブ区切り）。1 つのセルのコピーは選んだ範囲の全部に入る（範囲がコピーの行数・列数の倍数なら繰り返す） |\n| Delete | 範囲のセルを空にする |\n| Ctrl+D | 範囲の先頭の行の値で下を埋める |\n| Ctrl+Z | その行の直前の変更を戻す（行ごとに 10 回まで） |\n\n- Mac では Ctrl の代わりに ⌘ を使います\n- 貼り付けで、変換できない値（日付でない文字、選択肢に無い値など）が 1 つでもあれば何も書かず、理由を一覧で表示します\n- 編集できないセルは飛ばします\n\n![貼り付けで変換できなかったときの一覧（何も書き込まない）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5fd924af-e628-4e0c-8408-b8d85b65f540.png)\n\n## ルックアップ\n\n- ルックアップのセルの編集を始めると、取得画面が開きます。表示する列と絞り込み・並び順は、kintone のルックアップの設定に従います\n- 選ぶと、コピー先の項目に仮の値を表示します。保存した後に kintone が入れた値で表示し直します\n- REST API の制限で、参照先のキーの項目が重複禁止（またはレコード番号）のルックアップだけ編集できます\n- 取得画面の検索欄をダブルクリック（または ↓ キー）すると、直近 20 件の検索文字と、名前を付けて保存した検索条件（★）を選べます。検索欄の右の ☆ で、いまの検索文字に名前を付けて保存します（最大 20 件）。履歴と保存した条件は、このアプリで同じアプリを参照するルックアップと共有し、このブラウザーにだけ残ります\n- 検索の行の右端のツールのアイコンで、取得件数の切り替え、列の状態を初期化、表示する項目を出します。手で変えた列幅・並び・表示する項目は、ルックアップの項目ごとにブラウザーに記憶します\n\n![ルックアップの取得画面 — 検索欄の履歴とツールバー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ba77a8e5-37fb-4956-84c2-d4b7203b5b42.png)\n\n# 保存\n\nプラグイン設定の「保存方式」で、自動保存と明示保存を選びます。\n\n- 自動保存: セルを確定して少し待つと、その行を保存します。保存中にその行を続けて変えると、保存が終わってからもう一度保存します。複数の行への貼り付けは 1 回でまとめて保存します\n- 明示保存: ツールバーの［保存］で、変更をまとめて保存します（設定で、件数を確かめる画面を出せます）。［すべて取り消す］で全部の変更を戻します\n- 検索で隠れている行の変更も保存の対象です（「保存前の確認」が on なら、確かめる画面にその件数も出します）\n- 2,000 件を超える変更は分けて保存します。途中で失敗すると、それより前の回の分だけが保存されます\n\n左端の印\n\n| 印 | 意味 |\n|---|---|\n| ● | 変更あり |\n| ⟳ | 保存中 |\n| ✓ | 保存した |\n| ! | 保存できなかった（セルは赤枠。印に理由） |\n| ⇄ | ほかの人が先に更新した |\n| ＋ | 追加した行 |\n| × | 削除の印 |\n\n- ● ! を押すと、その行の変更を取り消して、取得したときの値に戻します\n- 自動保存で保存できなかった行は、フッターの［未保存 n 件を保存］でまとめて保存し直せます\n- 保存していない変更があるときに、ページを離れる・一覧に戻す・取得件数を変える・再読込のアイコンを押すと確かめます\n\n![保存できなかったセル — 赤枠と ! の印、下に理由](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/1381212e-9e80-4995-b84b-e4816fd53245.png)\n\n## ほかの人が先に更新したとき\n\n取得した後にほかの人がレコードを更新していると、そのレコードは保存せず ⇄ の印を付けます。⇄ を押すと、最新の値の取り込み方を選べます。\n\n- 最新の値を取り込む（自分の変更を捨てる）\n- 自分の変更を残して、ほかの項目を最新にする: 自分が変えた項目は、ほかの人が同じ項目を変えていても自分の値で保存し直します。テーブルを変えていれば、子行を含めてテーブル全体が自分の値になります\n\n![⇄ を押したときの画面 — 最新の値の取り込み方を選ぶ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ac2665aa-345d-4830-9b0e-8394930a497d.png)\n\n# 行の追加と削除\n\nプラグイン設定で一覧ごとに「追加」「削除」を許可します。\n\n- タイトル行の ＋（行を追加）で末尾に行を足します。プラグイン設定の「追加行の初期値」と、フォームの初期値が入ります\n- 自動保存の一覧では、［追加を確定 (n)］か行の ＋ を押すと追加行を保存します（それまでは kintone に何も送りません）。［追加を確定 (n)］は確定していない追加行があるときだけタイトル行に出ます（n はその数）\n- 左の列のチェックで行を選び、タイトル行の複写のアイコン（選択行を複写）を押すと、選んだ行を写した新しい行を末尾に足します。写すのはプラグイン設定の「選択行の複写」で選んだ項目だけで、ほかの項目は追加行の初期値です（テーブルは子行ごと写します）。保存は追加行と同じです\n- 左の列のチェックで行を選び、タイトル行のゴミ箱（選択行を削除）を押します。自動保存の一覧はすぐに削除します（確かめる画面が出ます）。明示保存の一覧は × の印を付け、［保存］で削除します\n- 削除したレコードは元に戻せません\n- ＋（行を追加）は、レコードの追加の権限がある利用者にだけ表示します\n\n![行を追加した状態 — 行の ＋ の印と［追加を確定 (1)］](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/8005c1d4-1a8f-46ed-8cfe-d01c96618147.png)\n\n# テーブル\n\n- テーブルの列（「n 行」の表示）か、行の左端の ▸ を押すと、行の下にテーブルを開きます。もう一度押すと閉じます。テーブルが複数ならタブで切り替えます\n- 子のセルは、一番上の表と同じ操作で編集できます（範囲・貼り付け・Ctrl+Z も）\n- 子行の右端の ＋ はその行のすぐ下に新しい行（初期値入り）を、複製のアイコンはその行の値を写した行を足します。↑ ↓ で並べ替え、× で削除の印（もう一度押すと外します）。子行が無いテーブルでは、子の表の右端の見出しの ＋ で 1 行目を足します\n- 子の列見出しの右端をドラッグすると列幅を変えられます。一番上の表と同じく、ブラウザーにアプリと一覧ごとに記憶します\n- 展開部の［表示する項目］を押すと、今のテーブルの子の項目のタグの欄が出ます。タグを外すと列を隠し、足すと出し、ドラッグで並びを変えます。初めはプラグイン設定の「テーブルの表示項目」の並びで、変えた状態はブラウザーに記憶し、ツールバーの［列の状態を初期化］で戻ります\n- 子行の変更は親のレコードの変更として保存します（テーブルの列に ●）\n- 表の左上（▸ の列の見出し）の ▸ で、表に出ている行のテーブルを全部開きます（表の並びで先頭から 300 行まで。取得件数とは別です）。開いている間は ▾ になり、押すと全部閉じます。検索や取得し直しの後も開きます。プラグイン設定の「テーブルの全展開」をチェックすると、開いたときに全展開にできます\n- テーブルの子の項目を「編集を許可する項目」で 1 つでも選ぶと、そのテーブルの子行の追加・並べ替え・削除ができます\n\n![テーブルを開いた状態 — タブ、［表示する項目］、子行の ↑ ↓ ＋ 複製 ×](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7bf01882-85a9-43bd-b2fa-e97e60a67106.png)\n\n# 計算式プラグイン連携\n\n計算式プラグインが入っているアプリで、プラグイン設定の［詳細設定］の「計算式連携」を on にすると、プラグインを使う一覧で、セルを確定するたびに計算式プラグインの式で計算して画面に入れ、保存します。詳細画面で編集したときと同じ式で計算します。\n\n- テーブルの子行を確定したときも、レコード全体で計算します\n- 計算に失敗した行は ! の印を付け、保存しません。入力した値は画面に残ります\n- 計算式連携が on なら、プラグインを使う一覧はどれもレコードを全項目で取得します（式が参照する項目をそろえるため）\n- 計算式プラグインで「編集」を off にした項目は、一覧編集でも編集できません。テーブルを off にしたときは、子行の追加・削除・並べ替え・複製ができません（子の項目の入力はそれぞれの指定どおり。計算式プラグイン Ver.102 以降）\n- ほかの計算する項目を手で入力しても、次の計算で上書きされます\n- 計算式でレコード番号・作成者・作成日時・更新者・更新日時を使うと、保存の前の値で計算します（追加行ではどれも空、更新では前の保存の値）。添付ファイルを足したときの fileKey も、アップロードしたときの一時的な値で計算します。保存で kintone が入れた値は、その保存の計算には入りません\n- プラグイン設定の［詳細設定］に、このアプリに計算式プラグインが追加されているか（有効 / 無効 / 未追加）を表示します\n\n![計算式連携 — 数値を確定すると計算式の列も変わる（● は保存前）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7dc5d265-5ed4-49bf-aede-57e5dbd19430.png)\n\n# 権限\n\n- 一覧編集はアクセス権を確かめません（確かめる API の分だけ、kintone の 1 日の API の回数を使うため）\n- 権限の無いレコード・項目の変更や削除は、保存のときに kintone がエラーにします。行に ! の印を付け、セルを赤枠にして理由を出します\n- 貼り付けなどで複数の行をまとめて保存するとき、権限の無い行が 1 行でもあると、その回（2,000 件まで）の保存は全部取り消されます\n- ＋（行を追加）と選択行の複写は、レコードの追加の権限がある利用者にだけ表示します\n\n# 検索文字の書き方\n\nタイトル行の検索欄では、取得したレコードを画面の上で絞り込みます（kintone への再取得はしません）。書き方は文字検索プラグインと同じで、一覧は右端の「?」で開く操作の説明の「検索の書き方」タブにあります。\n\n| 書き方 | 意味 |\n|---|---|\n| A B | スペース区切り: すべて含む（AND） |\n| A \\| B | \\| か , 区切り: どれかを含む（OR） |\n| -語 | 含まない |\n| \"A B\" | 語句をそのまま |\n| 分類:飲料 | 列名を付けてその列だけ（文字） |\n| =400 !=400 | 数値・日付が等しい / 等しくない |\n| \u003e300 \u003e=300 \u003c300 \u003c=300 | 数値・日付の大小 |\n| 300..500 | 範囲（300 以上 500 以下） |\n| 価格\u003e300 | 数値・日付の列に条件を付ける |\n\n![操作の説明（?）の「検索の書き方」タブ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/b30ed9f1-2651-4f05-b49a-69bbb00b7418.png)\n\n## 検索文字の履歴と保存した検索条件\n\n- 検索欄をダブルクリック（または ↓ キー）すると、直近 20 件の検索文字と、名前を付けて保存した検索条件（★）を選べます。選ぶとその文字で絞り込みます。履歴は Enter を押したときと、入力した検索欄を離れたときに残ります\n- 検索欄の右の ☆ を押すと、いまの検索文字に名前を付けて保存できます（最大 20 件）。保存した条件は候補の上段に「★ 名前 — 検索文字」で出て、左端の ≡ をドラッグして並べ替えられます\n- 各行の × （または Shift+Delete）で履歴や保存した条件から消せます\n- 列見出しを検索欄にドラッグ＆ドロップするか、列見出しを Ctrl+クリック（Mac は ⌘+クリック）すると「列名:」が入るので、続けて語を入力します\n- 履歴と保存した条件はブラウザーにアプリごとに保存されます。別のブラウザーや PC には引き継がれません\n\n![検索文字の履歴と保存した条件（☆）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c4e017ef-4fb8-4e2c-b43b-0fbb01ef233d.png)\n\n# ツールバーと列の操作\n\n- タイトル行（検索欄の右）に、＋（行を追加）・ゴミ箱（選択行を削除）のアイコンと、［追加を確定 (n)］（自動保存で確定していない追加行があるとき）または［保存］［すべて取り消す］（明示保存）を、設定と保存方式に合わせて出します\n- タイトル行の右端の再読込のアイコン（回る矢印）で、レコードを取得し直します\n- 件数の左の ⧉ を押すと、表に出ているレコード（検索で絞り込んだ分）を kintone の一覧で新しいタブに開きます。その一覧から一括更新プラグインなどで一括の処理ができます（一括更新プラグインは一覧の絞り込み条件を対象にします）。処理した後は、こちらの再読込のアイコンで取り直してください\n  - 一覧の URL にレコード番号を並べる仕組みのため、URL の長さの制限に収まる先頭の件数までになります（超えるときは確認が出ます）。カスタム一覧では「（すべて）」の一覧で開きます\n  - 保存していない変更があるときは確認が出ます（開く一覧には保存済みの値が出ます。確定していない追加行は入りません）\n- タイトル行の右端のツールのアイコン（? の左）を押すと、ツールバーが出ます（押している間はアイコンが青）。ツールバーには次のものがあります\n  - 取得件数: 取得するレコード数の上限（500 / 1,000 / 5,000 / 10,000 件）\n  - 固定カラム数: 横に送っても左に残す列の数\n  - 画像サイズ: 添付ファイルの縮小画像の大きさ（なし / 100〜500）。表か展開部に添付ファイルの列があるときだけ出ます。この画面だけの切り替えで、次に開くとプラグイン設定の値に戻ります\n  - 列の状態を初期化: 覚えている列幅・並び・表示する項目・固定カラム数を消して、プラグイン設定の初期値に戻します（レコードは取得し直さず、保存していない変更は残ります）\n  - 表示する項目: 押すと項目のタグの欄が出ます。タグを外すと列を隠し、足すと出します。タグをドラッグすると列の並びが変わります（列見出しのドラッグと同じ）。テーブルのタグを外すと、行の展開部にもそのテーブルを出しません\n- 文字列（複数行）は改行して出します。4 行まで出し、続きはセルの中でスクロールします（行の高さが行数で伸びません）\n- 列見出しの右端をドラッグすると列幅、列見出しをドラッグすると列の順番を変えます\n- 右上の全画面のアイコンで、全画面表示・通常表示を切り替えます。その左の「?」で操作の説明（検索の書き方、検索の操作、編集、保存、追加と削除、テーブル、表示 のタブ）が開きます\n- 列幅、列の並び、表示する項目、固定カラム数は、ブラウザーにアプリと一覧ごとに記憶し、次に開いたときに戻します\n\n![タイトル行とツールバー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d71cc880-fb32-415e-93c6-d18c35ff29e2.png)\n\n# 添付ファイル\n\n## 縮小画像\n\nプラグイン設定の［詳細設定］の「画像サイズ」を選ぶと、添付ファイルの列に縮小画像を出します（なしを選ぶと出しません。文字検索プラグインと同じ）。\n\n- 画像の枠は画像サイズの正方形です。画像は枠に収めて出します\n- 縮小画像は 1 段分の高さまで出し、ファイルが多いときはセルの中でスクロールします（行の高さが画像の数で伸びません）。ファイル名と ✎ はスクロールしても見えます\n- 画像 / pdf のファイル名と縮小画像を押すと、ビューワで開きます\n- テーブルの子の添付ファイルも同じです\n\n![添付ファイルの縮小画像（画像サイズ 100）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4e1392e0-a6e7-4ded-bc86-938b5fdd1ef4.png)\n\n## 追加・削除・並べ替え\n\n「編集を許可する項目」で添付ファイルを選ぶと、セルの先頭に ✎ が出ます。✎ を押すと（Enter・ダブルクリックでも）添付ファイルの画面が開きます。\n\n- ［ファイルを追加］（複数選べます）か、画面へのドロップで足します。足したファイルはその場でアップロードします\n- ↑ ↓ で並べ替え、× で外します\n- OK でセルに入れます。保存はほかの項目と同じです（自動保存 / 明示保存）。外したファイルは、保存すると元に戻せません\n- 保存済みのファイルを並べ替えると、OK で、動かしたファイルから後ろのファイルを上げ直します。kintone は保存済みのファイルの並びを変えないためです（足したファイルは後ろに付きます）。ファイルが大きいとその分時間がかかります\n- 足したファイルと上げ直したファイルは、保存するまで kintone の一時保管領域に置かれます。保存しなければ 3 日で消えます（ディスク使用量に入ります）\n- テーブルの子の添付ファイルも同じです\n- 貼り付け・Delete・下へ埋める（Ctrl+D）は、添付ファイルのセルを変えません\n- 選択行の複写と子行の複製では、添付ファイルは写しません（ほかの行のファイルはそのまま送れないため）\n\n![添付ファイルの画面 — 足したファイルに「追加」](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/cf9ce233-b16e-4631-bc22-af18984be220.png)\n\n![操作の説明（?）の「編集」タブ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/806e5944-9740-405d-8d1c-e8f8788d25f8.png)\n\n# カスタム一覧\n\nプラグイン設定でカスタム一覧を選ぶと、カスタム一覧の画面でグリッドを表示します（初期表示は固定で on）。表示する項目はプラグイン設定の「表示する項目」で指定します。指定しない場合はフォームの全項目です。\n\n# プラグインの追加\n\n- 「kintone システム管理 \u003e プラグイン」で追加します\n- 「アプリの設定 \u003e プラグイン」で、アプリに追加します\n\n![アプリの設定のプラグイン — 一覧編集の歯車から設定画面へ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4e56ad9a-162e-4350-b65c-8f383398d8ad.png)\n\n# プラグインの設定\n\n![プラグインの設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ebfc50c5-0329-4acd-a1b4-1e7e2ea2681a.png)\n\n共通の設定（ツールバー）\n\n- プラグインを使う: プラグインを有効にする場合、チェック\n- ［詳細設定］: 全部の一覧に共通の設定を開きます。ボタンの右に、今の保存方式・計算式連携（画像を出すときは画像サイズも）を表示します\n\n詳細設定\n\n- 保存方式: 自動保存 / 明示保存\n- 保存前の確認: 明示保存の［保存］で件数を確かめる画面を出します（自動保存では使いません）\n- 分割保存の確認: 2,000 件を超える変更を分けて保存するときに確かめます\n- 計算式プラグイン: このアプリに計算式プラグインが追加されているかを表示します（設定ではありません）\n- 計算式連携: 「計算式プラグイン連携」参照\n- 画像サイズ: 添付ファイルの縮小画像の大きさの初期値。なしなら出しません（「添付ファイル」参照）\n- ［保存］は設定画面に入れるだけです。設定画面の「保存する」で保存します\n\n![詳細設定の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/643bc506-f303-43f0-afd9-133fe4450d4b.png)\n\n一覧ごとの設定（対象の一覧にチェックを入れます。カスタム一覧も選べます）\n\n- 初期表示: 一覧を開いた直後からグリッドを表示します（カスタム一覧は固定で on）\n- 取得件数、固定カラム数: 一覧画面の初期値です\n- 表示する項目: グリッドに出す項目と並び。選ばなければ一覧の項目（カスタム一覧はフォームの全項目）\n- 表示するテーブル: 行の展開部に出すテーブル。選ばなければ、表示する項目に入っているテーブル\n- テーブルの表示項目: 展開部のテーブルに出す子の項目と並び。テーブルごとに、1 つも選ばなければ全部の項目\n- 編集を許可する項目: グリッドで編集できる項目。計算・ルックアップのコピー先・自動計算の文字列・レコード番号などは候補に出ません。テーブルの子の項目も選べます\n- 追加 / 削除: 一覧画面のタイトル行に ＋（行を追加）とゴミ箱（選択行を削除）を出します\n- 選択行の複写: 写す項目を選ぶと、一覧画面のタイトル行に複写のアイコンを出します。何も選ばなければ出しません（レコードの追加の権限がある利用者だけ使えます）\n- 追加行の初期値: ＋（行を追加）で入れる値。ドロップダウン・ラジオボタン・チェックボックス・複数選択は、セルを押して選択肢の一覧から選びます（言語ごとの名称を付けた選択肢も、保存されるのはデフォルトの名称なので、どの言語の利用者にも入ります）。ほかの項目の書き方は貼り付けと同じです（日付は 2026-10-24、複数の値はカンマ区切り、ユーザー・組織・グループはコードか名前）。ログインユーザーにしたいときは、kintone のフォームでユーザー選択の初期値を「ログインユーザー」にします。種別ごとの書き方は設定の説明（?）の「編集」タブにあります\n- テーブルの全展開: チェックすると、一覧を開いたときにテーブルのある行を開きます（表の並びで先頭から 300 行まで）\n- 「保存する」をクリックします\n\nツールバーの［一覧の設定をコピー］で、ある一覧の設定をほかの一覧に写せます。コピー元の一覧（初めは最後に押した行）、写す設定（初期表示・取得件数・表示する項目など。初めは全部。［すべて選択］［すべて解除］でまとめて選べます）、コピー先の一覧を選んで［コピー］を押します。「コピー先の一覧で使う」をチェックすると、コピー先の左端のチェックも付けます。保存は「保存する」です。\n\n![一覧の設定をコピーの画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a032968e-a4b1-4e16-a8c6-12a0c5764a78.png)\n\n「表示する項目」「表示するテーブル」「テーブルの表示項目」「編集を許可する項目」「追加行の初期値」の列は、セルを押すと選ぶ画面が開きます。候補はフォームの配置の順に並びます。「表示する項目」「表示するテーブル」「テーブルの表示項目」は、チェックした項目を上から順に使い、ドラッグで並べ替えられます。\n\n![編集を許可する項目の選択 — テーブルの子の項目も選べる](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d71fadb8-c86a-4a8b-b3f6-17a4db12251c.png)\n\n![追加行の初期値 — ドロップダウンは選択肢から選ぶ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/b0648c11-b291-4fab-9f38-6cb1f243c632.png)\n\n## 設定の説明（?）とプラグインの概要（i）\n\n「一覧画面情報」の右端のアイコンで、次の 2 つの画面が開きます。\n\n- 「?」（全画面の左）: 設定の説明です。「一覧画面情報」「編集」「保存」「一覧画面との関係」のタブで、設定画面の各欄の意味を説明します\n- 「i」（? の左）: プラグインの概要です\n\n![設定の説明（?）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3af878f3-bf42-44cb-94b5-88fc388c62f6.png)\n\n## 設定の保存とバックアップ\n\n設定画面の下端のボタンで、設定のダウンロード（JSON）とアップロード、設定の Markdown 形式でのクリップボードへのコピーができます。\n\n※フォーム変更時は、本番環境にフォーム変更を反映後に、本プラグイン設定を行ってください。\n\n# 注意事項\n- 既に、JavaScript によるカスタマイズを行っているアプリの場合、処理が競合して、エラーになる場合があります。その場合は、該当するアプリでプラグインの使用を中止してください\n- 削除したレコードは元に戻せません\n- 計算式プラグイン連携で、計算式がレコード番号・作成者・作成日時・更新者・更新日時や、添付ファイルの fileKey を使っているときは、保存の前の値で計算します（足したファイルの fileKey はアップロードしたときの一時的な値）。追加・更新で kintone が入れた値は計算に入りません（「計算式プラグイン連携」参照）\n- 検索文字の履歴、保存した検索条件、列の状態はブラウザー（localStorage）に保存されます。ブラウザーのサイトデータを消すと無くなります\n- 表示項目が多くかつレコード数が多い場合、ブラウザーで大量のメモリを使用し動作が遅くなります。その場合は、標準のフィルター機能や取得件数でレコード数を絞って使用してください\n","coediting":false,"comments_count":0,"created_at":"2026-10-25T19:14:44+09:00","group":null,"id":"ad4705f630e97c605f54","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]}],"title":"rex0220 一覧編集プラグイン","updated_at":"2026-10-26T08:44:36+09:00","url":"https://qiita.com/rex0220/items/ad4705f630e97c605f54","user":{"description":"","facebook_id":"","followees_count":0,"followers_count":155,"github_login_name":"rex0220","id":"rex0220","items_count":756,"linkedin_id":"","location":"","name":"","organization":"","permanent_id":100572,"profile_image_url":"https://qiita-image-store.s3.amazonaws.com/0/100572/profile-images/1473708137","team_only":false,"twitter_screen_name":"rex02201","website_url":"https://rex0220.stores.jp/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:271\"\u003ekintacoです。自社のいいね！ボタンでは、反応したユーザーの表示名をHTMLへ差し込む前にエスケープしています。この記事では実コードのescapeHtmlをそのまま取り出し、文字列とHTMLの違いを確認します。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:203\"\u003eいいねの保存処理や、kintone REST APIは含みません。APIから取得した値だから、そのままHTMLとして扱ってよいわけではない、という点に絞った解説です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:71\"\u003e\n\u003cspan id=\"textcontentで表示できるならまず文字列として扱う\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#textcontent%E3%81%A7%E8%A1%A8%E7%A4%BA%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%AA%E3%82%89%E3%81%BE%E3%81%9A%E6%96%87%E5%AD%97%E5%88%97%E3%81%A8%E3%81%97%E3%81%A6%E6%89%B1%E3%81%86\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003etextContentで表示できるなら、まず文字列として扱う\u003c/h2\u003e\n\u003cp data-sourcepos=\"6:1-6:240\"\u003e名前を表示するだけなら、DOM要素のtextContentへ設定すると、タグを文字として扱えます。HTMLテンプレートへ差し込む構成を使う場合は、差し込む文脈に合わせた処理が必要です。\u003c/p\u003e\n\u003cp data-sourcepos=\"8:1-8:175\"\u003e以下はHTMLのテキスト部分向けのエスケープです。スクリプト、CSS、URL、イベント属性に使う汎用的な無害化関数ではありません。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"10:1-19:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003eescapeHtml\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003estr\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003estr\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/\u0026amp;/g\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026amp;amp;\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/\u0026lt;/g\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026amp;lt;\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/\u0026gt;/g\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026amp;gt;\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/\"/g\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026amp;quot;\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/'/g\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026amp;#039;\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003ch2 data-sourcepos=\"21:1-21:28\"\u003e\n\u003cspan id=\"を先に置き換える\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%82%92%E5%85%88%E3%81%AB%E7%BD%AE%E3%81%8D%E6%8F%9B%E3%81%88%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e\u0026amp;を先に置き換える\u003c/h2\u003e\n\u003cp data-sourcepos=\"22:1-22:209\"\u003e最初に\u0026amp;を置き換え、そのあと\u0026lt;・\u0026gt;・ダブルクオート・シングルクオートを置き換えます。あとから生成した\u0026lt;などの\u0026amp;まで再度変換しないための順番です。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"24:1-27:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003eescapeHtml\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026lt;管理者 \u0026amp; 担当者\u0026gt;\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e// \u0026amp;lt;管理者 \u0026amp;amp; 担当者\u0026amp;gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"29:1-29:241\"\u003e同じ文字列へ二度適用すると、エンティティ中の\u0026amp;も変換されます。加工済みかどうか曖昧な値を何度も通すのではなく、元データを保持し、表示する直前に一度だけ変換します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"31:1-31:66\"\u003e\n\u003cspan id=\"ユーザー名の表示とユーザーの識別を分ける\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E5%90%8D%E3%81%AE%E8%A1%A8%E7%A4%BA%E3%81%A8%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E8%AD%98%E5%88%A5%E3%82%92%E5%88%86%E3%81%91%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eユーザー名の表示と、ユーザーの識別を分ける\u003c/h2\u003e\n\u003cp data-sourcepos=\"32:1-32:339\"\u003eいいね済みかを判断する場合には、表示名ではなくユーザーコードを比較します。同じ表示名が複数存在したり、名前が変更されたりするからです。表示用テキストのエスケープだけで、ユーザーの一意性や編集権限が保証されるわけではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"34:1-34:33\"\u003e\n\u003cspan id=\"保存の競合も別の問題\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BF%9D%E5%AD%98%E3%81%AE%E7%AB%B6%E5%90%88%E3%82%82%E5%88%A5%E3%81%AE%E5%95%8F%E9%A1%8C\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e保存の競合も別の問題\u003c/h2\u003e\n\u003cp data-sourcepos=\"35:1-35:345\"\u003e画面へ安全に文字を表示できても、複数人が同時にいいねを保存したときの競合は解決しません。レコード更新を実装する場合には、権限、取得と更新の間の変更、リビジョン指定、失敗後の表示を別に設計します。このサンプルに保存処理はありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"37:1-37:42\"\u003e\n\u003cspan id=\"確認したことと未確認のこと\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%A2%BA%E8%AA%8D%E3%81%97%E3%81%9F%E3%81%93%E3%81%A8%E3%81%A8%E6%9C%AA%E7%A2%BA%E8%AA%8D%E3%81%AE%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e確認したことと未確認のこと\u003c/h2\u003e\n\u003cp data-sourcepos=\"38:1-38:360\"\u003e特殊文字、複数の文字が混ざる場合、日本語、二重適用をNode.jsで確認しました。実ブラウザーでの攻撃コード実行テストや、kintoneでのいいね保存テストは含みません。テンプレートへ組み込む場合は、その出力箇所が本当にHTMLテキストの文脈かも確認してください。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"40:1-40:57\"\u003e\n\u003cspan id=\"ボタンと保存先を設定して使いたい場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%9C%E3%82%BF%E3%83%B3%E3%81%A8%E4%BF%9D%E5%AD%98%E5%85%88%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%A6%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eボタンと保存先を設定して使いたい場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"42:1-42:326\"\u003e\u003ca href=\"https://kintaco.wisemap.biz/plugins/like-button/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=like\" rel=\"nofollow noopener\" target=\"_blank\"\u003e自社のいいね！ボタンプラグインの仕様・設定画面\u003c/a\u003eに、設定から利用する方法もまとめています。サンプルと製品版の対応範囲は異なります。\u003c/p\u003e\n\u003cp data-sourcepos=\"44:1-44:351\"\u003e無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"46:1-46:15\"\u003e\n\u003cspan id=\"参考資料\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8F%82%E8%80%83%E8%B3%87%E6%96%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e参考資料\u003c/h2\u003e\n\u003cul data-sourcepos=\"47:1-49:0\"\u003e\n\u003cli data-sourcepos=\"47:1-47:117\"\u003e\u003ca href=\"https://developer.mozilla.org/ja/docs/Web/API/Element/innerHTML\" rel=\"nofollow noopener\" target=\"_blank\"\u003e安全でないinnerHTMLの利用に注意する\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"48:1-49:0\"\u003e\u003ca href=\"https://developer.mozilla.org/ja/docs/Web/API/Node/textContent\" rel=\"nofollow noopener\" target=\"_blank\"\u003eNode.textContent\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"50:1-50:84\"\u003e製品仕様と実コードの確認元：LikeButton/src/js/desktop.js（1.0.6）。\u003c/p\u003e\n","body":"kintacoです。自社のいいね！ボタンでは、反応したユーザーの表示名をHTMLへ差し込む前にエスケープしています。この記事では実コードのescapeHtmlをそのまま取り出し、文字列とHTMLの違いを確認します。\n\nいいねの保存処理や、kintone REST APIは含みません。APIから取得した値だから、そのままHTMLとして扱ってよいわけではない、という点に絞った解説です。\n\n## textContentで表示できるなら、まず文字列として扱う\n名前を表示するだけなら、DOM要素のtextContentへ設定すると、タグを文字として扱えます。HTMLテンプレートへ差し込む構成を使う場合は、差し込む文脈に合わせた処理が必要です。\n\n以下はHTMLのテキスト部分向けのエスケープです。スクリプト、CSS、URL、イベント属性に使う汎用的な無害化関数ではありません。\n\n```javascript\nfunction escapeHtml(str) {\n  return String(str)\n    .replace(/\u0026/g, '\u0026amp;')\n    .replace(/\u003c/g, '\u0026lt;')\n    .replace(/\u003e/g, '\u0026gt;')\n    .replace(/\"/g, '\u0026quot;')\n    .replace(/'/g, '\u0026#039;');\n}\n```\n\n## \u0026を先に置き換える\n最初に\u0026を置き換え、そのあと\u003c・\u003e・ダブルクオート・シングルクオートを置き換えます。あとから生成した\u0026lt;などの\u0026まで再度変換しないための順番です。\n\n```javascript\nconsole.log(escapeHtml('\u003c管理者 \u0026 担当者\u003e'));\n// \u0026lt;管理者 \u0026amp; 担当者\u0026gt;\n```\n\n同じ文字列へ二度適用すると、エンティティ中の\u0026も変換されます。加工済みかどうか曖昧な値を何度も通すのではなく、元データを保持し、表示する直前に一度だけ変換します。\n\n## ユーザー名の表示と、ユーザーの識別を分ける\nいいね済みかを判断する場合には、表示名ではなくユーザーコードを比較します。同じ表示名が複数存在したり、名前が変更されたりするからです。表示用テキストのエスケープだけで、ユーザーの一意性や編集権限が保証されるわけではありません。\n\n## 保存の競合も別の問題\n画面へ安全に文字を表示できても、複数人が同時にいいねを保存したときの競合は解決しません。レコード更新を実装する場合には、権限、取得と更新の間の変更、リビジョン指定、失敗後の表示を別に設計します。このサンプルに保存処理はありません。\n\n## 確認したことと未確認のこと\n特殊文字、複数の文字が混ざる場合、日本語、二重適用をNode.jsで確認しました。実ブラウザーでの攻撃コード実行テストや、kintoneでのいいね保存テストは含みません。テンプレートへ組み込む場合は、その出力箇所が本当にHTMLテキストの文脈かも確認してください。\n\n## ボタンと保存先を設定して使いたい場合\n\n[自社のいいね！ボタンプラグインの仕様・設定画面](https://kintaco.wisemap.biz/plugins/like-button/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=like)に、設定から利用する方法もまとめています。サンプルと製品版の対応範囲は異なります。\n\n無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\n\n## 参考資料\n- [安全でないinnerHTMLの利用に注意する](https://developer.mozilla.org/ja/docs/Web/API/Element/innerHTML)\n- [Node.textContent](https://developer.mozilla.org/ja/docs/Web/API/Node/textContent)\n\n製品仕様と実コードの確認元：LikeButton/src/js/desktop.js（1.0.6）。\n","coediting":false,"comments_count":0,"created_at":"2026-10-24T16:16:44+09:00","group":null,"id":"674030ef0793787dfe75","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"xss","versions":[]}],"title":"kintoneのいいね表示を題材にHTMLエスケープを確認する｜ユーザー名を安全に表示するJavaScript","updated_at":"2026-10-24T16:16:44+09:00","url":"https://qiita.com/kintaco/items/674030ef0793787dfe75","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:192\"\u003ekintacoです。自社のテーブル値計算プラグインのcopyValueを題材に、「前の行のvalueを、そのまま次の行へ代入する」ときの注意点を解説します。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:262\"\u003eこの記事は、コピーする値を作る純粋関数です。kintoneのフィールド変更イベントには接続せず、レコードの保存も行いません。製品版の追加行検出・再計算順・循環参照チェックは含みません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:63\"\u003e\n\u003cspan id=\"文字列選択肢ユーザーでは値構造が違う\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%96%87%E5%AD%97%E5%88%97%E9%81%B8%E6%8A%9E%E8%82%A2%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%A7%E3%81%AF%E5%80%A4%E6%A7%8B%E9%80%A0%E3%81%8C%E9%81%95%E3%81%86\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e文字列、選択肢、ユーザーでは値構造が違う\u003c/h2\u003e\n\u003cp data-sourcepos=\"6:1-6:265\"\u003e文字列は文字列ですが、チェックボックスは配列、ユーザー選択はcodeを持つオブジェクトの配列です。配列を同じ参照のまま渡すと、次の行を変えたつもりが元の値にも影響することがあります。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"8:1-28:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003ecopyPreviousValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eCHECK_BOX\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003esome\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ev\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003ev\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003estring\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eチェックボックスには選択肢の配列が必要です。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e[...\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003esome\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ev\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003ev\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003ev\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003estring\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eユーザー選択にはcodeを持つ配列が必要です。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ev\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e({\u003c/span\u003e\u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ev\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e}));\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSINGLE_LINE_TEXT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e!=\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003estring\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e文字列が必要です。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eこのサンプルの対象外です。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003ch2 data-sourcepos=\"30:1-30:52\"\u003e\n\u003cspan id=\"ユーザーは表示名ではなくcodeを渡す\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AF%E8%A1%A8%E7%A4%BA%E5%90%8D%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8Fcode%E3%82%92%E6%B8%A1%E3%81%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eユーザーは表示名ではなくcodeを渡す\u003c/h2\u003e\n\u003cp data-sourcepos=\"31:1-31:299\"\u003e製品内のcopyValueも、ユーザー・組織・グループをcodeの配列へ作り直します。このサンプルはチェックボックスとユーザー選択だけを対象にし、他の形式はエラーにしています。表示名nameを識別子の代わりには使いません。\u003c/p\u003e\n\u003cp data-sourcepos=\"33:1-33:315\"\u003eコピー元のオブジェクトへ新しい値を足すのではなく、毎回新しい配列とオブジェクトを作ります。ただし、これだけでは編集権限や選択肢の整合まで保証しません。実際のコピー前に、元と先の型・選択肢・編集可否を確認します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"35:1-35:30\"\u003e\n\u003cspan id=\"最終行とは限らない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%9C%80%E7%B5%82%E8%A1%8C%E3%81%A8%E3%81%AF%E9%99%90%E3%82%89%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e最終行とは限らない\u003c/h2\u003e\n\u003cp data-sourcepos=\"36:1-36:285\"\u003e行の追加位置は末尾とは限りません。途中に追加した行へコピーしたい場合は、そのイベントで追加された行を特定する必要があります。「テーブルの最後の行」をいつも対象にする実装にはしないでください。\u003c/p\u003e\n\u003cp data-sourcepos=\"38:1-38:253\"\u003e製品版は、イベントのchanges.rowや行IDなどから追加行を確認し、特定できないときに推測して既存行を書き換えない設計です。既存行の再計算と、新規追加行だけのコピーも分けています。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"40:1-40:45\"\u003e\n\u003cspan id=\"参照が共有されていないか試す\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8F%82%E7%85%A7%E3%81%8C%E5%85%B1%E6%9C%89%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%81%8B%E8%A9%A6%E3%81%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e参照が共有されていないか試す\u003c/h2\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"41:1-46:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eoriginal\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[{\u003c/span\u003e\u003cspan class=\"na\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003euser_a\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e担当者A\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e}];\u003c/span\u003e\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ecopied\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003ecopyPreviousValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eoriginal\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003ecopied\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003euser_b\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eoriginal\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e \u003cspan class=\"c1\"\u003e// user_a\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"48:1-48:201\"\u003e配列の独立性・codeの引き継ぎ・空配列・不正な型をNode.jsで確認しました。実際のkintone画面や、ユーザーコードが有効かどうかの確認は含みません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"50:1-50:63\"\u003e\n\u003cspan id=\"値のコピーと初期表示累計計算は別の役割\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%80%A4%E3%81%AE%E3%82%B3%E3%83%94%E3%83%BC%E3%81%A8%E5%88%9D%E6%9C%9F%E8%A1%A8%E7%A4%BA%E7%B4%AF%E8%A8%88%E8%A8%88%E7%AE%97%E3%81%AF%E5%88%A5%E3%81%AE%E5%BD%B9%E5%89%B2\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e値のコピーと初期表示・累計計算は別の役割\u003c/h2\u003e\n\u003cp data-sourcepos=\"51:1-51:297\"\u003eこのサンプルには、固定行の初期表示や累計計算は含みません。業務で必要なのが「追加時だけ引き継ぐ」動作なら、その後の手入力を再計算で上書きしないことも大切です。製品版では設定からタイミングを選べます。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"53:1-53:42\"\u003e\n\u003cspan id=\"画面で設定して使いたい場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%94%BB%E9%9D%A2%E3%81%A7%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%A6%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e画面で設定して使いたい場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"55:1-55:342\"\u003e\u003ca href=\"https://kintaco.wisemap.biz/plugins/table-value-calculation/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=previous\" rel=\"nofollow noopener\" target=\"_blank\"\u003e自社のテーブル値計算プラグインの仕様・設定画面\u003c/a\u003eに、設定から利用する方法もまとめています。サンプルと製品版の対応範囲は異なります。\u003c/p\u003e\n\u003cp data-sourcepos=\"57:1-57:351\"\u003e無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"59:1-59:15\"\u003e\n\u003cspan id=\"参考資料\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8F%82%E8%80%83%E8%B3%87%E6%96%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e参考資料\u003c/h2\u003e\n\u003cul data-sourcepos=\"60:1-62:0\"\u003e\n\u003cli data-sourcepos=\"60:1-60:83\"\u003e\u003ca href=\"https://cybozu.dev/ja/kintone/docs/overview/field-types/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eフィールド形式\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"61:1-62:0\"\u003e\u003ca href=\"https://cybozu.dev/ja/kintone/docs/js-api/events/create/create-change-event/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eレコード追加画面のフィールド変更イベント\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"63:1-63:92\"\u003e製品仕様と実コードの確認元：TableValueCalculation/src/js/core.js（1.0.1）。\u003c/p\u003e\n","body":"kintacoです。自社のテーブル値計算プラグインのcopyValueを題材に、「前の行のvalueを、そのまま次の行へ代入する」ときの注意点を解説します。\n\nこの記事は、コピーする値を作る純粋関数です。kintoneのフィールド変更イベントには接続せず、レコードの保存も行いません。製品版の追加行検出・再計算順・循環参照チェックは含みません。\n\n## 文字列、選択肢、ユーザーでは値構造が違う\n文字列は文字列ですが、チェックボックスは配列、ユーザー選択はcodeを持つオブジェクトの配列です。配列を同じ参照のまま渡すと、次の行を変えたつもりが元の値にも影響することがあります。\n\n```javascript\nfunction copyPreviousValue(type, value) {\n  if (type === 'CHECK_BOX') {\n    if (!Array.isArray(value) || value.some(v =\u003e typeof v !== 'string')) {\n      throw new Error('チェックボックスには選択肢の配列が必要です。');\n    }\n    return [...value];\n  }\n  if (type === 'USER_SELECT') {\n    if (!Array.isArray(value) || value.some(v =\u003e !v || typeof v.code !== 'string')) {\n      throw new Error('ユーザー選択にはcodeを持つ配列が必要です。');\n    }\n    return value.map(v =\u003e ({code: v.code}));\n  }\n  if (type === 'SINGLE_LINE_TEXT') {\n    if (value != null \u0026\u0026 typeof value !== 'string') throw new Error('文字列が必要です。');\n    return value == null ? '' : value;\n  }\n  throw new Error('このサンプルの対象外です。');\n}\n```\n\n## ユーザーは表示名ではなくcodeを渡す\n製品内のcopyValueも、ユーザー・組織・グループをcodeの配列へ作り直します。このサンプルはチェックボックスとユーザー選択だけを対象にし、他の形式はエラーにしています。表示名nameを識別子の代わりには使いません。\n\nコピー元のオブジェクトへ新しい値を足すのではなく、毎回新しい配列とオブジェクトを作ります。ただし、これだけでは編集権限や選択肢の整合まで保証しません。実際のコピー前に、元と先の型・選択肢・編集可否を確認します。\n\n## 最終行とは限らない\n行の追加位置は末尾とは限りません。途中に追加した行へコピーしたい場合は、そのイベントで追加された行を特定する必要があります。「テーブルの最後の行」をいつも対象にする実装にはしないでください。\n\n製品版は、イベントのchanges.rowや行IDなどから追加行を確認し、特定できないときに推測して既存行を書き換えない設計です。既存行の再計算と、新規追加行だけのコピーも分けています。\n\n## 参照が共有されていないか試す\n```javascript\nconst original = [{code: 'user_a', name: '担当者A'}];\nconst copied = copyPreviousValue('USER_SELECT', original);\ncopied[0].code = 'user_b';\nconsole.log(original[0].code); // user_a\n```\n\n配列の独立性・codeの引き継ぎ・空配列・不正な型をNode.jsで確認しました。実際のkintone画面や、ユーザーコードが有効かどうかの確認は含みません。\n\n## 値のコピーと初期表示・累計計算は別の役割\nこのサンプルには、固定行の初期表示や累計計算は含みません。業務で必要なのが「追加時だけ引き継ぐ」動作なら、その後の手入力を再計算で上書きしないことも大切です。製品版では設定からタイミングを選べます。\n\n## 画面で設定して使いたい場合\n\n[自社のテーブル値計算プラグインの仕様・設定画面](https://kintaco.wisemap.biz/plugins/table-value-calculation/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=previous)に、設定から利用する方法もまとめています。サンプルと製品版の対応範囲は異なります。\n\n無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\n\n## 参考資料\n- [フィールド形式](https://cybozu.dev/ja/kintone/docs/overview/field-types/)\n- [レコード追加画面のフィールド変更イベント](https://cybozu.dev/ja/kintone/docs/js-api/events/create/create-change-event/)\n\n製品仕様と実コードの確認元：TableValueCalculation/src/js/core.js（1.0.1）。\n","coediting":false,"comments_count":0,"created_at":"2026-10-24T16:16:32+09:00","group":null,"id":"69c298146c85accf1163","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"テーブル","versions":[]}],"title":"kintoneのテーブルで前行の値をコピーする前に｜配列とユーザー選択を壊さないJavaScript","updated_at":"2026-10-24T16:16:32+09:00","url":"https://qiita.com/kintaco/items/69c298146c85accf1163","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:287\"\u003ekintacoです。自社のアプリ情報出力プラグインには、フィールド定義からテーブル内の項目も取り出すflatten処理があります。この記事では、一覧用の配列に変換し、所属テーブルを残す小さな関数に再構成します。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:262\"\u003e入力はフォームのフィールド定義APIが返すpropertiesを想定したオブジェクトです。レコードの値を取得するAPIとは構造も目的も異なります。サンプルでは固定のデータを使い、APIへ通信しません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:82\"\u003e\n\u003cspan id=\"propertiesだけを浅く列挙するとテーブル内の列を見落とす\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#properties%E3%81%A0%E3%81%91%E3%82%92%E6%B5%85%E3%81%8F%E5%88%97%E6%8C%99%E3%81%99%E3%82%8B%E3%81%A8%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E5%86%85%E3%81%AE%E5%88%97%E3%82%92%E8%A6%8B%E8%90%BD%E3%81%A8%E3%81%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003epropertiesだけを浅く列挙すると、テーブル内の列を見落とす\u003c/h2\u003e\n\u003cp data-sourcepos=\"6:1-6:255\"\u003eサブテーブルはtypeがSUBTABLEで、その中のfieldsへ子項目が入ります。親だけを一覧へ入れると、商品名・数量などの列を確認できません。そこでテーブル自身を出力し、子のfieldsへ進みます。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"8:1-24:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003ecollectFields\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eproperties\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erows\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003ewalk\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efields\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003etableCode\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"nb\"\u003eObject\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eentries\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efields\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"p\"\u003e{}).\u003c/span\u003e\u003cspan class=\"nf\"\u003eforEach\u003c/span\u003e\u003cspan class=\"p\"\u003e(([\u003c/span\u003e\u003cspan class=\"nx\"\u003ekey\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e])\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003estring\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n        \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eフィールド定義の形式を確認してください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n      \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n      \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003ekey\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003elabel\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elabel\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003etableCode\u003c/span\u003e\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n      \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSUBTABLE\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"nf\"\u003ewalk\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003efields\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"nf\"\u003ewalk\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eproperties\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003ch2 data-sourcepos=\"26:1-26:54\"\u003e\n\u003cspan id=\"所属を残して値と定義を混同しない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%89%80%E5%B1%9E%E3%82%92%E6%AE%8B%E3%81%97%E3%81%A6%E5%80%A4%E3%81%A8%E5%AE%9A%E7%BE%A9%E3%82%92%E6%B7%B7%E5%90%8C%E3%81%97%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e所属を残して、値と定義を混同しない\u003c/h2\u003e\n\u003cp data-sourcepos=\"27:1-27:286\"\u003e例えば行が「テーブル: 明細、コード: 数量、type: NUMBER」であれば、フォームの列定義を表します。数量の実データを出しているわけではありません。この関数にはレコードの取得・追加・更新処理はありません。\u003c/p\u003e\n\u003cp data-sourcepos=\"29:1-29:303\"\u003e実コードのflattenはコードをキーにした辞書を作ります。この記事では所属テーブルを確認しやすい配列へ変換し、扱う情報を名前・コード・型に絞っています。製品版のExcel出力、権限一覧、参照先名称の取得は含みません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"31:1-31:48\"\u003e\n\u003cspan id=\"フォームの見た目順にはならない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%81%AE%E8%A6%8B%E3%81%9F%E7%9B%AE%E9%A0%86%E3%81%AB%E3%81%AF%E3%81%AA%E3%82%89%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eフォームの見た目順にはならない\u003c/h2\u003e\n\u003cp data-sourcepos=\"32:1-32:274\"\u003eこの関数の順番はpropertiesとfieldsの列挙順であり、画面の配置順ではありません。グループやラベルを含む見た目に合わせたい場合は、フォームのレイアウト定義も取得し、配置をたどる必要があります。\u003c/p\u003e\n\u003cp data-sourcepos=\"34:1-34:222\"\u003e製品版はフィールド定義とレイアウトを組み合わせ、ラベルやグループ所属なども出力します。この短いサンプルを、完全な設計書出力として扱わないでください。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"36:1-36:12\"\u003e\n\u003cspan id=\"検証例\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%A4%9C%E8%A8%BC%E4%BE%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e検証例\u003c/h2\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"37:1-44:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003ecollectFields\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e\n  \u003cspan class=\"na\"\u003e件名\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSINGLE_LINE_TEXT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003elabel\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e件名\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e},\u003c/span\u003e\n  \u003cspan class=\"na\"\u003e明細\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSUBTABLE\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003elabel\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e明細\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003efields\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"na\"\u003e数量\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eNUMBER\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003elabel\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e数量\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}));\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"46:1-46:243\"\u003e通常項目・テーブル・空の定義・コードの補完・入力を変更しないことをNode.jsで確認しました。実際のアプリ管理権限やAPI応答、Excelの出力結果をテストしたものではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"48:1-48:36\"\u003e\n\u003cspan id=\"実際にapiへ接続する場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%AE%9F%E9%9A%9B%E3%81%ABapi%E3%81%B8%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e実際にAPIへ接続する場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"49:1-49:318\"\u003e運用中と設定中のどちらを取得するか、取得するユーザーの権限、取得失敗をどう表示するかを設計します。設定を含む出力ファイルは、共有先にも注意します。設定一覧はバックアップやユーザー別の実効権限の計算とは異なります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"51:1-51:50\"\u003e\n\u003cspan id=\"設定と権限をexcelへまとめたい場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%AD%E5%AE%9A%E3%81%A8%E6%A8%A9%E9%99%90%E3%82%92excel%E3%81%B8%E3%81%BE%E3%81%A8%E3%82%81%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e設定と権限をExcelへまとめたい場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"53:1-53:333\"\u003e\u003ca href=\"https://kintaco.wisemap.biz/plugins/app-info-export/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=appinfo\" rel=\"nofollow noopener\" target=\"_blank\"\u003e自社のアプリ情報出力プラグインの仕様・設定画面\u003c/a\u003eに、設定から利用する方法もまとめています。サンプルと製品版の対応範囲は異なります。\u003c/p\u003e\n\u003cp data-sourcepos=\"55:1-55:351\"\u003e無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"57:1-57:15\"\u003e\n\u003cspan id=\"参考資料\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8F%82%E8%80%83%E8%B3%87%E6%96%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e参考資料\u003c/h2\u003e\n\u003cul data-sourcepos=\"58:1-60:0\"\u003e\n\u003cli data-sourcepos=\"58:1-58:106\"\u003e\u003ca href=\"https://cybozu.dev/ja/kintone/docs/rest-api/apps/form/get-form-fields/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eフィールドを取得する\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"59:1-60:0\"\u003e\u003ca href=\"https://cybozu.dev/ja/kintone/docs/rest-api/apps/form/get-form-layout/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eフォームのレイアウトを取得する\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"61:1-61:92\"\u003e製品仕様と実コードの確認元：AppInfoExport/src/js/export-model.js（1.0.2）。\u003c/p\u003e\n","body":"kintacoです。自社のアプリ情報出力プラグインには、フィールド定義からテーブル内の項目も取り出すflatten処理があります。この記事では、一覧用の配列に変換し、所属テーブルを残す小さな関数に再構成します。\n\n入力はフォームのフィールド定義APIが返すpropertiesを想定したオブジェクトです。レコードの値を取得するAPIとは構造も目的も異なります。サンプルでは固定のデータを使い、APIへ通信しません。\n\n## propertiesだけを浅く列挙すると、テーブル内の列を見落とす\nサブテーブルはtypeがSUBTABLEで、その中のfieldsへ子項目が入ります。親だけを一覧へ入れると、商品名・数量などの列を確認できません。そこでテーブル自身を出力し、子のfieldsへ進みます。\n\n```javascript\nfunction collectFields(properties) {\n  const rows = [];\n  function walk(fields, tableCode = '') {\n    Object.entries(fields || {}).forEach(([key, field]) =\u003e {\n      if (!field || typeof field.type !== 'string') {\n        throw new Error('フィールド定義の形式を確認してください。');\n      }\n      const code = field.code || key;\n      rows.push({code, label: field.label || code, type: field.type, tableCode});\n      if (field.type === 'SUBTABLE') walk(field.fields, code);\n    });\n  }\n  walk(properties);\n  return rows;\n}\n```\n\n## 所属を残して、値と定義を混同しない\n例えば行が「テーブル: 明細、コード: 数量、type: NUMBER」であれば、フォームの列定義を表します。数量の実データを出しているわけではありません。この関数にはレコードの取得・追加・更新処理はありません。\n\n実コードのflattenはコードをキーにした辞書を作ります。この記事では所属テーブルを確認しやすい配列へ変換し、扱う情報を名前・コード・型に絞っています。製品版のExcel出力、権限一覧、参照先名称の取得は含みません。\n\n## フォームの見た目順にはならない\nこの関数の順番はpropertiesとfieldsの列挙順であり、画面の配置順ではありません。グループやラベルを含む見た目に合わせたい場合は、フォームのレイアウト定義も取得し、配置をたどる必要があります。\n\n製品版はフィールド定義とレイアウトを組み合わせ、ラベルやグループ所属なども出力します。この短いサンプルを、完全な設計書出力として扱わないでください。\n\n## 検証例\n```javascript\nconsole.log(collectFields({\n  件名: {type: 'SINGLE_LINE_TEXT', label: '件名'},\n  明細: {type: 'SUBTABLE', label: '明細', fields: {\n    数量: {type: 'NUMBER', label: '数量'}\n  }}\n}));\n```\n\n通常項目・テーブル・空の定義・コードの補完・入力を変更しないことをNode.jsで確認しました。実際のアプリ管理権限やAPI応答、Excelの出力結果をテストしたものではありません。\n\n## 実際にAPIへ接続する場合\n運用中と設定中のどちらを取得するか、取得するユーザーの権限、取得失敗をどう表示するかを設計します。設定を含む出力ファイルは、共有先にも注意します。設定一覧はバックアップやユーザー別の実効権限の計算とは異なります。\n\n## 設定と権限をExcelへまとめたい場合\n\n[自社のアプリ情報出力プラグインの仕様・設定画面](https://kintaco.wisemap.biz/plugins/app-info-export/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=appinfo)に、設定から利用する方法もまとめています。サンプルと製品版の対応範囲は異なります。\n\n無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\n\n## 参考資料\n- [フィールドを取得する](https://cybozu.dev/ja/kintone/docs/rest-api/apps/form/get-form-fields/)\n- [フォームのレイアウトを取得する](https://cybozu.dev/ja/kintone/docs/rest-api/apps/form/get-form-layout/)\n\n製品仕様と実コードの確認元：AppInfoExport/src/js/export-model.js（1.0.2）。\n","coediting":false,"comments_count":0,"created_at":"2026-10-24T16:10:32+09:00","group":null,"id":"fd3cec4f12bd9455490b","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"REST-API","versions":[]}],"title":"kintoneのフィールド定義をJavaScriptで一覧化する｜テーブル内項目とレコードデータを分けて扱う","updated_at":"2026-10-24T16:10:32+09:00","url":"https://qiita.com/kintaco/items/fd3cec4f12bd9455490b","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:204\"\u003ekintaco編集部です。自社のレコード差分プラグインにあるcanonical処理を題材に、kintoneの値を「そのままJSON化して比較する」と起きる問題を整理します。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:312\"\u003eこの記事では、文字列・チェックボックス・ユーザー選択の3種類だけを比較します。画面への着色、基準値の取得タイミング、テーブル行IDの追跡は含みません。製品版にある数値・日時・添付ファイル等の正規化も省いています。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:48\"\u003e\n\u003cspan id=\"同じ意味なら同じ比較キーにする\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%90%8C%E3%81%98%E6%84%8F%E5%91%B3%E3%81%AA%E3%82%89%E5%90%8C%E3%81%98%E6%AF%94%E8%BC%83%E3%82%AD%E3%83%BC%E3%81%AB%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e同じ意味なら同じ比較キーにする\u003c/h2\u003e\n\u003cp data-sourcepos=\"6:1-6:253\"\u003e文字列では改行コードを揃えます。チェックボックスは選択順を無視します。ユーザー選択は表示名ではなくcodeを比べます。比較用の文字列を返し、実際のレコード値は書き換えません。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"8:1-33:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eSET_TYPES\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eSet\u003c/span\u003e\u003cspan class=\"p\"\u003e([\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eCHECK_BOX\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e]);\u003c/span\u003e\n\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003ecanonical\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eMULTI_LINE_TEXT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e...\u003c/span\u003e\u003cspan class=\"nx\"\u003eSET_TYPES\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"nf\"\u003eincludes\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eこのサンプルの比較対象外です。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eSET_TYPES\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ehas\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e配列を指定してください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eJSON\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003estringify\u003c/span\u003e\u003cspan class=\"p\"\u003e([...\u003c/span\u003e\u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eSet\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eitem\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003efield\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n        \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003eitem\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003eitem\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003estring\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ecodeが必要です。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n        \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eitem\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n      \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eitem\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}))].\u003c/span\u003e\u003cspan class=\"nf\"\u003esort\u003c/span\u003e\u003cspan class=\"p\"\u003e());\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e??\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/\u003c/span\u003e\u003cspan class=\"se\"\u003e\\r\\n?\u003c/span\u003e\u003cspan class=\"sr\"\u003e/g\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"se\"\u003e\\n\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003echanged\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ebefore\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eafter\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003ebefore\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003eafter\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003ebefore\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"nx\"\u003eafter\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e同じ型のフィールドを比較してください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nf\"\u003ecanonical\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ebefore\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"nf\"\u003ecanonical\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eafter\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003ch2 data-sourcepos=\"35:1-35:72\"\u003e\n\u003cspan id=\"選択順を無視するならコピーしてから並べ替える\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E9%81%B8%E6%8A%9E%E9%A0%86%E3%82%92%E7%84%A1%E8%A6%96%E3%81%99%E3%82%8B%E3%81%AA%E3%82%89%E3%82%B3%E3%83%94%E3%83%BC%E3%81%97%E3%81%A6%E3%81%8B%E3%82%89%E4%B8%A6%E3%81%B9%E6%9B%BF%E3%81%88%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e選択順を無視するなら、コピーしてから並べ替える\u003c/h2\u003e\n\u003cp data-sourcepos=\"36:1-36:328\"\u003eチェックボックスの配列をそのままsortすると、比較のために元データを変更してしまいます。サンプルではSetで重複を取り除き、別配列へ展開してから並べ替えます。チェックボックスに順序の意味を持たせる業務には適用しないでください。\u003c/p\u003e\n\u003cp data-sourcepos=\"38:1-38:252\"\u003eユーザー選択も同じ考え方で、codeを比較キーにします。表示名だけが変わっても、同じユーザーコードなら差分にしません。オブジェクト全体のJSON.stringifyでは、この区別ができません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"40:1-40:45\"\u003e\n\u003cspan id=\"基準値は参照のまま保持しない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%9F%BA%E6%BA%96%E5%80%A4%E3%81%AF%E5%8F%82%E7%85%A7%E3%81%AE%E3%81%BE%E3%81%BE%E4%BF%9D%E6%8C%81%E3%81%97%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e基準値は参照のまま保持しない\u003c/h2\u003e\n\u003cp data-sourcepos=\"41:1-41:310\"\u003e比較前に、基準となる値を複製しておく必要があります。基準と現在値が同じオブジェクトを指していると、編集後の値が両方へ反映され、差分が消えてしまいます。今回のサンプルの値はJSON互換なので、次の形で複製できます。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"43:1-45:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ebaseline\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eJSON\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eparse\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eJSON\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003estringify\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"47:1-47:378\"\u003eただし「いつ基準を固定するか」は別の設計問題です。編集画面表示直後に自動補正が走る場合や、別プラグインの初期設定がある場合には、表示直後と入力開始前で値が異なることがあります。製品版は入力開始前の表示値を基準にし、入力開始後の自動変更も差分に含めます。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"49:1-49:27\"\u003e\n\u003cspan id=\"サンプルの確認例\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AE%E7%A2%BA%E8%AA%8D%E4%BE%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eサンプルの確認例\u003c/h2\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"50:1-55:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003echanged\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eCHECK_BOX\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e外観\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e異音\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e]},\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eCHECK_BOX\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e異音\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e外観\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e]}\u003c/span\u003e\n\u003cspan class=\"p\"\u003e));\u003c/span\u003e \u003cspan class=\"c1\"\u003e// false\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"57:1-57:317\"\u003e改行差、選択順、ユーザー表示名、コード変更、型の不一致をNode.jsで確認しました。kintoneの実画面でのテストは含みません。基準値の取得、変更イベントとの接続、権限で取得できない項目を扱う処理は、組み込み先で別途必要です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"59:1-59:60\"\u003e\n\u003cspan id=\"違わないと比較できないを分ける\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E9%81%95%E3%82%8F%E3%81%AA%E3%81%84%E3%81%A8%E6%AF%94%E8%BC%83%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E3%82%92%E5%88%86%E3%81%91%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e「違わない」と「比較できない」を分ける\u003c/h2\u003e\n\u003cp data-sourcepos=\"60:1-60:401\"\u003eこのサンプルは型が違う・対象フィールドがない場合をエラーにします。判定不能をfalseにすると、値が変わっていないと誤解されるためです。一方、製品版の処理では比較対象外の項目をスキップするなど、フォーム全体を扱うための設計があります。そのまま置き換えるコードではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"62:1-62:54\"\u003e\n\u003cspan id=\"保存前の確認画面として使いたい場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BF%9D%E5%AD%98%E5%89%8D%E3%81%AE%E7%A2%BA%E8%AA%8D%E7%94%BB%E9%9D%A2%E3%81%A8%E3%81%97%E3%81%A6%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e保存前の確認画面として使いたい場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"64:1-64:323\"\u003e\u003ca href=\"https://kintaco.wisemap.biz/plugins/record-diff/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=diff\" rel=\"nofollow noopener\" target=\"_blank\"\u003e自社のレコード差分プラグインの仕様・設定画面\u003c/a\u003eで、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。\u003c/p\u003e\n\u003cp data-sourcepos=\"66:1-66:351\"\u003e無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"68:1-68:15\"\u003e\n\u003cspan id=\"参考資料\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8F%82%E8%80%83%E8%B3%87%E6%96%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e参考資料\u003c/h2\u003e\n\u003cul data-sourcepos=\"69:1-71:0\"\u003e\n\u003cli data-sourcepos=\"69:1-69:83\"\u003e\u003ca href=\"https://cybozu.dev/ja/kintone/docs/overview/field-types/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eフィールド形式\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"70:1-71:0\"\u003e\u003ca href=\"https://cybozu.dev/ja/kintone/docs/js-api/record/get-record/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eレコードの値を取得する\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"72:1-72:81\"\u003e製品仕様と実コードの確認元：RecordDiff/src/js/core.js（1.0.2）。\u003c/p\u003e\n","body":"kintaco編集部です。自社のレコード差分プラグインにあるcanonical処理を題材に、kintoneの値を「そのままJSON化して比較する」と起きる問題を整理します。\n\nこの記事では、文字列・チェックボックス・ユーザー選択の3種類だけを比較します。画面への着色、基準値の取得タイミング、テーブル行IDの追跡は含みません。製品版にある数値・日時・添付ファイル等の正規化も省いています。\n\n## 同じ意味なら同じ比較キーにする\n文字列では改行コードを揃えます。チェックボックスは選択順を無視します。ユーザー選択は表示名ではなくcodeを比べます。比較用の文字列を返し、実際のレコード値は書き換えません。\n\n```javascript\nconst SET_TYPES = new Set(['CHECK_BOX', 'USER_SELECT']);\nfunction canonical(field) {\n  if (!field || !['MULTI_LINE_TEXT', ...SET_TYPES].includes(field.type)) {\n    throw new Error('このサンプルの比較対象外です。');\n  }\n  const value = field.value;\n  if (SET_TYPES.has(field.type)) {\n    if (!Array.isArray(value)) throw new Error('配列を指定してください。');\n    return JSON.stringify([...new Set(value.map(item =\u003e {\n      if (field.type === 'USER_SELECT') {\n        if (!item || typeof item.code !== 'string') throw new Error('codeが必要です。');\n        return item.code;\n      }\n      return String(item);\n    }))].sort());\n  }\n  return String(value ?? '').replace(/\\r\\n?/g, '\\n');\n}\nfunction changed(before, after) {\n  if (!before || !after || before.type !== after.type) {\n    throw new Error('同じ型のフィールドを比較してください。');\n  }\n  return canonical(before) !== canonical(after);\n}\n```\n\n## 選択順を無視するなら、コピーしてから並べ替える\nチェックボックスの配列をそのままsortすると、比較のために元データを変更してしまいます。サンプルではSetで重複を取り除き、別配列へ展開してから並べ替えます。チェックボックスに順序の意味を持たせる業務には適用しないでください。\n\nユーザー選択も同じ考え方で、codeを比較キーにします。表示名だけが変わっても、同じユーザーコードなら差分にしません。オブジェクト全体のJSON.stringifyでは、この区別ができません。\n\n## 基準値は参照のまま保持しない\n比較前に、基準となる値を複製しておく必要があります。基準と現在値が同じオブジェクトを指していると、編集後の値が両方へ反映され、差分が消えてしまいます。今回のサンプルの値はJSON互換なので、次の形で複製できます。\n\n```javascript\nconst baseline = JSON.parse(JSON.stringify(record));\n```\n\nただし「いつ基準を固定するか」は別の設計問題です。編集画面表示直後に自動補正が走る場合や、別プラグインの初期設定がある場合には、表示直後と入力開始前で値が異なることがあります。製品版は入力開始前の表示値を基準にし、入力開始後の自動変更も差分に含めます。\n\n## サンプルの確認例\n```javascript\nconsole.log(changed(\n  {type: 'CHECK_BOX', value: ['外観', '異音']},\n  {type: 'CHECK_BOX', value: ['異音', '外観']}\n)); // false\n```\n\n改行差、選択順、ユーザー表示名、コード変更、型の不一致をNode.jsで確認しました。kintoneの実画面でのテストは含みません。基準値の取得、変更イベントとの接続、権限で取得できない項目を扱う処理は、組み込み先で別途必要です。\n\n## 「違わない」と「比較できない」を分ける\nこのサンプルは型が違う・対象フィールドがない場合をエラーにします。判定不能をfalseにすると、値が変わっていないと誤解されるためです。一方、製品版の処理では比較対象外の項目をスキップするなど、フォーム全体を扱うための設計があります。そのまま置き換えるコードではありません。\n\n## 保存前の確認画面として使いたい場合\n\n[自社のレコード差分プラグインの仕様・設定画面](https://kintaco.wisemap.biz/plugins/record-diff/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=diff)で、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。\n\n無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\n\n## 参考資料\n- [フィールド形式](https://cybozu.dev/ja/kintone/docs/overview/field-types/)\n- [レコードの値を取得する](https://cybozu.dev/ja/kintone/docs/js-api/record/get-record/)\n\n製品仕様と実コードの確認元：RecordDiff/src/js/core.js（1.0.2）。\n","coediting":false,"comments_count":0,"created_at":"2026-10-24T16:10:14+09:00","group":null,"id":"bd834d6f6bae57027ba9","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"差分","versions":[]}],"title":"kintoneの変更前後をJavaScriptで比較する｜改行・選択順・ユーザーコードの正規化","updated_at":"2026-10-24T16:10:14+09:00","url":"https://qiita.com/kintaco/items/bd834d6f6bae57027ba9","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:296\"\u003ekintacoです。自社の重複有無・サジェスト表示プラグインでは、候補比較にNFKC正規化を使っています。この記事では実コードのnormal関数と同じ処理を使い、前方一致・部分一致・正規化後の重複除外に絞って解説します。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:244\"\u003eサンプルは配列を受け取って候補を返す純粋関数です。kintoneへのAPI照会、入力欄のDOM操作、候補の選択・入力は含みません。製品版にある編集距離による類似候補も省いています。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:54\"\u003e\n\u003cspan id=\"元の表記と比較用の文字列を分ける\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%85%83%E3%81%AE%E8%A1%A8%E8%A8%98%E3%81%A8%E6%AF%94%E8%BC%83%E7%94%A8%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E5%88%86%E3%81%91%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e元の表記と、比較用の文字列を分ける\u003c/h2\u003e\n\u003cp data-sourcepos=\"6:1-6:261\"\u003e表示用の値を正規化後の文字列に置き換えるのではなく、比較に使うキーだけを作ります。「ＡＢＣ　商事」と「abc商事」は同じキーになりますが、候補の表示文字列は最初の値を保持します。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"8:1-32:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003enormal\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003enormalize\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eNFKC\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003etoLocaleLowerCase\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eja\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003ereplace\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sr\"\u003e/\u003c/span\u003e\u003cspan class=\"se\"\u003e\\s\u003c/span\u003e\u003cspan class=\"sr\"\u003e+/g\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003esuggest\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eitems\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003elimit\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nb\"\u003eNumber\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisInteger\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003elimit\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003elimit\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003elimit\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e20\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003elimitは1～20の整数にしてください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eterm\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003enormal\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003eterm\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eseen\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eSet\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eranked\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[];\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003eitems\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eforEach\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003eitem\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eindex\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003eitem\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003estring\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ekey\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003enormal\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eitem\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003ekey\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003ekey\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"nx\"\u003eterm\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003eseen\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ehas\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ekey\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003escore\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003ekey\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003estartsWith\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eterm\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003ekey\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eincludes\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eterm\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003escore\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"nx\"\u003eseen\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eadd\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ekey\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"nx\"\u003eranked\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003epush\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e\u003cspan class=\"nx\"\u003eitem\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003escore\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eindex\u003c/span\u003e\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eranked\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003esort\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003escore\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"nx\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003escore\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eindex\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"nx\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eindex\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eslice\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003elimit\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erow\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eitem\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003ch2 data-sourcepos=\"34:1-34:30\"\u003e\n\u003cspan id=\"この順番にする理由\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%93%E3%81%AE%E9%A0%86%E7%95%AA%E3%81%AB%E3%81%99%E3%82%8B%E7%90%86%E7%94%B1\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eこの順番にする理由\u003c/h2\u003e\n\u003cp data-sourcepos=\"35:1-35:225\"\u003e空欄は候補検索しません。次に、入力自体と同じ候補は除きます。そのあと前方一致を先、部分一致を後として並べ、同じ比較キーを持つ候補は一度だけ採用します。\u003c/p\u003e\n\u003cp data-sourcepos=\"37:1-37:231\"\u003e候補内にHTMLらしい文字列があっても、この関数は文字列として返すだけです。画面へ表示する場合はtextContentなどを使い、innerHTMLへ未検証の値を流し込まないでください。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"39:1-39:31\"\u003e\n\u003cspan id=\"nfkcで解決しないこと\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#nfkc%E3%81%A7%E8%A7%A3%E6%B1%BA%E3%81%97%E3%81%AA%E3%81%84%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eNFKCで解決しないこと\u003c/h2\u003e\n\u003cp data-sourcepos=\"40:1-40:427\"\u003eNFKCは意味を理解する処理ではありません。「株式会社」と「（株）」、旧社名と新社名、カナの読み、翻訳語を同義語へ変換するわけではありません。また、空白をすべて除くと、業務によっては別の名前を同一候補として扱ってしまいます。空白や大小文字を区別すべき識別子には、そのまま使わないでください。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"42:1-42:48\"\u003e\n\u003cspan id=\"候補の整理と重複禁止は別の機能\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%80%99%E8%A3%9C%E3%81%AE%E6%95%B4%E7%90%86%E3%81%A8%E9%87%8D%E8%A4%87%E7%A6%81%E6%AD%A2%E3%81%AF%E5%88%A5%E3%81%AE%E6%A9%9F%E8%83%BD\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e候補の整理と重複禁止は別の機能\u003c/h2\u003e\n\u003cp data-sourcepos=\"43:1-43:279\"\u003eこの関数はブラウザーに渡された候補配列しか見ません。候補が出ないことを「同じデータが存在しない」根拠にしてはいけません。API取得件数の上限、閲覧権限、取得後に登録されたデータも考慮します。\u003c/p\u003e\n\u003cp data-sourcepos=\"45:1-45:213\"\u003e保存時の同時登録まで防ぎたい場合には、標準の重複禁止設定などを別途検討します。製品版の重複表示も警告であり、保存を禁止する機能ではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"47:1-47:24\"\u003e\n\u003cspan id=\"確認する入力例\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E5%85%A5%E5%8A%9B%E4%BE%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e確認する入力例\u003c/h2\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"48:1-51:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003esuggest\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eabc\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eＡＢＣ商事\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eabc 商事\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e東京ABC\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eabc\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e]));\u003c/span\u003e\n\u003cspan class=\"c1\"\u003e// ['ＡＢＣ商事', '東京ABC']\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"52:1-52:325\"\u003e正規化・完全一致除外・重複除外・順位・件数制限をNode.jsで確認しました。kintoneの実画面へ組み込んだ動作テストは含みません。日本語IME変換中に照会しない、古い非同期応答を破棄するなどの処理は、UIに接続する段階で必要になります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"54:1-54:54\"\u003e\n\u003cspan id=\"設定画面付きの入力支援が必要な場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%AD%E5%AE%9A%E7%94%BB%E9%9D%A2%E4%BB%98%E3%81%8D%E3%81%AE%E5%85%A5%E5%8A%9B%E6%94%AF%E6%8F%B4%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%AA%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e設定画面付きの入力支援が必要な場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"56:1-56:352\"\u003e\u003ca href=\"https://kintaco.wisemap.biz/plugins/duplicate-suggest/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=duplicate\" rel=\"nofollow noopener\" target=\"_blank\"\u003e自社の重複有無・サジェスト表示プラグインの仕様・設定画面\u003c/a\u003eで、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。\u003c/p\u003e\n\u003cp data-sourcepos=\"58:1-58:351\"\u003e無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"60:1-60:15\"\u003e\n\u003cspan id=\"参考資料\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8F%82%E8%80%83%E8%B3%87%E6%96%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e参考資料\u003c/h2\u003e\n\u003cul data-sourcepos=\"61:1-62:0\"\u003e\n\u003cli data-sourcepos=\"61:1-62:0\"\u003e\u003ca href=\"https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/normalize\" rel=\"nofollow noopener\" target=\"_blank\"\u003eString.prototype.normalize\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"63:1-63:87\"\u003e製品仕様と実コードの確認元：DuplicateSuggest/src/js/core.js（1.0.4）。\u003c/p\u003e\n","body":"kintacoです。自社の重複有無・サジェスト表示プラグインでは、候補比較にNFKC正規化を使っています。この記事では実コードのnormal関数と同じ処理を使い、前方一致・部分一致・正規化後の重複除外に絞って解説します。\n\nサンプルは配列を受け取って候補を返す純粋関数です。kintoneへのAPI照会、入力欄のDOM操作、候補の選択・入力は含みません。製品版にある編集距離による類似候補も省いています。\n\n## 元の表記と、比較用の文字列を分ける\n表示用の値を正規化後の文字列に置き換えるのではなく、比較に使うキーだけを作ります。「ＡＢＣ　商事」と「abc商事」は同じキーになりますが、候補の表示文字列は最初の値を保持します。\n\n```javascript\nfunction normal(value) {\n  return String(value).normalize('NFKC').toLocaleLowerCase('ja').replace(/\\s+/g, '');\n}\nfunction suggest(input, items, limit = 5) {\n  if (!Number.isInteger(limit) || limit \u003c 1 || limit \u003e 20) {\n    throw new Error('limitは1～20の整数にしてください。');\n  }\n  const term = normal(input);\n  if (!term) return [];\n  const seen = new Set();\n  const ranked = [];\n  items.forEach((item, index) =\u003e {\n    if (typeof item !== 'string') return;\n    const key = normal(item);\n    if (!key || key === term || seen.has(key)) return;\n    const score = key.startsWith(term) ? 0 : key.includes(term) ? 1 : -1;\n    if (score \u003c 0) return;\n    seen.add(key);\n    ranked.push({item, score, index});\n  });\n  return ranked.sort((a, b) =\u003e a.score - b.score || a.index - b.index)\n    .slice(0, limit).map(row =\u003e row.item);\n}\n```\n\n## この順番にする理由\n空欄は候補検索しません。次に、入力自体と同じ候補は除きます。そのあと前方一致を先、部分一致を後として並べ、同じ比較キーを持つ候補は一度だけ採用します。\n\n候補内にHTMLらしい文字列があっても、この関数は文字列として返すだけです。画面へ表示する場合はtextContentなどを使い、innerHTMLへ未検証の値を流し込まないでください。\n\n## NFKCで解決しないこと\nNFKCは意味を理解する処理ではありません。「株式会社」と「（株）」、旧社名と新社名、カナの読み、翻訳語を同義語へ変換するわけではありません。また、空白をすべて除くと、業務によっては別の名前を同一候補として扱ってしまいます。空白や大小文字を区別すべき識別子には、そのまま使わないでください。\n\n## 候補の整理と重複禁止は別の機能\nこの関数はブラウザーに渡された候補配列しか見ません。候補が出ないことを「同じデータが存在しない」根拠にしてはいけません。API取得件数の上限、閲覧権限、取得後に登録されたデータも考慮します。\n\n保存時の同時登録まで防ぎたい場合には、標準の重複禁止設定などを別途検討します。製品版の重複表示も警告であり、保存を禁止する機能ではありません。\n\n## 確認する入力例\n```javascript\nconsole.log(suggest('abc', ['ＡＢＣ商事', 'abc 商事', '東京ABC', 'abc']));\n// ['ＡＢＣ商事', '東京ABC']\n```\n正規化・完全一致除外・重複除外・順位・件数制限をNode.jsで確認しました。kintoneの実画面へ組み込んだ動作テストは含みません。日本語IME変換中に照会しない、古い非同期応答を破棄するなどの処理は、UIに接続する段階で必要になります。\n\n## 設定画面付きの入力支援が必要な場合\n\n[自社の重複有無・サジェスト表示プラグインの仕様・設定画面](https://kintaco.wisemap.biz/plugins/duplicate-suggest/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=duplicate)で、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。\n\n無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\n\n## 参考資料\n- [String.prototype.normalize](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/normalize)\n\n製品仕様と実コードの確認元：DuplicateSuggest/src/js/core.js（1.0.4）。\n","coediting":false,"comments_count":0,"created_at":"2026-10-23T16:13:03+09:00","group":null,"id":"8ad352c8d4e94028781e","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"Unicode","versions":[]}],"title":"JavaScriptで入力候補の表記ゆれを揃える｜NFKC正規化・前方一致・重複除外を実装","updated_at":"2026-10-23T16:13:03+09:00","url":"https://qiita.com/kintaco/items/8ad352c8d4e94028781e","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:238\"\u003ekintaco編集部です。自社のテーブルデータ初期表示プラグインにある「型に応じて値を整える」処理を題材に、レコード追加画面へ定型行を設定する小さなサンプルを作ります。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:370\"\u003e製品版の設定保存・項目取得・モバイル処理は含めず、PCの新規作成と、文字列・チェックボックス・ユーザー選択の3種類に絞ります。既存値がある場合は上書きせず、複製作成を対象外にしています。アクション経由では、対象3列に引き継いだ値がある場合に保持します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:30\"\u003e\n\u003cspan id=\"検証用のフィールド\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%A4%9C%E8%A8%BC%E7%94%A8%E3%81%AE%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e検証用のフィールド\u003c/h2\u003e\n\u003cul data-sourcepos=\"6:1-10:0\"\u003e\n\u003cli data-sourcepos=\"6:1-6:41\"\u003eテーブルコード：点検明細。\u003c/li\u003e\n\u003cli data-sourcepos=\"7:1-7:54\"\u003eテーブル内の文字列（1行）：設備名。\u003c/li\u003e\n\u003cli data-sourcepos=\"8:1-8:110\"\u003eテーブル内のチェックボックス：点検項目。選択肢に「外観」「異音」を用意。\u003c/li\u003e\n\u003cli data-sourcepos=\"9:1-10:0\"\u003eテーブル内のユーザー選択：担当者。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"11:1-11:195\"\u003eラベルではなくフィールドコードを合わせてください。自動計算・ルックアップ・入力不可のフィールドには、そのまま流用しないでください。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"13:1-47:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003efunction \u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003euse strict\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003etoFieldValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eCHECK_BOX\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"nf\"\u003eincludes\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003evalues\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e\n      \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003esplit\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e,\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ev\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nx\"\u003ev\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003etrim\u003c/span\u003e\u003cspan class=\"p\"\u003e()).\u003c/span\u003e\u003cspan class=\"nf\"\u003efilter\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nb\"\u003eBoolean\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e({\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e}))\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e[...\u003c/span\u003e\u003cspan class=\"nx\"\u003evalues\u003c/span\u003e\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003einitialize\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ereuse\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003etable\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e点検明細\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003etable\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003etable\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSUBTABLE\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erows\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003etable\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003etypes\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003e設備名\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSINGLE_LINE_TEXT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003e点検項目\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eCHECK_BOX\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003e担当者\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e};\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003esome\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erow\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nb\"\u003eObject\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eentries\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etypes\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003esome\u003c/span\u003e\u003cspan class=\"p\"\u003e(([\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e])\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e\n      \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"nx\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"nx\"\u003etype\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"nx\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e)))\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ehasValue\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erows\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003esome\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erow\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nb\"\u003eObject\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003ekeys\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003etypes\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003esome\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erow\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e!=\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}));\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ehasValue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"nx\"\u003etable\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e溶接ロボットX\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e真空ポンプB\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e].\u003c/span\u003e\u003cspan class=\"nf\"\u003emap\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ename\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"p\"\u003e({\u003c/span\u003e\u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"na\"\u003e設備名\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSINGLE_LINE_TEXT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nf\"\u003etoFieldValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eSINGLE_LINE_TEXT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e)},\u003c/span\u003e\n      \u003cspan class=\"na\"\u003e点検項目\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eCHECK_BOX\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nf\"\u003etoFieldValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eCHECK_BOX\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e外観,異音\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)},\u003c/span\u003e\n      \u003cspan class=\"na\"\u003e担当者\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"na\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nf\"\u003etoFieldValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eUSER_SELECT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e[])}\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}}));\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eevents\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eon\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eapp.record.create.show\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003einitialize\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e})();\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003ch2 data-sourcepos=\"49:1-49:58\"\u003e\n\u003cspan id=\"行のvalueとフィールドのvalueを区別する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A1%8C%E3%81%AEvalue%E3%81%A8%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%AEvalue%E3%82%92%E5%8C%BA%E5%88%A5%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e行のvalueと、フィールドのvalueを区別する\u003c/h2\u003e\n\u003cp data-sourcepos=\"50:1-50:372\"\u003eテーブルのvalueは「行オブジェクトの配列」です。各行のvalueには、フィールドコードをキーにしたオブジェクトが入ります。さらに、それぞれにtypeとvalueがあります。文字列は文字列、チェックボックスは選択肢の配列、ユーザー選択は「{code: ユーザーコード}」の配列です。\u003c/p\u003e\n\u003cp data-sourcepos=\"52:1-52:304\"\u003eユーザー名の表示文字列をcodeへ入れる実装にはしません。実在するコードと、対象利用者の権限・フィールド設定を確認します。このサンプルの担当者は未選択にし、ユーザーコードの変換自体はtoFieldValue単体で確認します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"54:1-54:54\"\u003e\n\u003cspan id=\"初期行を入れてよいかを先に判断する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%88%9D%E6%9C%9F%E8%A1%8C%E3%82%92%E5%85%A5%E3%82%8C%E3%81%A6%E3%82%88%E3%81%84%E3%81%8B%E3%82%92%E5%85%88%E3%81%AB%E5%88%A4%E6%96%AD%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e初期行を入れてよいかを先に判断する\u003c/h2\u003e\n\u003cp data-sourcepos=\"55:1-55:341\"\u003e新規作成でも、複製やアクションによって値を引き継ぐ場合があります。「表示イベントだから必ず空」とは限りません。そのため、reuseや既存の対象値を確認してから代入します。テーブルの構造が想定どおりでない場合も、推測して置き換えません。\u003c/p\u003e\n\u003cp data-sourcepos=\"57:1-57:256\"\u003eこの空欄判定は、今回の3列専用です。別の列を加える場合は、その列の値も含めて判定を設計してください。製品版は設定行を代入するため、このサンプルとは既存行の扱いが異なります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"59:1-59:24\"\u003e\n\u003cspan id=\"確認するケース\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E3%82%B1%E3%83%BC%E3%82%B9\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e確認するケース\u003c/h2\u003e\n\u003cul data-sourcepos=\"60:1-65:0\"\u003e\n\u003cli data-sourcepos=\"60:1-60:51\"\u003e通常の新規作成で2行が表示される。\u003c/li\u003e\n\u003cli data-sourcepos=\"61:1-61:80\"\u003e既存の設備名・チェック・担当者がある場合は保持する。\u003c/li\u003e\n\u003cli data-sourcepos=\"62:1-62:101\"\u003e複製作成、対象列に値を引き継いだアクション経由の作成では保持する。\u003c/li\u003e\n\u003cli data-sourcepos=\"63:1-63:71\"\u003eテーブルや列が見つからない場合は値を変えない。\u003c/li\u003e\n\u003cli data-sourcepos=\"64:1-65:0\"\u003e初期行の配列を生成し直しても、前回の変更が混ざらない。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"66:1-66:320\"\u003eNode.jsの模擬イベントで確認した範囲です。実際のkintone画面・権限・併用カスタマイズでの確認は含まないため、検証用アプリで表示と保存の両方を確かめてください。イベント内ではkintone.app.record.setを呼ばず、変更したeventを返します。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"68:1-68:51\"\u003e\n\u003cspan id=\"初期行を設定画面から管理する場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%88%9D%E6%9C%9F%E8%A1%8C%E3%82%92%E8%A8%AD%E5%AE%9A%E7%94%BB%E9%9D%A2%E3%81%8B%E3%82%89%E7%AE%A1%E7%90%86%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e初期行を設定画面から管理する場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"70:1-70:346\"\u003e\u003ca href=\"https://kintaco.wisemap.biz/plugins/table-data-initial/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=table\" rel=\"nofollow noopener\" target=\"_blank\"\u003e自社のテーブルデータ初期表示プラグインの仕様・設定画面\u003c/a\u003eで、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。\u003c/p\u003e\n\u003cp data-sourcepos=\"72:1-72:351\"\u003e無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"74:1-74:15\"\u003e\n\u003cspan id=\"参考資料\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8F%82%E8%80%83%E8%B3%87%E6%96%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e参考資料\u003c/h2\u003e\n\u003cul data-sourcepos=\"75:1-77:0\"\u003e\n\u003cli data-sourcepos=\"75:1-75:125\"\u003e\u003ca href=\"https://cybozu.dev/ja/kintone/docs/js-api/events/create/create-show-event/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eレコード追加画面の表示イベント\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"76:1-77:0\"\u003e\u003ca href=\"https://cybozu.dev/ja/kintone/docs/overview/field-types/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eフィールド形式\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"78:1-78:90\"\u003e製品仕様と実コードの確認元：TableDataInitial/src/js/desktop.js（1.0.5）。\u003c/p\u003e\n","body":"kintaco編集部です。自社のテーブルデータ初期表示プラグインにある「型に応じて値を整える」処理を題材に、レコード追加画面へ定型行を設定する小さなサンプルを作ります。\n\n製品版の設定保存・項目取得・モバイル処理は含めず、PCの新規作成と、文字列・チェックボックス・ユーザー選択の3種類に絞ります。既存値がある場合は上書きせず、複製作成を対象外にしています。アクション経由では、対象3列に引き継いだ値がある場合に保持します。\n\n## 検証用のフィールド\n- テーブルコード：点検明細。\n- テーブル内の文字列（1行）：設備名。\n- テーブル内のチェックボックス：点検項目。選択肢に「外観」「異音」を用意。\n- テーブル内のユーザー選択：担当者。\n\nラベルではなくフィールドコードを合わせてください。自動計算・ルックアップ・入力不可のフィールドには、そのまま流用しないでください。\n\n```javascript\n(function () {\n  'use strict';\n  function toFieldValue(type, value) {\n    if (!['CHECK_BOX', 'USER_SELECT'].includes(type)) {\n      return value == null ? '' : String(value);\n    }\n    const values = Array.isArray(value) ? value :\n      String(value || '').split(',').map(v =\u003e v.trim()).filter(Boolean);\n    return type === 'USER_SELECT' ? values.map(code =\u003e ({code})) : [...values];\n  }\n  function initialize(event) {\n    if (event.reuse) return event;\n    const table = event.record['点検明細'];\n    if (!table || table.type !== 'SUBTABLE') return event;\n    const rows = table.value;\n    if (!Array.isArray(rows)) return event;\n    const types = {設備名: 'SINGLE_LINE_TEXT', 点検項目: 'CHECK_BOX', 担当者: 'USER_SELECT'};\n    if (rows.some(row =\u003e Object.entries(types).some(([code, type]) =\u003e\n      !row.value[code] || row.value[code].type !== type))) return event;\n    const hasValue = rows.some(row =\u003e Object.keys(types).some(code =\u003e {\n      const value = row.value[code].value;\n      return Array.isArray(value) ? value.length \u003e 0 : value != null \u0026\u0026 value !== '';\n    }));\n    if (hasValue) return event;\n    table.value = ['溶接ロボットX', '真空ポンプB'].map(name =\u003e ({value: {\n      設備名: {type: 'SINGLE_LINE_TEXT', value: toFieldValue('SINGLE_LINE_TEXT', name)},\n      点検項目: {type: 'CHECK_BOX', value: toFieldValue('CHECK_BOX', '外観,異音')},\n      担当者: {type: 'USER_SELECT', value: toFieldValue('USER_SELECT', [])}\n    }}));\n    return event;\n  }\n  kintone.events.on('app.record.create.show', initialize);\n})();\n```\n\n## 行のvalueと、フィールドのvalueを区別する\nテーブルのvalueは「行オブジェクトの配列」です。各行のvalueには、フィールドコードをキーにしたオブジェクトが入ります。さらに、それぞれにtypeとvalueがあります。文字列は文字列、チェックボックスは選択肢の配列、ユーザー選択は「{code: ユーザーコード}」の配列です。\n\nユーザー名の表示文字列をcodeへ入れる実装にはしません。実在するコードと、対象利用者の権限・フィールド設定を確認します。このサンプルの担当者は未選択にし、ユーザーコードの変換自体はtoFieldValue単体で確認します。\n\n## 初期行を入れてよいかを先に判断する\n新規作成でも、複製やアクションによって値を引き継ぐ場合があります。「表示イベントだから必ず空」とは限りません。そのため、reuseや既存の対象値を確認してから代入します。テーブルの構造が想定どおりでない場合も、推測して置き換えません。\n\nこの空欄判定は、今回の3列専用です。別の列を加える場合は、その列の値も含めて判定を設計してください。製品版は設定行を代入するため、このサンプルとは既存行の扱いが異なります。\n\n## 確認するケース\n- 通常の新規作成で2行が表示される。\n- 既存の設備名・チェック・担当者がある場合は保持する。\n- 複製作成、対象列に値を引き継いだアクション経由の作成では保持する。\n- テーブルや列が見つからない場合は値を変えない。\n- 初期行の配列を生成し直しても、前回の変更が混ざらない。\n\nNode.jsの模擬イベントで確認した範囲です。実際のkintone画面・権限・併用カスタマイズでの確認は含まないため、検証用アプリで表示と保存の両方を確かめてください。イベント内ではkintone.app.record.setを呼ばず、変更したeventを返します。\n\n## 初期行を設定画面から管理する場合\n\n[自社のテーブルデータ初期表示プラグインの仕様・設定画面](https://kintaco.wisemap.biz/plugins/table-data-initial/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=table)で、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。\n\n無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\n\n## 参考資料\n- [レコード追加画面の表示イベント](https://cybozu.dev/ja/kintone/docs/js-api/events/create/create-show-event/)\n- [フィールド形式](https://cybozu.dev/ja/kintone/docs/overview/field-types/)\n\n製品仕様と実コードの確認元：TableDataInitial/src/js/desktop.js（1.0.5）。\n","coediting":false,"comments_count":0,"created_at":"2026-10-23T16:08:02+09:00","group":null,"id":"38657f02b9c37fe32707","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"テーブル","versions":[]}],"title":"kintoneのテーブルに初期行を設定するJavaScript｜チェックボックスとユーザー選択の値構造","updated_at":"2026-10-23T16:08:02+09:00","url":"https://qiita.com/kintaco/items/38657f02b9c37fe32707","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:233\"\u003e自社でkintone向けプラグインを開発しているkintacoです。「Googleカレンダー予定作成」の実装にあるUTC変換と、予定作成URLの組み立てを、小さな関数に切り出して解説します。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:249\"\u003eこの記事のコードはURLを生成するだけです。Googleへの通信、予定登録、OAuth認証、kintoneの値更新は行いません。予定の作成画面を開く操作と、Googleカレンダーに保存する操作は別です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:63\"\u003e\n\u003cspan id=\"utcで整形してから値ごとにエンコードする\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#utc%E3%81%A7%E6%95%B4%E5%BD%A2%E3%81%97%E3%81%A6%E3%81%8B%E3%82%89%E5%80%A4%E3%81%94%E3%81%A8%E3%81%AB%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eUTCで整形してから、値ごとにエンコードする\u003c/h2\u003e\n\u003cp data-sourcepos=\"6:1-6:296\"\u003ekintoneの日時値を受け取る想定で、タイムゾーンを含むISO形式を入力します。タイムゾーンなしの「2026-10-23T10:00:00」は、このサンプルでは受け付けません。実行端末のローカル時刻として解釈されるのを避けるためです。\u003c/p\u003e\n\u003cp data-sourcepos=\"8:1-8:207\"\u003e製品内のformatGCalDateTimeと同じUTC取得・ゼロ埋めの考え方に、この記事では入力形式・終了順序のチェックを加えています。製品版の全文ではありません。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"10:1-32:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003eformatGCalDateTime\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003etypeof\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003estring\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e\n      \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"sr\"\u003e/^\u003c/span\u003e\u003cspan class=\"se\"\u003e\\d{4}\u003c/span\u003e\u003cspan class=\"sr\"\u003e-\u003c/span\u003e\u003cspan class=\"se\"\u003e\\d{2}\u003c/span\u003e\u003cspan class=\"sr\"\u003e-\u003c/span\u003e\u003cspan class=\"se\"\u003e\\d{2}\u003c/span\u003e\u003cspan class=\"sr\"\u003eT\u003c/span\u003e\u003cspan class=\"se\"\u003e\\d{2}\u003c/span\u003e\u003cspan class=\"sr\"\u003e:\u003c/span\u003e\u003cspan class=\"se\"\u003e\\d{2}\u003c/span\u003e\u003cspan class=\"sr\"\u003e:\u003c/span\u003e\u003cspan class=\"se\"\u003e\\d{2}(?:\\.\\d\u003c/span\u003e\u003cspan class=\"sr\"\u003e+\u003c/span\u003e\u003cspan class=\"se\"\u003e)?(?:\u003c/span\u003e\u003cspan class=\"sr\"\u003eZ|\u003c/span\u003e\u003cspan class=\"se\"\u003e[\u003c/span\u003e\u003cspan class=\"sr\"\u003e+-\u003c/span\u003e\u003cspan class=\"se\"\u003e]\\d{2}\u003c/span\u003e\u003cspan class=\"sr\"\u003e:\u003c/span\u003e\u003cspan class=\"se\"\u003e\\d{2})\u003c/span\u003e\u003cspan class=\"sr\"\u003e$/\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003etest\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eタイムゾーンを含む日時を指定してください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003edate\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nb\"\u003eNumber\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisNaN\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003edate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetTime\u003c/span\u003e\u003cspan class=\"p\"\u003e()))\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e日時が不正です。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003epad\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003en\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003en\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003epadStart\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e0\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003edate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetUTCFullYear\u003c/span\u003e\u003cspan class=\"p\"\u003e()).\u003c/span\u003e\u003cspan class=\"nf\"\u003epadStart\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e0\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e\n    \u003cspan class=\"nf\"\u003epad\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003edate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetUTCMonth\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"nf\"\u003epad\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003edate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetUTCDate\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e\n    \u003cspan class=\"nf\"\u003epad\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003edate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetUTCHours\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"nf\"\u003epad\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003edate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetUTCMinutes\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e\n    \u003cspan class=\"nf\"\u003epad\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003edate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetUTCSeconds\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eZ\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003ebuildCalendarUrl\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e\u003cspan class=\"nx\"\u003etitle\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003estart\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003elocation\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003edetails\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e})\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003edates\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003eformatGCalDateTime\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003estart\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e/\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"nf\"\u003eformatGCalDateTime\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eparse\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eparse\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003estart\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"k\"\u003ethrow\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eError\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e終了は開始より後にしてください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eurl\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eURL\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ehttps://calendar.google.com/calendar/render\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"nx\"\u003eurl\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003esearch\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eURLSearchParams\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e\u003cspan class=\"na\"\u003eaction\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eTEMPLATE\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n    \u003cspan class=\"na\"\u003etext\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003etitle\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ekintone予定\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003edates\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003elocation\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003edetails\u003c/span\u003e\u003cspan class=\"p\"\u003e}).\u003c/span\u003e\u003cspan class=\"nf\"\u003etoString\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eurl\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003etoString\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003ch2 data-sourcepos=\"34:1-34:21\"\u003e\n\u003cspan id=\"何が起きるか\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BD%95%E3%81%8C%E8%B5%B7%E3%81%8D%E3%82%8B%E3%81%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e何が起きるか\u003c/h2\u003e\n\u003cp data-sourcepos=\"35:1-35:278\"\u003e日本時間の2026年10月23日10時は、UTCでは同日01時です。結果のdatesパラメーターは「20261023T010000Z/20261023T020000Z」になります。「Z」を付けるだけではUTCへ変換されないため、getUTCFullYearなどで値を取り出します。\u003c/p\u003e\n\u003cp data-sourcepos=\"37:1-37:238\"\u003etextやlocationを文字列連結でそのまま足すと、件名に「\u0026amp;」がある場合などにURLの区切りと衝突します。URLSearchParamsで値を設定し、二重にencodeURIComponentを適用しないようにします。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"39:1-39:15\"\u003e\n\u003cspan id=\"検証の例\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%A4%9C%E8%A8%BC%E3%81%AE%E4%BE%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e検証の例\u003c/h2\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"40:1-48:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eurl\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nf\"\u003ebuildCalendarUrl\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e\n  \u003cspan class=\"na\"\u003etitle\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e商談 \u0026amp; 次回提案\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n  \u003cspan class=\"na\"\u003estart\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-23T10:00:00+09:00\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n  \u003cspan class=\"na\"\u003eend\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e2026-10-23T11:00:00+09:00\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n  \u003cspan class=\"na\"\u003elocation\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e東京都内の訪問先\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\n\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003cspan class=\"nx\"\u003econsole\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003elog\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eURL\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eurl\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nx\"\u003esearchParams\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eget\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003edates\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e));\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"50:1-50:244\"\u003eこのサンプルの確認対象は、UTC変換、日付をまたぐ変換、空欄・不正値、終了前後、特殊文字の復元です。Node.jsで確認し、実際のGoogleカレンダーへの登録テストは含めていません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"52:1-52:39\"\u003e\n\u003cspan id=\"業務へ組み込むときの境界\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%A5%AD%E5%8B%99%E3%81%B8%E7%B5%84%E3%81%BF%E8%BE%BC%E3%82%80%E3%81%A8%E3%81%8D%E3%81%AE%E5%A2%83%E7%95%8C\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e業務へ組み込むときの境界\u003c/h2\u003e\n\u003cp data-sourcepos=\"53:1-53:249\"\u003eレコード詳細画面のイベントから値を取り出し、ボタン操作時にURLを開く構成にできます。その場合も、閲覧権限で取得できない項目、空欄、ポップアップ制限を扱う必要があります。\u003c/p\u003e\n\u003cp data-sourcepos=\"55:1-55:332\"\u003e件名・説明・場所は、URLを開けばGoogleに渡る情報です。機密情報を無条件に説明へ入れないでください。また、予定作成URLはCalendar APIによる登録・更新ではなく、自動同期にもなりません。UIやURLパラメーターの将来的な変更にも注意が必要です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"57:1-57:39\"\u003e\n\u003cspan id=\"設定画面で管理したい場合\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%AD%E5%AE%9A%E7%94%BB%E9%9D%A2%E3%81%A7%E7%AE%A1%E7%90%86%E3%81%97%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e設定画面で管理したい場合\u003c/h2\u003e\n\u003cp data-sourcepos=\"59:1-59:347\"\u003e\u003ca href=\"https://kintaco.wisemap.biz/plugins/create-gcalendar/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=calendar\" rel=\"nofollow noopener\" target=\"_blank\"\u003e自社のGoogleカレンダー予定作成プラグインの仕様・設定画面\u003c/a\u003eで、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。\u003c/p\u003e\n\u003cp data-sourcepos=\"61:1-61:351\"\u003e無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"63:1-63:15\"\u003e\n\u003cspan id=\"参考資料\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8F%82%E8%80%83%E8%B3%87%E6%96%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e参考資料\u003c/h2\u003e\n\u003cul data-sourcepos=\"64:1-65:0\"\u003e\n\u003cli data-sourcepos=\"64:1-65:0\"\u003e\u003ca href=\"https://cybozu.dev/ja/kintone/docs/js-api/events/detail/detail-show-event/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eレコード詳細画面の表示イベント\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"66:1-66:94\"\u003e製品仕様と実コードの確認元：GoogleCalendarCreate/src/js/desktop.js（1.0.2）。\u003c/p\u003e\n","body":"自社でkintone向けプラグインを開発しているkintacoです。「Googleカレンダー予定作成」の実装にあるUTC変換と、予定作成URLの組み立てを、小さな関数に切り出して解説します。\n\nこの記事のコードはURLを生成するだけです。Googleへの通信、予定登録、OAuth認証、kintoneの値更新は行いません。予定の作成画面を開く操作と、Googleカレンダーに保存する操作は別です。\n\n## UTCで整形してから、値ごとにエンコードする\nkintoneの日時値を受け取る想定で、タイムゾーンを含むISO形式を入力します。タイムゾーンなしの「2026-10-23T10:00:00」は、このサンプルでは受け付けません。実行端末のローカル時刻として解釈されるのを避けるためです。\n\n製品内のformatGCalDateTimeと同じUTC取得・ゼロ埋めの考え方に、この記事では入力形式・終了順序のチェックを加えています。製品版の全文ではありません。\n\n```javascript\nfunction formatGCalDateTime(value) {\n  if (typeof value !== 'string' ||\n      !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/.test(value)) {\n    throw new Error('タイムゾーンを含む日時を指定してください。');\n  }\n  const date = new Date(value);\n  if (Number.isNaN(date.getTime())) throw new Error('日時が不正です。');\n  const pad = n =\u003e String(n).padStart(2, '0');\n  return String(date.getUTCFullYear()).padStart(4, '0') +\n    pad(date.getUTCMonth() + 1) + pad(date.getUTCDate()) + 'T' +\n    pad(date.getUTCHours()) + pad(date.getUTCMinutes()) +\n    pad(date.getUTCSeconds()) + 'Z';\n}\nfunction buildCalendarUrl({title, start, end, location = '', details = ''}) {\n  const dates = formatGCalDateTime(start) + '/' + formatGCalDateTime(end);\n  if (Date.parse(end) \u003c= Date.parse(start)) throw new Error('終了は開始より後にしてください。');\n  const url = new URL('https://calendar.google.com/calendar/render');\n  url.search = new URLSearchParams({action: 'TEMPLATE',\n    text: title || 'kintone予定', dates, location, details}).toString();\n  return url.toString();\n}\n```\n\n## 何が起きるか\n日本時間の2026年10月23日10時は、UTCでは同日01時です。結果のdatesパラメーターは「20261023T010000Z/20261023T020000Z」になります。「Z」を付けるだけではUTCへ変換されないため、getUTCFullYearなどで値を取り出します。\n\ntextやlocationを文字列連結でそのまま足すと、件名に「\u0026」がある場合などにURLの区切りと衝突します。URLSearchParamsで値を設定し、二重にencodeURIComponentを適用しないようにします。\n\n## 検証の例\n```javascript\nconst url = buildCalendarUrl({\n  title: '商談 \u0026 次回提案',\n  start: '2026-10-23T10:00:00+09:00',\n  end: '2026-10-23T11:00:00+09:00',\n  location: '東京都内の訪問先'\n});\nconsole.log(new URL(url).searchParams.get('dates'));\n```\n\nこのサンプルの確認対象は、UTC変換、日付をまたぐ変換、空欄・不正値、終了前後、特殊文字の復元です。Node.jsで確認し、実際のGoogleカレンダーへの登録テストは含めていません。\n\n## 業務へ組み込むときの境界\nレコード詳細画面のイベントから値を取り出し、ボタン操作時にURLを開く構成にできます。その場合も、閲覧権限で取得できない項目、空欄、ポップアップ制限を扱う必要があります。\n\n件名・説明・場所は、URLを開けばGoogleに渡る情報です。機密情報を無条件に説明へ入れないでください。また、予定作成URLはCalendar APIによる登録・更新ではなく、自動同期にもなりません。UIやURLパラメーターの将来的な変更にも注意が必要です。\n\n## 設定画面で管理したい場合\n\n[自社のGoogleカレンダー予定作成プラグインの仕様・設定画面](https://kintaco.wisemap.biz/plugins/create-gcalendar/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=calendar)で、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。\n\n無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。\n\n## 参考資料\n- [レコード詳細画面の表示イベント](https://cybozu.dev/ja/kintone/docs/js-api/events/detail/detail-show-event/)\n\n製品仕様と実コードの確認元：GoogleCalendarCreate/src/js/desktop.js（1.0.2）。\n","coediting":false,"comments_count":0,"created_at":"2026-10-23T16:02:01+09:00","group":null,"id":"36ae38137d612e670520","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"GoogleCalendar","versions":[]}],"title":"kintoneの日時をGoogleカレンダー用URLに渡す｜UTC変換とURLエンコードをJavaScriptで確認","updated_at":"2026-10-23T16:02:01+09:00","url":"https://qiita.com/kintaco/items/36ae38137d612e670520","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:301\"\u003ekintone向けの無料プラグインを開発・提供しているkintacoです。この記事では、自社の「条件付き入力制御・書式変更プラグイン」で使用している空欄判定と保存時チェックを題材に、条件を1つに絞ったJavaScriptを解説します。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:345\"\u003e製品版のソース全体を掲載するものではありません。空欄判定は実コードと同じ処理を使い、設定の読み込み・複数条件・テーブル対応などを省いて、単独で読み込めるサンプルに再構成しています。サンプルだけで、今回の条件チェックを実装できます。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"5:1-5:27\"\u003e\n\u003cspan id=\"今回実現する動作\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BB%8A%E5%9B%9E%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B%E5%8B%95%E4%BD%9C\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e今回実現する動作\u003c/h2\u003e\n\u003cp data-sourcepos=\"7:1-7:183\"\u003e「申請区分」が「特別」の場合に、「理由」が空ならレコードの保存を止めます。「通常」の場合は、理由が空でも保存を許可します。\u003c/p\u003e\n\u003cp data-sourcepos=\"9:1-9:232\"\u003e対象はPC版のレコード追加・編集画面の保存です。一覧のインライン編集、REST API、CSV読み込み、プロセス管理のアクション実行をこのコードで制御することはできません。\u003c/p\u003e\n\u003cp data-sourcepos=\"11:1-11:321\"\u003e常に必須なら、フォームの標準設定を使う方が簡単です。この記事の例では、理由フィールドの標準の必須設定をオフにし、保存イベント内で条件を確認します。フィールドオブジェクトへ「required = true」を設定する方法ではありません。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"13:1-13:51\"\u003e\n\u003cspan id=\"検証用アプリに用意するフィールド\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%A4%9C%E8%A8%BC%E7%94%A8%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AB%E7%94%A8%E6%84%8F%E3%81%99%E3%82%8B%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e検証用アプリに用意するフィールド\u003c/h2\u003e\n\u003cul data-sourcepos=\"15:1-17:0\"\u003e\n\u003cli data-sourcepos=\"15:1-15:110\"\u003eドロップダウン：フィールドコード「申請区分」。選択肢は「通常」「特別」。\u003c/li\u003e\n\u003cli data-sourcepos=\"16:1-17:0\"\u003e文字列（複数行）：フィールドコード「理由」。標準の必須設定はオフ。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"18:1-18:315\"\u003e今回は項目名とコードを同じにしていますが、コードではフィールドコードを使います。すでに別のコードがある場合は、後述の定数を合わせてください。対象の利用者が両フィールドを閲覧でき、理由を編集できることも前提です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"20:1-20:24\"\u003e\n\u003cspan id=\"サンプルコード\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eサンプルコード\u003c/h2\u003e\n\u003cp data-sourcepos=\"22:1-22:350\"\u003e次の内容をJavaScriptファイルとして保存し、検証用アプリの「JavaScript / CSSでカスタマイズ」のPC用JavaScriptへ追加します。適用対象の利用者を確認し、設定を保存してアプリを更新してください。同じ処理を行う既存カスタマイズとは重複適用しないでください。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"24:1-65:3\"\u003e\n\u003cdiv class=\"code-lang\"\u003e\u003cspan class=\"bold\"\u003econditional-required.js\u003c/span\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nf\"\u003efunction \u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003euse strict\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eCATEGORY_CODE\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e申請区分\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eREASON_CODE\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e理由\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eREQUIRED_CATEGORY\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e特別\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eFIELD_ERROR\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e特別申請では理由を入力してください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003eRECORD_ERROR\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e特別申請の入力内容を確認してください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n  \u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003eisEmptyValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003etrim\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\n  \u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eevents\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eon\u003c/span\u003e\u003cspan class=\"p\"\u003e([\u003c/span\u003e\n    \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eapp.record.create.submit\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n    \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eapp.record.edit.submit\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e],\u003c/span\u003e \u003cspan class=\"nf\"\u003efunction \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ecategory\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003eCATEGORY_CODE\u003c/span\u003e\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ereason\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003erecord\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"nx\"\u003eREASON_CODE\u003c/span\u003e\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003ecategory\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003ereason\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e申請区分・理由のフィールドコードと閲覧権限を確認してください。\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\n    \u003cspan class=\"c1\"\u003e// このサンプル自身が設定したメッセージだけを解除する。\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ereason\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"nx\"\u003eFIELD_ERROR\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"nx\"\u003ereason\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"nx\"\u003eRECORD_ERROR\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\n    \u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003erequired\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003ecategory\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"nx\"\u003eREQUIRED_CATEGORY\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003erequired\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"nf\"\u003eisEmptyValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003ereason\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n      \u003cspan class=\"nx\"\u003ereason\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eFIELD_ERROR\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n      \u003cspan class=\"c1\"\u003e// 先に実行された別の処理の画面上部エラーは残す。\u003c/span\u003e\n      \u003cspan class=\"k\"\u003eif \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eerror\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003eRECORD_ERROR\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\n    \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003eevent\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n  \u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003cspan class=\"p\"\u003e})();\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/div\u003e\n\u003ch2 data-sourcepos=\"67:1-67:56\"\u003e\n\u003cspan id=\"1空欄判定で数値の0を未入力にしない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#1%E7%A9%BA%E6%AC%84%E5%88%A4%E5%AE%9A%E3%81%A7%E6%95%B0%E5%80%A4%E3%81%AE0%E3%82%92%E6%9C%AA%E5%85%A5%E5%8A%9B%E3%81%AB%E3%81%97%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e1．空欄判定で数値の0を未入力にしない\u003c/h2\u003e\n\u003cp data-sourcepos=\"69:1-69:84\"\u003eisEmptyValueは、実際のプラグインでも使っている空欄判定です。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"javascript\" data-sourcepos=\"71:1-75:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003efunction\u003c/span\u003e \u003cspan class=\"nf\"\u003eisEmptyValue\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e \u003cspan class=\"o\"\u003e||\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nb\"\u003eArray\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eisArray\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e?\u003c/span\u003e \u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elength\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nc\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003evalue\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nf\"\u003etrim\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"dl\"\u003e''\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"77:1-77:263\"\u003e「!value」だけで判定すると、数値の0も未入力扱いになります。この実装は、null・undefined、要素0件の配列、空文字・空白だけの文字列を空と判定します。数値の0と文字列の「0」は入力済みです。\u003c/p\u003e\n\u003cp data-sourcepos=\"79:1-79:279\"\u003e今回の対象は文字列（複数行）ですが、空欄判定の考え方は数値や複数選択でも再利用できます。ただし、計算フィールドなど、エラー表示に対応しないフィールドへそのまま広げないようにしてください。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"81:1-81:55\"\u003e\n\u003cspan id=\"2保存イベントで条件と値を確認する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#2%E4%BF%9D%E5%AD%98%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%A7%E6%9D%A1%E4%BB%B6%E3%81%A8%E5%80%A4%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e2．保存イベントで条件と値を確認する\u003c/h2\u003e\n\u003cp data-sourcepos=\"83:1-83:249\"\u003e条件は「category.value === REQUIRED_CATEGORY」です。ドロップダウンの値が「特別」の場合だけ、理由の空欄を調べます。表示名の似た選択肢や、前後の空白がある別の文字列は一致しません。\u003c/p\u003e\n\u003cp data-sourcepos=\"85:1-85:295\"\u003e空なら、理由フィールドのerrorへメッセージを設定します。続いてイベントオブジェクトをreturnすると、対象フィールドにエラーが表示され、保存がキャンセルされます。画面上部のevent.errorも補助的に設定しています。\u003c/p\u003e\n\u003cp data-sourcepos=\"87:1-87:233\"\u003eエラー表示と対象イベントの対応は、\u003ca href=\"https://cybozu.dev/ja/kintone/docs/js-api/events/event-object-actions/\" rel=\"nofollow noopener\" target=\"_blank\"\u003e公式ドキュメント「イベントオブジェクトで実行できる操作」\u003c/a\u003eで確認できます。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"89:1-89:52\"\u003e\n\u003cspan id=\"3自分のメッセージだけを解除する\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#3%E8%87%AA%E5%88%86%E3%81%AE%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%A0%E3%81%91%E3%82%92%E8%A7%A3%E9%99%A4%E3%81%99%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e3．自分のメッセージだけを解除する\u003c/h2\u003e\n\u003cp data-sourcepos=\"91:1-91:160\"\u003eエラーのあとに値や申請区分を直して再保存する場合を考え、このサンプルが設定した文言だけをnullに戻しています。\u003c/p\u003e\n\u003cp data-sourcepos=\"93:1-93:268\"\u003e無条件に「reason.error = null」「event.error = null」とすると、ほかのカスタマイズが設定したメッセージまで消す可能性があります。また、画面上部に先行するエラーがある場合は、その文言を残します。\u003c/p\u003e\n\u003cp data-sourcepos=\"95:1-95:308\"\u003eただし、複数の処理が同じフィールドのerrorを変更する場合や、後続の処理がエラーを上書きする場合まで保護できる仕組みではありません。導入時には、同じ項目に対する入力チェックとイベントの実行順を確認してください。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"97:1-97:85\"\u003e\n\u003cspan id=\"4フィールドが取得できない場合を通常申請とみなさない\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#4%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%8C%E5%8F%96%E5%BE%97%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%82%92%E9%80%9A%E5%B8%B8%E7%94%B3%E8%AB%8B%E3%81%A8%E3%81%BF%E3%81%AA%E3%81%95%E3%81%AA%E3%81%84\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e4．フィールドが取得できない場合を、通常申請とみなさない\u003c/h2\u003e\n\u003cp data-sourcepos=\"99:1-99:261\"\u003eフィールドコードの違いや閲覧権限によって、recordから対象を取得できない場合があります。このサンプルでは、条件を評価できないまま保存を通さず、画面上部へ確認メッセージを出します。\u003c/p\u003e\n\u003cp data-sourcepos=\"101:1-101:288\"\u003eこれはアクセス権を付与する処理ではありません。コードと権限を直し、実際の利用者で確認してください。非表示・編集不可の項目を条件付き必須にすると入力できなくなるため、画面設計との整合も必要です。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"103:1-103:33\"\u003e\n\u003cspan id=\"動作を確認するケース\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8B%95%E4%BD%9C%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E3%82%B1%E3%83%BC%E3%82%B9\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e動作を確認するケース\u003c/h2\u003e\n\u003col data-sourcepos=\"105:1-111:0\"\u003e\n\u003cli data-sourcepos=\"105:1-105:93\"\u003e「特別」＋理由が空：保存を止め、理由にメッセージを表示する。\u003c/li\u003e\n\u003cli data-sourcepos=\"106:1-106:81\"\u003e「特別」＋理由が空白・改行だけ：同じく保存を止める。\u003c/li\u003e\n\u003cli data-sourcepos=\"107:1-107:81\"\u003e「特別」＋理由あり：このチェックでは保存を止めない。\u003c/li\u003e\n\u003cli data-sourcepos=\"108:1-108:81\"\u003e「通常」＋理由が空：このチェックでは保存を止めない。\u003c/li\u003e\n\u003cli data-sourcepos=\"109:1-109:117\"\u003eエラー後に「特別」から「通常」へ変更して再保存：自分のメッセージを解除する。\u003c/li\u003e\n\u003cli data-sourcepos=\"110:1-111:0\"\u003e追加・編集の両方と、実際の担当者の権限で確認する。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp data-sourcepos=\"112:1-112:377\"\u003eこの掲載コードは、Node.jsの模擬イベントオブジェクトで、空欄・条件不一致・再判定・別のエラーの保持・フィールド欠落・空欄判定の0と配列など17ケースを確認しました。kintoneの実画面での動作検証は含みません。組み込む前に検証用アプリで上のケースを確認してください。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"114:1-114:45\"\u003e\n\u003cspan id=\"条件が増えたときに見直すこと\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%9D%A1%E4%BB%B6%E3%81%8C%E5%A2%97%E3%81%88%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AB%E8%A6%8B%E7%9B%B4%E3%81%99%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e条件が増えたときに見直すこと\u003c/h2\u003e\n\u003cp data-sourcepos=\"116:1-116:368\"\u003e複数条件をAND／ORで結ぶ、対象をテーブル内の列にする、同じ対象へ複数ルールを適用する、といった要件では、判定と対象フィールドの取得を分けて設計すると整理しやすくなります。とくにテーブル内の必須チェックは、各行のフィールドに対して行う必要があります。\u003c/p\u003e\n\u003cp data-sourcepos=\"118:1-118:562\"\u003e設定画面から条件を管理したい場合は、自社で公開している\u003ca href=\"https://kintaco.wisemap.biz/plugins/conditional-input-control/?utm_source=qiita\u0026amp;utm_medium=referral\u0026amp;utm_campaign=external_howto\u0026amp;utm_content=conditional_required_code\" rel=\"nofollow noopener\" target=\"_blank\"\u003e条件付き入力制御・書式変更プラグイン\u003c/a\u003eでも設定できます。複数条件・テーブル内項目・非表示・編集不可・書式変更などの対応範囲と設定画面は、リンク先で確認できます。今回のサンプルと製品版では、対応範囲が異なります。\u003c/p\u003e\n\u003cp data-sourcepos=\"120:1-120:372\"\u003eプラグインは無料です。無料利用時は、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されず、一度閉じると同じブラウザー・同じkintoneドメインでは全Kintacoプラグイン共通で24時間非表示になります。\u003c/p\u003e\n\u003cp data-sourcepos=\"122:1-122:158\"\u003eまずは1条件・1項目で動作を確かめ、利用する画面と保存経路を増やす際にチェック範囲を見直すのがおすすめです。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"124:1-124:15\"\u003e\n\u003cspan id=\"参考資料\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8F%82%E8%80%83%E8%B3%87%E6%96%99\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e参考資料\u003c/h2\u003e\n\u003cul data-sourcepos=\"126:1-128:0\"\u003e\n\u003cli data-sourcepos=\"126:1-126:160\"\u003e\u003ca href=\"https://cybozu.dev/ja/kintone/docs/js-api/events/event-object-actions/\" rel=\"nofollow noopener\" target=\"_blank\"\u003eイベントオブジェクトで実行できる操作（cybozu developer network）\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"127:1-128:0\"\u003e\u003ca href=\"https://kintaco.wisemap.biz/plugins/conditional-input-control/\" rel=\"nofollow noopener\" target=\"_blank\"\u003e条件付き入力制御・書式変更プラグインの仕様・設定画面\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"129:1-129:120\"\u003e記事の製品仕様は1.0.17をもとにしています。最新の仕様は詳細ページをご確認ください。\u003c/p\u003e\n","body":"kintone向けの無料プラグインを開発・提供しているkintacoです。この記事では、自社の「条件付き入力制御・書式変更プラグイン」で使用している空欄判定と保存時チェックを題材に、条件を1つに絞ったJavaScriptを解説します。\n\n製品版のソース全体を掲載するものではありません。空欄判定は実コードと同じ処理を使い、設定の読み込み・複数条件・テーブル対応などを省いて、単独で読み込めるサンプルに再構成しています。サンプルだけで、今回の条件チェックを実装できます。\n\n## 今回実現する動作\n\n「申請区分」が「特別」の場合に、「理由」が空ならレコードの保存を止めます。「通常」の場合は、理由が空でも保存を許可します。\n\n対象はPC版のレコード追加・編集画面の保存です。一覧のインライン編集、REST API、CSV読み込み、プロセス管理のアクション実行をこのコードで制御することはできません。\n\n常に必須なら、フォームの標準設定を使う方が簡単です。この記事の例では、理由フィールドの標準の必須設定をオフにし、保存イベント内で条件を確認します。フィールドオブジェクトへ「required = true」を設定する方法ではありません。\n\n## 検証用アプリに用意するフィールド\n\n- ドロップダウン：フィールドコード「申請区分」。選択肢は「通常」「特別」。\n- 文字列（複数行）：フィールドコード「理由」。標準の必須設定はオフ。\n\n今回は項目名とコードを同じにしていますが、コードではフィールドコードを使います。すでに別のコードがある場合は、後述の定数を合わせてください。対象の利用者が両フィールドを閲覧でき、理由を編集できることも前提です。\n\n## サンプルコード\n\n次の内容をJavaScriptファイルとして保存し、検証用アプリの「JavaScript / CSSでカスタマイズ」のPC用JavaScriptへ追加します。適用対象の利用者を確認し、設定を保存してアプリを更新してください。同じ処理を行う既存カスタマイズとは重複適用しないでください。\n\n```javascript:conditional-required.js\n(function () {\n  'use strict';\n\n  const CATEGORY_CODE = '申請区分';\n  const REASON_CODE = '理由';\n  const REQUIRED_CATEGORY = '特別';\n  const FIELD_ERROR = '特別申請では理由を入力してください。';\n  const RECORD_ERROR = '特別申請の入力内容を確認してください。';\n\n  function isEmptyValue(value) {\n    return value == null || (Array.isArray(value) ? value.length === 0 : String(value).trim() === '');\n  }\n\n  kintone.events.on([\n    'app.record.create.submit',\n    'app.record.edit.submit'\n  ], function (event) {\n    const record = event.record;\n    const category = record[CATEGORY_CODE];\n    const reason = record[REASON_CODE];\n\n    if (!category || !reason) {\n      event.error = '申請区分・理由のフィールドコードと閲覧権限を確認してください。';\n      return event;\n    }\n\n    // このサンプル自身が設定したメッセージだけを解除する。\n    if (reason.error === FIELD_ERROR) reason.error = null;\n    if (event.error === RECORD_ERROR) event.error = null;\n\n    const required = category.value === REQUIRED_CATEGORY;\n    if (required \u0026\u0026 isEmptyValue(reason.value)) {\n      reason.error = FIELD_ERROR;\n      // 先に実行された別の処理の画面上部エラーは残す。\n      if (!event.error) event.error = RECORD_ERROR;\n    }\n\n    return event;\n  });\n})();\n```\n\n## 1．空欄判定で数値の0を未入力にしない\n\nisEmptyValueは、実際のプラグインでも使っている空欄判定です。\n\n```javascript\nfunction isEmptyValue(value) {\n  return value == null || (Array.isArray(value) ? value.length === 0 : String(value).trim() === '');\n}\n```\n\n「!value」だけで判定すると、数値の0も未入力扱いになります。この実装は、null・undefined、要素0件の配列、空文字・空白だけの文字列を空と判定します。数値の0と文字列の「0」は入力済みです。\n\n今回の対象は文字列（複数行）ですが、空欄判定の考え方は数値や複数選択でも再利用できます。ただし、計算フィールドなど、エラー表示に対応しないフィールドへそのまま広げないようにしてください。\n\n## 2．保存イベントで条件と値を確認する\n\n条件は「category.value === REQUIRED_CATEGORY」です。ドロップダウンの値が「特別」の場合だけ、理由の空欄を調べます。表示名の似た選択肢や、前後の空白がある別の文字列は一致しません。\n\n空なら、理由フィールドのerrorへメッセージを設定します。続いてイベントオブジェクトをreturnすると、対象フィールドにエラーが表示され、保存がキャンセルされます。画面上部のevent.errorも補助的に設定しています。\n\nエラー表示と対象イベントの対応は、[公式ドキュメント「イベントオブジェクトで実行できる操作」](https://cybozu.dev/ja/kintone/docs/js-api/events/event-object-actions/)で確認できます。\n\n## 3．自分のメッセージだけを解除する\n\nエラーのあとに値や申請区分を直して再保存する場合を考え、このサンプルが設定した文言だけをnullに戻しています。\n\n無条件に「reason.error = null」「event.error = null」とすると、ほかのカスタマイズが設定したメッセージまで消す可能性があります。また、画面上部に先行するエラーがある場合は、その文言を残します。\n\nただし、複数の処理が同じフィールドのerrorを変更する場合や、後続の処理がエラーを上書きする場合まで保護できる仕組みではありません。導入時には、同じ項目に対する入力チェックとイベントの実行順を確認してください。\n\n## 4．フィールドが取得できない場合を、通常申請とみなさない\n\nフィールドコードの違いや閲覧権限によって、recordから対象を取得できない場合があります。このサンプルでは、条件を評価できないまま保存を通さず、画面上部へ確認メッセージを出します。\n\nこれはアクセス権を付与する処理ではありません。コードと権限を直し、実際の利用者で確認してください。非表示・編集不可の項目を条件付き必須にすると入力できなくなるため、画面設計との整合も必要です。\n\n## 動作を確認するケース\n\n1. 「特別」＋理由が空：保存を止め、理由にメッセージを表示する。\n2. 「特別」＋理由が空白・改行だけ：同じく保存を止める。\n3. 「特別」＋理由あり：このチェックでは保存を止めない。\n4. 「通常」＋理由が空：このチェックでは保存を止めない。\n5. エラー後に「特別」から「通常」へ変更して再保存：自分のメッセージを解除する。\n6. 追加・編集の両方と、実際の担当者の権限で確認する。\n\nこの掲載コードは、Node.jsの模擬イベントオブジェクトで、空欄・条件不一致・再判定・別のエラーの保持・フィールド欠落・空欄判定の0と配列など17ケースを確認しました。kintoneの実画面での動作検証は含みません。組み込む前に検証用アプリで上のケースを確認してください。\n\n## 条件が増えたときに見直すこと\n\n複数条件をAND／ORで結ぶ、対象をテーブル内の列にする、同じ対象へ複数ルールを適用する、といった要件では、判定と対象フィールドの取得を分けて設計すると整理しやすくなります。とくにテーブル内の必須チェックは、各行のフィールドに対して行う必要があります。\n\n設定画面から条件を管理したい場合は、自社で公開している[条件付き入力制御・書式変更プラグイン](https://kintaco.wisemap.biz/plugins/conditional-input-control/?utm_source=qiita\u0026utm_medium=referral\u0026utm_campaign=external_howto\u0026utm_content=conditional_required_code)でも設定できます。複数条件・テーブル内項目・非表示・編集不可・書式変更などの対応範囲と設定画面は、リンク先で確認できます。今回のサンプルと製品版では、対応範囲が異なります。\n\nプラグインは無料です。無料利用時は、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されず、一度閉じると同じブラウザー・同じkintoneドメインでは全Kintacoプラグイン共通で24時間非表示になります。\n\nまずは1条件・1項目で動作を確かめ、利用する画面と保存経路を増やす際にチェック範囲を見直すのがおすすめです。\n\n## 参考資料\n\n- [イベントオブジェクトで実行できる操作（cybozu developer network）](https://cybozu.dev/ja/kintone/docs/js-api/events/event-object-actions/)\n- [条件付き入力制御・書式変更プラグインの仕様・設定画面](https://kintaco.wisemap.biz/plugins/conditional-input-control/)\n\n記事の製品仕様は1.0.17をもとにしています。最新の仕様は詳細ページをご確認ください。\n","coediting":false,"comments_count":0,"created_at":"2026-10-23T15:24:07+09:00","group":null,"id":"2a2ff718789b0d8665a9","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"JavaScript","versions":[]},{"name":"入力チェック","versions":[]}],"title":"kintoneで「特別申請のときだけ理由を必須」にするJavaScript｜保存時チェックの実装","updated_at":"2026-10-23T15:24:07+09:00","url":"https://qiita.com/kintaco/items/2a2ff718789b0d8665a9","user":{"description":"","facebook_id":"","followees_count":1,"followers_count":0,"github_login_name":null,"id":"kintaco","items_count":14,"linkedin_id":"","location":"","name":"kintaco 編集部","organization":"wisemap","permanent_id":2520286,"profile_image_url":"https://s3-ap-northeast-1.amazonaws.com/qiita-image-store/0/2520286/818799bb8f8e60df4521518fc82a6a73c44e39d3/large.png?1792734994","team_only":false,"twitter_screen_name":null,"website_url":"https://kintaco.wisemap.biz/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:340\"\u003ekintone プラグインの修正を出す前の最後の確かめは、実際の kintone の画面です。プラグインの zip を入れ替えて、テスト用のアプリを作り、設定を入れて、レコードを開いてボタンを押す……。手順は決まっていても、毎回それなりに時間がかかります。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:253\"\u003e今回は、\u003cstrong\u003eClaude Code（VS Code の拡張機能）と Claude in Chrome（Chrome の拡張機能）\u003c/strong\u003e に、この実機テストをまとめて任せてみました。頼んだのは、kintone のスペースの URL を添えた 1 行だけです。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"5:1-8:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e下記スペースにテスト用アプリを作成して、ブラウザー操作でチェックして\nhttps://（サブドメイン）.cybozu.com/k/#/space/（番号）/thread/（番号）\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"10:1-10:325\"\u003eClaude は、プラグインの入れ替え、テスト用アプリの作成、プラグインの設定の取り込み、詳細画面・プレビュー・モバイルでの確認までを済ませ、結果を表にして報告しました。本記事では、その流れと、どこでつまずいたかを紹介します。\u003c/p\u003e\n\u003chr data-sourcepos=\"12:1-13:0\"\u003e\n\u003ch1 data-sourcepos=\"14:1-14:29\"\u003e\n\u003cspan id=\"確かめたかったこと\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%A2%BA%E3%81%8B%E3%82%81%E3%81%9F%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e確かめたかったこと\u003c/h1\u003e\n\u003cp data-sourcepos=\"16:1-16:203\"\u003eリリース前の \u003cstrong\u003e印刷屋プラグイン Ver.9\u003c/strong\u003e と \u003cstrong\u003e計算式プラグイン Ver.102\u003c/strong\u003e は、同じ計算式エンジンを使います。このエンジンに、次の直しを入れました。\u003c/p\u003e\n\u003ctable data-sourcepos=\"18:1-22:196\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"18:1-18:46\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"18:2-18:18\"\u003e直したこと\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"18:20-18:30\"\u003e直す前\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"18:32-18:45\"\u003e直した後\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"20:1-20:242\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"20:2-20:99\"\u003e\n\u003ccode\u003e\u0026amp;\u003c/code\u003e でつないだ関数の結果が \u003ccode\u003e(\u003c/code\u003e で始まる・関数名の字面を含む・真偽値\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"20:101-20:226\"\u003e\n\u003ccode\u003e\"\u0026lt;td\u0026gt;\" \u0026amp; ESC_HTML(\"(株)山田\") \u0026amp; \"\u0026lt;/td\u0026gt;\"\u003c/code\u003e がエラー、\u003ccode\u003e\"[\" \u0026amp; TRIM(\"見積 ROUND(1.5) 件\") \u0026amp; \"]\"\u003c/code\u003e が \u003ccode\u003e[見積 2 件]\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"20:228-20:241\"\u003e値のまま\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"21:1-21:149\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"21:2-21:48\"\u003e式全体や関数の引数を括弧で包む\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"21:50-21:127\"\u003e\n\u003ccode\u003eIF((数値 \u0026gt; 5), \"A\", \"B\")\u003c/code\u003e がエラー、\u003ccode\u003e(\"test\")\u003c/code\u003e が項目 test の値\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"21:129-21:148\"\u003e中の値のまま\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"22:1-22:196\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"22:2-22:64\"\u003eLET の変数名が項目のフィールドコードと同じ\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"22:66-22:142\"\u003e\n\u003ccode\u003eLET() variable name (0) is already defined.\u003c/code\u003e（\u003ccode\u003e(0)\u003c/code\u003e は引数の位置）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"22:144-22:195\"\u003e\u003ccode\u003eLET() variable name (数値) is already defined.\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"24:1-24:71\"\u003e直しは、Node で動かす確かめで済ませてありました。\u003c/p\u003e\n\u003cul data-sourcepos=\"26:1-29:0\"\u003e\n\u003cli data-sourcepos=\"26:1-26:28\"\u003e回帰の確かめ 170 件\u003c/li\u003e\n\u003cli data-sourcepos=\"27:1-27:42\"\u003e関数の説明文の使用例 1,218 件\u003c/li\u003e\n\u003cli data-sourcepos=\"28:1-29:0\"\u003e手元の帳票の設定 620 行（直す前のエンジンと、出力・エラー・評価回数が同じか）\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"30:1-30:261\"\u003e残っていたのが実機です。印刷屋のボタンの表示条件・プレビュー・PDF の保存・更新項目と、計算式プラグインのデスクトップ・モバイルの計算を、kintone の画面で見ておきたいところでした。\u003c/p\u003e\n\u003chr data-sourcepos=\"32:1-33:0\"\u003e\n\u003ch1 data-sourcepos=\"34:1-34:20\"\u003e\n\u003cspan id=\"仕組みの構成\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%AE%E6%A7%8B%E6%88%90\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e仕組みの構成\u003c/h1\u003e\n\u003ciframe id=\"qiita-embed-content__5fb307f76b8c2635447fee89dcd6cdc1\" src=\"https://qiita.com/embed-contents/mermaid#qiita-embed-content__5fb307f76b8c2635447fee89dcd6cdc1\" style=\"width:100%;\" frameborder=\"0\" scrolling=\"no\" loading=\"lazy\" data-content='{\"data\":\"flowchart LR\\n U[\\\"利用者\\\"]\\n\\n subgraph PC[\\\"利用者の PC\\\"]\\n CC[\\\"Claude Code\u0026lt;br\u0026gt;（VS Code）\\\"]\\n CH[\\\"Chrome\u0026lt;br\u0026gt;Claude in Chrome\u0026lt;br\u0026gt;（kintone にログイン済み）\\\"]\\n FS[(\\\"ファイル\u0026lt;br\u0026gt;プラグインの zip\u0026lt;br\u0026gt;設定の JSON\\\")]\\n TL[\\\"設定づくりの tools\u0026lt;br\u0026gt;（CLI）\\\"]\\n end\\n\\n KT[\\\"kintone\u0026lt;br\u0026gt;（開発環境）\\\"]\\n\\n U -- \\\"頼む\\\" --\u0026gt; CC\\n CC -- \\\"開く・押す・読む\u0026lt;br\u0026gt;ページで JavaScript\\\" --\u0026gt; CH\\n CH -- \\\"画面の操作\u0026lt;br\u0026gt;REST API（ログインのまま）\\\" --\u0026gt; KT\\n CC -- \\\"設定を作る・検査する\\\" --\u0026gt; TL\\n TL --\u0026gt; FS\\n CC -- \\\"ファイルを入力欄に渡す\\\" --\u0026gt; CH\",\"key\":\"d6c1193a8f6697da08d10b9cac97ed54\"}'\u003e\n\u003c/iframe\u003e\n\n\u003cul data-sourcepos=\"57:1-60:0\"\u003e\n\u003cli data-sourcepos=\"57:1-57:216\"\u003eClaude in Chrome は、\u003cstrong\u003e利用者がふだん使っている Chrome\u003c/strong\u003e で動きます。kintone にログインしたままなので、Claude にパスワードや API トークンを渡す必要はありません\u003c/li\u003e\n\u003cli data-sourcepos=\"58:1-58:237\"\u003eClaude は、ページを開く、クリックする、入力する、スクリーンショットを撮る、ページで JavaScript を動かす、ページのファイルの入力欄に手元のファイルを渡す、ができます\u003c/li\u003e\n\u003cli data-sourcepos=\"59:1-60:0\"\u003eページで動かす JavaScript から kintone の REST API を呼ぶと、ログインしている利用者の権限で動きます。今回の利用者は、開発環境のシステム管理の権限を持っています（プラグインの入れ替えに要ります）\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr data-sourcepos=\"61:1-62:0\"\u003e\n\u003ch1 data-sourcepos=\"63:1-63:50\"\u003e\n\u003cspan id=\"1-入っているプラグインの版を見る\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#1-%E5%85%A5%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%AE%E7%89%88%E3%82%92%E8%A6%8B%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e1. 入っているプラグインの版を見る\u003c/h1\u003e\n\u003cp data-sourcepos=\"65:1-65:250\"\u003eClaude は、スペースのページを開いたあと、まず開発環境に入っている印刷屋と計算式プラグインの版を調べました。ページの JavaScript から REST API（\u003ccode\u003eGET /k/v1/plugins.json\u003c/code\u003e）を呼んでいます。\u003c/p\u003e\n\u003cp data-sourcepos=\"67:1-67:210\"\u003e結果は、印刷屋が版 9、計算式が版 102。どちらも\u003cstrong\u003e今回の直しの前のビルド\u003c/strong\u003eです。確かめるには、作り直した zip に入れ替える必要があると判断しました。\u003c/p\u003e\n\u003cp data-sourcepos=\"69:1-69:279\"\u003e計算式プラグインの zip はまだ作っていなかったので、Claude が作りました。このとき、手元の \u003ccode\u003edist/\u003c/code\u003e に置いてあった未追跡の zip を上書きしないように、git に入らないフォルダーに別の名前で作っています。\u003c/p\u003e\n\u003chr data-sourcepos=\"71:1-72:0\"\u003e\n\u003ch1 data-sourcepos=\"73:1-73:38\"\u003e\n\u003cspan id=\"2-プラグインを入れ替える\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#2-%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%92%E5%85%A5%E3%82%8C%E6%9B%BF%E3%81%88%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e2. プラグインを入れ替える\u003c/h1\u003e\n\u003cp data-sourcepos=\"75:1-75:317\"\u003eこれまで、プラグインの入れ替えは自作のスクリプト（\u003ccode\u003enpm run upload-*\u003c/code\u003e）で行っていました。スクリプトは Node から REST API（\u003ccode\u003e/k/v1/file.json\u003c/code\u003e と \u003ccode\u003e/k/v1/plugin.json\u003c/code\u003e）を呼びます。認証は、環境変数に置いた kintone のユーザー名とパスワードです。\u003c/p\u003e\n\u003cp data-sourcepos=\"77:1-77:208\"\u003e今回は、\u003cstrong\u003eClaude が Chrome の操作で入れ替えました\u003c/strong\u003e。呼ぶ REST API は同じ 2 つですが、ログイン中の Chrome のページから呼ぶので、パスワードを使いません。\u003c/p\u003e\n\u003ctable data-sourcepos=\"79:1-84:101\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"79:1-79:70\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"79:2-79:2\"\u003e\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"79:4-79:38\"\u003eこれまで（スクリプト）\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"79:40-79:69\"\u003e今回（Chrome の操作）\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"81:1-81:96\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"81:2-81:15\"\u003e動かす所\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"81:17-81:32\"\u003e手元の Node\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"81:34-81:95\"\u003eログイン中の Chrome のページ（Claude in Chrome）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"82:1-82:76\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"82:2-82:13\"\u003e呼ぶ API\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"82:15-82:66\"\u003e\n\u003ccode\u003ePOST /k/v1/file.json\u003c/code\u003e → \u003ccode\u003ePUT /k/v1/plugin.json\u003c/code\u003e\n\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"82:68-82:75\"\u003e同じ\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"83:1-83:130\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"83:2-83:9\"\u003e認証\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"83:11-83:60\"\u003e環境変数のユーザー名とパスワード\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"83:62-83:129\"\u003eブラウザーのログイン（パスワードは使わない）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"84:1-84:101\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"84:2-84:19\"\u003ezip の渡し方\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"84:21-84:52\"\u003eファイルのパスを指定\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"84:54-84:100\"\u003eページのファイルの入力欄に渡す\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"86:1-86:58\"\u003eClaude は、ページで次の順に処理しました。\u003c/p\u003e\n\u003col data-sourcepos=\"88:1-92:0\"\u003e\n\u003cli data-sourcepos=\"88:1-88:66\"\u003eページに見えないファイルの入力欄を 1 つ作る\u003c/li\u003e\n\u003cli data-sourcepos=\"89:1-89:125\"\u003eその入力欄に、手元の zip を Claude in Chrome の機能で渡す（ファイル選択の画面は開かない）\u003c/li\u003e\n\u003cli data-sourcepos=\"90:1-90:113\"\u003e入力欄のファイルの SHA-256 をページで計算し、手元の zip の値と同じかを確かめる\u003c/li\u003e\n\u003cli data-sourcepos=\"91:1-92:0\"\u003eファイルを kintone に上げて（\u003ccode\u003ePOST /k/v1/file.json\u003c/code\u003e）、プラグインを更新する（\u003ccode\u003ePUT /k/v1/plugin.json\u003c/code\u003e）\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"js\" data-sourcepos=\"93:1-107:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003etoken\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nx\"\u003ekintone\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetRequestToken\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003ef\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nb\"\u003edocument\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003egetElementById\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eclaude-upload\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"nx\"\u003efiles\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"nx\"\u003efd\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003enew\u003c/span\u003e \u003cspan class=\"nc\"\u003eFormData\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003cspan class=\"nx\"\u003efd\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eappend\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e__REQUEST_TOKEN__\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003etoken\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"nx\"\u003efd\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003eappend\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003efile\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ef\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003ef\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003cspan class=\"kd\"\u003econst\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"nx\"\u003efileKey\u003c/span\u003e \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003eawait \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nf\"\u003efetch\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e/k/v1/file.json\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ePOST\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eX-Requested-With\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eXMLHttpRequest\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e \u003cspan class=\"na\"\u003ebody\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003efd\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003cspan class=\"p\"\u003e})).\u003c/span\u003e\u003cspan class=\"nf\"\u003ejson\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003cspan class=\"k\"\u003eawait\u003c/span\u003e \u003cspan class=\"nf\"\u003efetch\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e/k/v1/plugin.json\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n  \u003cspan class=\"na\"\u003emethod\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003ePUT\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n  \u003cspan class=\"na\"\u003eheaders\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eX-Requested-With\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eXMLHttpRequest\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eContent-Type\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003eapplication/json\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e \u003cspan class=\"p\"\u003e},\u003c/span\u003e\n  \u003cspan class=\"na\"\u003ebody\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003eJSON\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nf\"\u003estringify\u003c/span\u003e\u003cspan class=\"p\"\u003e({\u003c/span\u003e \u003cspan class=\"na\"\u003eid\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"s1\"\u003e（プラグイン ID）\u003c/span\u003e\u003cspan class=\"dl\"\u003e'\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"nx\"\u003efileKey\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"na\"\u003e__REQUEST_TOKEN__\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nx\"\u003etoken\u003c/span\u003e \u003cspan class=\"p\"\u003e}),\u003c/span\u003e\n\u003cspan class=\"p\"\u003e});\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"109:1-109:83\"\u003e印刷屋、計算式の順に入れ替え、どちらも 200 で返りました。\u003c/p\u003e\n\u003cblockquote data-sourcepos=\"111:1-111:345\"\u003e\n\u003cp data-sourcepos=\"111:3-111:345\"\u003eプラグインの入れ替えは、その環境でプラグインを使っている\u003cstrong\u003eすべてのアプリ\u003c/strong\u003eに効きます。今回は開発環境で、前の zip を入れ直せば戻せるので、Claude は確認を求めずに進めました。本番の環境なら、入れ替えの前に止めて聞くように頼むところです。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr data-sourcepos=\"113:1-114:0\"\u003e\n\u003ch1 data-sourcepos=\"115:1-115:35\"\u003e\n\u003cspan id=\"3-テスト用アプリを作る\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#3-%E3%83%86%E3%82%B9%E3%83%88%E7%94%A8%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E4%BD%9C%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e3. テスト用アプリを作る\u003c/h1\u003e\n\u003cp data-sourcepos=\"117:1-117:187\"\u003eアプリも、ページの JavaScript から REST API で作りました。画面でアプリを作り、項目を 1 つずつ置くより速く、項目コードを間違えません。\u003c/p\u003e\n\u003col data-sourcepos=\"119:1-124:0\"\u003e\n\u003cli data-sourcepos=\"119:1-119:154\"\u003eアプリを作る（\u003ccode\u003ePOST /k/v1/preview/app.json\u003c/code\u003e に \u003ccode\u003espace\u003c/code\u003e と \u003ccode\u003ethread\u003c/code\u003e を付けると、そのスペースのスレッドのアプリになる）\u003c/li\u003e\n\u003cli data-sourcepos=\"120:1-120:65\"\u003e項目を足す（\u003ccode\u003ePOST /k/v1/preview/app/form/fields.json\u003c/code\u003e）\u003c/li\u003e\n\u003cli data-sourcepos=\"121:1-121:106\"\u003eアプリに印刷屋と計算式プラグインを入れる（\u003ccode\u003ePOST /k/v1/preview/app/plugins.json\u003c/code\u003e）\u003c/li\u003e\n\u003cli data-sourcepos=\"122:1-122:91\"\u003e運用環境に反映して、終わるのを待つ（\u003ccode\u003e/k/v1/preview/app/deploy.json\u003c/code\u003e）\u003c/li\u003e\n\u003cli data-sourcepos=\"123:1-124:0\"\u003eテスト用のレコードを 1 件作る（会社名「(株)山田」、数値 1200）\u003c/li\u003e\n\u003c/ol\u003e\n\u003ctable data-sourcepos=\"125:1-131:63\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"125:1-125:37\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"125:2-125:18\"\u003e項目コード\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"125:20-125:24\"\u003e型\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"125:26-125:36\"\u003e使い道\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"127:1-127:62\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"127:2-127:12\"\u003e会社名\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"127:14-127:35\"\u003e文字列（1 行）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"127:37-127:61\"\u003e\n\u003ccode\u003e(株)\u003c/code\u003e で始まる値\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"128:1-128:46\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"128:2-128:9\"\u003e数値\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"128:11-128:18\"\u003e数値\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"128:20-128:45\"\u003e括弧で包んだ条件\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"129:1-129:130\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"129:2-129:70\"\u003e結果_連結 / 結果_括弧 / 結果_括弧文字 / 結果_真偽\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"129:72-129:93\"\u003e文字列（1 行）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"129:95-129:129\"\u003e計算式プラグインの結果\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"130:1-130:87\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"130:2-130:18\"\u003e備考 / 区分\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"130:20-130:41\"\u003e文字列（1 行）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"130:43-130:86\"\u003e印刷屋の更新項目の書き込み先\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"131:1-131:63\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"131:2-131:9\"\u003e帳票\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"131:11-131:30\"\u003e添付ファイル\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"131:32-131:62\"\u003e印刷屋の PDF の保存先\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"133:1-133:383\"\u003e「帳票」は、あとから足した項目です。印刷屋は、保存先の添付ファイル項目を決めないと PDF をダウンロードします。Claude は\u003cstrong\u003eファイルのダウンロードを、利用者の許可を取ってからにする決まり\u003c/strong\u003eで動いているため、PDF をレコードに保存する形にして、ダウンロードを避けました。\u003c/p\u003e\n\u003chr data-sourcepos=\"135:1-136:0\"\u003e\n\u003ch1 data-sourcepos=\"137:1-137:53\"\u003e\n\u003cspan id=\"4-プラグインの設定を作って取り込む\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#4-%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E5%8F%96%E3%82%8A%E8%BE%BC%E3%82%80\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e4. プラグインの設定を作って取り込む\u003c/h1\u003e\n\u003ch2 data-sourcepos=\"139:1-139:12\"\u003e\n\u003cspan id=\"印刷屋\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8D%B0%E5%88%B7%E5%B1%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e印刷屋\u003c/h2\u003e\n\u003cp data-sourcepos=\"141:1-141:140\"\u003e印刷屋の設定は、設定づくりの tools（\u003ccode\u003e@rex0220/print-craft-authoring-tools\u003c/code\u003e）で作りました。ボタンは 4 つです。\u003c/p\u003e\n\u003ctable data-sourcepos=\"143:1-148:88\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"143:1-143:49\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"143:2-143:12\"\u003eボタン\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"143:14-143:27\"\u003e表示条件\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"143:29-143:48\"\u003e確かめること\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"145:1-145:117\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"145:2-145:22\"\u003e確認A（出る）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"145:24-145:49\"\u003e\u003ccode\u003eIF((数値 \u0026gt; 5), 1, 0)\u003c/code\u003e\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"145:51-145:116\"\u003e本文の \u003ccode\u003e${}\u003c/code\u003e、ファイル名、PDF の保存、更新項目\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"146:1-146:178\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"146:2-146:25\"\u003e確認B（出ない）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"146:27-146:63\"\u003e\u003ccode\u003e\"[\" \u0026amp; TRIM(会社名) \u0026amp; \"]\" = \"x\"\u003c/code\u003e\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"146:65-146:177\"\u003e直す前のエンジンなら、表示条件のエラーで「真」として扱われて出ていたボタン\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"147:1-147:99\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"147:2-147:25\"\u003e確認C（出ない）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"147:27-147:56\"\u003e\u003ccode\u003eIF((数値 \u0026gt; 99999), 1, 0)\u003c/code\u003e\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"147:58-147:98\"\u003e括弧で包んだ条件が偽になる\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"148:1-148:88\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"148:2-148:25\"\u003e確認D（エラー）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"148:27-148:31\"\u003e\u003ccode\u003e1\u003c/code\u003e\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"148:33-148:87\"\u003e\n\u003ccode\u003e${LET(数値, 5, 数値 * 2)}\u003c/code\u003e のエラーの表示\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"150:1-150:65\"\u003e確認A の本文には、直した形の式を並べました。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"html\" data-sourcepos=\"152:1-163:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e\u003cspan class=\"nt\"\u003e\u0026lt;div\u003c/span\u003e \u003cspan class=\"na\"\u003eclass=\u003c/span\u003e\u003cspan class=\"s\"\u003e\"rex0220-pcraft-page\"\u003c/span\u003e\u003cspan class=\"nt\"\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"nt\"\u003e\u0026lt;h2\u0026gt;\u003c/span\u003eVer.102 エンジン確認\u003cspan class=\"nt\"\u003e\u0026lt;/h2\u0026gt;\u003c/span\u003e\n\u003cspan class=\"nt\"\u003e\u0026lt;p\u0026gt;\u003c/span\u003eT1 連結: [${\"\u003cspan class=\"nt\"\u003e\u0026lt;b\u0026gt;\u003c/span\u003e\" \u003cspan class=\"err\"\u003e\u0026amp;\u003c/span\u003e ESC_HTML(会社名) \u003cspan class=\"err\"\u003e\u0026amp;\u003c/span\u003e \"\u003cspan class=\"nt\"\u003e\u0026lt;/b\u0026gt;\u003c/span\u003e\"}]\u003cspan class=\"nt\"\u003e\u0026lt;/p\u0026gt;\u003c/span\u003e\n\u003cspan class=\"nt\"\u003e\u0026lt;p\u0026gt;\u003c/span\u003eT2 括弧の条件: [${IF((数値 \u0026gt; 5), \"大\", \"小\")}]\u003cspan class=\"nt\"\u003e\u0026lt;/p\u0026gt;\u003c/span\u003e\n\u003cspan class=\"nt\"\u003e\u0026lt;p\u0026gt;\u003c/span\u003eT3 括弧の文字列: [${(\"test\")}]\u003cspan class=\"nt\"\u003e\u0026lt;/p\u0026gt;\u003c/span\u003e\n\u003cspan class=\"nt\"\u003e\u0026lt;p\u0026gt;\u003c/span\u003eT4 関数名の字面: ${\"[\" \u003cspan class=\"err\"\u003e\u0026amp;\u003c/span\u003e TRIM(\"見積 ROUND(1.5) 件\") \u003cspan class=\"err\"\u003e\u0026amp;\u003c/span\u003e \"]\"}\u003cspan class=\"nt\"\u003e\u0026lt;/p\u0026gt;\u003c/span\u003e\n\u003cspan class=\"nt\"\u003e\u0026lt;p\u0026gt;\u003c/span\u003eT5 真偽: [${IF(1, 1=1, 0) \u003cspan class=\"err\"\u003e\u0026amp;\u003c/span\u003e \"\"}]\u003cspan class=\"nt\"\u003e\u0026lt;/p\u0026gt;\u003c/span\u003e\n\u003cspan class=\"nt\"\u003e\u0026lt;p\u0026gt;\u003c/span\u003eT6 空白の削り: ${\"[\" \u003cspan class=\"err\"\u003e\u0026amp;\u003c/span\u003e IF(1=1, \" a \", \"\") \u003cspan class=\"err\"\u003e\u0026amp;\u003c/span\u003e \"]\"}\u003cspan class=\"nt\"\u003e\u0026lt;/p\u0026gt;\u003c/span\u003e\n\u003cspan class=\"nt\"\u003e\u0026lt;p\u0026gt;\u003c/span\u003eT7 括弧で包む: ${\"[\" \u003cspan class=\"err\"\u003e\u0026amp;\u003c/span\u003e (IF(1=1, \" a \", \"\")) \u003cspan class=\"err\"\u003e\u0026amp;\u003c/span\u003e \"]\"}\u003cspan class=\"nt\"\u003e\u0026lt;/p\u0026gt;\u003c/span\u003e\n\u003cspan class=\"nt\"\u003e\u0026lt;/div\u0026gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"165:1-165:353\"\u003e更新項目は、更新条件 \u003ccode\u003e\"[\" \u0026amp; TRIM(会社名) \u0026amp; \"]\" = \"[(株)山田]\"\u003c/code\u003e、備考 \u003ccode\u003e\"\u0026lt;\" \u0026amp; TRIM(会社名) \u0026amp; \"\u0026gt;\"\u003c/code\u003e、区分 \u003ccode\u003eIF((数値 \u0026gt; 1000), \"大\", \"小\")\u003c/code\u003e です。ファイル名は \u003ccode\u003eTRIM(会社名) \u0026amp; \"_見積\"\u003c/code\u003e、「ボタンを押したとき」は「プレビューを表示」にしました（PDF を作る前に本文を読めます）。\u003c/p\u003e\n\u003cp data-sourcepos=\"167:1-167:222\"\u003etools の \u003ccode\u003enormalize\u003c/code\u003e で検査すると、エラー 0、警告 2 でした。警告は「\u003ccode\u003e${}\u003c/code\u003e が文字列をエスケープせずに差し込んでいる」で、テストのためにわざとそう書いた所です。\u003c/p\u003e\n\u003cp data-sourcepos=\"169:1-169:272\"\u003eできた設定のファイルを、Claude は印刷屋の設定画面の「設定のアップロード」の入力欄に渡し、取り込み方「全置換」→「取り込む」→「運用環境に反映」にチェック →「保存する」と操作しました。\u003c/p\u003e\n\u003cp data-sourcepos=\"171:1-171:222\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F57e82109-19fe-48e6-ae85-a89ed4024232.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=8ae5993e3365d09fa1f90e2a0fc3df8f\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F57e82109-19fe-48e6-ae85-a89ed4024232.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=8ae5993e3365d09fa1f90e2a0fc3df8f\" alt=\"印刷屋の設定のアップロード — 取り込み方「全置換」で 4 つのボタンを取り込む\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F57e82109-19fe-48e6-ae85-a89ed4024232.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=88be4a51b8098c547c80c1659a2b0538 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/57e82109-19fe-48e6-ae85-a89ed4024232.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 data-sourcepos=\"173:1-173:27\"\u003e\n\u003cspan id=\"計算式プラグイン\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%88%E7%AE%97%E5%BC%8F%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e計算式プラグイン\u003c/h2\u003e\n\u003cp data-sourcepos=\"175:1-175:126\"\u003e計算式プラグインの設定も tools で検査しようとしたところ、tools が zip を読みませんでした。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"177:1-179:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003eauthoring API のプラグインの版 101 が zip の manifest の版 102 と違う（組み替えられた zip）\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"181:1-181:342\"\u003e調べると、設定画面が tools に渡す API のファイルが、版を 102 に上げる前に作ったままでした。リリースの手順に作り直しがあり、その手前の段階だったためです。\u003cstrong\u003e実機テストのついでに、リリースの前にしておくことを 1 つ見つけた\u003c/strong\u003eことになります。\u003c/p\u003e\n\u003cp data-sourcepos=\"183:1-183:268\"\u003eこの確かめには tools を使わず、設定の元のファイル（項目ごとに項目コードと計算式を並べたもの）を、計算式プラグインの設定画面で直接取り込みました。設定画面が既定値を補い、検査します。\u003c/p\u003e\n\u003ctable data-sourcepos=\"185:1-190:40\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"185:1-185:22\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"185:2-185:9\"\u003e項目\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"185:11-185:21\"\u003e計算式\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"187:1-187:49\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"187:2-187:16\"\u003e結果_連結\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"187:18-187:48\"\u003e\u003ccode\u003e\"\u0026lt;\" \u0026amp; TRIM(会社名) \u0026amp; \"\u0026gt;\"\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"188:1-188:52\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"188:2-188:16\"\u003e結果_括弧\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"188:18-188:51\"\u003e\u003ccode\u003eIF((数値 \u0026gt; 5), \"大\", \"小\")\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"189:1-189:36\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"189:2-189:22\"\u003e結果_括弧文字\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"189:24-189:35\"\u003e\u003ccode\u003e(\"test\")\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"190:1-190:40\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"190:2-190:16\"\u003e結果_真偽\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"190:18-190:39\"\u003e\u003ccode\u003eIF(1, 1=1, 0) \u0026amp; \"\"\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"192:1-192:207\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc690a5b9-18b3-435d-a3bb-58ca01f31efb.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=5fd98a31e1ac3df0aa380f9f8efe40f2\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc690a5b9-18b3-435d-a3bb-58ca01f31efb.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=5fd98a31e1ac3df0aa380f9f8efe40f2\" alt=\"計算式プラグインの設定画面 — 取り込んだ 4 つの計算式（6〜9 行目）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc690a5b9-18b3-435d-a3bb-58ca01f31efb.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=a4273e4243f0bf895f2b66c045fae136 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c690a5b9-18b3-435d-a3bb-58ca01f31efb.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003chr data-sourcepos=\"194:1-195:0\"\u003e\n\u003ch1 data-sourcepos=\"196:1-196:26\"\u003e\n\u003cspan id=\"5-画面で確かめる\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#5-%E7%94%BB%E9%9D%A2%E3%81%A7%E7%A2%BA%E3%81%8B%E3%82%81%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e5. 画面で確かめる\u003c/h1\u003e\n\u003ch2 data-sourcepos=\"198:1-198:12\"\u003e\n\u003cspan id=\"印刷屋-1\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%8D%B0%E5%88%B7%E5%B1%8B-1\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e印刷屋\u003c/h2\u003e\n\u003cp data-sourcepos=\"200:1-200:174\"\u003eレコードの詳細画面を開くと、出たボタンは「確認A（出る）」と「確認D（エラー）」の 2 つでした。確認B と確認C は出ません。\u003c/p\u003e\n\u003cp data-sourcepos=\"202:1-202:283\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fd8fcea64-a8ae-4f9e-8ee1-10e896294d36.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=c2c90c2a29a56ef92262993a858f17e2\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fd8fcea64-a8ae-4f9e-8ee1-10e896294d36.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=c2c90c2a29a56ef92262993a858f17e2\" alt=\"テスト用アプリの詳細画面 — 出たボタンは確認A と確認D の 2 つ。項目には計算式プラグインの結果と、印刷屋の更新項目・PDF\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fd8fcea64-a8ae-4f9e-8ee1-10e896294d36.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=1a0099ccfe174492a09320f5b5db340d 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d8fcea64-a8ae-4f9e-8ee1-10e896294d36.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"204:1-204:177\"\u003e確認A を押して開いたプレビューの文字は、Claude がページの JavaScript で読みました。スクリーンショットを目で読むより確実です。\u003c/p\u003e\n\u003cp data-sourcepos=\"206:1-206:157\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc6c46a9c-b0c7-4973-9c5f-8b402915f603.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=c1a7a9f4df16c2c36bf208f73a395926\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc6c46a9c-b0c7-4973-9c5f-8b402915f603.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=c1a7a9f4df16c2c36bf208f73a395926\" alt=\"確認A のプレビュー — T1〜T7 の行\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fc6c46a9c-b0c7-4973-9c5f-8b402915f603.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=9c09594630ccef0b8835f79292f8b392 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c6c46a9c-b0c7-4973-9c5f-8b402915f603.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ctable data-sourcepos=\"208:1-216:42\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"208:1-208:52\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"208:2-208:6\"\u003e行\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"208:8-208:24\"\u003eプレビュー\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"208:26-208:51\"\u003e直す前のエンジン\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"210:1-210:55\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"210:2-210:12\"\u003eT1 連結\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"210:14-210:42\"\u003e\n\u003ccode\u003e[(株)山田]\u003c/code\u003e（太字）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"210:44-210:54\"\u003eエラー\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"211:1-211:44\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"211:2-211:21\"\u003eT2 括弧の条件\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"211:23-211:31\"\u003e\u003ccode\u003e[大]\u003c/code\u003e\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"211:33-211:43\"\u003eエラー\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"212:1-212:75\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"212:2-212:24\"\u003eT3 括弧の文字列\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"212:26-212:35\"\u003e\u003ccode\u003e[test]\u003c/code\u003e\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"212:37-212:74\"\u003eエラー（項目 test を探す）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"213:1-213:72\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"213:2-213:24\"\u003eT4 関数名の字面\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"213:26-213:52\"\u003e\u003ccode\u003e[見積 ROUND(1.5) 件]\u003c/code\u003e\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"213:54-213:71\"\u003e\u003ccode\u003e[見積 2 件]\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"214:1-214:36\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"214:2-214:12\"\u003eT5 真偽\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"214:14-214:23\"\u003e\u003ccode\u003e[true]\u003c/code\u003e\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"214:25-214:35\"\u003eエラー\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"215:1-215:71\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"215:2-215:21\"\u003eT6 空白の削り\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"215:23-215:29\"\u003e\u003ccode\u003e[a]\u003c/code\u003e\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"215:31-215:70\"\u003e\n\u003ccode\u003e[a]\u003c/code\u003e（今回は変えていない）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"216:1-216:42\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"216:2-216:21\"\u003eT7 括弧で包む\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"216:23-216:31\"\u003e\u003ccode\u003e[ a ]\u003c/code\u003e\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"216:33-216:41\"\u003e\u003ccode\u003e[ a ]\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"218:1-218:478\"\u003eプレビューの「確認A（出る）」を押して PDF を作ると、添付ファイル項目に \u003ccode\u003e(株)山田_見積.pdf\u003c/code\u003e が保存され、備考が \u003ccode\u003e\u0026lt;(株)山田\u0026gt;\u003c/code\u003e、区分が \u003ccode\u003e大\u003c/code\u003e になりました。Claude は、この 3 つの値を画面だけでなく REST API（\u003ccode\u003eGET /k/v1/record.json\u003c/code\u003e）でも読み、文字まで確かめています。直す前のエンジンなら、ファイル名は既定の名前、更新項目は空になっていたところです。\u003c/p\u003e\n\u003cp data-sourcepos=\"220:1-220:150\"\u003e確認D を押すと、印刷屋のエラーのダイアログに \u003ccode\u003eLET() variable name (数値) is already defined.\u003c/code\u003e と、変数名が出ました。\u003c/p\u003e\n\u003cp data-sourcepos=\"222:1-222:202\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fe786bece-e3c3-412f-af5e-9442f1479957.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=0012004f77783695fa561dc99496f356\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fe786bece-e3c3-412f-af5e-9442f1479957.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=0012004f77783695fa561dc99496f356\" alt=\"確認D のエラーのダイアログ（上の部分）— 変数名「数値」が出る\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Fe786bece-e3c3-412f-af5e-9442f1479957.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=1c50332c5e51ac154779885a4cef0581 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/e786bece-e3c3-412f-af5e-9442f1479957.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"224:1-224:206\"\u003eダイアログの下には、エラーの経路（プラグインのファイルの URL）も出ます。URL に開発環境のホスト名が入るので、画像はその上までにしてあります。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"226:1-226:27\"\u003e\n\u003cspan id=\"計算式プラグイン-1\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%88%E7%AE%97%E5%BC%8F%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3-1\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e計算式プラグイン\u003c/h2\u003e\n\u003cp data-sourcepos=\"228:1-228:222\"\u003eデスクトップでレコードを編集画面で開くと、4 つの結果の項目に \u003ccode\u003e\u0026lt;(株)山田\u0026gt;\u003c/code\u003e、\u003ccode\u003e大\u003c/code\u003e、\u003ccode\u003etest\u003c/code\u003e、\u003ccode\u003etrue\u003c/code\u003e が入っていました。保存して、REST API でも同じ値を確かめました。\u003c/p\u003e\n\u003cp data-sourcepos=\"230:1-230:215\"\u003eモバイルは、モバイル版の URL（\u003ccode\u003e/k/m/（アプリ番号）/edit?record=1\u003c/code\u003e）で開きました。数値を 3 に変えると、結果_括弧が「小」に変わり、そのまま保存できました。\u003c/p\u003e\n\u003cp data-sourcepos=\"232:1-232:198\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F0103a53e-451f-4bac-a7c2-3eb07b73f940.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=75ad685bd784b10737c2165c548ab41d\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F0103a53e-451f-4bac-a7c2-3eb07b73f940.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=75ad685bd784b10737c2165c548ab41d\" alt=\"モバイル版で保存した後のレコード — 数値 3、結果_括弧「小」\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F0103a53e-451f-4bac-a7c2-3eb07b73f940.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=861f22eace96599e1052b5f5db98e4e2 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/0103a53e-451f-4bac-a7c2-3eb07b73f940.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"234:1-234:210\"\u003eこの画像は、記事のために数値を 1200 に戻す前（モバイルで保存した直後）に撮りました。PC の詳細画面の画像は、数値を 1200 に戻してから撮っています。\u003c/p\u003e\n\u003cp data-sourcepos=\"236:1-236:188\"\u003e同じアプリに印刷屋と計算式プラグインの両方を入れているので、2 つのプラグインが同じ画面で動くことも、あわせて確かめられました。\u003c/p\u003e\n\u003chr data-sourcepos=\"238:1-239:0\"\u003e\n\u003ch1 data-sourcepos=\"240:1-240:17\"\u003e\n\u003cspan id=\"結果の報告\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%B5%90%E6%9E%9C%E3%81%AE%E5%A0%B1%E5%91%8A\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e結果の報告\u003c/h1\u003e\n\u003cp data-sourcepos=\"242:1-242:121\"\u003eClaude の報告は、確かめた項目と結果の表に、「確かめていないこと」を添えた形でした。\u003c/p\u003e\n\u003cul data-sourcepos=\"244:1-246:0\"\u003e\n\u003cli data-sourcepos=\"244:1-244:215\"\u003e帳票例のアプリ（重い帳票）の実機の確かめは、していない。ボタンによっては、すぐに PDF を作ってダウンロードするため（Node の確かめでは 620 行が同じ）\u003c/li\u003e\n\u003cli data-sourcepos=\"245:1-246:0\"\u003e計算式プラグインの zip は、リリース用ではなく試しのビルド（リリースの前に、設定画面の API を作り直す）\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"247:1-247:255\"\u003e確かめていないことを、確かめたように書かないのは、ここでも同じでした。結果は、作業の記録（計画の文書）にも書き足してあります。開発環境のホスト名は、記録では伏せています。\u003c/p\u003e\n\u003chr data-sourcepos=\"249:1-250:0\"\u003e\n\u003ch1 data-sourcepos=\"251:1-251:40\"\u003e\n\u003cspan id=\"記事の画像も-claude-が撮った\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%98%E4%BA%8B%E3%81%AE%E7%94%BB%E5%83%8F%E3%82%82-claude-%E3%81%8C%E6%92%AE%E3%81%A3%E3%81%9F\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e記事の画像も Claude が撮った\u003c/h1\u003e\n\u003cp data-sourcepos=\"253:1-253:172\"\u003e本記事の 6 枚の画像も、Claude が Claude in Chrome で撮ったものです。記事の原稿ができた後に、「画像を追加して」と頼みました。\u003c/p\u003e\n\u003ctable data-sourcepos=\"255:1-264:163\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"255:1-255:32\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"255:2-255:6\"\u003e順\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"255:8-255:31\"\u003eClaude がしたこと\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"257:1-257:230\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"257:2-257:4\"\u003e1\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"257:6-257:229\"\u003eテスト用アプリを開き直し、記事の章ごとに要る画面（設定のアップロード、計算式の設定画面、詳細画面、プレビュー、エラーのダイアログ、モバイル）を決める\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"258:1-258:131\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"258:2-258:4\"\u003e2\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"258:6-258:130\"\u003e画面全体を撮って切り取るのでなく、範囲を指定して拡大して撮る（文字が粗くならない）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"259:1-259:128\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"259:2-259:4\"\u003e3\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"259:6-259:127\"\u003e撮る前に、マウスのカーソルを画面の端へ動かす（最初の 1 枚に写ったので撮り直した）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"260:1-260:195\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"260:2-260:4\"\u003e4\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"260:6-260:194\"\u003eログイン名が出る上の帯、設定画面の下の「更新者」、エラーのダイアログの下の経路（開発環境のホスト名入りの URL）を、範囲から外す\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"261:1-261:236\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"261:2-261:4\"\u003e5\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"261:6-261:235\"\u003e記事の本文と同じ状態にするため、モバイルで 3 にした数値を、PC の編集画面で 1200 に戻す（計算式プラグインが結果を計算し直す）。モバイルの画像は、戻す前に撮る\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"262:1-262:206\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"262:2-262:4\"\u003e6\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"262:6-262:205\"\u003e設定のアップロードのダイアログは、同じ設定のファイルをもう一度入力欄に渡して出し、撮った後に「キャンセル」で閉じる（設定は変えない）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"263:1-263:119\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"263:2-263:4\"\u003e7\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"263:6-263:118\"\u003eモバイル版は PC の Chrome では横に広がるので、項目名と値が入る左側の範囲で撮る\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"264:1-264:163\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"264:2-264:4\"\u003e8\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"264:6-264:162\"\u003e画像を git に入れない場所（\u003ccode\u003e~/Projects/claude_out/\u003c/code\u003e）に、記事の順の番号付きの名前で置き、原稿の該当の場所に入れる\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"266:1-266:365\"\u003eQiita への画像のアップロードは、\u003ca href=\"https://qiita.com/rex0220/items/691f50272359dfb02a87\" id=\"reference-6614829276727f4196b3\"\u003e前の記事\u003c/a\u003e と同じく人が行いました。6 枚を上げて「画像アドレスを一括コピー」した Markdown を Claude Code に貼ると、Claude がファイル名で突き合わせて、原稿の画像を Qiita の URL に差し替えました。\u003c/p\u003e\n\u003cp data-sourcepos=\"268:1-268:168\"\u003eテストのために作ったアプリを、そのまま記事の画像にも使えるので、テストと記事を続けて頼むと手間が少なく済みます。\u003c/p\u003e\n\u003chr data-sourcepos=\"270:1-271:0\"\u003e\n\u003ch1 data-sourcepos=\"272:1-272:78\"\u003e\n\u003cspan id=\"指示していない手順はclaude-ができる範囲で組み立てた\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%8C%87%E7%A4%BA%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E6%89%8B%E9%A0%86%E3%81%AFclaude-%E3%81%8C%E3%81%A7%E3%81%8D%E3%82%8B%E7%AF%84%E5%9B%B2%E3%81%A7%E7%B5%84%E3%81%BF%E7%AB%8B%E3%81%A6%E3%81%9F\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e指示していない手順は、Claude ができる範囲で組み立てた\u003c/h1\u003e\n\u003cp data-sourcepos=\"274:1-274:338\"\u003e頼んだのは「テスト用アプリを作成して、ブラウザー操作でチェックして」の 1 行だけです。プラグインの入れ替え方や設定の作り方は指示していません。振り返ると、指示していない手順は、Claude が\u003cstrong\u003e自分で実行できる範囲\u003c/strong\u003eで組み立てていました。\u003c/p\u003e\n\u003ctable data-sourcepos=\"276:1-285:200\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"276:1-276:99\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"276:2-276:9\"\u003e場面\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"276:11-276:37\"\u003eClaude が選んだ手順\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"276:39-276:98\"\u003e選んだわけ（Claude ができる範囲・決まり）\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"278:1-278:374\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"278:2-278:33\"\u003eプラグインの入れ替え\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"278:35-278:89\"\u003eログイン中の Chrome のページから REST API\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"278:91-278:373\"\u003eいつものスクリプトは環境変数のパスワードで動き、プロジェクトの規則（CLAUDE.md）では、kintone へのアップロードを伴うスクリプトは指示がない限り動かさない。Chrome ならログインのまま、同じ API を呼べる\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"279:1-279:167\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"279:2-279:34\"\u003e計算式プラグインの zip\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"279:36-279:98\"\u003egit に入らないフォルダーに、別の名前で作る\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"279:100-279:166\"\u003e手元の \u003ccode\u003edist/\u003c/code\u003e にある未追跡の zip を上書きしない\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"280:1-280:148\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"280:2-280:33\"\u003eテスト用アプリと項目\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"280:35-280:75\"\u003eページの JavaScript から REST API\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"280:77-280:147\"\u003e画面のクリックより速く、項目コードを間違えない\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"281:1-281:285\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"281:2-281:30\"\u003e項目定義のファイル\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"281:32-281:124\"\u003eブラウザーの REST API で取り、tools が読む形のファイルを自分で書く\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"281:126-281:284\"\u003etools に kintone の接続が設定されていなかった。接続のファイルは利用者のもので、Claude は読まない・書かない決まり\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"282:1-282:161\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"282:2-282:21\"\u003e印刷屋の設定\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"282:23-282:72\"\u003e設定づくりの MCP でなく、tools の CLI\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"282:74-282:160\"\u003eMCP は作業フォルダーとして登録したフォルダーでしか動かない\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"283:1-283:140\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"283:2-283:36\"\u003e計算式プラグインの設定\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"283:38-283:90\"\u003etools でなく、設定画面で直接取り込む\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"283:92-283:139\"\u003etools が zip を読まなかった（4 章）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"284:1-284:185\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"284:2-284:19\"\u003e印刷屋の PDF\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"284:21-284:94\"\u003e添付ファイル項目に保存し、まずプレビューで止める\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"284:96-284:184\"\u003eファイルのダウンロードは、利用者の許可を取ってからの決まり\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"285:1-285:200\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"285:2-285:18\"\u003e記事の画像\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"285:20-285:96\"\u003eログイン名やホスト名が写らない範囲を選んで撮り直す\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"285:98-285:199\"\u003e開発環境のホスト名を記録に書かない、と Claude Code のメモリに残してある\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"287:1-287:323\"\u003e使える道具（Chrome の操作、手元のシェルとファイル）と、プロジェクトの規則・メモリ、Claude 自身の決まり（パスワードを扱わない、ダウンロードは許可を取る）の内側で手順を選ぶので、頼む側が細かい手順まで書かなくても進みます。\u003c/p\u003e\n\u003cp data-sourcepos=\"289:1-289:277\"\u003eただし、選んだ手順が人の想定と同じとは限りません。プラグインの入れ替えは、筆者はいつもスクリプトで行っています。Claude は報告に手順を書くので、それを読んで、違えば伝えるのが人の役目です。\u003c/p\u003e\n\u003chr data-sourcepos=\"291:1-292:0\"\u003e\n\u003ch1 data-sourcepos=\"293:1-293:26\"\u003e\n\u003cspan id=\"つまずいたところ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%A4%E3%81%BE%E3%81%9A%E3%81%84%E3%81%9F%E3%81%A8%E3%81%93%E3%82%8D\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eつまずいたところ\u003c/h1\u003e\n\u003ctable data-sourcepos=\"295:1-304:181\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"295:1-295:52\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"295:2-295:15\"\u003eつまずき\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"295:17-295:33\"\u003e起きたこと\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"295:35-295:51\"\u003eどうしたか\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"297:1-297:214\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"297:2-297:41\"\u003e設定づくりの MCP が使えない\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"297:43-297:159\"\u003eClaude Code を起動したフォルダーが、MCP の作業フォルダーとして登録されていなかった\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"297:161-297:213\"\u003e同じことができる tools の CLI を使った\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"298:1-298:194\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"298:2-298:27\"\u003etools の書き出し先\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"298:29-298:96\"\u003e\n\u003ccode\u003enormalize\u003c/code\u003e の書き出し先は決まったフォルダーだけ\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"298:98-298:193\"\u003e決まったフォルダーに書いてから、git に入らないフォルダーに移した\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"299:1-299:190\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"299:2-299:32\"\u003etools が zip を読まない\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"299:34-299:99\"\u003e計算式プラグインの API の版が古いまま（4 章）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"299:101-299:189\"\u003e設定画面で直接取り込んだ。リリースの前の作業として記録した\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"300:1-300:162\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"300:2-300:32\"\u003eJavaScript の結果が長い\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"300:34-300:92\"\u003e項目定義をまるごと返すと、途中で切れた\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"300:94-300:161\"\u003e項目コード・型・レイアウトだけに絞って返した\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"301:1-301:148\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"301:2-301:24\"\u003eモバイルの案内\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"301:26-301:102\"\u003eモバイル版を初めて開くと、案内の吹き出しが重なった\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"301:104-301:147\"\u003e吹き出しを閉じてから入力した\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"302:1-302:225\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"302:2-302:33\"\u003eダウンロードを避ける\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"302:35-302:107\"\u003e印刷屋の PDF は、保存先が無いとダウンロードになる\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"302:109-302:224\"\u003e添付ファイル項目を足して保存先にし、「ボタンを押したとき」をプレビューにした\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"303:1-303:279\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"303:2-303:30\"\u003e開発環境のホスト名\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"303:32-303:168\"\u003eURL や記録に入る。印刷屋のエラーのダイアログの下のエラーの経路にも、ホスト名入りの URL が出る\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"303:170-303:278\"\u003e記事と記録の URL は伏せた。エラーのダイアログの画像は、経路の上までにした\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"304:1-304:181\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"304:2-304:33\"\u003e画像にカーソルが写る\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"304:35-304:108\"\u003e記事用の画像を撮ったら、マウスのカーソルが入った\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"304:110-304:180\"\u003e撮る前にカーソルを画面の端へ動かして撮り直した\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003chr data-sourcepos=\"306:1-307:0\"\u003e\n\u003ch1 data-sourcepos=\"308:1-308:44\"\u003e\n\u003cspan id=\"人がすること任せられること\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BA%BA%E3%81%8C%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E4%BB%BB%E3%81%9B%E3%82%89%E3%82%8C%E3%82%8B%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e人がすること、任せられること\u003c/h1\u003e\n\u003ctable data-sourcepos=\"310:1-319:122\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"310:1-310:46\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"310:2-310:24\"\u003e任せられたこと\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"310:26-310:45\"\u003e人がしたこと\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"312:1-312:113\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"312:2-312:51\"\u003e入っているプラグインの版を調べる\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"312:53-312:112\"\u003eテストに使うスペースを決めて、URL を渡す\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"313:1-313:168\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"313:2-313:104\"\u003ezip を作って、Chrome の操作でプラグインを入れ替える（ファイルの照合も）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"313:106-313:167\"\u003eテスト用のスペース（開発環境）を用意する\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"314:1-314:115\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"314:2-314:57\"\u003eテスト用アプリと項目、レコードを作る\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"314:59-314:114\"\u003e何を確かめるか（直したこと）を決める\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"315:1-315:178\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"315:2-315:81\"\u003eプラグインの設定を作り、検査して、設定画面で取り込む\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"315:83-315:177\"\u003e重い帳票のアプリの確かめ（ダウンロードを伴う）をするかを決める\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"316:1-316:121\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"316:2-316:90\"\u003eボタンを押す、プレビューの文字を読む、REST API で値を確かめる\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"316:92-316:120\"\u003eコミットとリリース\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"317:1-317:97\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"317:2-317:45\"\u003eモバイル版で編集して保存する\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"317:47-317:96\"\u003eQiita への画像のアップロードと公開\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"318:1-318:48\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"318:2-318:45\"\u003e結果を表にまとめ、記録に書く\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"318:47-318:47\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"319:1-319:122\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"319:2-319:119\"\u003e記事の画像を撮る（範囲、カーソル、写してはいけない所）、Qiita の URL への差し替え\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"319:121-319:121\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"321:1-321:437\"\u003e実機テストで手間なのは、確かめる操作そのものより、\u003cstrong\u003eその前の準備\u003c/strong\u003e（zip の入れ替え、アプリと項目、設定の取り込み）です。準備から確認まで続けて任せられたのが、一番の収穫でした。設定画面で取り込むところは画面を操作し、アプリや項目を作るところは REST API を使う、という使い分けも Claude が決めています。\u003c/p\u003e\n\u003chr data-sourcepos=\"323:1-324:0\"\u003e\n\u003ch1 data-sourcepos=\"325:1-325:11\"\u003e\n\u003cspan id=\"まとめ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%BE%E3%81%A8%E3%82%81\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eまとめ\u003c/h1\u003e\n\u003cul data-sourcepos=\"327:1-336:0\"\u003e\n\u003cli data-sourcepos=\"327:1-327:210\"\u003eClaude Code に kintone のスペースの URL を渡して頼むと、ログイン済みの Chrome で、プラグインの入れ替えからテスト用アプリの作成、画面での確認までできる\u003c/li\u003e\n\u003cli data-sourcepos=\"328:1-328:239\"\u003eプラグインの入れ替えは、これまでのスクリプト（Node から REST API。パスワードで認証）と同じ API を、ログイン中の Chrome のページから呼んで済ませた。パスワードを使わない\u003c/li\u003e\n\u003cli data-sourcepos=\"329:1-329:177\"\u003eアプリや項目は、ページの JavaScript から REST API で作ると速く、項目コードを間違えない（ログインしている利用者の権限で動く）\u003c/li\u003e\n\u003cli data-sourcepos=\"330:1-330:144\"\u003eプラグインの zip や設定のファイルは、ページの入力欄に渡せる。SHA-256 で手元のファイルと照らすと安心\u003c/li\u003e\n\u003cli data-sourcepos=\"331:1-331:140\"\u003eダウンロードを避けるため、PDF の保存先を添付ファイル項目にするなど、テストの形も Claude が考える\u003c/li\u003e\n\u003cli data-sourcepos=\"332:1-332:81\"\u003e結果は REST API でも読むので、画面の見た目だけに頼らない\u003c/li\u003e\n\u003cli data-sourcepos=\"333:1-333:111\"\u003e実機テストの途中で、リリースの前の作業（API の作り直し）の漏れも見つかった\u003c/li\u003e\n\u003cli data-sourcepos=\"334:1-334:189\"\u003e指示していない手順は、Claude が使える道具と、規則・メモリ・自身の決まりの内側で組み立てる。報告の手順を読み、想定と違えば伝える\u003c/li\u003e\n\u003cli data-sourcepos=\"335:1-336:0\"\u003e記事の画像も、テスト用アプリを開き直して Claude が撮る。ログイン名やホスト名が写る所は範囲から外す\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 data-sourcepos=\"337:1-337:14\"\u003e\n\u003cspan id=\"関連記事\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E9%96%A2%E9%80%A3%E8%A8%98%E4%BA%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e関連記事\u003c/h1\u003e\n\u003cul data-sourcepos=\"339:1-341:90\"\u003e\n\u003cli data-sourcepos=\"339:1-339:90\"\u003e\u003ca href=\"https://qiita.com/rex0220/items/9be2d9b20a3a1f016c76\" id=\"reference-07adbe2e54acfc2304cb\"\u003erex0220 印刷屋プラグイン\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"340:1-340:168\"\u003e\u003ca href=\"https://qiita.com/rex0220/items/691f50272359dfb02a87\"\u003eClaude Code + Claude in Chrome で Qiita の記事を作る（印刷屋プラグインの組織図の記事）\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"341:1-341:90\"\u003e\u003ca href=\"https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73\" id=\"reference-0a53fb8802e0fa3d0a4a\"\u003erex0220 計算式プラグイン\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","body":"kintone プラグインの修正を出す前の最後の確かめは、実際の kintone の画面です。プラグインの zip を入れ替えて、テスト用のアプリを作り、設定を入れて、レコードを開いてボタンを押す……。手順は決まっていても、毎回それなりに時間がかかります。\n\n今回は、**Claude Code（VS Code の拡張機能）と Claude in Chrome（Chrome の拡張機能）** に、この実機テストをまとめて任せてみました。頼んだのは、kintone のスペースの URL を添えた 1 行だけです。\n\n```\n下記スペースにテスト用アプリを作成して、ブラウザー操作でチェックして\nhttps://（サブドメイン）.cybozu.com/k/#/space/（番号）/thread/（番号）\n```\n\nClaude は、プラグインの入れ替え、テスト用アプリの作成、プラグインの設定の取り込み、詳細画面・プレビュー・モバイルでの確認までを済ませ、結果を表にして報告しました。本記事では、その流れと、どこでつまずいたかを紹介します。\n\n---\n\n# 確かめたかったこと\n\nリリース前の **印刷屋プラグイン Ver.9** と **計算式プラグイン Ver.102** は、同じ計算式エンジンを使います。このエンジンに、次の直しを入れました。\n\n| 直したこと | 直す前 | 直した後 |\n| :--- | :--- | :--- |\n| `\u0026` でつないだ関数の結果が `(` で始まる・関数名の字面を含む・真偽値 | `\"\u003ctd\u003e\" \u0026 ESC_HTML(\"(株)山田\") \u0026 \"\u003c/td\u003e\"` がエラー、`\"[\" \u0026 TRIM(\"見積 ROUND(1.5) 件\") \u0026 \"]\"` が `[見積 2 件]` | 値のまま |\n| 式全体や関数の引数を括弧で包む | `IF((数値 \u003e 5), \"A\", \"B\")` がエラー、`(\"test\")` が項目 test の値 | 中の値のまま |\n| LET の変数名が項目のフィールドコードと同じ | `LET() variable name (0) is already defined.`（`(0)` は引数の位置） | `LET() variable name (数値) is already defined.` |\n\n直しは、Node で動かす確かめで済ませてありました。\n\n- 回帰の確かめ 170 件\n- 関数の説明文の使用例 1,218 件\n- 手元の帳票の設定 620 行（直す前のエンジンと、出力・エラー・評価回数が同じか）\n\n残っていたのが実機です。印刷屋のボタンの表示条件・プレビュー・PDF の保存・更新項目と、計算式プラグインのデスクトップ・モバイルの計算を、kintone の画面で見ておきたいところでした。\n\n---\n\n# 仕組みの構成\n\n```mermaid\nflowchart LR\n  U[\"利用者\"]\n\n  subgraph PC[\"利用者の PC\"]\n    CC[\"Claude Code\u003cbr\u003e（VS Code）\"]\n    CH[\"Chrome\u003cbr\u003eClaude in Chrome\u003cbr\u003e（kintone にログイン済み）\"]\n    FS[(\"ファイル\u003cbr\u003eプラグインの zip\u003cbr\u003e設定の JSON\")]\n    TL[\"設定づくりの tools\u003cbr\u003e（CLI）\"]\n  end\n\n  KT[\"kintone\u003cbr\u003e（開発環境）\"]\n\n  U -- \"頼む\" --\u003e CC\n  CC -- \"開く・押す・読む\u003cbr\u003eページで JavaScript\" --\u003e CH\n  CH -- \"画面の操作\u003cbr\u003eREST API（ログインのまま）\" --\u003e KT\n  CC -- \"設定を作る・検査する\" --\u003e TL\n  TL --\u003e FS\n  CC -- \"ファイルを入力欄に渡す\" --\u003e CH\n```\n\n- Claude in Chrome は、**利用者がふだん使っている Chrome** で動きます。kintone にログインしたままなので、Claude にパスワードや API トークンを渡す必要はありません\n- Claude は、ページを開く、クリックする、入力する、スクリーンショットを撮る、ページで JavaScript を動かす、ページのファイルの入力欄に手元のファイルを渡す、ができます\n- ページで動かす JavaScript から kintone の REST API を呼ぶと、ログインしている利用者の権限で動きます。今回の利用者は、開発環境のシステム管理の権限を持っています（プラグインの入れ替えに要ります）\n\n---\n\n# 1. 入っているプラグインの版を見る\n\nClaude は、スペースのページを開いたあと、まず開発環境に入っている印刷屋と計算式プラグインの版を調べました。ページの JavaScript から REST API（`GET /k/v1/plugins.json`）を呼んでいます。\n\n結果は、印刷屋が版 9、計算式が版 102。どちらも**今回の直しの前のビルド**です。確かめるには、作り直した zip に入れ替える必要があると判断しました。\n\n計算式プラグインの zip はまだ作っていなかったので、Claude が作りました。このとき、手元の `dist/` に置いてあった未追跡の zip を上書きしないように、git に入らないフォルダーに別の名前で作っています。\n\n---\n\n# 2. プラグインを入れ替える\n\nこれまで、プラグインの入れ替えは自作のスクリプト（`npm run upload-*`）で行っていました。スクリプトは Node から REST API（`/k/v1/file.json` と `/k/v1/plugin.json`）を呼びます。認証は、環境変数に置いた kintone のユーザー名とパスワードです。\n\n今回は、**Claude が Chrome の操作で入れ替えました**。呼ぶ REST API は同じ 2 つですが、ログイン中の Chrome のページから呼ぶので、パスワードを使いません。\n\n| | これまで（スクリプト） | 今回（Chrome の操作） |\n| :--- | :--- | :--- |\n| 動かす所 | 手元の Node | ログイン中の Chrome のページ（Claude in Chrome） |\n| 呼ぶ API | `POST /k/v1/file.json` → `PUT /k/v1/plugin.json` | 同じ |\n| 認証 | 環境変数のユーザー名とパスワード | ブラウザーのログイン（パスワードは使わない） |\n| zip の渡し方 | ファイルのパスを指定 | ページのファイルの入力欄に渡す |\n\nClaude は、ページで次の順に処理しました。\n\n1. ページに見えないファイルの入力欄を 1 つ作る\n2. その入力欄に、手元の zip を Claude in Chrome の機能で渡す（ファイル選択の画面は開かない）\n3. 入力欄のファイルの SHA-256 をページで計算し、手元の zip の値と同じかを確かめる\n4. ファイルを kintone に上げて（`POST /k/v1/file.json`）、プラグインを更新する（`PUT /k/v1/plugin.json`）\n\n```js\nconst token = kintone.getRequestToken();\nconst f = document.getElementById('claude-upload').files[0];\nconst fd = new FormData();\nfd.append('__REQUEST_TOKEN__', token);\nfd.append('file', f, f.name);\nconst { fileKey } = await (await fetch('/k/v1/file.json', {\n  method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest' }, body: fd,\n})).json();\nawait fetch('/k/v1/plugin.json', {\n  method: 'PUT',\n  headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json' },\n  body: JSON.stringify({ id: '（プラグイン ID）', fileKey, __REQUEST_TOKEN__: token }),\n});\n```\n\n印刷屋、計算式の順に入れ替え、どちらも 200 で返りました。\n\n\u003e プラグインの入れ替えは、その環境でプラグインを使っている**すべてのアプリ**に効きます。今回は開発環境で、前の zip を入れ直せば戻せるので、Claude は確認を求めずに進めました。本番の環境なら、入れ替えの前に止めて聞くように頼むところです。\n\n---\n\n# 3. テスト用アプリを作る\n\nアプリも、ページの JavaScript から REST API で作りました。画面でアプリを作り、項目を 1 つずつ置くより速く、項目コードを間違えません。\n\n1. アプリを作る（`POST /k/v1/preview/app.json` に `space` と `thread` を付けると、そのスペースのスレッドのアプリになる）\n2. 項目を足す（`POST /k/v1/preview/app/form/fields.json`）\n3. アプリに印刷屋と計算式プラグインを入れる（`POST /k/v1/preview/app/plugins.json`）\n4. 運用環境に反映して、終わるのを待つ（`/k/v1/preview/app/deploy.json`）\n5. テスト用のレコードを 1 件作る（会社名「(株)山田」、数値 1200）\n\n| 項目コード | 型 | 使い道 |\n| :--- | :--- | :--- |\n| 会社名 | 文字列（1 行） | `(株)` で始まる値 |\n| 数値 | 数値 | 括弧で包んだ条件 |\n| 結果_連結 / 結果_括弧 / 結果_括弧文字 / 結果_真偽 | 文字列（1 行） | 計算式プラグインの結果 |\n| 備考 / 区分 | 文字列（1 行） | 印刷屋の更新項目の書き込み先 |\n| 帳票 | 添付ファイル | 印刷屋の PDF の保存先 |\n\n「帳票」は、あとから足した項目です。印刷屋は、保存先の添付ファイル項目を決めないと PDF をダウンロードします。Claude は**ファイルのダウンロードを、利用者の許可を取ってからにする決まり**で動いているため、PDF をレコードに保存する形にして、ダウンロードを避けました。\n\n---\n\n# 4. プラグインの設定を作って取り込む\n\n## 印刷屋\n\n印刷屋の設定は、設定づくりの tools（`@rex0220/print-craft-authoring-tools`）で作りました。ボタンは 4 つです。\n\n| ボタン | 表示条件 | 確かめること |\n| :--- | :--- | :--- |\n| 確認A（出る） | `IF((数値 \u003e 5), 1, 0)` | 本文の `${}`、ファイル名、PDF の保存、更新項目 |\n| 確認B（出ない） | `\"[\" \u0026 TRIM(会社名) \u0026 \"]\" = \"x\"` | 直す前のエンジンなら、表示条件のエラーで「真」として扱われて出ていたボタン |\n| 確認C（出ない） | `IF((数値 \u003e 99999), 1, 0)` | 括弧で包んだ条件が偽になる |\n| 確認D（エラー） | `1` | `${LET(数値, 5, 数値 * 2)}` のエラーの表示 |\n\n確認A の本文には、直した形の式を並べました。\n\n```html\n\u003cdiv class=\"rex0220-pcraft-page\"\u003e\n\u003ch2\u003eVer.102 エンジン確認\u003c/h2\u003e\n\u003cp\u003eT1 連結: [${\"\u003cb\u003e\" \u0026 ESC_HTML(会社名) \u0026 \"\u003c/b\u003e\"}]\u003c/p\u003e\n\u003cp\u003eT2 括弧の条件: [${IF((数値 \u003e 5), \"大\", \"小\")}]\u003c/p\u003e\n\u003cp\u003eT3 括弧の文字列: [${(\"test\")}]\u003c/p\u003e\n\u003cp\u003eT4 関数名の字面: ${\"[\" \u0026 TRIM(\"見積 ROUND(1.5) 件\") \u0026 \"]\"}\u003c/p\u003e\n\u003cp\u003eT5 真偽: [${IF(1, 1=1, 0) \u0026 \"\"}]\u003c/p\u003e\n\u003cp\u003eT6 空白の削り: ${\"[\" \u0026 IF(1=1, \" a \", \"\") \u0026 \"]\"}\u003c/p\u003e\n\u003cp\u003eT7 括弧で包む: ${\"[\" \u0026 (IF(1=1, \" a \", \"\")) \u0026 \"]\"}\u003c/p\u003e\n\u003c/div\u003e\n```\n\n更新項目は、更新条件 `\"[\" \u0026 TRIM(会社名) \u0026 \"]\" = \"[(株)山田]\"`、備考 `\"\u003c\" \u0026 TRIM(会社名) \u0026 \"\u003e\"`、区分 `IF((数値 \u003e 1000), \"大\", \"小\")` です。ファイル名は `TRIM(会社名) \u0026 \"_見積\"`、「ボタンを押したとき」は「プレビューを表示」にしました（PDF を作る前に本文を読めます）。\n\ntools の `normalize` で検査すると、エラー 0、警告 2 でした。警告は「`${}` が文字列をエスケープせずに差し込んでいる」で、テストのためにわざとそう書いた所です。\n\nできた設定のファイルを、Claude は印刷屋の設定画面の「設定のアップロード」の入力欄に渡し、取り込み方「全置換」→「取り込む」→「運用環境に反映」にチェック →「保存する」と操作しました。\n\n![印刷屋の設定のアップロード — 取り込み方「全置換」で 4 つのボタンを取り込む](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/57e82109-19fe-48e6-ae85-a89ed4024232.png)\n\n## 計算式プラグイン\n\n計算式プラグインの設定も tools で検査しようとしたところ、tools が zip を読みませんでした。\n\n```\nauthoring API のプラグインの版 101 が zip の manifest の版 102 と違う（組み替えられた zip）\n```\n\n調べると、設定画面が tools に渡す API のファイルが、版を 102 に上げる前に作ったままでした。リリースの手順に作り直しがあり、その手前の段階だったためです。**実機テストのついでに、リリースの前にしておくことを 1 つ見つけた**ことになります。\n\nこの確かめには tools を使わず、設定の元のファイル（項目ごとに項目コードと計算式を並べたもの）を、計算式プラグインの設定画面で直接取り込みました。設定画面が既定値を補い、検査します。\n\n| 項目 | 計算式 |\n| :--- | :--- |\n| 結果_連結 | `\"\u003c\" \u0026 TRIM(会社名) \u0026 \"\u003e\"` |\n| 結果_括弧 | `IF((数値 \u003e 5), \"大\", \"小\")` |\n| 結果_括弧文字 | `(\"test\")` |\n| 結果_真偽 | `IF(1, 1=1, 0) \u0026 \"\"` |\n\n![計算式プラグインの設定画面 — 取り込んだ 4 つの計算式（6〜9 行目）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c690a5b9-18b3-435d-a3bb-58ca01f31efb.png)\n\n---\n\n# 5. 画面で確かめる\n\n## 印刷屋\n\nレコードの詳細画面を開くと、出たボタンは「確認A（出る）」と「確認D（エラー）」の 2 つでした。確認B と確認C は出ません。\n\n![テスト用アプリの詳細画面 — 出たボタンは確認A と確認D の 2 つ。項目には計算式プラグインの結果と、印刷屋の更新項目・PDF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d8fcea64-a8ae-4f9e-8ee1-10e896294d36.png)\n\n確認A を押して開いたプレビューの文字は、Claude がページの JavaScript で読みました。スクリーンショットを目で読むより確実です。\n\n![確認A のプレビュー — T1〜T7 の行](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c6c46a9c-b0c7-4973-9c5f-8b402915f603.png)\n\n| 行 | プレビュー | 直す前のエンジン |\n| :--- | :--- | :--- |\n| T1 連結 | `[(株)山田]`（太字） | エラー |\n| T2 括弧の条件 | `[大]` | エラー |\n| T3 括弧の文字列 | `[test]` | エラー（項目 test を探す） |\n| T4 関数名の字面 | `[見積 ROUND(1.5) 件]` | `[見積 2 件]` |\n| T5 真偽 | `[true]` | エラー |\n| T6 空白の削り | `[a]` | `[a]`（今回は変えていない） |\n| T7 括弧で包む | `[ a ]` | `[ a ]` |\n\nプレビューの「確認A（出る）」を押して PDF を作ると、添付ファイル項目に `(株)山田_見積.pdf` が保存され、備考が `\u003c(株)山田\u003e`、区分が `大` になりました。Claude は、この 3 つの値を画面だけでなく REST API（`GET /k/v1/record.json`）でも読み、文字まで確かめています。直す前のエンジンなら、ファイル名は既定の名前、更新項目は空になっていたところです。\n\n確認D を押すと、印刷屋のエラーのダイアログに `LET() variable name (数値) is already defined.` と、変数名が出ました。\n\n![確認D のエラーのダイアログ（上の部分）— 変数名「数値」が出る](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/e786bece-e3c3-412f-af5e-9442f1479957.png)\n\nダイアログの下には、エラーの経路（プラグインのファイルの URL）も出ます。URL に開発環境のホスト名が入るので、画像はその上までにしてあります。\n\n## 計算式プラグイン\n\nデスクトップでレコードを編集画面で開くと、4 つの結果の項目に `\u003c(株)山田\u003e`、`大`、`test`、`true` が入っていました。保存して、REST API でも同じ値を確かめました。\n\nモバイルは、モバイル版の URL（`/k/m/（アプリ番号）/edit?record=1`）で開きました。数値を 3 に変えると、結果_括弧が「小」に変わり、そのまま保存できました。\n\n![モバイル版で保存した後のレコード — 数値 3、結果_括弧「小」](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/0103a53e-451f-4bac-a7c2-3eb07b73f940.png)\n\nこの画像は、記事のために数値を 1200 に戻す前（モバイルで保存した直後）に撮りました。PC の詳細画面の画像は、数値を 1200 に戻してから撮っています。\n\n同じアプリに印刷屋と計算式プラグインの両方を入れているので、2 つのプラグインが同じ画面で動くことも、あわせて確かめられました。\n\n---\n\n# 結果の報告\n\nClaude の報告は、確かめた項目と結果の表に、「確かめていないこと」を添えた形でした。\n\n- 帳票例のアプリ（重い帳票）の実機の確かめは、していない。ボタンによっては、すぐに PDF を作ってダウンロードするため（Node の確かめでは 620 行が同じ）\n- 計算式プラグインの zip は、リリース用ではなく試しのビルド（リリースの前に、設定画面の API を作り直す）\n\n確かめていないことを、確かめたように書かないのは、ここでも同じでした。結果は、作業の記録（計画の文書）にも書き足してあります。開発環境のホスト名は、記録では伏せています。\n\n---\n\n# 記事の画像も Claude が撮った\n\n本記事の 6 枚の画像も、Claude が Claude in Chrome で撮ったものです。記事の原稿ができた後に、「画像を追加して」と頼みました。\n\n| 順 | Claude がしたこと |\n| :--- | :--- |\n| 1 | テスト用アプリを開き直し、記事の章ごとに要る画面（設定のアップロード、計算式の設定画面、詳細画面、プレビュー、エラーのダイアログ、モバイル）を決める |\n| 2 | 画面全体を撮って切り取るのでなく、範囲を指定して拡大して撮る（文字が粗くならない） |\n| 3 | 撮る前に、マウスのカーソルを画面の端へ動かす（最初の 1 枚に写ったので撮り直した） |\n| 4 | ログイン名が出る上の帯、設定画面の下の「更新者」、エラーのダイアログの下の経路（開発環境のホスト名入りの URL）を、範囲から外す |\n| 5 | 記事の本文と同じ状態にするため、モバイルで 3 にした数値を、PC の編集画面で 1200 に戻す（計算式プラグインが結果を計算し直す）。モバイルの画像は、戻す前に撮る |\n| 6 | 設定のアップロードのダイアログは、同じ設定のファイルをもう一度入力欄に渡して出し、撮った後に「キャンセル」で閉じる（設定は変えない） |\n| 7 | モバイル版は PC の Chrome では横に広がるので、項目名と値が入る左側の範囲で撮る |\n| 8 | 画像を git に入れない場所（`~/Projects/claude_out/`）に、記事の順の番号付きの名前で置き、原稿の該当の場所に入れる |\n\nQiita への画像のアップロードは、[前の記事](https://qiita.com/rex0220/items/691f50272359dfb02a87) と同じく人が行いました。6 枚を上げて「画像アドレスを一括コピー」した Markdown を Claude Code に貼ると、Claude がファイル名で突き合わせて、原稿の画像を Qiita の URL に差し替えました。\n\nテストのために作ったアプリを、そのまま記事の画像にも使えるので、テストと記事を続けて頼むと手間が少なく済みます。\n\n---\n\n# 指示していない手順は、Claude ができる範囲で組み立てた\n\n頼んだのは「テスト用アプリを作成して、ブラウザー操作でチェックして」の 1 行だけです。プラグインの入れ替え方や設定の作り方は指示していません。振り返ると、指示していない手順は、Claude が**自分で実行できる範囲**で組み立てていました。\n\n| 場面 | Claude が選んだ手順 | 選んだわけ（Claude ができる範囲・決まり） |\n| :--- | :--- | :--- |\n| プラグインの入れ替え | ログイン中の Chrome のページから REST API | いつものスクリプトは環境変数のパスワードで動き、プロジェクトの規則（CLAUDE.md）では、kintone へのアップロードを伴うスクリプトは指示がない限り動かさない。Chrome ならログインのまま、同じ API を呼べる |\n| 計算式プラグインの zip | git に入らないフォルダーに、別の名前で作る | 手元の `dist/` にある未追跡の zip を上書きしない |\n| テスト用アプリと項目 | ページの JavaScript から REST API | 画面のクリックより速く、項目コードを間違えない |\n| 項目定義のファイル | ブラウザーの REST API で取り、tools が読む形のファイルを自分で書く | tools に kintone の接続が設定されていなかった。接続のファイルは利用者のもので、Claude は読まない・書かない決まり |\n| 印刷屋の設定 | 設定づくりの MCP でなく、tools の CLI | MCP は作業フォルダーとして登録したフォルダーでしか動かない |\n| 計算式プラグインの設定 | tools でなく、設定画面で直接取り込む | tools が zip を読まなかった（4 章） |\n| 印刷屋の PDF | 添付ファイル項目に保存し、まずプレビューで止める | ファイルのダウンロードは、利用者の許可を取ってからの決まり |\n| 記事の画像 | ログイン名やホスト名が写らない範囲を選んで撮り直す | 開発環境のホスト名を記録に書かない、と Claude Code のメモリに残してある |\n\n使える道具（Chrome の操作、手元のシェルとファイル）と、プロジェクトの規則・メモリ、Claude 自身の決まり（パスワードを扱わない、ダウンロードは許可を取る）の内側で手順を選ぶので、頼む側が細かい手順まで書かなくても進みます。\n\nただし、選んだ手順が人の想定と同じとは限りません。プラグインの入れ替えは、筆者はいつもスクリプトで行っています。Claude は報告に手順を書くので、それを読んで、違えば伝えるのが人の役目です。\n\n---\n\n# つまずいたところ\n\n| つまずき | 起きたこと | どうしたか |\n| :--- | :--- | :--- |\n| 設定づくりの MCP が使えない | Claude Code を起動したフォルダーが、MCP の作業フォルダーとして登録されていなかった | 同じことができる tools の CLI を使った |\n| tools の書き出し先 | `normalize` の書き出し先は決まったフォルダーだけ | 決まったフォルダーに書いてから、git に入らないフォルダーに移した |\n| tools が zip を読まない | 計算式プラグインの API の版が古いまま（4 章） | 設定画面で直接取り込んだ。リリースの前の作業として記録した |\n| JavaScript の結果が長い | 項目定義をまるごと返すと、途中で切れた | 項目コード・型・レイアウトだけに絞って返した |\n| モバイルの案内 | モバイル版を初めて開くと、案内の吹き出しが重なった | 吹き出しを閉じてから入力した |\n| ダウンロードを避ける | 印刷屋の PDF は、保存先が無いとダウンロードになる | 添付ファイル項目を足して保存先にし、「ボタンを押したとき」をプレビューにした |\n| 開発環境のホスト名 | URL や記録に入る。印刷屋のエラーのダイアログの下のエラーの経路にも、ホスト名入りの URL が出る | 記事と記録の URL は伏せた。エラーのダイアログの画像は、経路の上までにした |\n| 画像にカーソルが写る | 記事用の画像を撮ったら、マウスのカーソルが入った | 撮る前にカーソルを画面の端へ動かして撮り直した |\n\n---\n\n# 人がすること、任せられること\n\n| 任せられたこと | 人がしたこと |\n| :--- | :--- |\n| 入っているプラグインの版を調べる | テストに使うスペースを決めて、URL を渡す |\n| zip を作って、Chrome の操作でプラグインを入れ替える（ファイルの照合も） | テスト用のスペース（開発環境）を用意する |\n| テスト用アプリと項目、レコードを作る | 何を確かめるか（直したこと）を決める |\n| プラグインの設定を作り、検査して、設定画面で取り込む | 重い帳票のアプリの確かめ（ダウンロードを伴う）をするかを決める |\n| ボタンを押す、プレビューの文字を読む、REST API で値を確かめる | コミットとリリース |\n| モバイル版で編集して保存する | Qiita への画像のアップロードと公開 |\n| 結果を表にまとめ、記録に書く | |\n| 記事の画像を撮る（範囲、カーソル、写してはいけない所）、Qiita の URL への差し替え | |\n\n実機テストで手間なのは、確かめる操作そのものより、**その前の準備**（zip の入れ替え、アプリと項目、設定の取り込み）です。準備から確認まで続けて任せられたのが、一番の収穫でした。設定画面で取り込むところは画面を操作し、アプリや項目を作るところは REST API を使う、という使い分けも Claude が決めています。\n\n---\n\n# まとめ\n\n- Claude Code に kintone のスペースの URL を渡して頼むと、ログイン済みの Chrome で、プラグインの入れ替えからテスト用アプリの作成、画面での確認までできる\n- プラグインの入れ替えは、これまでのスクリプト（Node から REST API。パスワードで認証）と同じ API を、ログイン中の Chrome のページから呼んで済ませた。パスワードを使わない\n- アプリや項目は、ページの JavaScript から REST API で作ると速く、項目コードを間違えない（ログインしている利用者の権限で動く）\n- プラグインの zip や設定のファイルは、ページの入力欄に渡せる。SHA-256 で手元のファイルと照らすと安心\n- ダウンロードを避けるため、PDF の保存先を添付ファイル項目にするなど、テストの形も Claude が考える\n- 結果は REST API でも読むので、画面の見た目だけに頼らない\n- 実機テストの途中で、リリースの前の作業（API の作り直し）の漏れも見つかった\n- 指示していない手順は、Claude が使える道具と、規則・メモリ・自身の決まりの内側で組み立てる。報告の手順を読み、想定と違えば伝える\n- 記事の画像も、テスト用アプリを開き直して Claude が撮る。ログイン名やホスト名が写る所は範囲から外す\n\n# 関連記事\n\n- [rex0220 印刷屋プラグイン](https://qiita.com/rex0220/items/9be2d9b20a3a1f016c76)\n- [Claude Code + Claude in Chrome で Qiita の記事を作る（印刷屋プラグインの組織図の記事）](https://qiita.com/rex0220/items/691f50272359dfb02a87)\n- [rex0220 計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)\n","coediting":false,"comments_count":0,"created_at":"2026-10-21T13:13:52+09:00","group":null,"id":"89a05ac0b8befecd540d","likes_count":1,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"ClaudeCode","versions":[]},{"name":"Claude","versions":[]},{"name":"Chrome","versions":[]}],"title":"Claude Code + Claude in Chrome に kintone プラグインの実機テストを任せる（印刷屋・計算式プラグインの計算式エンジンの直しを確かめる）","updated_at":"2026-10-21T13:25:30+09:00","url":"https://qiita.com/rex0220/items/89a05ac0b8befecd540d","user":{"description":"","facebook_id":"","followees_count":0,"followers_count":155,"github_login_name":"rex0220","id":"rex0220","items_count":756,"linkedin_id":"","location":"","name":"","organization":"","permanent_id":100572,"profile_image_url":"https://qiita-image-store.s3.amazonaws.com/0/100572/profile-images/1473708137","team_only":false,"twitter_screen_name":"rex02201","website_url":"https://rex0220.stores.jp/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null},{"rendered_body":"\u003cp data-sourcepos=\"1:1-1:233\"\u003ekintone プラグインの紹介記事を書くとき、手間がかかるのはスクリーンショットです。画面を開いて、撮って、記事に合う範囲に切り取って、ファイルに名前を付けて……。\u003c/p\u003e\n\u003cp data-sourcepos=\"3:1-3:532\"\u003e今回は、\u003cstrong\u003eClaude Code（VS Code の拡張機能）と Claude in Chrome（Chrome の拡張機能）\u003c/strong\u003e を組み合わせて、スクリーンショットを撮るところから記事の原稿までを AI に任せてみました。できたのは、印刷屋プラグインで組織図を PDF にする入門の記事 \u003ca href=\"https://qiita.com/rex0220/items/76318504f0e88ded2dc2\" id=\"reference-18aa4068edeff288fdf9\"\u003erex0220 印刷屋プラグイン - 組織図を PDF にする（詳細画面の手順と設定画面の紹介）\u003c/a\u003e（以下、組織図の記事）です。\u003c/p\u003e\n\u003cp data-sourcepos=\"5:1-5:144\"\u003e下は、Claude が Chrome で組織図のプレビューを開いて撮った画像です（組織図の記事の先頭に使いました）。\u003c/p\u003e\n\u003cp data-sourcepos=\"7:1-7:168\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F2873e307-ae37-4d73-b3b2-d97cf242b467.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=719fba54436dbb959053806beef54ade\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F2873e307-ae37-4d73-b3b2-d97cf242b467.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=719fba54436dbb959053806beef54ade\" alt=\"Claude in Chrome で撮った組織図のプレビュー\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F2873e307-ae37-4d73-b3b2-d97cf242b467.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=17f231b598c2cd6c696b2d08386ab814 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/2873e307-ae37-4d73-b3b2-d97cf242b467.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"9:1-9:128\"\u003e本記事では、頼んだ順に、何を頼んで Claude が何をしたか、どこでつまずいたかを紹介します。\u003c/p\u003e\n\u003chr data-sourcepos=\"11:1-12:0\"\u003e\n\u003ch1 data-sourcepos=\"13:1-13:20\"\u003e\n\u003cspan id=\"仕組みの構成\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%AE%E6%A7%8B%E6%88%90\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e仕組みの構成\u003c/h1\u003e\n\u003ciframe id=\"qiita-embed-content__f08f4b94c4c0b12a6843099e8cf5c1c5\" src=\"https://qiita.com/embed-contents/mermaid#qiita-embed-content__f08f4b94c4c0b12a6843099e8cf5c1c5\" style=\"width:100%;\" frameborder=\"0\" scrolling=\"no\" loading=\"lazy\" data-content='{\"data\":\"flowchart LR\\n U[\\\"利用者\\\"]\\n\\n subgraph PC[\\\"利用者の PC\\\"]\\n CC[\\\"Claude Code\u0026lt;br\u0026gt;（VS Code）\\\"]\\n CH[\\\"Chrome\u0026lt;br\u0026gt;Claude in Chrome\u0026lt;br\u0026gt;（kintone にログイン済み）\\\"]\\n FS[(\\\"ファイル\u0026lt;br\u0026gt;記事の原稿\u0026lt;br\u0026gt;スクリーンショット\\\")]\\n end\\n\\n KT[\\\"kintone\u0026lt;br\u0026gt;（開発環境）\\\"]\\n QI[\\\"Qiita\\\"]\\n\\n U -- \\\"頼む\\\" --\u0026gt; CC\\n CC -- \\\"開く・押す・撮る\\\" --\u0026gt; CH\\n CH --\u0026gt; KT\\n CC -- \\\"書く・写す\\\" --\u0026gt; FS\\n U -- \\\"画像のアップロード・公開（手で操作）\\\" --\u0026gt; QI\\n FS -. \\\"原稿\\\" .-\u0026gt; QI\",\"key\":\"5997867c90d289b5b25c26c3ca02cf1b\"}'\u003e\n\u003c/iframe\u003e\n\n\u003cul data-sourcepos=\"36:1-40:0\"\u003e\n\u003cli data-sourcepos=\"36:1-36:213\"\u003eClaude in Chrome は、\u003cstrong\u003e利用者がふだん使っている Chrome\u003c/strong\u003e で動きます。kintone にログインしたままの Chrome を使うので、Claude にパスワードを渡す必要はありません\u003c/li\u003e\n\u003cli data-sourcepos=\"37:1-37:160\"\u003eVS Code の Claude Code で、最初の依頼の文に \u003ccode\u003e@browser\u003c/code\u003e を付けて頼みました（以後は付けなくても Chrome を使い続けました）\u003c/li\u003e\n\u003cli data-sourcepos=\"38:1-38:180\"\u003eClaude は、ページを開く、クリックする、スクリーンショットを撮る、範囲を拡大して撮る、ページで JavaScript を動かす、ができます\u003c/li\u003e\n\u003cli data-sourcepos=\"39:1-40:0\"\u003eQiita への画像のアップロードと公開は、自分で行いました\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr data-sourcepos=\"41:1-42:0\"\u003e\n\u003ch1 data-sourcepos=\"43:1-43:41\"\u003e\n\u003cspan id=\"1-スクリーンショットを撮る\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#1-%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E3%82%92%E6%92%AE%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e1. スクリーンショットを撮る\u003c/h1\u003e\n\u003cp data-sourcepos=\"45:1-45:57\"\u003e最初は、ポータルを開いて撮るだけです。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"47:1-49:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e@browser kintone のポータルを開いて、スクリーンショットを保存して\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"51:1-51:133\"\u003eClaude は、環境変数にある kintone のドメインでポータルを開き、スクリーンショットを撮りました。\u003c/p\u003e\n\u003cp data-sourcepos=\"53:1-53:202\"\u003e撮った画像は、まず拡張機能が決めた一時フォルダーに保存されます。この保存先は変えられないので、残す場所を決めて、Claude に覚えさせました。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"55:1-57:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e~/Projects/claude_out のフォルダーを作って、そこに出力先に設定して\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"59:1-59:283\"\u003eClaude はフォルダーを作り、プロジェクトの規則のファイル（CLAUDE.md）に「git に入れない出力（スクリーンショットなど）は \u003ccode\u003e~/Projects/claude_out/\u003c/code\u003e に置く」と書き足しました。以後は、撮るたびにそこへ写します。\u003c/p\u003e\n\u003cblockquote data-sourcepos=\"61:1-61:338\"\u003e\n\u003cp data-sourcepos=\"61:3-61:338\"\u003egit に入れない場所にしたのは、ポータルのお知らせに開発環境の URL（ホスト名）が写っていたためです。Claude Code のメモリに「開発環境のホスト名は記録に書かない」と残してあったので、Claude は作業の記録用のリポジトリには置きませんでした。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003chr data-sourcepos=\"63:1-64:0\"\u003e\n\u003ch1 data-sourcepos=\"65:1-65:29\"\u003e\n\u003cspan id=\"2-記事用に切り取る\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#2-%E8%A8%98%E4%BA%8B%E7%94%A8%E3%81%AB%E5%88%87%E3%82%8A%E5%8F%96%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e2. 記事用に切り取る\u003c/h1\u003e\n\u003cp data-sourcepos=\"67:1-67:121\"\u003e次は、印刷屋の設定画面です。URL を渡して撮ってもらい、続けて切り取りを頼みました。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"69:1-71:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003ehttps://（サブドメイン）.cybozu.com/k/admin/app/4326/plugin/config?pluginId=lcapkanpjdabgphknkabojmcfhonhkhp　のスクリーンショットを作成\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"73:1-75:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003eqiita 記事用にプラグイン設定の部分を切り取って\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"77:1-77:296\"\u003eここで Claude は、撮った画像を切り取らずに、\u003cstrong\u003eページを開き直して、設定の部分だけを拡大して撮り直しました\u003c/strong\u003e。スクリーンショットは画面全体を 1413×840 の JPEG に縮めたもので、切り取ると文字が粗くなるためです。\u003c/p\u003e\n\u003cp data-sourcepos=\"79:1-79:249\"\u003e撮り直した画像は 1512×793 の PNG です。kintone の上の帯（ログイン中の名前）やパンくずは外し、マウスのカーソルが写らないように、カーソルを画面の端に動かしてから撮っています。\u003c/p\u003e\n\u003cp data-sourcepos=\"81:1-81:64\"\u003e画面全体のスクリーンショット（1413×840、JPEG）\u003c/p\u003e\n\u003cp data-sourcepos=\"83:1-83:155\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F00a65f74-186d-43cd-8789-af8b92d4a6c1.jpeg?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=69ac9545b883b3c56737eecdf6856062\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F00a65f74-186d-43cd-8789-af8b92d4a6c1.jpeg?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=69ac9545b883b3c56737eecdf6856062\" alt=\"画面全体のスクリーンショット\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F00a65f74-186d-43cd-8789-af8b92d4a6c1.jpeg?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=63ad16279ec20179cb89a3101c77c8db 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/00a65f74-186d-43cd-8789-af8b92d4a6c1.jpeg\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"85:1-85:60\"\u003e設定の部分を撮り直したもの（1512×793、PNG）\u003c/p\u003e\n\u003cp data-sourcepos=\"87:1-87:163\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7a89f813-2fbd-4887-bf8e-72767878c61e.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=d6219469492bcf578cd77360de9e6f6c\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7a89f813-2fbd-4887-bf8e-72767878c61e.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=d6219469492bcf578cd77360de9e6f6c\" alt=\"設定の部分を拡大して撮り直したもの\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F7a89f813-2fbd-4887-bf8e-72767878c61e.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=82283742c096b0c0fd5062cec7720050 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7a89f813-2fbd-4887-bf8e-72767878c61e.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003chr data-sourcepos=\"89:1-90:0\"\u003e\n\u003ch1 data-sourcepos=\"91:1-91:32\"\u003e\n\u003cspan id=\"3-画面を操作して撮る\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#3-%E7%94%BB%E9%9D%A2%E3%82%92%E6%93%8D%E4%BD%9C%E3%81%97%E3%81%A6%E6%92%AE%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e3. 画面を操作して撮る\u003c/h1\u003e\n\u003cp data-sourcepos=\"93:1-93:81\"\u003eダイアログのように、操作しないと出ない画面も撮れます。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"95:1-97:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e1行目のHTML欄をクリックして、編集ダイアログを表示してスクリーンショット\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"99:1-99:304\"\u003eClaude は HTML 欄をクリックしてダイアログを開き、ページの JavaScript で\u003cstrong\u003eダイアログの要素の位置と大きさ\u003c/strong\u003e（\u003ccode\u003egetBoundingClientRect\u003c/code\u003e）を測ってから、その範囲だけを撮りました。目で見て範囲を決めるより、枠にぴったり合います。\u003c/p\u003e\n\u003cp data-sourcepos=\"101:1-101:90\"\u003e下は、組織図の記事のために、同じ範囲で撮ったダイアログです。\u003c/p\u003e\n\u003cp data-sourcepos=\"103:1-103:193\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F60dad359-12ff-4c9b-9c5e-2af3f9268a27.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=13af8924714fa11c73b612d7d1efaa94\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F60dad359-12ff-4c9b-9c5e-2af3f9268a27.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=13af8924714fa11c73b612d7d1efaa94\" alt=\"印刷屋の HTML 設定のダイアログ（枠に合わせて撮ったもの）\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F60dad359-12ff-4c9b-9c5e-2af3f9268a27.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=cdd588e11efc7d4b810ab0af15841de9 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/60dad359-12ff-4c9b-9c5e-2af3f9268a27.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"105:1-105:72\"\u003eダイアログでは何も変えず、保存も押していません。\u003c/p\u003e\n\u003chr data-sourcepos=\"107:1-108:0\"\u003e\n\u003ch1 data-sourcepos=\"109:1-109:20\"\u003e\n\u003cspan id=\"4-記事を頼む\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#4-%E8%A8%98%E4%BA%8B%E3%82%92%E9%A0%BC%E3%82%80\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e4. 記事を頼む\u003c/h1\u003e\n\u003cp data-sourcepos=\"111:1-111:196\"\u003eここまでで撮り方がわかったので、記事そのものを頼みました。渡したのは、テーマ、書いてほしいこと、原稿の置き場所、画面の URL 4 つです。\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"113:1-123:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003e印刷屋プラグインで組織図を作るというテーマで qiita 記事を作成して\n\n詳細画面からPDF作成する簡単な手順と、プラグイン設定画面の紹介\n出力先：print-craft/docs/qiita\n\nhttps://（サブドメイン）.cybozu.com/k/4285/\nhttps://（サブドメイン）.cybozu.com/k/4285/show#record=3\u0026amp;l.view=20\u0026amp;l.q\u0026amp;l.next=2\u0026amp;l.prev=0\nhttps://（サブドメイン）.cybozu.com/k/admin/app/4285/plugin/#/\nhttps://（サブドメイン）.cybozu.com/k/admin/app/4285/plugin/config?pluginId=lcapkanpjdabgphknkabojmcfhonhkhp\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"125:1-125:49\"\u003eClaude がしたことを、順に並べます。\u003c/p\u003e\n\u003ctable data-sourcepos=\"127:1-134:86\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"127:1-127:32\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"127:2-127:6\"\u003e順\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"127:8-127:31\"\u003eClaude がしたこと\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"129:1-129:154\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"129:2-129:4\"\u003e1\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"129:6-129:153\"\u003e同じフォルダーの既存の記事を読み、原稿の形（先頭のコメントに題とタグ、画像は Qiita の URL）に合わせる\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"130:1-130:173\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"130:2-130:4\"\u003e2\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"130:6-130:172\"\u003e組織図の記事がすでに 1 本あるのを見つけて読み、中身が重ならないように「AI で設計した話」はそちらへのリンクにする\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"131:1-131:155\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"131:2-131:4\"\u003e3\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"131:6-131:154\"\u003e4 つの画面を開いて、7 枚撮る（一覧、詳細画面、プラグインの一覧、設定画面、HTML 設定、プレビュー 2 枚）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"132:1-132:222\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"132:2-132:4\"\u003e4\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"132:6-132:221\"\u003e詳細画面のボタンを押す前に、設定画面で「ボタンを押したとき」が「プレビューを表示する」、PDF の保存先が「---」（ダウンロード）であることを確かめる\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"133:1-133:153\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"133:2-133:4\"\u003e5\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"133:6-133:152\"\u003e設定画面の各部の名前と説明は、プラグインのソースにある説明の文（設定画面の「?」の中身）に合わせる\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"134:1-134:86\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"134:2-134:4\"\u003e6\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"134:6-134:85\"\u003e原稿を書き、画像はいったん手元のファイルを指しておく\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"136:1-136:145\"\u003e3 の途中で、Claude は「組織図」のプレビューで\u003cstrong\u003e右端の経理部が用紙からはみ出ている\u003c/strong\u003eのに気付きました。\u003c/p\u003e\n\u003cp data-sourcepos=\"138:1-138:186\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Feba77260-f37e-42db-9b90-b36c5fcdecd6.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=d9e5a7b92ad9a6a832783ec8f9ed9aa2\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Feba77260-f37e-42db-9b90-b36c5fcdecd6.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=d9e5a7b92ad9a6a832783ec8f9ed9aa2\" alt=\"「組織図」のプレビュー — 右端の経理部が切れている\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2Feba77260-f37e-42db-9b90-b36c5fcdecd6.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=5434c7026ef92f980d05949a9c147add 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/eba77260-f37e-42db-9b90-b36c5fcdecd6.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp data-sourcepos=\"140:1-140:301\"\u003e同じアプリには、箱が縮む版の「組織図 (2)」ボタンもあったので、両方のプレビューを撮って、「プレビューで端まで入っているかを確かめる」という節を記事に足しました。画面を実際に見ているからこそ入った節です。\u003c/p\u003e\n\u003cp data-sourcepos=\"142:1-142:471\"\u003eもう 1 つ、Claude は\u003cstrong\u003eプレビューの「組織図」ボタン（PDF のダウンロード）を押しませんでした\u003c/strong\u003e。ファイルのダウンロードは、利用者の許可を取ってからにする決まりがあるためです。原稿の先頭のメモにその手順を「未確認」として書き、報告でも押してよいかを聞いてきました。確かめていないことを、確かめたように書かないのは助かります。\u003c/p\u003e\n\u003chr data-sourcepos=\"144:1-145:0\"\u003e\n\u003ch1 data-sourcepos=\"146:1-146:48\"\u003e\n\u003cspan id=\"5-画像を-qiita-に上げて差し替える\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#5-%E7%94%BB%E5%83%8F%E3%82%92-qiita-%E3%81%AB%E4%B8%8A%E3%81%92%E3%81%A6%E5%B7%AE%E3%81%97%E6%9B%BF%E3%81%88%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e5. 画像を Qiita に上げて差し替える\u003c/h1\u003e\n\u003cp data-sourcepos=\"148:1-148:78\"\u003eQiita への画像のアップロードは、今回は手で行いました。\u003c/p\u003e\n\u003col data-sourcepos=\"150:1-153:0\"\u003e\n\u003cli data-sourcepos=\"150:1-150:215\"\u003eQiita の「ファイルのアップロード」画面で、\u003ccode\u003e~/Projects/claude_out/\u003c/code\u003e の画像 7 枚をアップロードする（ドラッグ\u0026amp;ドロップ、ペースト、「画像を選択」のどれでも）\u003c/li\u003e\n\u003cli data-sourcepos=\"151:1-151:178\"\u003e「画像アドレスを一括コピー」を押す。アップロードした画像の Markdown が、\u003ccode\u003e![ファイル名](https://~~)\u003c/code\u003e の形でまとめてコピーされる\u003c/li\u003e\n\u003cli data-sourcepos=\"152:1-153:0\"\u003eClaude Code に貼る\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp data-sourcepos=\"154:1-154:201\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F54de58c5-f19e-40f0-9ddf-94d8e4012276.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=1dbd6595413b508fa6dfad098c62dd35\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F54de58c5-f19e-40f0-9ddf-94d8e4012276.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=1dbd6595413b508fa6dfad098c62dd35\" alt=\"Qiita のファイルのアップロード — 「画像アドレスを一括コピー」\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F54de58c5-f19e-40f0-9ddf-94d8e4012276.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=27f0ce269a12dc93e68ae3f55d836ba8 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/54de58c5-f19e-40f0-9ddf-94d8e4012276.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"code-frame\" data-lang=\"text\" data-sourcepos=\"156:1-159:3\"\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre\u003e\u003ccode\u003eQiita 画像アップロード\n（ここに 7 行を貼る）\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cp data-sourcepos=\"161:1-161:232\"\u003eClaude は、ファイル名で突き合わせて、原稿の 7 か所を Qiita の URL に差し替えました。画像を上げる順番がばらばらでも、ファイル名に番号を付けておいたので迷いません。\u003c/p\u003e\n\u003chr data-sourcepos=\"163:1-164:0\"\u003e\n\u003ch1 data-sourcepos=\"165:1-165:17\"\u003e\n\u003cspan id=\"できた記事\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%A7%E3%81%8D%E3%81%9F%E8%A8%98%E4%BA%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eできた記事\u003c/h1\u003e\n\u003cp data-sourcepos=\"167:1-167:114\"\u003e\u003ca href=\"https://qiita.com/rex0220/items/76318504f0e88ded2dc2\"\u003e組織図の記事\u003c/a\u003e の見出しは次のとおりです。\u003c/p\u003e\n\u003cul data-sourcepos=\"169:1-173:0\"\u003e\n\u003cli data-sourcepos=\"169:1-169:35\"\u003e使うアプリ（項目の表）\u003c/li\u003e\n\u003cli data-sourcepos=\"170:1-170:95\"\u003e詳細画面から PDF を作る（手順、「組織図」と「組織図 (2)」の違い）\u003c/li\u003e\n\u003cli data-sourcepos=\"171:1-171:103\"\u003eプラグイン設定画面（開き方、画面の全体、HTML 設定、設定を変えるとき）\u003c/li\u003e\n\u003cli data-sourcepos=\"172:1-173:0\"\u003eまとめ\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp data-sourcepos=\"174:1-174:119\"\u003e7 枚の画像は、どれも Claude in Chrome で撮ったものです。下は、そのうちの設定画面です。\u003c/p\u003e\n\u003cp data-sourcepos=\"176:1-176:154\"\u003e\u003ca href=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F0b67c1c0-c77f-40c1-8e4a-db67e4575005.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=17fdb5afe4cce91d0d7f1de78b3c3854\" target=\"_blank\" rel=\"nofollow noopener\"\u003e\u003cimg src=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F0b67c1c0-c77f-40c1-8e4a-db67e4575005.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;s=17fdb5afe4cce91d0d7f1de78b3c3854\" alt=\"組織図の記事に使った設定画面\" srcset=\"https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F100572%2F0b67c1c0-c77f-40c1-8e4a-db67e4575005.png?ixlib=rb-4.1.1\u0026amp;auto=format\u0026amp;gif-q=60\u0026amp;q=75\u0026amp;w=1400\u0026amp;fit=max\u0026amp;s=7beea5869b79d4dd13ba2320dc890384 1x\" data-canonical-src=\"https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/0b67c1c0-c77f-40c1-8e4a-db67e4575005.png\" loading=\"lazy\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003chr data-sourcepos=\"178:1-179:0\"\u003e\n\u003ch1 data-sourcepos=\"180:1-180:26\"\u003e\n\u003cspan id=\"つまずいたところ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%A4%E3%81%BE%E3%81%9A%E3%81%84%E3%81%9F%E3%81%A8%E3%81%93%E3%82%8D\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eつまずいたところ\u003c/h1\u003e\n\u003ctable data-sourcepos=\"182:1-189:220\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"182:1-182:52\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"182:2-182:15\"\u003eつまずき\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"182:17-182:33\"\u003e起きたこと\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"182:35-182:51\"\u003eどうしたか\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"184:1-184:464\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"184:2-184:36\"\u003eクリックの位置がずれる\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"184:38-184:220\"\u003e開いたばかりのタブで、「スクリーンショット → クリック」を 1 回の呼び出しにまとめると、クリックが狙った所から外れた（3 回）\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"184:222-184:463\"\u003e一括の呼び出しの中の座標は、その呼び出しの前に撮ったスクリーンショットに合わせて読まれる。先にスクリーンショットだけを撮り、次の呼び出しでクリックすると当たった\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"185:1-185:136\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"185:2-185:24\"\u003eカーソルが写る\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"185:26-185:81\"\u003e撮った画像にマウスのカーソルが入った\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"185:83-185:135\"\u003e撮る前にカーソルを画面の端へ動かす\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"186:1-186:296\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"186:2-186:44\"\u003eダイアログが Escape で閉じない\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"186:46-186:194\"\u003e印刷屋の設定画面のダイアログが閉じず、続くクリックがダイアログの中の欄に当たって編集の状態になった\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"186:196-186:295\"\u003e文字は変えずに、JavaScript でダイアログを閉じた（保存は押していない）\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"187:1-187:240\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"187:2-187:41\"\u003eJavaScript の結果が止められる\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"187:43-187:182\"\u003e計算式の文（\u003ccode\u003e\u0026amp;\u003c/code\u003e や \u003ccode\u003e=\u003c/code\u003e が多い）を返そうとすると、拡張機能に「Cookie/query string data」として止められた\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"187:184-187:239\"\u003e\n\u003ccode\u003e\u0026amp;\u003c/code\u003e と \u003ccode\u003e=\u003c/code\u003e を別の文字に置き換えて返した\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"188:1-188:266\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"188:2-188:21\"\u003eタブが外れる\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"188:23-188:190\"\u003e新しいタブを作ってから元のタブを閉じたら、Claude の作業用のタブのグループが消え、新しいタブがグループの外に残った\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"188:192-188:265\"\u003eグループを作り直した。外れた空のタブは手で閉じる\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"189:1-189:220\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"189:2-189:30\"\u003e開発環境のホスト名\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"189:32-189:92\"\u003eポータルのお知らせや URL にホスト名が入る\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"189:94-189:219\"\u003e記事の URL は「（サブドメイン）」に伏せ、ホスト名が写る画像は git に入れない場所に置く\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003chr data-sourcepos=\"191:1-192:0\"\u003e\n\u003ch1 data-sourcepos=\"193:1-193:44\"\u003e\n\u003cspan id=\"人がすること任せられること\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E4%BA%BA%E3%81%8C%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E4%BB%BB%E3%81%9B%E3%82%89%E3%82%8C%E3%82%8B%E3%81%93%E3%81%A8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e人がすること、任せられること\u003c/h1\u003e\n\u003ctable data-sourcepos=\"195:1-201:35\"\u003e\n\u003cthead\u003e\n\u003ctr data-sourcepos=\"195:1-195:46\"\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"195:2-195:24\"\u003e任せられたこと\u003c/th\u003e\n\u003cth style=\"text-align: left\" data-sourcepos=\"195:26-195:45\"\u003e人がしたこと\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr data-sourcepos=\"197:1-197:133\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"197:2-197:66\"\u003e画面を開く、ボタンを押す、ダイアログを開く\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"197:68-197:132\"\u003e何の記事にするか、どの画面を使うかを決める\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"198:1-198:100\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"198:2-198:57\"\u003e撮る範囲を決めて撮る、カーソルを外す\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"198:59-198:99\"\u003eQiita への画像のアップロード\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"199:1-199:136\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"199:2-199:63\"\u003e既存の記事の形に合わせる、重なりを避ける\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"199:65-199:135\"\u003e未確認の所（ダウンロード）を確かめるかを決める\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"200:1-200:85\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"200:2-200:75\"\u003e設定画面の名前を、プラグインの説明の文に合わせる\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"200:77-200:84\"\u003e公開\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr data-sourcepos=\"201:1-201:35\"\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"201:2-201:32\"\u003e画像の URL の差し替え\u003c/td\u003e\n\u003ctd style=\"text-align: left\" data-sourcepos=\"201:34-201:34\"\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp data-sourcepos=\"203:1-203:216\"\u003eスクリーンショットは「撮る」より「記事に合うように撮る」ほうが手間です。範囲、カーソル、ファイル名、置き場所まで任せられたのが一番の収穫でした。\u003c/p\u003e\n\u003chr data-sourcepos=\"205:1-206:0\"\u003e\n\u003ch1 data-sourcepos=\"207:1-207:29\"\u003e\n\u003cspan id=\"セキュリティの観点\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%81%AE%E8%A6%B3%E7%82%B9\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eセキュリティの観点\u003c/h1\u003e\n\u003cp data-sourcepos=\"209:1-209:294\"\u003eClaude in Chrome は、\u003cstrong\u003eログイン済みの自分の Chrome を AI が操作する\u003c/strong\u003e仕組みです。便利な分、AI ができることは、自分がその画面でできることと同じになります。今回の作業で気を付けたこと、気付いたことをまとめます。\u003c/p\u003e\n\u003ch2 data-sourcepos=\"211:1-211:27\"\u003e\n\u003cspan id=\"権限は自分と同じ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E6%A8%A9%E9%99%90%E3%81%AF%E8%87%AA%E5%88%86%E3%81%A8%E5%90%8C%E3%81%98\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e権限は自分と同じ\u003c/h2\u003e\n\u003cul data-sourcepos=\"213:1-216:0\"\u003e\n\u003cli data-sourcepos=\"213:1-213:275\"\u003eClaude は利用者の Chrome のログインをそのまま使います。今回の kintone のユーザーはアプリの管理者なので、プラグインの設定画面も開けました。設定の保存やレコードの変更も、押せばできてしまいます\u003c/li\u003e\n\u003cli data-sourcepos=\"214:1-214:179\"\u003e今回の作業は、開発環境で行いました。本番の環境で試すなら、権限の小さいユーザーで、見るだけの画面から始めるのが安全です\u003c/li\u003e\n\u003cli data-sourcepos=\"215:1-216:0\"\u003eClaude はページで JavaScript を動かせます。JavaScript も利用者のログインのまま動きます。今回は、要素の位置や文字を読むのと、ダイアログを閉じるのにだけ使いました\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 data-sourcepos=\"217:1-217:36\"\u003e\n\u003cspan id=\"変える操作の前で止まる\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E5%A4%89%E3%81%88%E3%82%8B%E6%93%8D%E4%BD%9C%E3%81%AE%E5%89%8D%E3%81%A7%E6%AD%A2%E3%81%BE%E3%82%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e変える操作の前で止まる\u003c/h2\u003e\n\u003cul data-sourcepos=\"219:1-221:0\"\u003e\n\u003cli data-sourcepos=\"219:1-219:632\"\u003e今回、Claude は設定画面の「保存」を一度も押していません。ファイルのダウンロードは押してよいかを聞いてから、プラグインのリポジトリへの commit・push と、記事の中身を変える出し直しも、確かめてから行いました。作業の記録用のリポジトリへの commit と、先頭のコメントを外すだけの出し直しは、前もって許してある決まりに沿って、確かめずに行いました（どちらの決まりも、プロジェクトの規則のファイル CLAUDE.md や Claude Code のメモリに書いてあります）\u003c/li\u003e\n\u003cli data-sourcepos=\"220:1-221:0\"\u003e見るだけのつもりでも、画面の状態は変わります。つまずいたところの表のとおり、クリックがダイアログの中の欄に当たって編集の状態になりました。印刷屋の設定は「保存する」を押すまで保存されないので、保存せずに閉じて元のままにしました\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 data-sourcepos=\"222:1-222:15\"\u003e\n\u003cspan id=\"秘密の値\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E7%A7%98%E5%AF%86%E3%81%AE%E5%80%A4\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e秘密の値\u003c/h2\u003e\n\u003cul data-sourcepos=\"224:1-227:0\"\u003e\n\u003cli data-sourcepos=\"224:1-224:140\"\u003eClaude にパスワードは渡していません。ログイン済みの Chrome を使うので、ログインの操作が要りません\u003c/li\u003e\n\u003cli data-sourcepos=\"225:1-225:425\"\u003eシェルの環境変数には、kintone の接続に使うパスワードやトークンも入っていました。Claude は変数の名前だけを値を伏せて確かめ、読んだのはドメインだけでした。ただ、Claude Code はシェルの環境変数を読める立場にあります。AI に見せたくない値は環境変数に置かない、置くなら使うときだけにするのが安心です\u003c/li\u003e\n\u003cli data-sourcepos=\"226:1-227:0\"\u003e拡張機能には、Cookie やクエリ文字列に見える値を Claude に返さない仕組みがあります。今回は計算式の文（\u003ccode\u003e\u0026amp;\u003c/code\u003e や \u003ccode\u003e=\u003c/code\u003e が多い）がそう見えて止められました（つまずいたところの表）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 data-sourcepos=\"228:1-228:33\"\u003e\n\u003cspan id=\"記事と画像に写るもの\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E8%A8%98%E4%BA%8B%E3%81%A8%E7%94%BB%E5%83%8F%E3%81%AB%E5%86%99%E3%82%8B%E3%82%82%E3%81%AE\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e記事と画像に写るもの\u003c/h2\u003e\n\u003cul data-sourcepos=\"230:1-234:0\"\u003e\n\u003cli data-sourcepos=\"230:1-230:278\"\u003e\n\u003cstrong\u003eホスト名\u003c/strong\u003e: 開発環境の URL は記事では「（サブドメイン）」に伏せ、ホスト名が写った画像は git に入れない場所に置きました。この決まりは Claude Code のメモリに残してあるので、Claude が自分で守ります\u003c/li\u003e\n\u003cli data-sourcepos=\"231:1-231:229\"\u003e\n\u003cstrong\u003e撮る範囲\u003c/strong\u003e: kintone の上の帯（ログイン中の名前）などは外して撮りました。画面全体を撮ってから切るより、写したい範囲だけを撮るほうが、余計なものが入りません\u003c/li\u003e\n\u003cli data-sourcepos=\"232:1-232:503\"\u003e\n\u003cstrong\u003e原稿の先頭のメモ\u003c/strong\u003e: 原稿の先頭の HTML コメントに、作業のメモ（未確認の所、手元のファイルのパス、アプリの番号）を書いていました。Web の編集画面に原稿をそのまま貼って公開したら、コメントごと公開されました。コメントは記事の表示には出ませんが、本文の Markdown には残ります。CLI で外して出し直しましたが、公開する文章とメモは分けておくのが確実です\u003c/li\u003e\n\u003cli data-sourcepos=\"233:1-234:0\"\u003e\n\u003cstrong\u003eアップロードした画像\u003c/strong\u003e: Qiita にアップロードした画像は、記事を公開する前でも URL で開けます（今回、記事の公開前に、Claude が貼られた URL から画像を開いて中身を確かめました）。見せたくないものが写った画像は上げないようにします\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 data-sourcepos=\"235:1-235:18\"\u003e\n\u003cspan id=\"開くページ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E9%96%8B%E3%81%8F%E3%83%9A%E3%83%BC%E3%82%B8\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e開くページ\u003c/h2\u003e\n\u003cul data-sourcepos=\"237:1-239:0\"\u003e\n\u003cli data-sourcepos=\"237:1-237:414\"\u003eClaude はページの文を読んで、次の操作を決めます。ページの中に AI への指示を紛れ込ませる攻撃（プロンプトインジェクション）があるので、Claude に開かせるのは、自分の環境と信頼できるページにとどめます。今回開いたのは、自分の kintone の開発環境と、自分がアップロードした Qiita の画像だけです\u003c/li\u003e\n\u003cli data-sourcepos=\"238:1-239:0\"\u003eClaude が開いたタブは作業用のグループにまとまり、作業が終わると Claude が閉じます。グループから外れたタブ（つまずいたところの表）は手で閉じます\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr data-sourcepos=\"240:1-241:0\"\u003e\n\u003ch1 data-sourcepos=\"242:1-242:11\"\u003e\n\u003cspan id=\"まとめ\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E3%81%BE%E3%81%A8%E3%82%81\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003eまとめ\u003c/h1\u003e\n\u003cul data-sourcepos=\"244:1-250:0\"\u003e\n\u003cli data-sourcepos=\"244:1-244:154\"\u003eClaude Code に \u003ccode\u003e@browser\u003c/code\u003e を付けて頼むと、ログイン済みの Chrome で kintone の画面を開き、スクリーンショットを撮れる\u003c/li\u003e\n\u003cli data-sourcepos=\"245:1-245:116\"\u003e記事用の画像は、撮った画像を切り取るより、範囲を指定して撮り直すほうがきれい\u003c/li\u003e\n\u003cli data-sourcepos=\"246:1-246:95\"\u003eダイアログは JavaScript で位置を測ると、枠にぴったり合わせて撮れる\u003c/li\u003e\n\u003cli data-sourcepos=\"247:1-247:159\"\u003eダウンロードや保存のような操作は、Claude が許可を求めて止まる。確かめていない所は、原稿にも「未確認」と残る\u003c/li\u003e\n\u003cli data-sourcepos=\"248:1-248:113\"\u003e画像のアップロードは手で行い、貼った Markdown を Claude に渡すと差し替えまで済む\u003c/li\u003e\n\u003cli data-sourcepos=\"249:1-250:0\"\u003eClaude ができることは、自分がその画面でできることと同じ。開発環境で行い、変える操作の前で止め、記事や画像に写るものを確かめる\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 data-sourcepos=\"251:1-251:14\"\u003e\n\u003cspan id=\"関連記事\" class=\"fragment\"\u003e\u003c/span\u003e\u003ca href=\"#%E9%96%A2%E9%80%A3%E8%A8%98%E4%BA%8B\"\u003e\u003ci class=\"fa fa-link\"\u003e\u003c/i\u003e\u003c/a\u003e関連記事\u003c/h1\u003e\n\u003cul data-sourcepos=\"253:1-255:174\"\u003e\n\u003cli data-sourcepos=\"253:1-253:170\"\u003e\u003ca href=\"https://qiita.com/rex0220/items/76318504f0e88ded2dc2\"\u003erex0220 印刷屋プラグイン - 組織図を PDF にする（詳細画面の手順と設定画面の紹介）\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"254:1-254:90\"\u003e\u003ca href=\"https://qiita.com/rex0220/items/9be2d9b20a3a1f016c76\" id=\"reference-a47e8f39babaacd68157\"\u003erex0220 印刷屋プラグイン\u003c/a\u003e\u003c/li\u003e\n\u003cli data-sourcepos=\"255:1-255:174\"\u003e\u003ca href=\"https://qiita.com/rex0220/items/6e739ace80cffd2ad70a\" id=\"reference-d3a5244c971bb8171db9\"\u003erex0220 印刷屋プラグイン - AI(Claude Desktop)に組織図を設計させてから、アプリを作らせる\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","body":"kintone プラグインの紹介記事を書くとき、手間がかかるのはスクリーンショットです。画面を開いて、撮って、記事に合う範囲に切り取って、ファイルに名前を付けて……。\n\n今回は、**Claude Code（VS Code の拡張機能）と Claude in Chrome（Chrome の拡張機能）** を組み合わせて、スクリーンショットを撮るところから記事の原稿までを AI に任せてみました。できたのは、印刷屋プラグインで組織図を PDF にする入門の記事 [rex0220 印刷屋プラグイン - 組織図を PDF にする（詳細画面の手順と設定画面の紹介）](https://qiita.com/rex0220/items/76318504f0e88ded2dc2)（以下、組織図の記事）です。\n\n下は、Claude が Chrome で組織図のプレビューを開いて撮った画像です（組織図の記事の先頭に使いました）。\n\n![Claude in Chrome で撮った組織図のプレビュー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/2873e307-ae37-4d73-b3b2-d97cf242b467.png)\n\n本記事では、頼んだ順に、何を頼んで Claude が何をしたか、どこでつまずいたかを紹介します。\n\n---\n\n# 仕組みの構成\n\n```mermaid\nflowchart LR\n  U[\"利用者\"]\n\n  subgraph PC[\"利用者の PC\"]\n    CC[\"Claude Code\u003cbr\u003e（VS Code）\"]\n    CH[\"Chrome\u003cbr\u003eClaude in Chrome\u003cbr\u003e（kintone にログイン済み）\"]\n    FS[(\"ファイル\u003cbr\u003e記事の原稿\u003cbr\u003eスクリーンショット\")]\n  end\n\n  KT[\"kintone\u003cbr\u003e（開発環境）\"]\n  QI[\"Qiita\"]\n\n  U -- \"頼む\" --\u003e CC\n  CC -- \"開く・押す・撮る\" --\u003e CH\n  CH --\u003e KT\n  CC -- \"書く・写す\" --\u003e FS\n  U -- \"画像のアップロード・公開（手で操作）\" --\u003e QI\n  FS -. \"原稿\" .-\u003e QI\n```\n\n- Claude in Chrome は、**利用者がふだん使っている Chrome** で動きます。kintone にログインしたままの Chrome を使うので、Claude にパスワードを渡す必要はありません\n- VS Code の Claude Code で、最初の依頼の文に `@browser` を付けて頼みました（以後は付けなくても Chrome を使い続けました）\n- Claude は、ページを開く、クリックする、スクリーンショットを撮る、範囲を拡大して撮る、ページで JavaScript を動かす、ができます\n- Qiita への画像のアップロードと公開は、自分で行いました\n\n---\n\n# 1. スクリーンショットを撮る\n\n最初は、ポータルを開いて撮るだけです。\n\n```\n@browser kintone のポータルを開いて、スクリーンショットを保存して\n```\n\nClaude は、環境変数にある kintone のドメインでポータルを開き、スクリーンショットを撮りました。\n\n撮った画像は、まず拡張機能が決めた一時フォルダーに保存されます。この保存先は変えられないので、残す場所を決めて、Claude に覚えさせました。\n\n```\n~/Projects/claude_out のフォルダーを作って、そこに出力先に設定して\n```\n\nClaude はフォルダーを作り、プロジェクトの規則のファイル（CLAUDE.md）に「git に入れない出力（スクリーンショットなど）は `~/Projects/claude_out/` に置く」と書き足しました。以後は、撮るたびにそこへ写します。\n\n\u003e git に入れない場所にしたのは、ポータルのお知らせに開発環境の URL（ホスト名）が写っていたためです。Claude Code のメモリに「開発環境のホスト名は記録に書かない」と残してあったので、Claude は作業の記録用のリポジトリには置きませんでした。\n\n---\n\n# 2. 記事用に切り取る\n\n次は、印刷屋の設定画面です。URL を渡して撮ってもらい、続けて切り取りを頼みました。\n\n```\nhttps://（サブドメイン）.cybozu.com/k/admin/app/4326/plugin/config?pluginId=lcapkanpjdabgphknkabojmcfhonhkhp　のスクリーンショットを作成\n```\n\n```\nqiita 記事用にプラグイン設定の部分を切り取って\n```\n\nここで Claude は、撮った画像を切り取らずに、**ページを開き直して、設定の部分だけを拡大して撮り直しました**。スクリーンショットは画面全体を 1413×840 の JPEG に縮めたもので、切り取ると文字が粗くなるためです。\n\n撮り直した画像は 1512×793 の PNG です。kintone の上の帯（ログイン中の名前）やパンくずは外し、マウスのカーソルが写らないように、カーソルを画面の端に動かしてから撮っています。\n\n画面全体のスクリーンショット（1413×840、JPEG）\n\n![画面全体のスクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/00a65f74-186d-43cd-8789-af8b92d4a6c1.jpeg)\n\n設定の部分を撮り直したもの（1512×793、PNG）\n\n![設定の部分を拡大して撮り直したもの](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7a89f813-2fbd-4887-bf8e-72767878c61e.png)\n\n---\n\n# 3. 画面を操作して撮る\n\nダイアログのように、操作しないと出ない画面も撮れます。\n\n```\n1行目のHTML欄をクリックして、編集ダイアログを表示してスクリーンショット\n```\n\nClaude は HTML 欄をクリックしてダイアログを開き、ページの JavaScript で**ダイアログの要素の位置と大きさ**（`getBoundingClientRect`）を測ってから、その範囲だけを撮りました。目で見て範囲を決めるより、枠にぴったり合います。\n\n下は、組織図の記事のために、同じ範囲で撮ったダイアログです。\n\n![印刷屋の HTML 設定のダイアログ（枠に合わせて撮ったもの）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/60dad359-12ff-4c9b-9c5e-2af3f9268a27.png)\n\nダイアログでは何も変えず、保存も押していません。\n\n---\n\n# 4. 記事を頼む\n\nここまでで撮り方がわかったので、記事そのものを頼みました。渡したのは、テーマ、書いてほしいこと、原稿の置き場所、画面の URL 4 つです。\n\n```\n印刷屋プラグインで組織図を作るというテーマで qiita 記事を作成して\n\n詳細画面からPDF作成する簡単な手順と、プラグイン設定画面の紹介\n出力先：print-craft/docs/qiita\n\nhttps://（サブドメイン）.cybozu.com/k/4285/\nhttps://（サブドメイン）.cybozu.com/k/4285/show#record=3\u0026l.view=20\u0026l.q\u0026l.next=2\u0026l.prev=0\nhttps://（サブドメイン）.cybozu.com/k/admin/app/4285/plugin/#/\nhttps://（サブドメイン）.cybozu.com/k/admin/app/4285/plugin/config?pluginId=lcapkanpjdabgphknkabojmcfhonhkhp\n```\n\nClaude がしたことを、順に並べます。\n\n| 順 | Claude がしたこと |\n| :--- | :--- |\n| 1 | 同じフォルダーの既存の記事を読み、原稿の形（先頭のコメントに題とタグ、画像は Qiita の URL）に合わせる |\n| 2 | 組織図の記事がすでに 1 本あるのを見つけて読み、中身が重ならないように「AI で設計した話」はそちらへのリンクにする |\n| 3 | 4 つの画面を開いて、7 枚撮る（一覧、詳細画面、プラグインの一覧、設定画面、HTML 設定、プレビュー 2 枚） |\n| 4 | 詳細画面のボタンを押す前に、設定画面で「ボタンを押したとき」が「プレビューを表示する」、PDF の保存先が「---」（ダウンロード）であることを確かめる |\n| 5 | 設定画面の各部の名前と説明は、プラグインのソースにある説明の文（設定画面の「?」の中身）に合わせる |\n| 6 | 原稿を書き、画像はいったん手元のファイルを指しておく |\n\n3 の途中で、Claude は「組織図」のプレビューで**右端の経理部が用紙からはみ出ている**のに気付きました。\n\n![「組織図」のプレビュー — 右端の経理部が切れている](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/eba77260-f37e-42db-9b90-b36c5fcdecd6.png)\n\n同じアプリには、箱が縮む版の「組織図 (2)」ボタンもあったので、両方のプレビューを撮って、「プレビューで端まで入っているかを確かめる」という節を記事に足しました。画面を実際に見ているからこそ入った節です。\n\nもう 1 つ、Claude は**プレビューの「組織図」ボタン（PDF のダウンロード）を押しませんでした**。ファイルのダウンロードは、利用者の許可を取ってからにする決まりがあるためです。原稿の先頭のメモにその手順を「未確認」として書き、報告でも押してよいかを聞いてきました。確かめていないことを、確かめたように書かないのは助かります。\n\n---\n\n# 5. 画像を Qiita に上げて差し替える\n\nQiita への画像のアップロードは、今回は手で行いました。\n\n1. Qiita の「ファイルのアップロード」画面で、`~/Projects/claude_out/` の画像 7 枚をアップロードする（ドラッグ\u0026ドロップ、ペースト、「画像を選択」のどれでも）\n2. 「画像アドレスを一括コピー」を押す。アップロードした画像の Markdown が、`![ファイル名](https://~~)` の形でまとめてコピーされる\n3. Claude Code に貼る\n\n![Qiita のファイルのアップロード — 「画像アドレスを一括コピー」](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/54de58c5-f19e-40f0-9ddf-94d8e4012276.png)\n\n```\nQiita 画像アップロード\n（ここに 7 行を貼る）\n```\n\nClaude は、ファイル名で突き合わせて、原稿の 7 か所を Qiita の URL に差し替えました。画像を上げる順番がばらばらでも、ファイル名に番号を付けておいたので迷いません。\n\n---\n\n# できた記事\n\n[組織図の記事](https://qiita.com/rex0220/items/76318504f0e88ded2dc2) の見出しは次のとおりです。\n\n- 使うアプリ（項目の表）\n- 詳細画面から PDF を作る（手順、「組織図」と「組織図 (2)」の違い）\n- プラグイン設定画面（開き方、画面の全体、HTML 設定、設定を変えるとき）\n- まとめ\n\n7 枚の画像は、どれも Claude in Chrome で撮ったものです。下は、そのうちの設定画面です。\n\n![組織図の記事に使った設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/0b67c1c0-c77f-40c1-8e4a-db67e4575005.png)\n\n---\n\n# つまずいたところ\n\n| つまずき | 起きたこと | どうしたか |\n| :--- | :--- | :--- |\n| クリックの位置がずれる | 開いたばかりのタブで、「スクリーンショット → クリック」を 1 回の呼び出しにまとめると、クリックが狙った所から外れた（3 回） | 一括の呼び出しの中の座標は、その呼び出しの前に撮ったスクリーンショットに合わせて読まれる。先にスクリーンショットだけを撮り、次の呼び出しでクリックすると当たった |\n| カーソルが写る | 撮った画像にマウスのカーソルが入った | 撮る前にカーソルを画面の端へ動かす |\n| ダイアログが Escape で閉じない | 印刷屋の設定画面のダイアログが閉じず、続くクリックがダイアログの中の欄に当たって編集の状態になった | 文字は変えずに、JavaScript でダイアログを閉じた（保存は押していない） |\n| JavaScript の結果が止められる | 計算式の文（`\u0026` や `=` が多い）を返そうとすると、拡張機能に「Cookie/query string data」として止められた | `\u0026` と `=` を別の文字に置き換えて返した |\n| タブが外れる | 新しいタブを作ってから元のタブを閉じたら、Claude の作業用のタブのグループが消え、新しいタブがグループの外に残った | グループを作り直した。外れた空のタブは手で閉じる |\n| 開発環境のホスト名 | ポータルのお知らせや URL にホスト名が入る | 記事の URL は「（サブドメイン）」に伏せ、ホスト名が写る画像は git に入れない場所に置く |\n\n---\n\n# 人がすること、任せられること\n\n| 任せられたこと | 人がしたこと |\n| :--- | :--- |\n| 画面を開く、ボタンを押す、ダイアログを開く | 何の記事にするか、どの画面を使うかを決める |\n| 撮る範囲を決めて撮る、カーソルを外す | Qiita への画像のアップロード |\n| 既存の記事の形に合わせる、重なりを避ける | 未確認の所（ダウンロード）を確かめるかを決める |\n| 設定画面の名前を、プラグインの説明の文に合わせる | 公開 |\n| 画像の URL の差し替え | |\n\nスクリーンショットは「撮る」より「記事に合うように撮る」ほうが手間です。範囲、カーソル、ファイル名、置き場所まで任せられたのが一番の収穫でした。\n\n---\n\n# セキュリティの観点\n\nClaude in Chrome は、**ログイン済みの自分の Chrome を AI が操作する**仕組みです。便利な分、AI ができることは、自分がその画面でできることと同じになります。今回の作業で気を付けたこと、気付いたことをまとめます。\n\n## 権限は自分と同じ\n\n- Claude は利用者の Chrome のログインをそのまま使います。今回の kintone のユーザーはアプリの管理者なので、プラグインの設定画面も開けました。設定の保存やレコードの変更も、押せばできてしまいます\n- 今回の作業は、開発環境で行いました。本番の環境で試すなら、権限の小さいユーザーで、見るだけの画面から始めるのが安全です\n- Claude はページで JavaScript を動かせます。JavaScript も利用者のログインのまま動きます。今回は、要素の位置や文字を読むのと、ダイアログを閉じるのにだけ使いました\n\n## 変える操作の前で止まる\n\n- 今回、Claude は設定画面の「保存」を一度も押していません。ファイルのダウンロードは押してよいかを聞いてから、プラグインのリポジトリへの commit・push と、記事の中身を変える出し直しも、確かめてから行いました。作業の記録用のリポジトリへの commit と、先頭のコメントを外すだけの出し直しは、前もって許してある決まりに沿って、確かめずに行いました（どちらの決まりも、プロジェクトの規則のファイル CLAUDE.md や Claude Code のメモリに書いてあります）\n- 見るだけのつもりでも、画面の状態は変わります。つまずいたところの表のとおり、クリックがダイアログの中の欄に当たって編集の状態になりました。印刷屋の設定は「保存する」を押すまで保存されないので、保存せずに閉じて元のままにしました\n\n## 秘密の値\n\n- Claude にパスワードは渡していません。ログイン済みの Chrome を使うので、ログインの操作が要りません\n- シェルの環境変数には、kintone の接続に使うパスワードやトークンも入っていました。Claude は変数の名前だけを値を伏せて確かめ、読んだのはドメインだけでした。ただ、Claude Code はシェルの環境変数を読める立場にあります。AI に見せたくない値は環境変数に置かない、置くなら使うときだけにするのが安心です\n- 拡張機能には、Cookie やクエリ文字列に見える値を Claude に返さない仕組みがあります。今回は計算式の文（`\u0026` や `=` が多い）がそう見えて止められました（つまずいたところの表）\n\n## 記事と画像に写るもの\n\n- **ホスト名**: 開発環境の URL は記事では「（サブドメイン）」に伏せ、ホスト名が写った画像は git に入れない場所に置きました。この決まりは Claude Code のメモリに残してあるので、Claude が自分で守ります\n- **撮る範囲**: kintone の上の帯（ログイン中の名前）などは外して撮りました。画面全体を撮ってから切るより、写したい範囲だけを撮るほうが、余計なものが入りません\n- **原稿の先頭のメモ**: 原稿の先頭の HTML コメントに、作業のメモ（未確認の所、手元のファイルのパス、アプリの番号）を書いていました。Web の編集画面に原稿をそのまま貼って公開したら、コメントごと公開されました。コメントは記事の表示には出ませんが、本文の Markdown には残ります。CLI で外して出し直しましたが、公開する文章とメモは分けておくのが確実です\n- **アップロードした画像**: Qiita にアップロードした画像は、記事を公開する前でも URL で開けます（今回、記事の公開前に、Claude が貼られた URL から画像を開いて中身を確かめました）。見せたくないものが写った画像は上げないようにします\n\n## 開くページ\n\n- Claude はページの文を読んで、次の操作を決めます。ページの中に AI への指示を紛れ込ませる攻撃（プロンプトインジェクション）があるので、Claude に開かせるのは、自分の環境と信頼できるページにとどめます。今回開いたのは、自分の kintone の開発環境と、自分がアップロードした Qiita の画像だけです\n- Claude が開いたタブは作業用のグループにまとまり、作業が終わると Claude が閉じます。グループから外れたタブ（つまずいたところの表）は手で閉じます\n\n---\n\n# まとめ\n\n- Claude Code に `@browser` を付けて頼むと、ログイン済みの Chrome で kintone の画面を開き、スクリーンショットを撮れる\n- 記事用の画像は、撮った画像を切り取るより、範囲を指定して撮り直すほうがきれい\n- ダイアログは JavaScript で位置を測ると、枠にぴったり合わせて撮れる\n- ダウンロードや保存のような操作は、Claude が許可を求めて止まる。確かめていない所は、原稿にも「未確認」と残る\n- 画像のアップロードは手で行い、貼った Markdown を Claude に渡すと差し替えまで済む\n- Claude ができることは、自分がその画面でできることと同じ。開発環境で行い、変える操作の前で止め、記事や画像に写るものを確かめる\n\n# 関連記事\n\n- [rex0220 印刷屋プラグイン - 組織図を PDF にする（詳細画面の手順と設定画面の紹介）](https://qiita.com/rex0220/items/76318504f0e88ded2dc2)\n- [rex0220 印刷屋プラグイン](https://qiita.com/rex0220/items/9be2d9b20a3a1f016c76)\n- [rex0220 印刷屋プラグイン - AI(Claude Desktop)に組織図を設計させてから、アプリを作らせる](https://qiita.com/rex0220/items/6e739ace80cffd2ad70a)\n","coediting":false,"comments_count":0,"created_at":"2026-10-21T09:04:27+09:00","group":null,"id":"691f50272359dfb02a87","likes_count":0,"private":false,"reactions_count":0,"stocks_count":0,"tags":[{"name":"kintone","versions":[]},{"name":"ClaudeCode","versions":[]},{"name":"Claude","versions":[]},{"name":"Chrome","versions":[]}],"title":"Claude Code + Claude in Chrome で Qiita の記事を作る（印刷屋プラグインの組織図の記事）","updated_at":"2026-10-21T14:29:55+09:00","url":"https://qiita.com/rex0220/items/691f50272359dfb02a87","user":{"description":"","facebook_id":"","followees_count":0,"followers_count":155,"github_login_name":"rex0220","id":"rex0220","items_count":756,"linkedin_id":"","location":"","name":"","organization":"","permanent_id":100572,"profile_image_url":"https://qiita-image-store.s3.amazonaws.com/0/100572/profile-images/1473708137","team_only":false,"twitter_screen_name":"rex02201","website_url":"https://rex0220.stores.jp/"},"page_views_count":null,"team_membership":null,"organization_url_name":null,"slide":false,"posting_campaign_uuid":null}]