成績処理 – Linux Home Server http://www.now.mfnet.ne.jp/~ozachin/wordpress Long Road Linux Sat, 18 Jan 2020 02:26:17 +0000 ja hourly 1 https://wordpress.org/?v=5.9.3 成績処理12 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=276 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=276#respond Tue, 07 Jan 2020 01:10:29 +0000 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=276 read more]]> 成績処理の連載も最終回となります。

VBAコードを示す前に、3つの印刷例を見てください。
左は何も制御しないで印刷した例、10件のレコードを印刷して終了しています。
中央は、10件目のレコードが連続して印刷されている例です。
右は、最終的に目指している形です。

「印刷されている」と思うと分かりにくいのですが、中央の例の11行目以降のデータが「見えなければ」目指す形になると考えればよいのです。
では、左の例と中央の例の違いは何かというと、前に紹介したNextRecordプロパティの違いです。通常の印刷では、詳細セクションが印刷(Format)される前にNextRecordプロパティがTrueに設定されます。最終10件目で次(Next)の11件目は無いと判断するわけです。従って、最終10件目になったら、印刷の前にNextRecordプロパティをFalseにすれば、レコード終了していないと判断され、10件目のまま印刷が続くという仕組みです。

レコード件数は、T_seitoテーブルのレコード数です。(変数rcとします。)
最大何行まで印刷するかは、各学校のクラス在籍数や、用紙のサイズ、フォントサイズや見栄え等も考慮しながら決めないといけませんが、B4サイズ横であれば40~45名程度は印刷できるでしょう。仮に45としておきます。(変数gmaxとします)
現在行は前回示した(変数i)を使います。
i < rc       普通に印刷
i = rc   NextRecord はFalse
i < gmax  NextRecord はFalse  テキストボックスのVisibleはFalse
コードを示します。(前のコードも含みます)

Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)

Dim ln, k As Integer
i = i + 1
ln = i Mod 5

    If ln = 0 Then
        line1.BorderStyle = 1
    Else
        line1.BorderStyle = 4
    End If
    
If i < rc Then

    Me.NextRecord = True
    
    Me.sname.Visible = True  '生徒名のテキストボックス
    Me.hei.Visible = True    '平均点のテキストボックス

    For k = 1 To 25
        Me.Controls("k" & k).Visible = True
    Next


ElseIf i = rc Then

    Me.NextRecord = False
    
    Me.sname.Visible = True  '生徒名のテキストボックス
    Me.hei.Visible = True    '平均点のテキストボックス

    For k = 1 To 25
        Me.Controls("k" & k).Visible = True
    Next

ElseIf i < gmax Then

    Me.NextRecord = False
    
    Me.sname.Visible = False  '生徒名のテキストボックス
    Me.hei.Visible = False    '平均点のテキストボックス

    For k = 1 To 25
        Me.Controls("k" & k).Visible = False
    Next

End If



End Sub

 

帳票設計はこだわりをもってやりましょう。縦罫線(直線)は大変ですが頑張ってデザインしてください。あまり細かい作業が好きではない方にお気軽縦罫線の設定方法を最後に示し、この連載を終了します。

お気軽罫線ですが、直接レポートデザイン画面で1つ1つ直線を描くのではなく、OLEオブジェクトとして貼りつける方法です。まずワードで必要な表を作成します。表のプロパティで高さやセル幅は指定します。これをPDFファイルとして保存して開きます。SnippingToolで縦罫線の部分だけ切り取り、レポートデザイン画面で詳細セクションに貼りつけます。その上にデータ用テキストボックスを配置していきます。OLEオブジェクトが前面にあるとデータが隠れてしまうので、最背面になるようにします。横罫線は簡単ですから直線を描けば無事縦横罫線の完成です。同様に、ヘッダー部分の文字も含めたデザインもワード等で作成したものを貼り付ければ、慣れないデザイン画面で苦労することもありません。

Version2007?からは、レポートデザインの配置の中に枠線を指定できるようになった。詳しくはないが、縦横(水平垂直)が指定できるようになっている。それを使えばそれなりの結果は得られるかもしれない。

]]>
http://www.now.mfnet.ne.jp/~ozachin/wordpress/?feed=rss2&p=276 0
成績処理11 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=269 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=269#respond Tue, 07 Jan 2020 00:26:47 +0000 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=269 read more]]> レポートに詳しくない人のために種明かしをしておきます。詳細セクションの高さを広げて印刷すると、以下のようになります。データの入った、氏名と各科目成績のテキストボックス、多数の縦の直線および横の直線(初期値は点線)から詳細セクションができています。

通常はレコードがなければ詳細セクションの印刷は終了してしまいますが、レコードが無くても詳細セクションを印刷するように制御します。レコード有無の判断を制御するので、直線は最大行まで全て印刷します。つまり、何もしなくてよいです。
問題はテキストボックスです。今回の場合、科目数が25個なのでその部分の制御だけでも同じ処理を繰り返し記述しなければなりません。

VisualBasicはコントロール配列を使うことができるので、同じコントロール名を付けると自動的に配列として扱われますが、VBAにはコントロール配列がありません。しかし、次のようにすると配列のように扱うことができます。同じ記述を繰り返さなくて済みます。
最初にそのコードを示しておきます。
今回、各科目のデータソースはkn1~kn25でした。レポートのテキストボックスの名前はk1~k25としてあります。

'--- テキストボックスの可視プロパティを設定する例 ---
Dim i As Integer
For i = 1 To 25
  Me.Controls("k" & i).Visible = True
Next

次に、5名(5行)毎に横罫線を実線にするためのコードも簡単ですから、示しておきます。
良く使われる手法です。割り算した余りが0(割り切れる)というやり方のMod演算子です。

Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)

Dim ln As Integer

i = i + 1    '行数をカウントする変数、別に定義しておく

 ln = i Mod 5

    If ln = 0 Then

       line1.BorderStyle = 1  '実線

    Else

       line1.BorderStyle = 4  '点線

    End If

 

End Sub

これで、準備ができました。続きは次回とします。

]]>
http://www.now.mfnet.ne.jp/~ozachin/wordpress/?feed=rss2&p=269 0
成績処理10 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=267 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=267#respond Mon, 06 Jan 2020 10:52:50 +0000 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=267 read more]]> 成績処理自体は正確にできて当たり前なので、システムの良し悪しの評価は操作性や出力された帳票の見た目に大きく左右されます。
日本人は罫線好きと言われます。特に、縦横罫線の表形式が好きなようです。 残念ながらアメリカ生まれのAccessは罫線が苦手です。
レポートの詳細セクションに直線を一緒に印刷して、横罫線が引かれているように見せることが基本的な機能です。
見た目の縦の罫線を印刷するには、かなり細かい作業が必要です。 ある意味開発者の意気込みとセンスの領域でしょうか。

「桐」というデータベースソフトがあります。
日本人好みの表がいとも簡単に作成できます。段組みであろうが、グループ集計であろうがワンタッチです。
便利に使っているユーザーも多いのではないでしょうか。

さて、話を元に戻してAccessの話です。
先に成績一覧表の例を示しました。10名の生徒について最低限必要な条件は整っています。
しかし、学校全体として帳票をバインダー等に綴じて保存することを考えると、クラス毎に在籍生徒数によって 帳票の縦方向のサイズが異なるのではなんとも統一性がありません。

従って、在籍数に関わらず帳票のサイズが統一されるようにすることが求められます。
例えば以下のようですが、データの有無に関わらず罫線が印刷されるように処理をします。
ついでに、5名毎に罫線の種類を変えて見やすくすることもよくある処理です。

縦罫線は頑張ってデザインしましょう。問題は横罫線をVBAでどう制御するかです。
いろいろ方法はあるのでしょうが、レポートの機能ついてあまり出てこないNextRecordプロパティというものを使ってみたいと思います。
ヘルプを見てみましょう。

レコードはないけれど、詳細セクションを印刷することで目的を実現します。
具体的なコードは次回とします。


尚、簡易的に縦横罫線に見せかけるには、テキストボックスのBorderStyleプロパティを1(実線)にして、左右の配置を重ねればなんとかなります。
しかし、なかなかきれいに印刷されません。何度も印刷して調整しないといけないでしょう。

]]>
http://www.now.mfnet.ne.jp/~ozachin/wordpress/?feed=rss2&p=267 0
成績処理9 余談2 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=262 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=262#respond Mon, 06 Jan 2020 04:34:50 +0000 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=262 read more]]> 成績処理システムあるいは教務システムなどと呼ばれているパッケージを導入している学校も多いと思われます。

パッケージが標準で用意している帳票だけでは足りない場合、現場で加工できるようにデータをCSVファイルとしてダウンロードして利用できることが多い。 どこの学校にもエクセルに超詳しい人がいて、いろいろな処理をしているようだが、慣れていない人がうっかりすると、とんでもないことが起こる。

それは、エクセルを使っていると、気軽に表やシートをコピーしていろいろ加工してしまうことから起こるようです。 最悪は、並べ替えをして正しくできていると思い込んでいると、一部だけソートされて元の表がくずれてしまうことがある。データベースでは起こりえないことです。そんなデータがコピーされ、次から次へと他の人に渡ると悲惨です。

さて、今回紹介した内容もパッケージを補足するために開発されたものの中の一つです。バックエンドはSQLServerです。開発理由はいろいろありましたが、その一つは選択科目が多いクラスだと一覧表が複数ページになってしまうことです。クラス担任としては不便極まりないことです。何とかならないかとう相談がありました。

パッケージのカスタマイズには莫大な費用がかかります。これからパッケージの導入を検討している場合は事前に必要な帳票の種類や内容を詳細に検討されるようお奨めします。
先の例でも、導入当初は問題なかったが、教育課程の変更で一気に選択科目が増えたために起きた問題でした。

]]>
http://www.now.mfnet.ne.jp/~ozachin/wordpress/?feed=rss2&p=262 0
成績処理8 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=252 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=252#respond Mon, 06 Jan 2020 04:19:24 +0000 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=252 read more]]> 最終的なコードを示す前に、もう一度準備段階の確認をしておく。今回は、連載6で科目名固定の処理として掲載したコードをどんな科目であっても処理できるよう一般化する。


1.集計対象となる生徒集団を抽出したテーブルを作成する。
 T_seito
2.1の生徒集団について、特定の試験についての成績情報を抽出したテーブルを作成する。
T_seiseki
3.2のテーブルから、集計対象の科目を抽出(重複クエリ)したテーブルを作成する。
T_kamoku
この3つのテーブルが作成できたら、今回紹介するVBAのコードを実行すればよい。
従って、3つのテーブルとコード実行中に新規作成されるテーブル(T_ichiran)で合計4つのテーブルを扱うことになる。

もちろん、実際の現場ではこれらすべてを自動化して、一覧表印刷まで行うことになる。
例えば、次のようなフォームから指定をしてボタンを押すだけで処理されるようにする。

直接入力はミスのもと、年度を指定し適切なクラス範囲の指定しかできないようにすべきである。

準備段階の3つのテーブル(読み取り専用)
T_seito
T_kamoku
T_seiseki
新規作成されるテーブル
T_ichiran

それでは、以下にVBAコードを示す。

Private Sub cmdLast_Click()

Dim cn As ADODB.Connection

'---- 4つのテーブルを使用します ----
Dim r1 As ADODB.Recordset
Dim r2 As ADODB.Recordset
Dim r3 As ADODB.Recordset
Dim r4 As ADODB.Recordset
'-----------------------------------

Dim h_avg As Double      '平均点
Dim i, j, k              'カウンター
Dim st_SQL As String     'sql用文字列
Dim all_k As String      '科目名をフィールド名にするための文字列、sql文で使用
Dim all_k_i As String    '科目名をフィールド名にするための文字列、sql文で使用
Dim all_k_h As String    '科目名をフィールド名にするための文字列、sql文で使用
Dim k_name(30) As String   '科目名を入れる配列
Dim k_n As Integer       '科目数を入れる変数

'科目数を取得
k_n = DCount("*", "T_kamoku")

all_k_i = "生徒名 varchar,"        'フィールド定義
all_k_h = "平均点 Double"         'フィールド定義

Set cn = CurrentProject.Connection

Set r1 = New ADODB.Recordset
Set r2 = New ADODB.Recordset
Set r3 = New ADODB.Recordset
Set r4 = New ADODB.Recordset


r1.Open "T_seiseki", cn, adOpenForwardOnly, adLockReadOnly '得点テーブル
r3.Open "T_kamoku", cn, adOpenForwardOnly, adLockReadOnly  '科目名テーブル

i = 1

'科目名を取得
Do Until r3.EOF

    k_name(i) = r3!科目名
    r3.MoveNext
    i = i + 1

Loop

'-----------------------
i = 1

'-------###ここがポイント###-------
'科目名を一般化してフィールド名に入れる準備
For i = 1 To 25
 all_k = all_k & "kn" & i & " double,"
Next


'最終的にフィールド名とするための処理
all_k = all_k_i & all_k & all_k_h


'処理前にテーブルを削除
On Error Resume Next
DoCmd.DeleteObject acTable, "T_ichiran"
On Error GoTo 0


'テーブル作成のSQL文およびSQL実行
st_SQL = "CREATE TABLE T_ichiran(" & all_k & ");"
DoCmd.RunSQL st_SQL

r2.Open "T_ichiran", cn, adOpenKeyset, adLockOptimistic    
 '新規に作成したテーブル


'生徒名を取り出し、新規テーブルに登録する処理

r4.Open "T_seito", cn, adOpenKeyset, adLockReadOnly      
 '生徒名を参照するテーブル

      Do Until r4.EOF
            r2.AddNew
            r2!生徒名 = r4!生徒名
            r2.Update
            r4.MoveNext
      Loop

'---------------------------------------------------------------
'ここから点数を書き込む処理
'参照テーブルは得点テーブルT_seideki(r1.open)→T_ichiran(r2.open)
'---------------------------------------------------------------

r1.MoveFirst
r2.MoveFirst


Do Until r2.EOF

    h_avg = 0
    k = 0
    r1.MoveFirst
    
    Do Until r1.EOF
    
        j = 1
    
        Do Until j > r2.Fields.Count - 1
            
            If r1!生徒名 = r2!生徒名 And k_name(j) = r1!科目名 Then
                 
                       r2("kn" & j) = r1!点数  '-- r2.Fields(j).Value = r1!点数 としても可 ---
                       h_avg = h_avg + Nz(r1!点数)
                       k = k + 1
                       If h_avg <> 0 Then r2!平均点 = Round((h_avg / k), 2)
                       r2.Update
                
            Else


            End If

            j = j + 1
   
        Loop

     r1.MoveNext
     Loop


r2.MoveNext
Loop

'-------レコードセットを閉じる------
r1.Close
Set r1 = Nothing
r2.Close
Set r2 = Nothing
r3.Close
Set r3 = Nothing
r4.Close
Set r4 = Nothing
cn.Close
Set cn = Nothing

End Sub
]]>
http://www.now.mfnet.ne.jp/~ozachin/wordpress/?feed=rss2&p=252 0
成績処理7 余談ですが・・・ http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=242 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=242#respond Sun, 05 Jan 2020 12:58:37 +0000 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=242 read more]]> データベースソフトは便利なのですが、なかなかハードルが高いようです。 学校現場でAccessをこなせる人は少ないようです。

エクセルは得意でデータベースはよく知らない先生から質問されたことがあります。
「なぜ最初から、T_ichiranのようなテーブルを作って入力するようにしたらダメなんですか」
この質問にはデータベースの根幹にかかわる問題が含まれています。これからデータベースを扱おうと思う人はよく理解しておいてください。

単純に1回だけの処理を考えれば、確かにもっともな質問です。 しかし、試験は1回だけではありません。 仮に、中間試験・期末試験・期末の評価(5段階や10段階)があったとします。 中学生や高校生の場合、一人の生徒について3年間に必要な成績情報はいくつになるでしょう。 単に試験成績と期末評価を入れるだけでも2期制の学校なら、1科目について、3年間で18になります。 1年で履修する科目は10科目程度が標準ですが、3年間で18×10=180です。 各科目の出席状況や単位認定なども管理するとすれば、さらに多くなります。

これだけのフィールドを仮に用意できたとして 今見ているT_ichiranは、その一部分を表示したにすぎないのです。しかも、全ての生徒が同一の科目並びでなければなりません。そんなことはあり得ませんので、現実には、このようなテーブルは作成できません。
横長のエクセル表のようなものを考えてはいけないのです。

結論的に、一例として成績情報は次のように格納されることになります。

(凡例) 学期コード 1:前期 2:後期   試験コード 1:中間  2:期末 3:期末評価(学校により、5段階や10段階)

この連載で示したT_seisekiは、このようなテーブルをいきなり示したのでは分かりにくいので、生徒コードの代わりに具体的な生徒名、科目コードの代わりに具体的な科目名そして点数を抜き出したものと理解してください。(さらに詳しく述べると、特定の生徒集団、年度、学期コード、試験コードを条件に抽出したものということになります。)

]]>
http://www.now.mfnet.ne.jp/~ozachin/wordpress/?feed=rss2&p=242 0
成績処理6 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=236 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=236#respond Sun, 05 Jan 2020 06:20:36 +0000 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=236 read more]]> 前回までの処理で、成績一覧表のもとになるテーブル(T_ichiran)ができあがる。

成績が登録されているテーブルから、このような一覧形式に変換すればレポート機能で自由に成績一覧表を作成できる。今回は説明のため単純化した内容になっているが、集計対象となる生徒名簿と成績情報があれば処理が可能である。

学校であれば、生徒名簿はクラス単位等で出席番号順に抽出が可能であろう。今回は全員が試験を受験した前提(一部欠席でもよいが)であるが、全科目欠席した生徒も含めて作成したければ、クラス等の在籍名簿を参照できるようにすればよい。ただし、実際に参照するのは生徒コードになるだろう。

さて、最初に説明した通り今回のような科目が固定(科目名と科目数)された内容では実際の学校現場では役に立たない。(時間と手間をかけてもよいなら別だが)
そこで、最後に科目や科目数に関係なく処理できる方法を示す。制約があるとすればAccessのテーブルのフィールド数の上限255だけである。事実上無制限である。

実際、月曜から金曜日(土曜日)まで30時間とか34時間の授業があるとして、全て1単位の授業であっても最大34科目である。主要科目の単位数は多くは3~5なので、どんなに多くても20科目程度処理できれば問題ない。小生が関係した学校で総合学科的なクラスで最大22科目というのが過去最大である。実際は選択科目が多いので、一覧表は虫食い状態に数値が並ぶことになる。以下にB4横用紙に今回のデータを印刷した場合の例を示す。

B4横用紙 30科目まで可能だが実質は多くが余白部分となる。
実際は、氏名欄にはクラスや出席番号なども表示される。順位が必要なら別に処理する 。

どんな科目名・科目数でもこのフォーマットのレポートに収まるようにVBAを変更してみよう。これまでの内容が理解できていれば簡単である。変更するのは1か所だけである。

なぜ今回示した内容が科目名と科目数が固定されたかを考えれば明らかであろう。
新規テーブル(T_ichiran)を作成する際に、フィールド名を科目名、科目フィールド数を科目数にしたからである。

この部分を一般化すればよい。仮に25科目として、科目フィールドを記号化してkn1~kn25(科目ナンバー)にする。科目名は科目名テーブルを参照するのでフィールド名が科目名である必要はない。一般的には科目には科目コードがついているので、コード順に参照すれば確実に書き込みできる。

これで、レポートの成績データソースが一般化され、kn1~kn25となる。あとは見出しとなる科目名ラベルの変更だけである。ラベルはlb1~lb25とし、科目名が格納されたk_name(i)を参照してラベルcaptionを変更する処理をヘッダーフォーマット時イベントに記述すれば完成である。

説明が長くなったので、実際のコードは次回とする。
理解できた方は自分で挑戦してみらよいだろう。

]]>
http://www.now.mfnet.ne.jp/~ozachin/wordpress/?feed=rss2&p=236 0
成績処理5 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=225 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=225#respond Sun, 05 Jan 2020 02:18:05 +0000 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=225 read more]]> 最終段階の各生徒の各科目の成績をテーブルにセットしていく処理である。
Recordsetは4つ必要である。
r1—T_seiseki 各科目の成績を参照するテーブル
r2—T_ichiran 各科目の成績を書き込むテーブル
r3—T_kamoku 科目を参照するテーブル(既に配列k_name(i)に読込済み)
r4ーT_seito 生徒名を参照するテーブル

単独の機能として説明の都合上、重複した記述となっているが(今回はコマンドボタンcmd3としている)、今回のコードが最終的な一括したコードである。

前回までの確認をすると
連載3では
r3を参照して、科目名をフィールド定義しT_ichiranを作成する処理
連載4では
r4を参照して、作成したT_ichiran(r2)に生徒名をセット

今回は
生徒名と科目名が一致するデータを順に書き込んでいけばよい。(全科目ループ)
点数が格納されるフィールドは1番目から、(科目数-1)番目までなのでループさせる。
0番目フィールドは生徒名、最終フィールドは平均点である。

Private Sub cmd3_Click()

Dim cnn As ADODB.Connection

'---- 4つのテーブルを使用します ----
Dim r1 As ADODB.Recordset
Dim r2 As ADODB.Recordset
Dim r3 As ADODB.Recordset
Dim r4 As ADODB.Recordset
'-----------------------------------

Dim h_avg As Double      '平均点
Dim i, j, k              'カウンター
Dim st_SQL As String     'sql用文字列
Dim all_k As String      '科目名をフィールド名にするための文字列、sql文で使用
Dim all_k_i As String    '科目名をフィールド名にするための文字列、sql文で使用
Dim all_k_h As String    '科目名をフィールド名にするための文字列、sql文で使用
Dim k_name(30) As String   '科目名を入れる配列
Dim k_n As Integer       '科目数を入れる変数

'科目数を取得
k_n = DCount("*", "T_kamoku")

all_k_i = "生徒名 varchar,"        'フィールド定義
all_k_h = "平均点 Double"         'フィールド定義

Set cnn = CurrentProject.Connection

Set r1 = New ADODB.Recordset
Set r2 = New ADODB.Recordset
Set r3 = New ADODB.Recordset
Set r4 = New ADODB.Recordset



r1.Open "T_seiseki", cnn, adOpenStatic, adLockReadOnly '得点テーブル
r3.Open "T_kamoku", cnn, adOpenStatic, adLockReadOnly  '科目名テーブル

i = 1

'科目名を取得
Do Until r3.EOF

    k_name(i) = r3!科目名
    r3.MoveNext
    i = i + 1

Loop

'-----------------------
i = 1

'科目名を一般化してフィールド名に入れる準備
For i = 1 To 25
 all_k = all_k & "kn" & i & " double,"
Next


'最終的にフィールド名とするための処理
all_k = all_k_i & all_k & all_k_h


'処理前にテーブルを削除
On Error Resume Next
DoCmd.DeleteObject acTable, "T_ichiran"
On Error GoTo 0


'テーブル作成のSQL文およびSQL実行
st_SQL = "CREATE TABLE T_ichiran(" & all_k & ");"
DoCmd.RunSQL st_SQL

r2.Open "T_ichiran", cnn, adOpenKeyset, adLockOptimistic     '新規に作成したテーブル


'生徒名を取り出し、新規テーブルに登録する処理

r4.Open "T_seito", cnn, adOpenStatic, adLockReadOnly      '生徒名を参照するテーブル

      Do Until r4.EOF
            r2.AddNew
            r2!生徒名 = r4!生徒名
            r2.Update
            r4.MoveNext
      Loop

'-------------------------------------------------------
'ここから点数を書き込む処理  参照テーブルは成績テーブル
     T_seideki(r1.open) →   T_ichiran(r2.open)
'-------------------------------------------------------
r1.MoveFirst
r2.MoveFirst

Do Until r2.EOF

    h_avg = 0
    k = 0
    r1.MoveFirst
    
    Do Until r1.EOF
    
        j = 1
    
        Do Until j > r2.Fields.Count - 1
            
            If r1!生徒名 = r2!生徒名 And k_name(j) = r1!科目名 Then
                 
                       'r2.Fields(j) = r1!点数
                       r2("kn" & j) = r1!点数
                       h_avg = h_avg + Nz(r1!点数)
                       k = k + 1
                       If h_avg <> 0 Then r2!平均点 = Round((h_avg / k), 2)
                       r2.Update
            Else

            End If

            j = j + 1
   
        Loop

     r1.MoveNext
     Loop


r2.MoveNext
Loop

'-------開いたものは閉じる------
r1.Close
Set r1 = Nothing
r2.Close
Set r2 = Nothing
r3.Close
Set r3 = Nothing
r4.Close
Set r4 = Nothing
cnn.Close
Set cnn = Nothing

End Sub

 

平均点は単純に科目数で割り算しているだけである。

]]>
http://www.now.mfnet.ne.jp/~ozachin/wordpress/?feed=rss2&p=225 0
成績処理4 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=214 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=214#respond Sat, 04 Jan 2020 06:39:11 +0000 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=214 read more]]> 説明が前後してしまったが、今回はADOによるデータ操作を行っている。コードエディタのツールから参照設定を適宜行ってください。
さて、前回の処理で成績一覧のもとになるテーブル(T_ichiran)が作成できた。
次は、このテーブルに各生徒名と各科目の点数をセットする処理である。

最初に生徒名をセットする処理から見ていく。
2つのテーブル(Recordsetをr2とr4とする)を操作するので
r2.Open “T_ichiran”, cn, adOpenKeyset, adLockOptimistic
r4.Open “T_seito”, cn, adOpenStatic,adLockReadOnly(読込専用)
としてOpenし、
r4の生徒名をr2の生徒名フィールドに新規追加していけばよい。

Private Sub cmd2_Click()

Dim cn As ADODB.Connection

'---- 最終的に4つのテーブルを使用します ----
Dim r1 As ADODB.Recordset
Dim r2 As ADODB.Recordset
Dim r3 As ADODB.Recordset
Dim r4 As ADODB.Recordset
'-----------------------------------
Set cn = CurrentProject.Connection

Set r2 = New ADODB.Recordset
Set r4 = New ADODB.Recordset


'T_seitoテーブルから生徒名を取り出し、T_ichiranテーブルにデータを追加する処理

r2.Open "T_ichiran", cn, adOpenKeyset, adLockOptimistic     '新規に作成したテーブル
r4.Open "T_seito", cn, adOpenStatic,adLockReadOnly          '生徒名を参照するテーブル

      Do Until r4.EOF
            r2.AddNew
            r2!生徒名 = r4!生徒名
            r2.Update
            r4.MoveNext
      Loop

'-------レコードセットを閉じる------------------------------------

r2.Close
Set r2 = Nothing
r4.Close
Set r4 = Nothing
cn.Close
Set cn = Nothing

End Sub

この処理によって生徒名がセットされる。
次は、成績テーブルの点数をセットすればよいのだが、もうお分かりであろう。各生徒の科目と点数を参照すればよい。
今回は生徒名だけ参照すればよかったのでループは1回で済んだ。そのことが理解できていれば次の段階も簡単だ。

各回で単独の処理として掲載したので(今回も新たにコマンドボタンを1つ作成したものとしている。)、前回と重複している定義があるが、実際には前回の処理の後に、必要な部分だけ付け加えればよい。最終的に一括したコードを掲載する。
この処理により、以下のようにT_ichiranテーブルに生徒名がセットされる。

T_ichiranテーブルに生徒名がセットされた。

]]>
http://www.now.mfnet.ne.jp/~ozachin/wordpress/?feed=rss2&p=214 0
成績処理3 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=206 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=206#respond Sat, 04 Jan 2020 04:17:05 +0000 http://www.now.mfnet.ne.jp/~ozachin/wordpress/?p=206 read more]]> 今回の連載はVBAの基本を確認することにある。
前回、クロス集計クエリを作成すれば成績処理としては目的を達成できるという話をした。しかし、それでは実際の現場での運用はできないのである。なぜなら、最終的にレポート機能で成績一覧表を印刷することになるが、一覧表の見出しになる科目名と科目数は1種類ではないからだ。

小生が関係した高校では、多い時で3学年で一覧表のパターン(科目名の並び)は10種類以上にもなる。年度によってもまた変化する。そのようなパターンすべてに対応するレポートのテンプレートを作成しなければならない。

クロス集計クエリを元にしたレポートでは、科目名見出しや成績のデータソースが固定してしまう。1種類のレポート形式で済むならよいが、おそらくそういうケースはまれであろう。高校で単一課程で全員が同じ科目を履修したとしても、3学年なので最低でも3種類は必要である。教育課程の改訂があればその都度変化する可能性もある。

とりあえず単純化した例で説明を進めるが、実際の運用場面で役に立つ説明も最後に付け加えるつもりだ。まずは基本のVBAをしっかりおさえていこう。

フォームを作成し、コマンドボタンを1つ配置し、クリックイベントに次のコードを記述すると、T_ichiranテーブルが作成される。

Private Sub cmd1_Click()
 
Dim cn As ADODB.Connection
 
'---- この連載では最終的に4つのテーブルを使用します ----
Dim r1 As ADODB.Recordset
Dim r2 As ADODB.Recordset
Dim r3 As ADODB.Recordset  '今回はこれだけ
Dim r4 As ADODB.Recordset
'-----------------------------------
 
Dim i, j, k              'カウンター
Dim kname(30)            '科目名を入れる配列
 
 
Dim st_SQL As String     'sql用文字列
Dim all_k As String      '科目名をフィールド名にするための文字列、sql文で使用
Dim all_k_i As String    'フィールド名にするための文字列、sql文で使用
Dim all_k_h As String    'フィールド名にするための文字列、sql文で使用
 
Dim k_name(30) As String
 
Dim k_n As Integer                 '科目数を入れる変数
k_n = DCount("*", "T_kamoku")      '科目数を取得
 
all_k_i = "生徒名 varchar,"        '生徒名フィールド定義゛
all_k_h = "平均点 Double"          '平均点フィールド定義
 
Set cn = CurrentProject.Connection
 
Set r3 = New ADODB.Recordset
 
'--- 科目名を取り出し、フィールド定義用文字列を作成する処理 ---
'--- 科目名テーブルを開く
r3.Open "T_kamoku", cn, adOpenForwardOnly, adLockReadOnly  
 
i = 1
Do Until r3.EOF
    k_name(i) = r3!科目名
    all_k = all_k & k_name(i) & " Double,"
    r3.MoveNext
    i = i + 1
Loop
' ----------------------------------------------------------
 
'最終的にフィールド名とするための処理 
'先頭に生徒名、最後に平均点を付加
 
all_k = all_k_i & all_k & all_k_h
 
'処理前にテーブルを削除
On Error Resume Next
 
DoCmd.DeleteObject acTable, "T_ichiran"
 
On Error GoTo 0
 
'テーブル作成のSQL文およびSQL実行
st_SQL = "CREATE TABLE T_ichiran(" & all_k & ");"
DoCmd.RunSQL st_SQL
 
'-------レコードセットを閉じる--------------------------------
r3.Close
Set r3 = Nothing
cn.Close
Set cn = Nothing
End Sub

 

この処理で、一覧表の見出しとなる
生徒名 国語 算数 理科 社会 英語 平均点
というフィールド並びのテーブルが作成される。
実際の学校現場では、科目にはコードが振られているので、コード順に並べるなどの処理が必要となる。

尚、このテーブルは一時(作業用)テーブルでなので、作成前に既存を削除処理を行う。なぜ一時テーブルなのかと言えば、点数入力等に誤りがあった場合、最新のデータを呼び出す必要があったり、複数のクラス等があった場合にはパラメータを切り替え連続処理をするためにその都度テーブルを新規に作成する必要があるからだ。

]]>
http://www.now.mfnet.ne.jp/~ozachin/wordpress/?feed=rss2&p=206 0