1列あたりの行数・全列数・選択肢の形式と選択肢数を「行・列・選択肢」順に並べています。 R は Row (=行)、すなわち1列 25 行より成ること、 C は Column (=列)、すなわち4列あること、 D は Double 型、すなわち複数マーク対応で、1行あたりの選択肢数は 19 個。 (ここが S の場合は Single 型、複数マーク不可)
Word や Excel で作成したマークシートを、同じインクジェットプリンタで印刷して使用しているので、試験を実施する度にテンプレートを登録する必要はないはずなのですが、筆者はなんとなく不安で、毎回新しくテンプレートを登録し直して作業しています・・・
これまでのマークシートは Word で作成していたので、今回も Word を利用。・・・と言うか、本当は印刷設定の自由度が大きい Excel を使いたいのだが、Excel で縦楕円の丸囲み数字を上手に作成する方法がわからない。そこで縦楕円の丸囲み数字が簡単に作成できる Word を利用した・・・というのが正直なところ。
ちなみに Word で縦楕円の丸囲み数字(=「囲い文字」というらしい)を作成する方法は・・・
Word なら、Font は「メイリオ」を選択(フォントサイズを大きくしない場合)、丸囲みしたい数字を半角で入力、入力した数字をマウスでドラッグして選択してから、フォントリボンの「囲い文字」アイコンをクリックすると・・・
//複数マークの読み取り方法
if (Copy(strMS_Type,10,2)='19') and (chk_MultipleMarks.Checked) then
begin
//選択肢数が19で、複数マーク許可であった場合
StrList.Add(' var1.Value = str(res)');
end else begin
//複数マークは不許可であった場合
StrList.Add(' var1.Value = "99"');
end;
Python側で読み取った値をDelphi側で処理する部分も変更(一部を抜粋)。
//選択肢の始まりは「ゼロ」
if (Copy(strMS_Type,10,2)='19') and (chk_MultipleMarks.Checked) then
begin
//複数マークに対応
//strAnsList[intSG_k]の文字数を調査
strCount:=ElementToCharLen(strAnsList[intSG_k],Length(strAnsList[intSG_k]));
//チェック内容は、以下の通り
{
文字数が2文字の場合、末尾の1文字を取得する
10 -> 0
11 -> 1
19 -> 9
末尾1文字がマークした選択肢の番号になる
文字数が5文字の場合、
1 10 -> 2文字目が1、末尾2文字が10 -> 10
2 11 -> 2文字目が2、末尾2文字が11 -> 21
3 12 -> 2文字目が3、末尾2文字が12 -> 32
(2文字目×10)+(末尾2文字 - 10)がマークした選択肢の番号になる
}
case strCount of
2:begin
//2文字の場合は、末尾1文字が選択した選択肢の番号
StringGrid1.Cells[intSG_Col,intSG_Row]:=RightStr(strAnsList[intSG_k],1);
end;
3:begin
//空欄と判定された場合
if strAnsList[intSG_k]='999' then
begin
StringGrid1.Cells[intSG_Col,intSG_Row]:=strAnsList[intSG_k];
end;
end;
5:begin
//(2文字目×10)+(末尾2文字 - 10)がマークした選択肢の番号
StringGrid1.Cells[intSG_Col,intSG_Row]:=IntToStr(
(StrToInt(Copy(strAnsList[intSG_k],2,1)) * 10) +
(StrToInt(RightStr(strAnsList[intSG_k],2))) - 10);
end;
end;
end else begin
//1行につき選択肢数分Loopする_複数選択肢に対応(New)_20240614
if (Copy(strMS_Type,10,2)='19') and (chk_MultipleMarks.Checked) then
begin
//複数選択可能な場合_選択肢の数だけLoopする
for p := 0 to intCol-1 do
begin
//対象値pが平均値の3倍より大きいか、どうかでマークありと判定
if AryVal[p]>dblAvg * intKeisu then
begin
//マークありとした判定の数を記録
q:=q+1;
//マークした番号(記号)を記録
//intMark:=p+1;
//10の位(0-8)
case p of
0:strMark_A:='1';
1:strMark_A:='2';
2:strMark_A:='3';
3:strMark_A:='4';
4:strMark_A:='5';
5:strMark_A:='6';
6:strMark_A:='7';
7:strMark_A:='8';
8:strMark_A:='9';
end;
//1の位
case p of
9:strMark_B:='0';
10:strMark_B:='1';
11:strMark_B:='2';
12:strMark_B:='3';
13:strMark_B:='4';
14:strMark_B:='5';
15:strMark_B:='6';
16:strMark_B:='7';
17:strMark_B:='8';
18:strMark_B:='9';
end;
end;
end;
//Loop終了時にマーク数を判定
if q=0 then
begin
//マークした番号がない場合
iArr[i,Rep]:=999;
end else begin
//マークした番号があり、それが一の位である場合
if (q=1) and (strMark_A='') then
begin
//マーク数が1、かつ十の位が空欄であったら
iArr[i,Rep]:=StrToInt(strMark_B);
end else begin
//マーク数は1だが、それが十の位であったら
iArr[i,Rep]:=100;
end;
if (q=2) and (strMark_A<>'') and (strMark_B<>'') then
begin
//マーク数が2、かつ十の位と一の位がともに空欄でなかったら
strMark:=strMark_A+strMark_B;
iArr[i,Rep]:=StrToInt(strMark);
end;
if q>2 then
begin
//トリプル以上のマーク数を見分けるフラグは100
iArr[i,Rep]:=100;
end;
end;
end else begin
//選択肢の始まりは「ゼロ」(1の位を基準)
if (Copy(strMS_Type,10,2)='19') and (chk_MultipleMarks.Checked) then
begin
//strAnsList[intSG_k]の文字数を調査
strCount:=ElementToCharLen(strAnsList[intSG_k],Length(strAnsList[intSG_k]));
//チェック内容は、以下の通り
{
文字数が2文字の場合、末尾の1文字を取得する
10 -> 0
11 -> 1
19 -> 9
末尾1文字がマークした選択肢の番号になる
文字数が5文字の場合、
1 10 -> 2文字目が1、末尾2文字が10 -> 10
2 11 -> 2文字目が2、末尾2文字が11 -> 21
3 12 -> 2文字目が3、末尾2文字が12 -> 32
(2文字目×10)+(末尾2文字 - 10)がマークした選択肢の番号になる
}
case strCount of
1:begin
if StrToInt(strAnsList[intSG_k])<10 then
begin
StringGrid1.Cells[intSG_Col,intSG_Row]:='100';
end;
end;
2:begin
//2文字の場合は、末尾1文字が選択した選択肢の番号
StringGrid1.Cells[intSG_Col,intSG_Row]:=RightStr(strAnsList[intSG_k],1);
end;
3:begin
//空欄と判定された場合
if strAnsList[intSG_k]='999' then
begin
StringGrid1.Cells[intSG_Col,intSG_Row]:=strAnsList[intSG_k];
end;
//3文字と判定された場合、十の位の1~9のダブルマークの場合、
//2文字目は必ず半角の空欄になる
if Copy(strAnsList[intSG_k],2,1)=' ' then
begin
StringGrid1.Cells[intSG_Col,intSG_Row]:='999';
end;
end;
5:begin
//文字列の置き換え(先頭2文字を抽出&半角スペースを削除する)
strData:=StringReplace(Copy(strAnsList[intSG_k],1,2),
' ', '', [rfReplaceAll, rfIgnoreCase]);
//Case 5で先頭2文字が10である場合はダブル以上のマークあり
if StrToInt(strData) > 9 then
begin
StringGrid1.Cells[intSG_Col,intSG_Row]:='999';
end else begin
//2文字目が半角スペースでなければ処理可能
if Copy(strAnsList[intSG_k],2,1)=' ' then
begin
StringGrid1.Cells[intSG_Col,intSG_Row]:='999';
end else begin
//(2文字目×10)+(末尾2文字 - 10)がマークした選択肢の番号
StringGrid1.Cells[intSG_Col,intSG_Row]:=IntToStr(
(StrToInt(Copy(strAnsList[intSG_k],2,1)) * 10) +
(StrToInt(RightStr(strAnsList[intSG_k],2))) - 10);
end;
end;
end;
6..99:begin
StringGrid1.Cells[intSG_Col,intSG_Row]:='999';
end;
end;
end else begin
//複数選択を許可しないマークシートの処理
end;
end;
この際、読み取りエラーをすべて「999」で処理すれば、これまでの経験から、読み取り結果のチェックプログラムは確実に「空欄」=「999」位置を教えてくれるし、もし、それが本当に「空欄」である場合は、人が見ればそれは一目瞭然、もし、それが空欄でない場合は、それを見た「人」に、マークの有無 or 空欄 or その他複数マークの判断を委ねればいい。そしてもし、「人」が見て、マークが正しければプログラムの判定結果を正しく修正、そうでなく、マークが「空欄でない」・「必要数以上にマークされていた」場合は、そのまま「空欄として処理(999)」してもらえば、採点結果には一切影響を与えないはずだ。
また、派生版であるため、プログラムには Excel Book に読み取り結果を出力する機能がありますが、大語群に対応した採点結果通知作成用の Excel ファイルは、Zipファイルを展開後、 eFile フォルダ内にあるテンプレートから生成できる Excel ファイルをマクロ有効な Excel Book として保存し、これを元にご自身で作成していただく必要があります。※ Zip ファイルに添付した Excel Book は、大語群マークシートに対応しておりません。