<小計・合計の表示、大昔の方法(笑)>
こんにちは、三流プログラマーのKen3です。 今回は、 小計・合計の表示 を行ってみたいと思います。/* * 1.今回のキッカケ */
掲示板 に 下記の書き込みをもらいました。 ※改行位置勝手に変更しました。 ---- 教えていただきたいことは小計の取り方です。 グループごとに縦横に小計を取って最後の行に総計を表示するようにしたいのです。 イメージとしては以下のようにしようとしています。 (うまく表示されているでしょうか?) サーバはSQLサーバで、ADOを使用しています。 使用するテーブルは2つあり、 T_商品(商品CD、商品名)とT_月別売上(商品CD、1月〜12月)です。 この2つを商品CDをキーに外部結合で結び、 T_商品にあるものを全ての月別売上を表示するようにしています。 テーブルの内容は表示できるのですが、 グループごとに小計を取って表示することができず悩んでいます。 ---------------------------------------------------------------- | 商品名 | 4月 | 5月 | 6月 | 7月 | 8月 | 9月 | 上期計 | ---------------------------------------------------------------- | A1 | 1 | 2 | 3 | 4 | 5 | 6 | 21 | ---------------------------------------------------------------- | A2 | 2 | 0 | 4 | 5 | 6 | 7 | 24 | ---------------------------------------------------------------- | A3 | 3 | 1 | 5 | 6 | 7 | 8 | 30 | ---------------------------------------------------------------- | 小計 | 6 | 3 | 12 | 15 | 18 | 21 | 75 | ---------------------------------------------------------------- | B1 | 4 | 2 | 6 | 7 | 8 | 9 | 36 | ---------------------------------------------------------------- | B2 | 5 | 3 | 7 | 8 | 9 | 10 | 42 | ---------------------------------------------------------------- | B3 | 6 | 4 | 8 | 9 | 10 | 11 | 48 | ---------------------------------------------------------------- | 小計 | 15 | 9 | 21 | 24 | 27 | 30 | 126 | ---------------------------------------------------------------- | 総計 | 42 | 24 | 66 | 78 | 90 | 102 | 402 | ---------------------------------------------------------------- 以上、内容が足りない等ありましたらご指摘ください。 よろしくお願いします。 ---- 2つのテーブルをつなげて、小計を取りたい、 そんな感じの処理ですね。/* * 2.大昔の方法でやってみます */
さてと、いろいろと方法があるのですが、 大昔の何もRDBの知識の無い、力技の人を今日は、演じてみます。 T_月別売上テーブル 商品CD 売上4 売上5 ・ ・ 売上12 売上1 売上2 売上3 とテーブル、フィールドを作成しました。 ※年度が無いとか、気になる部分はありますが、 たぶん、年度更新処理でうまくやっていると考えて、気にしない気にしない。 ↑作成したテーブルイメージ まずは、全てのデータを表示してみます。 えっと、DBにつなげてから、Select文を書くんだっけ。 http://www.ken3.org/cgi-bin/test/test072-1.asp で、テスト可能です。 <%@LANGUAGE=VBScript%> <html> <head> <title>テストでテーブル内の全データを表示してみる</title> </head> <body> <h2>テストでテーブル内の全データを表示してみる</h2> Set rs = db.Execute("Select * From T_月別売上")<br> と、全ての項目を呼び出してみる。<br> <hr> <% 'ADO DB Connection オブジェクトを作成する、英文そのままじゃん Set db=Server.CreateObject("ADODB.Connection") '.Provider?プロバイダー?通信会社?じゃなくって 'データアクセスにはJet.OLEDB.4.0を使うことを設定 db.Provider = "Microsoft.Jet.OLEDB.4.0" '次に、接続DBの位置を渡すので、Server.MapPathで変換して渡す db.ConnectionString = Server.MapPath("db072.mdb") 'やっとデータベースを開ける db.open 'お約束のレコードセットの作成 T_月別売上から全項目(*)を指定 Set rs = db.Execute("Select * From T_月別売上") 'データの表示をテーブルで行う Response.Write "<TABLE Border='1'>" '見出しを(フィールド名を)そのまま書き込む Response.Write "<TR>" For Each fld_A In Rs.Fields 'フィールドのアイテムに対してループ Response.Write "<TH>" & fld_A.Name & "</TH>" '↑.Nameでフィールド名を表示する Next Response.Write "</TR>" 'お約束のEOFまでループは(データが無くなるまでループ)、 Do While rs.EOF = False 'レコードセットの.EOFがFalseの間 Response.Write "<TR>" '内容を表示する For Each fld_A In Rs.Fields 'フィールドのアイテムに対してループ Response.Write "<TD>" & fld_A.Value & "</TD>" '↑.Valueでフィールドの値を表示する Next Response.Write "</TR>" '次のレコードにポインタを移動する rs.MoveNext 'これを忘れると悲惨なことに、、、 Loop Response.Write "</TABLE>" 'テーブルは終わりです '開いていたレコードセットを閉じる rs.Close 'データベースも閉じようよ db.Close 'お行儀よくオブジェクトも開放しましょう(通常は自動的に解放されるけど) Set db = Nothing %> <hr> 終了です。<br> </body> </html> 普通にテーブル内容を表示してみました。 For Each fld_A In Rs.Fields 'フィールドのアイテムに対してループ Response.Write "<TD>" & fld_A.Value & "</TD>" '↑.Valueでフィールドの値を表示する Next こんな感じのループで、フィールドにアクセスする、 そんなこともできる程度に覚えて置いてください。/* * 3.自分で上期計を計算する(笑) */
データを呼び出せたみたいなので、 さてと、次は、 | 商品名 | 4月 | 5月 | 6月 | 7月 | 8月 | 9月 | 上期計 | と、上期の合計を計算してみます。 http://www.ken3.org/cgi-bin/test/test072-2.asp で、テスト可能です。 追加したポイントは、 g_kamiki = 0 '集計用の変数を初期化する と変数を1つ作成して、初期化します。 4月〜9月のループを作ります。 For n = 4 To 9 'フィールドにフィールド名でアクセスする Response.Write "<TD>" & rs("売上" & n).Value & "</TD>" '↑"売上" & nでフィールド名売上4..売上9を作成してアクセス '自分で集計する g_kamiki = g_kamiki + rs("売上" & n).Value Next rs("売上" & n).Value と、フィールドに対して、文字列のフィールド名で参照してます。 <%@LANGUAGE=VBScript%> <html> <head> <title>上期(4〜9月)の合計を計算・表示してみる</title> </head> <body> <h2>上期(4〜9月)の合計を計算・表示してみる</h2> rs("売上" & n).Value<br> "売上" & nでフィールド名売上4..売上9を作成してアクセス<br> 自分で集計してみました。<br> g_kamiki = g_kamiki + rs("売上" & n).Value<br> <hr> <% 'ADO DB Connection オブジェクトを作成する、英文そのままじゃん Set db=Server.CreateObject("ADODB.Connection") '.Provider?プロバイダー?通信会社?じゃなくって 'データアクセスにはJet.OLEDB.4.0を使うことを設定 db.Provider = "Microsoft.Jet.OLEDB.4.0" '次に、接続DBの位置を渡すので、Server.MapPathで変換して渡す db.ConnectionString = Server.MapPath("db072.mdb") 'やっとデータベースを開ける db.open 'お約束のレコードセットの作成 T_月別売上から全項目(*)を指定 Set rs = db.Execute("Select * From T_月別売上") 'データの表示をテーブルで行う Response.Write "<TABLE Border='1'>" '見出しを表示する Response.Write "<TR>" Response.Write "<TH>商品名</TH>" For n = 4 To 9 '4月から9月と見出しを表示したいので Response.Write "<TH>" & n & "月</TH>" Next Response.Write "<TH>上期計</TH>" Response.Write "</TR>" 'お約束のEOFまでループは(データが無くなるまでループ)、 Do While rs.EOF = False 'レコードセットの.EOFがFalseの間 Response.Write "<TR>" '行を表示する Response.Write "<TD>" & rs("商品CD").Value & "</TD>" 'とりあえずコード g_kamiki = 0 '集計用の変数を初期化する For n = 4 To 9 'フィールドにフィールド名でアクセスする Response.Write "<TD>" & rs("売上" & n).Value & "</TD>" '↑"売上" & nでフィールド名売上4..売上9を作成してアクセス '自分で集計する g_kamiki = g_kamiki + rs("売上" & n).Value Next '上期の合計を表示する Response.Write "<TD>" & g_kamiki & "</TD>" Response.Write "</TR>" '次のレコードにポインタを移動する rs.MoveNext 'これを忘れると悲惨なことに、、、 Loop Response.Write "</TABLE>" 'テーブルは終わりです '開いていたレコードセットを閉じる rs.Close 'データベースも閉じようよ db.Close 'お行儀よくオブジェクトも開放しましょう(通常は自動的に解放されるけど) Set db = Nothing %> <hr> 終了です。<br> </body> </html>/* * 4.グループの小計を自分で行う */
上期の横計を自分で計算できたので、 今度はグループの頭が変更になった時の、縦計(小計、総合計)を計算してみます。 基本構想は、 集計用の配列を取り、1つ1つ集計する、 グループのコード、頭の1桁が変わったら、 とループを作成してみる。 '月別の小計・総合計を保存する配列を作成する Dim sum_group(12) 'グループ合計 Dim sum_all(12) '総合計 Dim sum_code 'グループ化のコード '総合計エリア、グループ合計を初期化する For n = 1 To 12 sum_group(n) = 0 sum_all(n) = 0 Next 'グループ化のコードを初期化する sum_code = Left(rs("商品CD").Value , 1) '先頭レコードの商品コード1桁目 'お約束のEOFまでループは(データが無くなるまでループ)、 Do While rs.EOF = False 'レコードセットの.EOFがFalseの間 Response.Write "<TR>" '行を表示する Response.Write "<TD>" & rs("商品CD").Value & "</TD>" 'とりあえずコード g_kamiki = 0 '集計用の変数を初期化する For n = 4 To 9 'フィールドにフィールド名でアクセスする Response.Write "<TD>" & rs("売上" & n).Value & "</TD>" '↑"売上" & nでフィールド名売上4..売上9を作成してアクセス '自分で上期を集計する g_kamiki = g_kamiki + rs("売上" & n).Value '月別、グループ、総合計を計算する sum_group(n) = sum_group(n) + rs("売上" & n).Value 'グループ sum_all(n) = sum_all(n) + rs("売上" & n).Value '総合計 Next '上期の合計を表示する Response.Write "<TD>" & g_kamiki & "</TD>" Response.Write "</TR>" '次のレコードにポインタを移動する rs.MoveNext 'これを忘れると悲惨なことに、、、 'グループコードが変わったかチェックする If sum_code <> Left(rs("商品CD").Value , 1) Then '小計を表示する Response.Write "<TR bgcolor=#FFE0FF>" '行を表示する Response.Write "<TD>小計</TD>" g_kamiki = 0 '小計の上期集計用の変数を初期化する For n = 4 To 9 '4〜9月 Response.Write "<TD>" & sum_group(n) & "</TD>" 'n月の値を表示 g_kamiki = g_kamiki + sum_group(n) '小計の上期のタメに計算 Next Response.Write "<TD>" & g_kamiki & "</TD>" '小計の上期計を表示 Response.Write "</TR>" '行の終わり '次のグループになるので、配列とCODEを初期化する sum_code = Left(rs("商品CD").Value , 1) '次のコードを代入 For n = 4 To 9 '小計値を初期化する sum_group(n) = 0 Next End If Loop ポイントは ^^^^^^^^^^ sum_code = Left(rs("商品CD").Value , 1) '先頭レコードの商品コード1桁目 と頭で、商品コードを代入しておきます。 A1ならAが入ります。 集計は普通に、明細の4月〜9月の表示の中で、 For n = 4 To 9 'フィールドにフィールド名でアクセスする Response.Write "<TD>" & rs("売上" & n).Value & "</TD>" ・ ・ '月別、グループ、総合計を計算する sum_group(n) = sum_group(n) + rs("売上" & n).Value 'グループ sum_all(n) = sum_all(n) + rs("売上" & n).Value '総合計 と、 n月分は、n月の配列に+してます。 あとは、グループのコードが変わったら、 小計を出力して、次のグループのタメにデータをクリア ^^^^^^^^^^^^^^ 'グループコードが変わったかチェックする If sum_code <> Left(rs("商品CD").Value , 1) Then '小計を表示する ・ ・ '次のグループになるので、配列とCODEを初期化する sum_code = Left(rs("商品CD").Value , 1) '次のコードを代入 For n = 4 To 9 '小計値を初期化する sum_group(n) = 0 Next End If の繰り返しを行います。 まぁ、楽勝かなぁと思ったら、 72: rs.MoveNext 'これを忘れると悲惨なことに、、、 73: 'グループコードが変わったかチェックする 74: If sum_code <> Left(rs("商品CD").Value , 1) Then ADODB.Field エラー '800a0bcd' BOF と EOF のいずれかが True になっているか、または現在のレコードが削除されています。 要求された操作には、現在のレコードが必要です。 /cgi-bin/test/test072-3.asp, 行 74 あらら、なんだぁ?74行目? そっか、rs.MoveNext で、EOFまで行っているからか・・・ 条件を rs.EOF = True Or sum_code <> Left(rs("商品CD").Value , 1) と、先にEOFか?きいてみます。 あれ、だめかぁ・・・ 流れを変えるか、、、 If rs.EOF = True Or sum_code <> Left(rs("商品CD").Value , 1) でチェックできないので、 商品コードのチェック処理をループの頭に回し、 Eof後(レコードが終了後) 最後の項目の小計を出力する流れに変えました。 http://www.ken3.org/cgi-bin/test/test072-3.asp で、テスト可能です。 <%@LANGUAGE=VBScript%> <html> <head> <title>小計(グループ)を計算・表示してみる</title> </head> <body> <h2>小計(グループ)を計算・表示してみる</h2> <hr> <% 'ADO DB Connection オブジェクトを作成する、英文そのままじゃん Set db=Server.CreateObject("ADODB.Connection") '.Provider?プロバイダー?通信会社?じゃなくって 'データアクセスにはJet.OLEDB.4.0を使うことを設定 db.Provider = "Microsoft.Jet.OLEDB.4.0" '次に、接続DBの位置を渡すので、Server.MapPathで変換して渡す db.ConnectionString = Server.MapPath("db072.mdb") 'やっとデータベースを開ける db.open 'お約束のレコードセットの作成 'T_月別売上から全項目(*)を指定、Order Byで商品コード順にする Set rs = db.Execute("Select * From T_月別売上 Order By 商品CD") 'データの表示をテーブルで行う Response.Write "<TABLE Border='1'>" '見出しを表示する Response.Write "<TR bgcolor=#E0FFFF>" Response.Write "<TH>商品名</TH>" For n = 4 To 9 '4月から9月と見出しを表示したいので Response.Write "<TH>" & n & "月</TH>" Next Response.Write "<TH>上期計</TH>" Response.Write "</TR>" '月別の小計・総合計を保存する配列を作成する Dim sum_group(12) 'グループ合計 Dim sum_all(12) '総合計 Dim sum_code 'グループ化のコード '総合計エリア、グループ合計を初期化する For n = 1 To 12 sum_group(n) = 0 sum_all(n) = 0 Next 'グループ化のコードを初期化する sum_code = Left(rs("商品CD").Value , 1) '先頭レコードの商品コード1桁目 'お約束のEOFまでループは(データが無くなるまでループ)、 Do While rs.EOF = False 'レコードセットの.EOFがFalseの間 'グループコードが変わったかチェックする If sum_code <> Left(rs("商品CD").Value , 1) Then '小計を表示する Response.Write "<TR bgcolor=#FFE0FF>" '行を表示する Response.Write "<TD>小計</TD>" g_kamiki = 0 '小計の上期集計用の変数を初期化する For n = 4 To 9 '4〜9月 Response.Write "<TD>" & sum_group(n) & "</TD>" 'n月の値を表示 g_kamiki = g_kamiki + sum_group(n) '小計の上期のタメに計算 Next Response.Write "<TD>" & g_kamiki & "</TD>" '小計の上期計を表示 Response.Write "</TR>" '行の終わり '次のグループになるので、配列とCODEを初期化する sum_code = Left(rs("商品CD").Value , 1) '次のコードを代入 For n = 4 To 9 '小計値を初期化する sum_group(n) = 0 Next End If Response.Write "<TR>" '行を表示する Response.Write "<TD>" & rs("商品CD").Value & "</TD>" 'とりあえずコード g_kamiki = 0 '集計用の変数を初期化する For n = 4 To 9 'フィールドにフィールド名でアクセスする Response.Write "<TD>" & rs("売上" & n).Value & "</TD>" '↑"売上" & nでフィールド名売上4..売上9を作成してアクセス '自分で上期を集計する g_kamiki = g_kamiki + rs("売上" & n).Value '月別、グループ、総合計を計算する sum_group(n) = sum_group(n) + rs("売上" & n).Value 'グループ sum_all(n) = sum_all(n) + rs("売上" & n).Value '総合計 Next '上期の合計を表示する Response.Write "<TD>" & g_kamiki & "</TD>" Response.Write "</TR>" '次のレコードにポインタを移動する rs.MoveNext 'これを忘れると悲惨なことに、、、 Loop 'ループを抜けたら、最後の小計を表示する '小計を表示する Response.Write "<TR bgcolor=#FFE0FF>" '行を表示する Response.Write "<TD>小計</TD>" g_kamiki = 0 '小計の上期集計用の変数を初期化する For n = 4 To 9 '4〜9月 Response.Write "<TD>" & sum_group(n) & "</TD>" 'n月の値を表示 g_kamiki = g_kamiki + sum_group(n) '小計の上期のタメに計算 Next Response.Write "<TD>" & g_kamiki & "</TD>" '小計の上期計を表示 Response.Write "</TR>" '行の終わり '総合計の表示(計算した総合計を表示する) Response.Write "<TR bgcolor=#FFFFE0>" '行を表示する Response.Write "<TD>総合計</TD>" g_kamiki = 0 '総合計の上期集計用の変数を初期化する For n = 4 To 9 '4〜9月の値を表示する Response.Write "<TD>" & sum_all(n) & "</TD>" 'n月の値を表示 g_kamiki = g_kamiki + sum_all(n) '総合計の上期のタメに計算 Next Response.Write "<TD>" & g_kamiki & "</TD>" '小計の上期計を表示 Response.Write "</TR>" '行の終わり Response.Write "</TABLE>" 'テーブルは終わりです '開いていたレコードセットを閉じる rs.Close 'データベースも閉じようよ db.Close 'お行儀よくオブジェクトも開放しましょう(通常は自動的に解放されるけど) Set db = Nothing %> <hr> 終了です。<br> </body> </html>/* * 5.商品名を1つ1つ自分で取ってくる・・・ */
さて、なんとか、小計、総合計まで、表示しました。 A1,A2,B1,B2とコードから商品名を取得してみたいと思います。 ※普通はテーブルをつなげるんだけど、 今回は、RDBの特徴を知らない設定でやってみます。 T_商品 テーブル 商品CD 商品名 のフィールドを作成します。 商品CD 商品名 A1 コーラ A2 オレンジ A3 りんご B1 スーパードライ B2 モルツ B3 黒ラベル ↑作成したテーブルイメージ 商品コードを受け取って、商品名を返すFunction関数を作成してみます。
Function get_sname(strCODE) strSQL = "Select 商品名 From T_商品 Where 商品CD='" & strCODE & "'" Set rs_master = db.Execute(strSQL) 'SQL文の発行 If rs_master.EOF = True Then 'データ無し? get_sname = strCODE & "はエラーです" Else get_sname = rs_master("商品名").Value End If rs_Master.Close 'クローズ Set rs_master = Nothing 'と開放で後始末・・・ End Function |
Function get_sname(strCODE) strSQL = "Select 商品名 From T_商品 Where 商品CD='" & strCODE & "'" Set rs_master = db.Execute(strSQL) 'SQL文の発行 If rs_master.EOF = True Then 'データ無し? get_sname = strCODE & "はエラーです" Else get_sname = rs_master("商品名").Value End If rs_Master.Close 'クローズ Set rs_master = Nothing 'と開放で後始末・・・ End Function |
ここまで、読んでいただきどうもです。目的の情報が見つかったか?少々心配しつつ、、、
感想や質問・要望・苦情など 三流君へメッセージを送る。
下記のフォームからメッセージを送ることができます。
[三流君(TOP ken3.org へ戻る)]
/ [ASPで遊ぶ、失敗する]
/ [ASP記事 バックナンバー目次]
まぁ、基本はデータの受け取りかなぁ。
・[Form等を使用したデータのやり取り]・・・ASPと言っても、HTMLの入力フォームからデータを受け取ります。POSTやGETでやりとりを押さえますか。
次は、データの入出力 で ADOを使った(ADOで接続) と SQLの解説を少々
・[ADOでMdbファイルを使う]・・・MDBと接続して、簡単な追加・更新・削除を行った。
・[ADOでExcelと接続してみた]・・・.xlsと接続してSQLを使ってみた。
・[ADOでCSVと接続してみた]・・・.CSV テキストを読み出した。※更新・削除はできません
広告:
DBが使えるので、あまり使用しないけど、普通のテキストファイル処理
・[テキストファイル処理]・・・ファイルを開いて、書き込む。1行読み込みなどを軽く
VBScriptでFormat関数が無いなど、微妙にVBAと違うけど
[VBScript関数関係の説明]・・・少し、処理を書いてみた。
[その他処理サンプル]・・・あまり良いサンプル作れなかったけど。。。
何かの参考となれば幸いです。
[三流君(TOP ken3.org へ戻る)]
/ [ASPで遊ぶ、失敗する]
/ [ASP記事 バックナンバー目次]