スポンサーリンク

【pleasanter】計算式(拡張)活用サンプル⑤~プリザンターでeラーニングテスト~

プリザンター
スポンサーリンク
※当サイトは広告を含みます

※おことわり
2025年3月時点の情報です。プリザンターのバージョンは 1.4.14.0 です。Google Chrome でやっています。
javascript,html,cssともに初心者です。調べながら、やってみながら、きっとこうすればいいんだ!という感じで書いていますので、間違っている、または効率的な書き方ではない可能性が大いにあります。間違ってるよ!とか、こうしたほうがいいよ!ということがありましたら、コメント等で教えていただけると大変ありがたいです。

1.はじめに

会社にeラーニングのシステムはあるのですが、それに載せるのが間に合わなかったのか?Excel(VBA)とメールの合わせ技でやっていたテストがあり、それはそれですごいな、と思ったのですが、全従業員分の回答を集計するとか、大変そうだな。。。プリザンターでやったら何の苦も無く集計できるのに。。。とモヤモヤしてきて、計算式(拡張)を使ってやれそうだな、と思ってワクワクしてきたので趣味レーションでやってみました。

2.やりたいこと

ざっくりと、以下の内容を実装していきたいと思います。

回答者がレコードを新規作成して、設問に回答し「回答を送信」ボタンクリックでレコードが作成され、入力データが保存される。同時に設問の正解と合否判定が回答者に表示される。といった感じ。

計算式、保存、チェックのあたりの内部での実行の順番は違うかもしれません。

イメージ

3.サイトの設定

(1)エディタの設定

設問1

項目名表示名設定内容
見出し設問1
説明A設問1規定値で設問を入力。読取専用。コントロールcss [style-q]
分類A回答1選択肢[1,○/2,✖]。
拡張HTML:フィールドの前
<div style=’clear:both; margin-left:120px; color: red;’>○か✖を選択してください</div>
分類B解答1選択肢[1,○/2,✖]。読取専用。
分類C結果1読取専用。選択肢(以下[]内)
[100,正解!,正,status-Correct/200,ざんねん不正解,不,status-Incorrect]
説明B解説規定値で解説を入力。読取専用。コントロールcss [style-answer]

設問2:設問1と同様のため、省略

設問3

目名表示名設定内容
見出し設問3
説明E設問3規定値で設問を入力。読取専用。コントロールcss [style-q]
チェックA~D表示名は右表示名:雨、風、カーテン、雪
拡張HTML(チェックA、フィールドの前)
<div style=’clear:both; margin-left:120px; color: red;’>正しいと思われるものすべてにチェックを付けてください。(複数選択可)</div>
分類G解答1選択肢[1,○/2,✖]。読取専用。
分類H結果1読取専用。選択肢 (以下[]内)
[100,正解!,正,status-Correct/200,ざんねん不正解,不,status-Incorrect]
説明F解説規定値で解説を入力。読取専用。コントロールcss [style-answer]
分類Z入力判定非表示。規定値NG。選択肢 [OK/NG]

成績

項目名表示名設定内容
見出し成績
数値A得点
分類I合否判定コントロールcss [style-result]。選択肢(以下[]内)
[100,合格,合,status-pass/200,不合格,不,status-fail]

受験者情報

項目名表示名設定内容
見出し受験者情報
担当者担当者規定値 [[Self]]。選択肢 [[Users]]。読取専用。重複禁止(※)
※同じ人が二重にテストを受けないように、重複禁止としました。
日付A受験日規定値 0。年月日。読取専用
状況選択肢読取専用。選択肢 [100,回答中/900,回答済]。規定値=100,回答中
タイトル担当者非表示。項目「担当者」を適用する

イメージ

(2)計算式

対象(出力先)と計算式を以下に示します。
方式はすべて「計算式(拡張)」です

対象(出力先)計算式
結果1(分類C)$IF(回答1 == 解答1, 100, 200)
結果2(分類F)$IF(回答2 == 解答2, 100, 200)
結果3(分類H)$IF($AND(雨,風,雪), 100, 200)
得点(数値A)$IF(結果1==’100′, 30, 0) + $IF(結果2==’100′, 30, 0) + $IF(結果3==’100′, 40, 0)
合否判定(分類I)$IF(得点 >= 60, ‘100’, ‘200’)
入力判定(分類Z)$IF($OR([CheckA],[CheckB],[CheckC],[CheckD]),”OK”,”NG”)
※表示名を使用しない、としています

(3)アクセス制御

作成者は自分の作成したレコードのみ閲覧可能。管理者はすべてのレコードを閲覧可能とするアクセス制御を設定します。
テストの結果がほかの人に見られたら恥ずかしいですもんね。

なお、アクセス制御についてはビューで閲覧を制御する方法もありますので、後述(項番6)に別の設定方法も示します。

サイトのアクセス制御
●管理者(一人以上のユーザー、または部署):パターン「管理者」を指定
●全てのユーザー「作成」のみ許可

レコードのアクセス制御
[ユーザー]を左ペインに指定。「作成」のチェックを外し「読取」「更新」にチェック。(メール送信は任意)

(4)プロセス

プロセスは1つ設定します。1つのプロセスの「全般」タブと「入力検証」タブを使用します。

今回は簡単な内容なので、「新規作成」から直接「回答を送信」ボタンで一発勝負で入力作業を終わらせるように設定しています。

全般

項目設定内容
名称回答
表示名回答を送信
画面種別新規作成
現在の状況回答中
変更後の状況回答済
確認メッセージ回答を送信します。よろしいですか?
成功メッセージ回答を送信しました。
実行種別追加したボタン
アクション保存

「作成」ボタンを押してから「回答を送信」ボタン押す、とすると「回答を送信」を押し忘れることがありそうなので「作成」ボタンはサーバースクリプトで非表示にしています。
今回はごく単純な内容なので、「作成」をすっ飛ばして「回答を送信」ボタンで「作成・保存」の処理をいっぺんにやってしまおうとしているものです。あまり正統的な手段ではないかもしれません。

「作成」ボタンを押してから「回答を送信」ボタンを表示するようにする場合は、画面種別を「編集」とします。その場合、サーバースクリプトで指定している「作成ボタン非表示」は削除します。

「作成」ボタンや「更新」ボタンも機能するようにする場合は、上の図と同じ内容で画面種別を「編集」にしたプロセスをもう一つ作成することにより、いけるのでは、と思います。

入力検証

入力検証項目設定内容
回答1入力必須
回答2入力必須
入力判定サーバー正規表現 : ^OK$
エラーメッセージ:設問3 いずれかにチェックを入れてください。

※「入力判定」には計算式でチェックA~Dのいずれかにチェックが入っていたら「OK」と出るように設定している。チェック項目のいずれかにチェックがついていれば入力検証は通り、プロセスが完了する。いずれにもチェックがついていない場合は入力検証でNGとなり、エラーメッセージが表示され、このプロセス処理が通らない。

(5)状況による制御

1)回答中の制御

名称 :回答中
状況 :回答中
項目の制御:非表示 [解答1,結果1,解説1,解答2,結果2,解説2,解答3,結果3,解説3,得点,合否判定]

2)回答済の制御

名称 :回答済
状況 :回答済
項目の制御:読取専用 [回答1,回答2,チェックA,チェックB,チェックC,チェックD]

項目の制御は項目を選択して上部の「読取専用」や「非表示」等のボタンを押すことで、項目を「読取専用」にしたり、「非表示」にしたりの設定ができます。

(6)サーバースクリプト

「更新」「コピー」「作成」ボタンを非表示にしています。

条件:画面表示の前

//更新ボタンを表示しない
elements.DisplayType('UpdateCommand', 1);
//コピーボタンを表示しない
elements.DisplayType('OpenCopyDialogCommand', 1);
//作成ボタンを表示しない
elements.DisplayType('CreateCommand', 1);

公式マニュアルを参考としています。
開発者向け機能:サーバスクリプト:elements.DisplayType

今回はサーバースクリプトでやっていますが、ボタンの非表示はスタイルでもできます。
FAQ:特定のボタンを非表示にしたい

(7)スタイル

これは。。。スタイルは今回は機能とは関係なく見た目だけなのでどうでもいいところですが、ご参考まで。ヨチヨチ歩きのcss、絶望的なセンスなので、あまり参考としないほうがいいかも。

/* 質問欄コントロール */
.style-q {
  border: none; /* 枠線をなくす */
  background-color: rgba(173, 216, 230, 0.5); /* 薄い青 */
}
/* 質問欄の見出し */ 
label[for='SectionFields1'],
label[for='SectionFields2'],
label[for='SectionFields3']
{
  background-color: lightblue; /* 薄い青 */
  font-size: 2em;                /* 文字の大きさ2倍 */
  padding-left: 15px;            /* 左余白 */
  padding-bottom: 3px;           /* 下余白 */
}
  
/* 設問3回答チェック欄 */ 
#Results_CheckAField,
#Results_CheckBField,
#Results_CheckCField
{
  height: 2em;    /* 高さ2倍 */
}

/* 解答説欄コントロール */
.style-answer {
  background-color: #f5f5dc;
}
/* 解説欄コントロール */
#Results_DescriptionB\.viewer,
#Results_DescriptionD\.viewer,
#Results_DescriptionF\.viewer 
{
    background-color: #f5f5dc;
}

/* 結果欄 正解*/
.status-Correct {
  background-color: #c3e6cb;
}
/* 結果欄 不正解*/
.status-Incorrect {
  background-color: #f8d7da;
}

/* 判定欄 合格*/
.status-pass {
  background-color: #A3D8F4;
}
/* 判定欄 不合格*/
.status-fail {
  background-color: #F5A3A3;
}
/* 判定欄 太字*/
.style-result {
  font-weight: bold;
}

上記のスタイルで特筆すべきポイントは
・結果欄、判定欄は「状況」のように、選択肢によって色を変えるようにしています。
選択肢にクラスを設定しておくのですが、その際にはクラス名の頭に status‐ をつける、というルールがあるようです。
・説明項目の背景色を変更するばあい、コントロールcssにクラス名を指定したのでは背景色が変わらなかったので、#Results_DescriptionB\.viewer のようにセレクタを指定しています。

4.出来上がりイメージ

こんな感じ

「新規作成」したところ。

「回答を送信」をクリックした後

5.計算式の部分をサーバースクリプトでやった場合

ちなみに、計算式(拡張)を使わずにサーバースクリプトでやった場合は以下のコードで同じ結果が得られました。

条件:作成前

try {
  //回答と回答が同じなら「100,正解」違う場合は「200,不正解」
  //設問1の判定
  model.ClassB = model.ClassA === model.ClassC ? '100' : '200'; 
  //設問2の判定
  model.ClassF = model.ClassD === model.ClassE ? '100' : '200';
  //設問3の判定
  //条件:CheckA,CheckB,CheckDgatrueかつCheckCがfalseであること
  model.ClassH = model.CheckA && model.CheckB && !model.CheckC && model.CheckD ? '100' : '200';

  //点数の算出
  //設問1と設問2は各30点、設問3は40点
  const score1 = model.ClassB === '100' ? 30 : 0;
  const score2 = model.ClassF === '100' ? 30 : 0;
  const score3 = model.ClassH === '100' ? 40 : 0;
  const totalScore = score1 + score2 + score3;  //総合得点
  model.NumA = totalScore;

  //判定: 60点以上で「100,合格」,60点j未満で「200,不合格」
  model.ClassI = totalScore >= 60 ? '100' : '200';
} catch(e) {
  context.Log('error!');
  context.Log(e.stack);
}

今回のサンプルでは「更新」ではなく「作成」一本でやるフローなので、出力条件を「作成前」としています。

なぜ、わざわざサーバースクリプトバージョンもやってみたかというと、会社のプリザンターは計算式(拡張)が使えないバージョンだからです。。。

あ、もちろん上記のコードはCopilot先生の添削、修正を受けたものです。コパ先生には大変お世話になっています。

6.アクセス制御をサーバースクリプトを利用してやった場合

3(3)で自分で作成したレコードしか見えない設定を「サイトのアクセス制御」「レコードのアクセス制御」にて行っています。

この方法は、設定が簡単ですが、この設定をした後のレコードにしかアクセス制御が適用されなかったりします。なので、柔軟な制御としたい場合等はサーバースクリプトで「自分が担当者となっているレコードしか見せない」という設定にすることが可能ですので、そちらを利用することもできます。

[アクセス制御]タブ

サイトのアクセス制御
●管理者(一人以上のユーザー、または部署):パターン「管理者」を指定
●全てのユーザー「作成」「読取」「更新」を許可(メール送信等は任意)

レコードのアクセス制御:なにも設定しません

[サーバースクリプト]タブ

以下のコードを入力します。条件は「ビュー処理時」とします。

//総務部(組織ID2)およびadministrator(ユーザーID1)以外のユーザーには担当者が自分以外のレコードは一覧に表示しない
if ( context.DeptId !== 2 && context.UserId !== 1 ) {
    view.Filters.Owner = context.UserId;
}

ログインユーザーの組織IDが2じゃないよ!ユーザーIDが1じゃないよ!というときに{}内のフィルター条件が発動します。
フィルター条件が発動されると、担当者が自分のIDのものだけが一覧に表示されます。なので、他の人が作成したレコードは表示されないので、見ることができません。
逆に、組織IDが2だよ!という時、ユーザーIDが1だよ!という時はフィルター条件が発動しません。なので、すべてのレコードが表示されます。
私はここを &&(アンド条件)ではなく ||(OR条件)にしてしまって「あれ?」となりました。

開発者向け機能:サーバスクリプト:view.Filters

7.最後に

一気にやったら疲れちゃった。ので、この辺で終了します。

プリザンターは入力したら即!データベースに反映され、集計ができるのでらくちんですね!

ちゃんとためしてないので、不整合はあるかもしれませんが、ご参考になれば幸いです!

8.参考文献、記事

公式マニュアル
テーブルの管理:計算式(既定)
テーブルの管理:計算式(拡張)
計算式(拡張)の関数一覧
計算式(拡張)の関数で使用する論理式

開発者向け機能:サーバスクリプト:elements.DisplayType
FAQ:特定のボタンを非表示にしたい
開発者向け機能:サーバスクリプト:view.Filters

参考記事
プリザンターのアクセス制御について改めて整理してみる

内部リンク
【pleasanter】計算式(規定・拡張)についてまとめてみた
【pleasanter】計算式(拡張)活用サンプル①~リマインダーの日付として利用する~
【pleasanter】計算式(拡張)活用サンプル②~入力チェックに利用する~
【pleasanter】計算式(拡張)活用サンプル③~タイトルを自由自在に~
【pleasanter】計算式(拡張)活用サンプル④~フィルタ項目として利用する~

内部リンク
【pleasanter】サーバースクリプト~一覧のフィルター~ユーザー組織あたりをあれこれやってみたシリーズ⑫
【pleasanter】レコードのアクセス制御についてあれこれやってみた①
【pleasanter】レコードのアクセス制御についてあれこれやってみた②

もう読みましたか?プリザンターの概要、インストール方法から基本操作方法、導入事例、サンプル等役に立つ情報が満載でしたよ!ちなみにこの記事のプロセスの部分はこの本を読んで「こうやればいいんだ!」と学習した成果が反映されています。

コメント

タイトルとURLをコピーしました