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
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.レポート用型番;
Private Sub Form_AfterUpdate()
With Parent.Parent.Recordset.Clone 'フォームのレコードセットのコピー
.Bookmark = Me.Bookmark 'カレントレコードを同期
.Edit
!chk = True
.Update
End With
Parent.Parent!チェック1 = True
Parent.Parent!コマンド6.Visible = True
End Sub
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納品書レポート用空行あり.注文番号;
よくわからんACCESSの仕様に付き合いながら速度気にするなら最初からVBAで組んじゃえばいいんじゃないかな。クエリ弄る必要ないし
※このコードを動かすにはレポートの改造も必要
サブレポートにしてもDSumにしても抽出条件どうするんだ?問題が別に発生するからそれはそれで簡単とは言えないけれど
リレーションシップやクエリの組み方云々は質問の本題から遠いのでhiroton的にはノータッチです
DSumを埋め込む方法でももちろん可能です。速度的に重くなる可能性があるので私の場合は仕様には慎重派です。
サブレポートを埋め込むのも同様に重くなる可能性があるので同様です。
まあ、このへんは自分が理解しやすい、使いやすいものを選択すればいいでしょう。
クエリの結合はAccessの基本なので、これを使えるようになるといろいろな場面で応用がききます。ですので、私が回答するときはまずはこれを提案します。
「Q納品書レポート用空行あり」というのは、ひょっとして現状のレポートのレコードソースのクエリですか。
「税込み日別合計を表示するクエリ」に「Q納品書レポート用空行あり」が含まれていますので、これを、
レポートのレコードソースのクエリ(Q納品書レポート用空行あり)に含めたら循環参照になります。
「税込み日別合計を表示するクエリ」は他のクエリから作成するのではなくテーブルから作成した方がトラブルは少ないです。
DSumを使うにしても、クエリで結合させるにしても、各テーブルのリレーション関係をしっかり理解できていないと、正しいものを作成するのは難しいです。
「リレーションシップ」は設定していますか。設定しているなら、その設定画面のスクリーンショットを提示してもらえるといいアドバイスができるかもしれません。
していないなら、まずはその設定から始めることをお勧めします。
下記も参考にしてください。
リレーションシップを設定した場合の利点 - hatena chips
さきほど途中で間違えて送信してしまい、すみません。
何が間違っているのでしょうか?
hiroton様の案も確かにそうですねDSum()の手がありますね。それも試してみます。
hatena様・hiroton様 ありがとうございました。
hatena様の通りにしてリレーションさせると今度は Q納品書レポート用空行あり循環参照が発生しています。(Error 3102) となりました。この原因は?
別建ててクエリを作成するならそのままそれぞれレポートにしてレポート印刷2回掛けるとか、サブレポートにして埋め込むとかすればいいんじゃないですかね
わざわざ結合する必要はないような
印刷データの抽出の仕方によってはDSum()とかでも行けるんじゃないですかね
原因を特定するために、まずはなるべくシンプルなもので確認するという手順をします。
まずは、コピーしたファイルでレポートのすべてのVBAを削除して、改ページコントロールも削除してどのような結果になるか確認してほしかったのです。
その状態で改ページされることがないのか、1行ごとに改ページされるのか、どちらでしょう。
集計実行に関しては、レポートヘッダーとフッターでは結果が異なりますね。
レポートの先頭レコードから順に出力(Formatイベント)していって、最終的に全体が出力されることになります。
集計実行は出力されるたびに実行されて加算されていきます。
レポートヘッダーでは先頭レコード分しか集計実行されていないことになります。
最初のクエリに関してですが、
まずは「税込み日別合計を表示するクエリ」を開いた場合、正しい日別合計になってますか。
Sum([小計]*([税率]/100+1)) AS 売上日毎の合計金額
となってますが、これだと日毎の合計で税率をけ計算するのではなくレコード毎に税額を計算していることになります。
税率をかけるのはSum()の外に出す必要があります。
Sum([小計])*([税率]/100+1) AS 売上日毎の合計金額
レコード毎に税率をかけてそれを集計するか、
日毎の合計に税率をかけるか、
の違いです。
ご希望のは後者だと理解してますが、どうでしょうか。
次に結合するとエラーになる件ですが、
2つのクエリを結合すると両方のクエリに「売上日付」があることになりますので、
「売上日付」がどちらのクエリのものか分からないので、そのようなエラーになります。
「税込み日別合計を表示するクエリ」の方で、Q納品書レポート用空行あり.売上日付 As 売上日付集計用
というように別名を付ければ 区別がつくようになりますので、エラーがでなくなると思います。
ご確認ありがとうございます。
削除したところ、下記のコードで「改ページフィールドが見つかりません」と表示されました。
Else
Me!改ページ.Visible = False
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.レポート用型番;
です(余分項目沢山ありすみません)。これの売上日付をリレーションさせるとエラーがでます。
あと私が全然分かっていないのですがレポートのヘッダーとフッターでは出来る事が違うのでしょうか? 単純に上にあるか下にあるかの違いの認識しかありませんでした。(恥ずかしながら・・・)。確かにレポートフッターにはテキスト配置するだけで最終累計が表示されました。
宜しくお願いします。
宜しくお願いします。
クエリの設計が間違っているのだと思われますので、
現状の、税込み日別合計を表示するクエリのSQLビューのSQL文と、レポートのレコードソースのSQL文をここに貼り付けてください。
このクエリを使う場合は、金額累計のテキストボックスは不要です。
前回の回答の前半は、レポートフッターに表示する場合の回答です。こちらは、集計実行で累計テキストボックスを配置してそれを使います。
後半は、レポートヘッダーに配置する場合です。こちらは集計実行ではできないので、クエリをつかって日別合計を計算します。累計テキストボックスは不要です。
「レポートヘッダーにこれを表示したいとなると、」以降が後半です。
確認したらプロパティには「可視」はないですね。
ならば、改ページコントロールを削除して試してみてください。
念のために、データベースファイルのコピーを作成して、そちらでいろいろ確認作業をしてください。
hatena様へ早速ありがとうございます。
(私の知識不足が原因につき)途中からが分からないので教えて頂きたいのです。グループの税込み日別合計累計のテキストボックス配置し、税込み日別合計のクエリまでは出来ました。その後のレコードソースに日付で結合すると”指定されたフィールド <フィールド名> が SQL ステートメントの FROM 句にある複数のテーブルを参照しました” のエラーが出ます。この対処はどうするといいでしょうか? また最終的に金額累計のテキストボックスは参照される事はないのでしょうか?
すみません、宜しくお願いします。
改ページコントロールのプロパティを開いたところ、
「可視」項目がございませんでした。
プロパティから設定するのでしょうか。
うまく行きましたか。それはよかった。
前の回答でも書きましたが、チェックボックスは非連結なので、レコード移動時やユーザーがチェックボックスを更新した場合にテーブルと同期させる処理は必要なのでご留意ください。
日別の税込み金額の合計を、レポートフッターに表示したいのなら、下記の設定で可能だと思います。
まず、納品日付毎のグループフッターに下記のテキストボックスを配置。
名前 日別合計
コントロールソース =Sum([金額])
集計実行 しない
名前 税込み日別合計
コントロールソース =[日別合計]*1.1
集計実行 しない
名前 税込み日別合計累計
コントロールソース =[税込み日別合計]
集計実行 全体
レポートフッターに下記のテキストボックスを配置
名前 月締め請求金額
コントロールソース =[税込み日別合計累計]
集計実行 しない
レポートヘッダーにこれを表示したいとなると、集計実行では無理ですので、クエリで「税込み日別合計」を計算してそれをレポートのレコードソースに追加することになります
レコードソースのテーブルからクエリを作成して、納品日でグループ化して、下記の演算フィールドを追加します。
税込み日別合計: Sum([金額])*1.1
このクエリをレポートのレコードソースに追加して納品日で結合します。
納品日フッターに「税込み日別合計」を配置します。
さらにレポートフッターにテキストボックスを配置してコントロールソースに下記の式を設定すれば請求金額を表示できます。
=Sum([税込み日別合計])
ヒントを出しておくと、A・B・C・D・Eの各フィールドの条件をOr演算子で連結すればいいでしょう。
あるいは、A・B・C・D・Eの各フィールド値を&演算子で結合してそれに対してLike演算子であいまい条件を設定すればいいでしょう。
上記のヒントで具体的にコードが分からない場合は、
現状のVBAを提示してください。
DAOの方法でうまくいきました。
Recordset.Cloneのおかげで、フォーカスが移動せずに済んでいます。
ありがとうございました。
お世話になりました。取り急ぎ以下のコードでパラメータクエリを使用することなく、パラメータのポップアップが出てこなくて、フィルターの掛かったデータをエクセルのシート1/2/3にエクスポートすることが出来ました。大変に有難う御座いました。
Dim strQryName As String
Dim strSQL As String
Dim FileName As String
strQryName = "Q_明細1" '←お好みの名前にする
strSQL = "SELECT * FROM Q_見積明細1_P WHERE T_見積物件情報.見積りNo=" & Forms!F_見積_1!見積りNo
On Error Resume Next
CurrentDb.CreateQueryDef strQryName, strSQL
'↑でエラーなら存在済みとみなし↓SQL変更処理を行う
If Err <> 0 Then
CurrentDb.QueryDefs(strQryName).SQL = strSQL
On Error GoTo 0
End If
CurrentDb.QueryDefs.Refresh
RefreshDatabaseWindow
FileName = Left(CurrentDb.Name, InStrRev(CurrentDb.Name, "\")) & "見積書.xlsx"
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, strQryName, FileName, True, "明細1"
シート2/3は、シート1とほぼ同様のコードです。
カスタムリボンの作成が既に出来ているのであれば、表示させたいリボンの名前を
それぞれのフォームの[リボン名]プロパティに設定なさればよろしいでしょう。
分かりました。
DAOの方法でやってみます。
他の作業が入ってきたので、やってみたら、またご連絡いたします。
ありがとうございます。
hirotonも各種機能は直接フォームに乗せるとかでリボンを弄ることはまずないですねぇ
ずばりで回答がつかないならリボンは一つにして中身だけ弄ったらどう?とか
[リボン・カスタマイズ]グループの表示・非表示をトグルボタンで切り替える。(初心者備忘録さん)
DAOで、フォームのレコードセットのコピーを生成して、それに対して更新する方法でどうだろう。
Chk はレコードソースのフィールド名
Chk1 はチェックボックス名(非連結)
チェックボックスは非連結なので、親フォームのレコード移動時にフィールド値を代入するなどの処理は別に必要。
ちょっと今出先なので、サンプルで動作確認してはしていませんので、うまくいくかは不確定。
なかなか回答がつかないですね。
リボンのカスタマイズはなかなか手ごわいので、私も手を出していないので、参考になりそうなリンクのみ紹介しておきます。(もう、見ているかもしれせまんが)
Access でカスタム リボンを作成する - Microsoft サポート
ExcelとAccessに独自のリボンを追加する 🌴 officeの杜 🥥
リボンのカスタイマイズ
これを気にするなら、Parent.parentのチェックボックスは非連結にしておいて、レコードソースのテーブルのフィールドを更新クエリかDAOまたはADOで直接更新するようにすればどうでしょう。
なるほど。そういう仕様もあるのですね。
ユーザーからは制御不能ですよね。
Parent.parent.Refreshを行わないと、すぐにはテーブルに反映しないのが引っかかります。
フォーカスを移動するなど、レコードを保存するタイミングにならないと保存されないと、
それまでの間にAccessがクラッシュやフリーズした際にレコードが保存されないのが問題になりますよね?
以下のどちらかを取るかと思っています。
Refreshをして、レコードが移動してしまい、ユーザー操作がやりづらくなったり入力ミス等が発生するかもしれないが、データの完全性を保持する事を優先するか。
Refreshをせず、レコードが移動しないことで、ユーザー操作に影響がないが、データの完全性に大きなリスクを背負わせるか。
hatena様ならどちらを取りますか?それとも他のお考えがございますか?
3階層のサブフォーム構成の場合、一番上のフォームでRefreshすると、3番目のサブフォームは再読込されるという仕様のようです。なぜこのような仕様なのか1ユーザーからは伺いすることはできませんが、各リンクテーブルのデータ整合性を保つために必要なことなのかもしれません。どちらにしても、このような内部処理をユーザーから変更するのは難しいかと。
とりあえず、当方のサンプルでは、
というようにRefreshをコメントアウトしておくと、先頭レコードへ移動せずにチェックが入りました。
ただし、テーブルにはすぐには反映せずに、メインフォームへフォーカスを移動するとテーブルに反映されました。
※「チェック1」はチェックボックス名
Accessのローカルテーブルでの確認ですので、SQL Serverだと動作が異なるかもしれません。
hatena様、ありがとうございます。
ご指示の内容を行なってみましたが、やはり症状は出ます。
なお、
「孫フォームで入力してレコード保存すると(更新処理)、親フォーム(Parent.parent)にフォーカス移動して、画面がスクロールして、先頭フィールドへフォーカスが移動するということですか。」
について。
親フォーム(Parent.parent)にフォーカス移動して → 中間のフォーム(Parent)にフォーカス移動して
です。
すみません。遅くなりましたが、大事なことを伝え忘れていました。
テーブルはSQL ServerよりODBCリンクです。
上記の回答を書いてから下記の追記に気が付きました。
孫フォームで先頭レコードへ移動するという現象ですか。
それなら、当方のサンプルでも現象を再現できました。
ちょっと対策を検討してみますのでお待ちください。
孫フォームで入力してレコード保存すると(更新処理)、親フォーム(Parent.parent)にフォーカス移動して、画面がスクロールして、先頭フィールドへフォーカスが移動するということですか。
こちらで下記のようなサンプルを作成して実験してみましたが、症状は再現できませんでした。
親テーブル、子テーブル、孫テーブルを作成してサンプルデータを入力。
それぞれをソースとするフォームを作成して、親テーブルフォームに子テーブルフォームをサブフォームとして配置。
子テーブルフォームに孫テーブルフォーム(帳票フォーム)をサブフォームとして配置。
孫テーブルフォームの更新後処理に下記のように記述。
親フォームへフォーカス移動しませんでした。
かなり複雑なことをしているようですし、こちらで状況を再現できないので、こちらから原因を特定するのは困難です。
まずは、現状の各フォームのコードをコメントアウトして、孫フォームの更新後処理の下記の部分だけコメントアウトを解除してサブフォームで更新してShift+Enterでレコード保存した場合、症状は出ますか。
別途、簡単なサンプルDBを作り、同じような構成(単票フォームの中に単票フォーム、その中に帳票フォーム)にしました。
その結果、一番子フォームの帳票フォーム内で、先頭レコードに移動する、という結果になりました。
Refreshでもレコードの移動があるようですが。
ファイルをアップできれば、見ていただけるかと思いますが、無理ですね。
Parent.parent.refreshの問題に関しては、「先頭フィールドに移動」です。
先頭フィールドに移動し、それにつれて画面が上に移動します。
Parent.parent.refreshの部分でブレークポイントを設定し、そこまではフォームもそのままです。
しかし、ステップインし、コードを実行すると、画面が上に移動します(先頭フィールドに移動)。
処理の中にはSetfocus等の処理は全くありません。
「先頭レコードかつ先頭フィールドにフォーカスが移動」
「先頭フィールドに移動」
「画面の位置が上へ移動」
複数の表現が混在していますが、現状の動作はどれでしょうか。
また、サブフォームの更新後処理で実行されているのなら、フォーカスはサブフォームにあるはずですので、「先頭フィールドにフォーカス移動」というのは、Refresh では発生するはずがないです。フォーカス移動させるような処理がどこかにあるのではないですか。
一番親のフォームはテーブル連結で、いくつかのコマンドボタンとそのボタンの表示非表示の状態を示すチェックボックスがあります。
その子フォームは一番親フォームのボタンを押すと、指定のフォームがソースオブジェクトになり、画面が表示されるようになっています。
その子フォームの子フォームが帳票フォームになっております。そこからの処理です。
追加です。
イベントは、Private Sub Form_AfterUpdate()
です。
hatena様、ご返答ありがとうございます。
先ほどは確かにフォーカスが移動してしまっていたのですが、いろいろコードをいじっていたらならなくなりました。
すみませんでした。
ですが、Parent.parent.refreshというのもあるのですが、
こちらは実行すると親フォーム(親の親ではなく)の先頭フィールドに移動してしまいます。
コードは以下の通りです。長すぎるので全ては載せきれません。
If Parent.Parent!書式ID <> 10 And Parent.Parent!書式ID <> 16 And Parent.Parent!書式ID <> 17 Then
Select Case Parent.Parent!書式ID
Case 1, 3, 5
Parent.Parent!巻替検査記録 = True ←チェックボックス(テーブルと連結)
Parent.Parent!巻替検査記録ボタン.Visible = True ←コマンドボタン
Parent.Parent.Refresh ←ここを処理すると画面の位置が上へ移動してしまいます。
Parent.Requeryではなくて、Parent.Refresh で間違いないですか。
当方で簡単なサンプルを作成して試してみましたが、そのような現象は確認できませんでした。
Parent.refresh はサブフォームのどのイベントに記述してますか。そのイベントプロシージャ全体を提示してもらえますか。
先頭レコードから、1行ごとに改ページされるのですか。
だとすると、現状のコードが原因ではないと思います。
まずは、改ページコントロールの「可視」を「いいえ」にして現状のVBAコードをすべてコメントアウトしてプレビューするとどうなりますか。
変更したところ、解決しました!
しかし、依然として1行ごとに改ページされております。
テーブルの「累計」の影響でしょうか。
現在、累計はテキストボックスで挿入しコントロールソースは無い状態です。
Private Ruikei As Long
の部分を
Private Ruikei As Currency
に変更してみてください。