Microsoft Access 掲示板

レポートグループ値の総合計をレポートヘッダーに表示させたい

25 コメント
views
4 フォロー

ACCESSビギナーのものです。訳あって未だACCESS2003を使っています。
月末締めの請求書をレポートで作成しようと思ってます。納品日付毎にグループフッダーに合計金額を表示しそれに対して税率をかけたものを表示させています(税込み合計)。そのグループ毎での税込み合計の総合計値(月締め請求金額)をレポートヘッダーに表示させたいのですが、上手くいきません。月締め請求金額のテキストボックスのプロパティを 集計実行=グループ全体 にしてソースを "税込み合計" にすると最初のグループ値しか表示されず、"Sum([税込み合計])"するとパラメータの入力 ?・・・となります。
因みに日付グループに対して税率を計算しているのは納品書と合わせる為です。月ごとの合計に一括で税率計算をすると四捨五入の関係で誤差が出る場合がある為です。
何かいい案があれば教えて頂く投稿しました。宜しくお願いします。

ジュン
作成: 2023/06/05 (月) 09:34:17
通報 ...
1

日別の税込み金額の合計を、レポートフッターに表示したいのなら、下記の設定で可能だと思います。

まず、納品日付毎のグループフッターに下記のテキストボックスを配置。

名前 日別合計
コントロールソース =Sum([金額])
集計実行 しない
名前 税込み日別合計
コントロールソース =[日別合計]*1.1
集計実行 しない

名前 税込み日別合計累計
コントロールソース =[税込み日別合計]
集計実行 全体

レポートフッターに下記のテキストボックスを配置

名前 月締め請求金額
コントロールソース =[税込み日別合計累計]
集計実行 しない

レポートヘッダーにこれを表示したいとなると、集計実行では無理ですので、クエリで「税込み日別合計」を計算してそれをレポートのレコードソースに追加することになります

レコードソースのテーブルからクエリを作成して、納品日でグループ化して、下記の演算フィールドを追加します。
税込み日別合計: Sum([金額])*1.1

このクエリをレポートのレコードソースに追加して納品日で結合します。
納品日フッターに「税込み日別合計」を配置します。
さらにレポートフッターにテキストボックスを配置してコントロールソースに下記の式を設定すれば請求金額を表示できます。
=Sum([税込み日別合計])

2
ジュン 2023/06/05 (月) 14:23:03 ddfe5@d8b89

hatena様へ早速ありがとうございます。
(私の知識不足が原因につき)途中からが分からないので教えて頂きたいのです。グループの税込み日別合計累計のテキストボックス配置し、税込み日別合計のクエリまでは出来ました。その後のレコードソースに日付で結合すると”指定されたフィールド <フィールド名> が SQL ステートメントの FROM 句にある複数のテーブルを参照しました” のエラーが出ます。この対処はどうするといいでしょうか? また最終的に金額累計のテキストボックスは参照される事はないのでしょうか?
すみません、宜しくお願いします。

3

クエリの設計が間違っているのだと思われますので、
現状の、税込み日別合計を表示するクエリのSQLビューのSQL文と、レポートのレコードソースのSQL文をここに貼り付けてください。

このクエリを使う場合は、金額累計のテキストボックスは不要です。

前回の回答の前半は、レポートフッターに表示する場合の回答です。こちらは、集計実行で累計テキストボックスを配置してそれを使います。

後半は、レポートヘッダーに配置する場合です。こちらは集計実行ではできないので、クエリをつかって日別合計を計算します。累計テキストボックスは不要です。

「レポートヘッダーにこれを表示したいとなると、」以降が後半です。

4
ジュン 2023/06/05 (月) 16:43:06 ddfe5@d8b89

hatena様へありがとうございます。
●税込み日別合計を表示するクエリが
SELECT Q納品書レポート用空行あり.顧客ID, Q納品書レポート用空行あり.顧客社名, Q納品書レポート用空行あり.売上日付, Q納品書レポート用空行あり.税率, Sum([小計]*([税率]/100+1)) AS 売上日毎の合計金額
FROM Q納品書レポート用空行あり
GROUP BY Q納品書レポート用空行あり.顧客ID, Q納品書レポート用空行あり.顧客社名, Q納品書レポート用空行あり.売上日付, Q納品書レポート用空行あり.税率;

●レポートのレコードソースが
SELECT Q出荷案内票Sub.出荷ID, Q出荷案内書Main.納品書番号, Q出荷案内書Main.税率, Q出荷案内書Main.出荷日付, Q出荷案内書Main.売上日付, Q出荷案内票Sub.顧客社名, Q出荷案内票Sub.[型番+新型番], Q出荷案内票Sub.出荷数量, Q出荷案内票Sub.単価, Q出荷案内票Sub.小計, Q出荷案内票Sub.注文番号, Q出荷案内票Sub.ロットNo., Q出荷案内票Sub.仕様・その他, Q出荷案内書Main.特記事項, Q出荷案内票Sub.レポート用型番, IIf(IsNull([レポート用型番]),[型番+新型番],[レポート用型番]) AS IF条件付き製品型番, Q出荷案内票Sub.出荷案内票の順番, Q出荷案内書Main.HP用支払い条件, Year([売上日付]) AS 売上年, Month([売上日付]) AS 売上月, Q出荷案内票Sub.顧客ID, Format([売上日付],"yyyy/mm") AS 売上年月
FROM Q出荷案内書Main INNER JOIN Q出荷案内票Sub ON Q出荷案内書Main.出荷ID = Q出荷案内票Sub.出荷ID
ORDER BY Q出荷案内票Sub.レポート用型番;

です(余分項目沢山ありすみません)。これの売上日付をリレーションさせるとエラーがでます。

あと私が全然分かっていないのですがレポートのヘッダーとフッターでは出来る事が違うのでしょうか? 単純に上にあるか下にあるかの違いの認識しかありませんでした。(恥ずかしながら・・・)。確かにレポートフッターにはテキスト配置するだけで最終累計が表示されました。
宜しくお願いします。

宜しくお願いします。

5

集計実行に関しては、レポートヘッダーとフッターでは結果が異なりますね。
レポートの先頭レコードから順に出力(Formatイベント)していって、最終的に全体が出力されることになります。
集計実行は出力されるたびに実行されて加算されていきます。
レポートヘッダーでは先頭レコード分しか集計実行されていないことになります。


最初のクエリに関してですが、
まずは「税込み日別合計を表示するクエリ」を開いた場合、正しい日別合計になってますか。

Sum([小計]*([税率]/100+1)) AS 売上日毎の合計金額

となってますが、これだと日毎の合計で税率をけ計算するのではなくレコード毎に税額を計算していることになります。
税率をかけるのはSum()の外に出す必要があります。

Sum([小計])*([税率]/100+1) AS 売上日毎の合計金額

レコード毎に税率をかけてそれを集計するか、
日毎の合計に税率をかけるか、
の違いです。

ご希望のは後者だと理解してますが、どうでしょうか。


次に結合するとエラーになる件ですが、
2つのクエリを結合すると両方のクエリに「売上日付」があることになりますので、
「売上日付」がどちらのクエリのものか分からないので、そのようなエラーになります。

「税込み日別合計を表示するクエリ」の方で、Q納品書レポート用空行あり.売上日付 As 売上日付集計用
というように別名を付ければ 区別がつくようになりますので、エラーがでなくなると思います。

6
hiroton 2023/06/06 (火) 09:00:23 74852@f966d

別建ててクエリを作成するならそのままそれぞれレポートにしてレポート印刷2回掛けるとか、サブレポートにして埋め込むとかすればいいんじゃないですかね
わざわざ結合する必要はないような

印刷データの抽出の仕方によってはDSum()とかでも行けるんじゃないですかね

7
ジュン 2023/06/06 (火) 09:53:43 ddfe5@d8b89

hatena様・hiroton様 ありがとうございました。
hatena様の通りにしてリレーションさせると今度は Q納品書レポート用空行あり循環参照が発生しています。(Error 3102) となりました。この原因は?

8
ジュン 2023/06/06 (火) 09:55:23 ddfe5@d8b89

さきほど途中で間違えて送信してしまい、すみません。
何が間違っているのでしょうか?
hiroton様の案も確かにそうですねDSum()の手がありますね。それも試してみます。

9

DSumを埋め込む方法でももちろん可能です。速度的に重くなる可能性があるので私の場合は仕様には慎重派です。
サブレポートを埋め込むのも同様に重くなる可能性があるので同様です。
まあ、このへんは自分が理解しやすい、使いやすいものを選択すればいいでしょう。

クエリの結合はAccessの基本なので、これを使えるようになるといろいろな場面で応用がききます。ですので、私が回答するときはまずはこれを提案します。

hatena様の通りにしてリレーションさせると今度は Q納品書レポート用空行あり循環参照が発生しています。(Error 3102) となりました。この原因は?

「Q納品書レポート用空行あり」というのは、ひょっとして現状のレポートのレコードソースのクエリですか。
「税込み日別合計を表示するクエリ」に「Q納品書レポート用空行あり」が含まれていますので、これを、
レポートのレコードソースのクエリ(Q納品書レポート用空行あり)に含めたら循環参照になります。

「税込み日別合計を表示するクエリ」は他のクエリから作成するのではなくテーブルから作成した方がトラブルは少ないです。

DSumを使うにしても、クエリで結合させるにしても、各テーブルのリレーション関係をしっかり理解できていないと、正しいものを作成するのは難しいです。

「リレーションシップ」は設定していますか。設定しているなら、その設定画面のスクリーンショットを提示してもらえるといいアドバイスができるかもしれません。
していないなら、まずはその設定から始めることをお勧めします。
下記も参考にしてください。

リレーションシップを設定した場合の利点 - hatena chips

10
hiroton 2023/06/06 (火) 12:42:55 修正 74852@f966d

よくわからんACCESSの仕様に付き合いながら速度気にするなら最初からVBAで組んじゃえばいいんじゃないかな。クエリ弄る必要ないし

Option Compare Database
Option Explicit

Dim 月合計 As Long

Private Sub グループフッター1_Format(Cancel As Integer, FormatCount As Integer)
    If Me.FormatCount = 1 Then 月合計 = 月合計 + Me!日合計 * 1.1
End Sub

Private Sub ページヘッダーセクション_Format(Cancel As Integer, FormatCount As Integer)
    Me!請求額総計 = 月合計
End Sub

※このコードを動かすにはレポートの改造も必要

サブレポートにしてもDSumにしても抽出条件どうするんだ?問題が別に発生するからそれはそれで簡単とは言えないけれど


リレーションシップやクエリの組み方云々は質問の本題から遠いのでhiroton的にはノータッチです

11
ジュン 2023/06/06 (火) 12:50:51 ddfe5@d8b89

hatena様ありがとうございました。
頂いたコメント通り別クエリを使って新たにクエリを作成して(リレーションもして)、それを請求書一覧のレコードソースにしました。そうするとエラーは出なくなりました。そして日付フッターに「税込み日別合計」を配置しレポートヘッダーにテキストボックスに作り =Sum([税込み日別合計]) としました。そうすると何故か総合計の計算が全く合いません。フッターの方は最終の合計値が表示されています。どこが間違っているのでしょうか? 度々すみません・・・新たなレコードソースのSQLは下記です。

SELECT Q納品書レポート用空行あり.売上日付, Q納品書レポート用空行あり.注文番号, Q納品書レポート用空行あり.納品書番号, Q納品書レポート用空行あり.税率, Q納品書レポート用空行あり.顧客ID, Q納品書レポート用空行あり.顧客社名, Q納品書レポート用空行あり.IF条件付き製品型番, Q納品書レポート用空行あり.出荷数量, Q納品書レポート用空行あり.単価, Q納品書レポート用空行あり.小計, [Q_ 請求書一覧用日付別合計金額].税込み日別合計, Q納品書レポート用空行あり.売上年, Q納品書レポート用空行あり.売上月, Q納品書レポート用空行あり.HP用支払い条件
FROM [Q_ 請求書一覧用日付別合計金額] INNER JOIN Q納品書レポート用空行あり ON [Q_ 請求書一覧用日付別合計金額].売上日付集計用 = Q納品書レポート用空行あり.売上日付
ORDER BY Q納品書レポート用空行あり.売上日付, Q納品書レポート用空行あり.注文番号;

12
ジュン 2023/06/06 (火) 13:31:41 ddfe5@d8b89

その後、レポートヘッダーに表示された総合計金額を調べると二重に計算されている事が分かりました。
例えば売上日が4/1に1品目、4/15に2品目の場合 総合計は日付合計の2つのSum値が正しいのですが、3つの日付合計値のSum値となっています。何か構成が間違えているのでしょうか?

*hiroton様ありがとうございました。色々と試してみますね。まずここまで来たのでクエリ方式でまず進めてみます。

13
ジュン 2023/06/06 (火) 16:39:14 ddfe5@d8b89

総合計金額が= Sum([税込み日別合計])だと重複してしまうのはレコードソースには同じ日付・同じ顧客で品目が複数の場合あるからどうしてもそうなってしまうのですね。1品目なら問題ないのですが。この解決は中々ないでしょうか?
レポートフッターには税込み金額の累計がいけてるので例えばそれを変数に入れてレポートヘッダーに表示させる事は無理でしょうか?(そんな事無理な気がしているのですが)・・・すみません知識不足で。

14

レポートヘッダーに =Sum([税込み日別合計]) とすると、全レコード分繰り返されて集計されてしまうので、ここは、DSum関数を使う必要があります。

=DSum("税込み日別合計","税込み日別合計を表示するクエリ")

hirotonさん提案のVBAで累計していく方法もレポートヘッダーに表示しようとなると、結構はまることになります。
レポートのイベントの発生メカニズムを理解しておく必要があります。

レポートのイベントの発生メカニズムの研究 - hatena chips

レポートのイベントの発生メカニズムの研究 その2 - hatena chips

方法としては、下記のような考え方になります。
=Pages と総ページ数を表示するテキストボックスを配置しておく。
すると、総ページ数を取得するために、先頭レコードから最終レコードまでFormatイベントのみが発生する。
これで総ページ数を取得できたら、改めて先頭レコードに戻って最終レコードまでFormatイベントとPrintイベントが発生して実際にレポートしてと出力します。

この最初のループの時にFormatイベントで合計を累計していきます。
2回目のループのレポートヘッダーのFormatイベントで累計した合計をテキストボックスに代入します。
1回目のループかどうかの判断は pages が0かどうかで判断できます。

Option Compare Database
Option Explicit

Dim 税込総合計 As Currency

Private Sub グループフッター1_Format(Cancel As Integer, FormatCount As Integer)
    If  Me.Pages = 0 And Me.FormatCount = 1 Then 税込総合計 = 税込総合計 + Me!日合計 * 1.1
End Sub

Private Sub レポートヘッダー_Format(Cancel As Integer, FormatCount As Integer)
    If  Me.Pages < 0 Then Me!請求額総計 = 税込総合計
End Sub

とりあえず上記のような感じですが、レポートの設定によってはいろいろ難しいことも発生しますので、実際に動作確認しながら、修正していく必要があるかもしれません。

15
hiroton 2023/06/06 (火) 18:00:11 74852@f966d

いずれにせよ、様々な条件に合わせて手を入れる必要は出るでしょう
細かいこと無視するなら

Private Sub レポートフッター_Format(Cancel As Integer, FormatCount As Integer)
    Me!月合計 = Me![日付毎数合計*1.1の集計:全体]
End Sub

画像1
画像2

こんなんでも動きますね
レポートに計算用コントロールを配置するか、VBAで変数を用意するかはまぁ好みで

[日付毎数合計*1.1]は数値確認用です(いらない)
※([日付毎数合計*1.1]とか[日付毎数合計*1.1の集計:全体]とか、実際にはこんな名前つけてはいけませんよ)


レポートヘッダーはACCESSの中でも特に厄介な案件ですね。正直「レポートヘッダー?じゃあVBAね」と思います。たいてい、何とかしようとするよりよっぽど楽なので

あとはまぁ、ヘッダーフッターの誤表記とか、フッターによる検索汚染とか、いつも以上に意識しておかないと話がかみ合わなくなったりするのも厄介ですね

16

おお!これはいいですね。
集計実行で累計を計算させて、VBAでフッターのフォーマット時にヘッダーに代入。
シンプルですし、確実です。

=Pages のテキストボックスは必須ですね。
こちらでサンプルも作成して動作確認できました。

18
hiroton 2023/06/07 (水) 10:48:07 修正 9c71f@f966d >> 16

個人的にはレポートあまりごちゃごちゃさせたくないんでVBA優先しちゃいますけどね

Option Compare Database
Option Explicit

'レポート上に「コントロールソース:=[pages]」のテキストボックスを配置すること

Dim lastDay As Date
Dim daySum As Currency
Dim total As Currency

Private Sub レポートフッター_Format(Cancel As Integer, FormatCount As Integer)
    total = total + daySum * 1.1
    Me!月合計 = total
End Sub

Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)
    If Me.FormatCount = 1 Then
        If Me!日付 = lastDay Then
            daySum = daySum + Me!数
        Else
            total = total + daySum * 1.1
            daySum = Me!数
            lastDay = Me!日付
        End If
    End If
End Sub

んー、ここまでVBA任せにするとなんか難しそうに見えますね

レポート上のコントロールのプロパティによって結果が変わるモノを使いたくない(プロパティ確認が手間)ってのもあるんですが、コントロールを使えばプレビューでイメージを掴みやすいってメリットも有難いところではあります

この先は、慣れと雰囲気でお好きなものをって感じですかね

17
ジュン 2023/06/07 (水) 10:21:27 ddfe5@d8b89

hatena様・hiroton様 ありがとうございました。
日付グループフッターに税込み金額の累計は出来てます---[tx税込金額の累計]。そしてレポートヘッダーにコード記述しました。
Private Sub レポートヘッダー_Format(Cancel As Integer, FormatCount As Integer)
     Me.[tx月合計] = Me.[tx税込金額の累計]
End Sub
でも[tx月合計]は総累計ではなく先頭の累計分が表示されます。何が間違っているのでしょうか?(コードはこれだけでは不足?)
すみません、私の理解が悪くて・・・ 因みに請求書一覧は1ページに必ず収まる量です。
宜しくお願いします。

19

そのコードであればレポートヘッダーではなくレポートフッターにコードを記述してみてください


レポートヘッダーを弄りたいのになぜレポートフッターで制御する(できる)のか?というのがhatenaさんの研究から学ぶことができます

同様に、hatenaさんの回答(>> 14)のように「レポートヘッダーで制御するように組む」のも解法の一つです

hirotonも横やり的に違う解法を出してしまっているので混乱させてしまっているところがあると思います。気になったところがあれば遠慮なく聞いてください

20
ジュン 2023/06/07 (水) 11:39:58 ddfe5@d8b89

hiroton様ありがとうございました。
レポートフッターにコード記述したら上手くいきました。イベントが上から順に発生するのでそうしないと正しくならないのですね(まだなんとなくしか理解してないのですが)。不思議なのは =Pages のテキストボックスがないとデータが表示されませんでした。これも必須なのですね?

21
hiroton 2023/06/07 (水) 13:10:04 9c71f@f966d

[Pages]は必須です
基本的な使い方の、ページ番号表示のために設置済みであれば改めて配置する必要はありませんが、未使用場合は配置する必要があります。表示不要なら可視プロパティを「いいえ」にしましょう


簡単に説明すると、レポートは「データの整形format」→「描画print」をレコードの数だけ繰り返します。そして、「描画」したら描画内容が確定され、修正できなくなります。プレビュー画面で見てるとイメージが付きにくいですが、実際に印刷されることを考えればわかりやすいですね
つまり、レポートヘッダーとは通常、真っ先に印刷済みになってしまうのであとから累計を書き込みたいといっても無理なのです

ここで、[pages]ですが、これは総ページ数を表示する変数です。しかしながら、総ページ数は出力してみないとわからないので上記の単純な仕組みでは描画することができません
そこで、ACCESSは[pages]が含まれるレポートを印刷しようとすると
『全レコード分(「データの整形」)→全レコード分(「データの整形」→「描画」)』
のように、印刷の仮データを作るかのような動作します

この動作をイベントで追いかければ

(仮)レポートヘッダー→(仮)詳細[レコード数分]→(仮)レポートフッター→(本番)レポートヘッダー→(本番)詳細[レコード数分]→(本番)レポートフッター

となるので、全レコード分の情報を反映した内容をレポートヘッダーに書き込むことができるようになります

処理するイベントがヘッダーでもフッターでもいいというのは、正確には「(仮)レポートフッター」か、「(本番)レポートヘッダー」のどちらかであればいいということですね


次に、コードがMe.[tx月合計] = Me.[tx税込金額の累計]の場合はフッターでなければならないのはなぜ?となるのですが、これは参照するデータの問題です。つまり、Me.[tx税込金額の累計]はイベントのタイミングで内容が異なるからということですね
レポート上のコントロールなので、描画するレコードに合わせて内容は変わっていて当然というわけです

22
ジュン 2023/06/07 (水) 13:34:01 ddfe5@d8b89

hiroton様 とても丁寧な説明ありがとうございました。レポートは複雑な動きがあるのですね。(今まで知りませんでした)
[pages]を配置することによって強制的に動作させるのですね。(思いもよらない発想です!)
自分の力ではとても解決出来ませんでした。本当にありがとうございました。hatena様にも感謝です。

あと今回の件とは関係ないのですが、私はまだまだ知識不足でクエリをよく作成してます。複雑になる場合はクエリを分割して作成しており、その結果クエリが大量に出来ています。こういうやり方はよくないでしょうか? その事がいつも疑問に思ってまして。

23
ジュン 2023/06/07 (水) 14:47:56 ddfe5@d8b89

度々申しわけありません、このレポートを印刷用として顧客・対象年・対象月のコンボを配置したフォームを作ってまして、コマンドボタンでプレビューの形です。レポートにデータがない場合 エラーとなるのでレポートの空データ時イベントに「 MsgBox "データはありません"
  Cancel = True 」とするとMsgBox表示後にエラーとなります。デバック見ると DoCmd.OpenReport "R_請求書一覧", acViewPreview, ,抽出条件 のところで止まってました。それでフォームのコマンドボタンに 「If DCount("売上日付", "Q_ 請求書一覧用レコードソース") = 0 Then MsgBox "データはありません" Exit Sub」としたのですがやはりMsgBox表示後エラーとなり、デバック見ると レポートフッターに記述の Me.[tx月合計] = Me.[tx税込金額の累計] のところで止まっていました。
どこにキャンセルの命令を入れたらいいのか分からないのです。 何度もすみません。

24
hiroton 2023/06/07 (水) 15:29:23 9c71f@f966d

質問に合わせて抜粋や改変してますけど、もともと全部hatenaさんの研究から読み取れることですねぇ
質問のやり取り中だったので控えてましたが、改めてhatenaさんの研究と情報公開に感謝します。ありがとうございます


追加の件
DCount("売上日付", "Q_ 請求書一覧用レコードソース")はきちんと0になってますか?

または、DoCmd.OpenReportはエラーでもいいんじゃない?という方法もあります
印刷データが無いとき印刷を中止する方法(cbcnetさん)


クエリの件は一概に言えるものでもないと思います。問題にすると結構大きくなると思うので、具体的にこういうデータでこういうクエリを作るときという形で改めて質問を立てたほうがいいと思います

25
ジュン 2023/06/07 (水) 16:31:55 ddfe5@d8b89

hiroton様 重ね重ねすみませんでした。
逆の発想でエラー時に処理するのも手ですね、これで上手く出来ました。
クエリの件は分かりました。また改めて具体的に投稿する様にします。
今回すごく勉強になりました。回答はどれも素晴らしいものばかりでした! もう一度hatena様へも感謝です。
本当にありがとうございました。