Private Sub コマンド25_Click()
Dim cnn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim rs1 As ADODB.Recordset
'Connectionは一つで共有する
Set cnn = Application.CurrentProject.Connection
Set rs = New ADODB.Recordset
Set rs1 = New ADODB.Recordset
rs.Open "月間請求書履歴", cnn, adOpenKeyset, adLockOptimistic 'テーブルを開く
rs1.Open "データ", cnn, adOpenKeyset, adLockOptimistic
rs.MoveFirst '"月間請求書履歴"(rs)の先頭レコードへ移動
Do Until rs.EOF
'"月間請求書履歴"(rs)のデータを"データ"(rs1)に新規追加
rs1.AddNew
rs1!請求書NO = rs!請求書NO
rs1!請求日 = rs!請求日
rs1!会社名 = rs!会社名
rs1!氏名 = rs!氏名
rs1!現場名 = rs!現場名
rs1!工事名 = rs!工事名
rs1!請求金額 = rs!請求金額
rs1.Update
'"月間請求書履歴"(rs)を次レコードへ移動
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
rs1.Close
Set rs1 = Nothing
cnn.Close
Set cnn = Nothing
DoCmd.OpenForm "請求書履歴"
End Sub
SELECT
Qクロス結合.[リマインダーID], Qクロス結合.[リマインダー内容], Qクロス結合.日付, Qクロス結合.曜日,
IIf( [曜日番号合計] = 0, 0, [曜日番号] ) AS 曜日条件,
IIf( [週番号合計] = 0, 0, [週番号] ) AS 週条件
FROM
Qクロス結合 LEFT JOIN ( SELECT [リマインダーID], sum(曜日番号) AS 曜日番号合計, sum(週番号) AS 週番号合計 FROM T条件 GROUP BY [リマインダーID] ) AS 番号合計 ON Qクロス結合.[リマインダーID] = 番号合計.[リマインダーID]
WHERE
( ( ( IIf( [曜日番号合計] = 0, 0, [曜日番号] ) ) In ( select 曜日番号 from T条件 where T条件.リマインダーID = Qクロス結合.リマインダーID ) )
AND ( ( IIf( [週番号合計] = 0, 0, [週番号] ) ) In ( select 週番号 from T条件 where T条件.リマインダーID = Qクロス結合.リマインダーID ) ) )
ORDER BY
Qクロス結合.[リマインダーID],
Qクロス結合.日付;
SELECT x.リマインダーID
, z.日付
, y.曜日番号
, y.週番号
FROM
(
SELECT リマインダーID
FROM T条件
GROUP BY リマインダーID
HAVING Sum( 週番号 ) = 0
OR Sum( 曜日番号 ) = 0
)
x
, T条件 y
, T日付 z
WHERE x.リマインダーID = y.リマインダーID
AND (
y.曜日番号 = Weekday( z.日付 )
OR
y.週番号 = ( Day( z.日付 ) + 6 ) \ 7
)
ORDER BY 1, 2 ;
テーブルのあるデータベースでの実行結果と、別のデータベースからリンクテーブルに対しての実行結果が異なるという現象でしょうか。
そのような現象を経験したこともないし、聞いたこともないですね。
症状を再現できる詳細な情報(テーブルのフィールド構成、データ例)を提示できますか。
あるいは、症状の再現できる最小限のデータベースファイルを送信してもらえますか。
送信は右カラムの一番下のファイル送信フォームからできます。
リンクを張り直したり、最適化修復は試みましたが不具合のままでした
SELECT Min([受注ID]) AS minID
FROM 受注伝票;
すいません、環境はwin10、Access2013です。
早速見て頂きありがとうございます。
直してみたらできました。
最初はシンプルなものだったのですが、あれもこれもと機能を足していったら複雑化してました。今回、ファイルを送る時に整理をしてみたら明らかに必要のないファイルも紛れており、見直すいい機会になりました。
本当に助かりました。ありがとうございました。
hatenaさま
度々のご回答ありがとうございます。
教わったことをベースに一度作ってみたいと思います。
ありがとうございました。
送信ファイルを確認しました。
質問のコードでは、
となってますが、ファイルのコードは、
となっており、クエリ名が異なってます。"月間日報履歴"クエリには"請求書NO"フィールドはないので当然エラーになります。
"月間日報履歴"を"月間請求書履歴"に変更したらエラーなく実行されました。
このような出力はレポートを使うと簡単に見やすく作ることができます。
履歴テーブルを選択しておいて、レポートウィザードでレポートを作成します。
「グループレベルを設定してください」のところで「取引相手」を選択します。
次の並べ替えを指定するところで、「取引日付」の昇順に設定します。
次でレイアウトを「表形式」を選択します。
あとレポート名を設定して完了をクリックで雛形が完成します。
デザインビューで開いて、詳細セクションにテキストボックスを配置して、その設定を下記のようにします。
コントロールソース 取引金額
集計実行 グループ全体
これで相手先ごとにグループ化されて、各行ごとに残高が表示されます。
hatenaさま
早速のご回答ありがとうございます。大変丁寧な説明で分かり易いので助かります。
テーブルとデータ例は理解できました。多分テーブルに備考などを付け加えれば
イメージしている処理ができそうです。
集計クエリについてですが、残高だけを表示せずにA氏履歴とB氏履歴に分けて
残高が0になるまでを行をわけて表示することは可能でしょうか?(0になったら非表示)
可能です。
どのように設計するかですが、Accessはデータベースソフトですので、データをため込んで、必要に応じて、必要なデータを、必要な形に加工して出力する、ということをするものです。
まず、最初に考える必要があることは、どのようなデータをどのうような形でため込むか、です。ため込む場所はテーブルです。ですので、テーブルの設計から始めます。
データを加工して出力するのはクエリだったり、フォームだったり、レポートということになります。しかし元のデータがしっかりしたものでないと自由に加工できません。
呈示の情報から必要なデータは、最低限下記の3つになります。
金額に関しては、預かり金額、支払い金額 と2つのフィールドに分ける方法と、
一つのフィールドで預り金はプラス、支払いはマイナスとする方法が考えられます。
このお金の出し入れの履歴を逐一ため込んでいく形になります。
この履歴テーブルの他に、
お金を借りる相手の情報が氏名だけでなく、連絡先など別に必要なら、
相手先情報のマスターテーブルも必要になります。
テーブルの設計には「正規化」という原則があり、それに沿った設計にしないとデータベースとしては使いものにならないものになります。ただ、かなり奥が深く理解するには敷居が高いものなので、これはおいおい勉強していくといいでしょう。
前置きが長くなりましたが、まずは質問内容を一番シンプルな形でテーブルにすると、下記のようなものになります。
テーブル名 取引履歴
呈示されている情報だけから原因を特定するのはむずかしそうです。
さしつかえなければ、右のファイル送信フォームから現状のファイルを送信してもらえますか。
エラーの再現できる最低限のテーブルデータとコードのみのファイルをZIPファイルにして、それを添付して送信してください。
ご迷惑をおかけします。
月間請求書履歴クエリのSQLです
SELECT 請求書メイン.請求書NO, 請求書メイン.請求日, 宛先マスタ.会社名, 宛先マスタ.部署, 宛先マスタ.氏名, 現場.現場名, 請求書メイン.工事名, 請求書メイン.請求状況CD, 請求書メイン.請求金額
FROM 宛先マスタ INNER JOIN (現場 INNER JOIN 請求書メイン ON 現場.現場ID = 請求書メイン.現場ID) ON 宛先マスタ.宛先ID = 請求書メイン.宛先ID
WHERE (((請求書メイン.請求日)>=#11/1/2019# And (請求書メイン.請求日)<=#11/15/2019#));
ということは、
rs.Open "月間請求書履歴", cnn, adOpenKeyset, adLockOptimistic
の部分はエラーなく通過したということですね。
一歩前進です。
エラーメッセージから"月間請求書履歴"クエリまたは"データ"テーブルに「請求書NO」フィールドがないということしか考えられません。両方に「請求書NO」フィールドが存在するか、もう一度確認してみてください。「請求書NO」とNOが全角になっていてもだめですよ。
どちらにも「請求書NO」が存在するということなら、「月間請求書履歴」クエリのSQL文をコピーしてここに貼り付けてください。
はいそうです。
上記のコードを試してみたところ
rs1!請求書NO = rs!請求書NO
で、要求された名前、または序数に対応する項目がコレクションでみつかりませんとでました。
請求書NOがないはずはないのですが・・・
エラーメッセージから判断するに "月間請求書履歴" クエリでエラーが発生しているので、このクエリの設計に問題があるか確認するために、まずは、このクエリを開いて正しくデータが表示できるかどうか確かめるのは、最初にすべき確認事項です。
このクエリがパラメータクエリということはないですよね。
回答ありがとうございます。申し訳ありませんが月間請求書履歴をダブルクリックしてデータというのは”データ”テーブル云々の話ではなく、請求書のデータということで合ってますか?ダブルクリックしたら見れます。
上記のコードを試してみます。
"月間請求書履歴"クエリをダブルクリックして開いてデータを見ることはできますか。
これについて回答ください。
あと、
s.Open "月間請求書履歴", cnn, adOpenKeyset, adLockOptimistic
でエラーになって進めないということなんですが、
それ以外の部分で間違っている部分がありますので、
コードを下記に修正してください。
おはようございます
”データ”テーブルはあります。ただ月間請求書履歴のクエリの中には”データ”テーブルの情報はありません。
フィールド名は統一してありますがあくまでも”月間請求書履歴”の情報を”データ”に蓄積がメインだったもので。
”データ”はリレーションシップも設定しておらず本当に単独テーブルです
"月間請求書履歴"クエリはあるのですね。
ならば、そのクエリは開いてデータをみることができますか。
また"データ"テーブルは存在していますか。
返信ありがとうございます。
クエリにはあるのですがテーブルに月間請求書履歴というものはありません。
テーブルには請求書と請求書明細があり、クエリで月間請求書履歴になっています。
’データ’テーブルは単独でどこにも属していません
ちょっとやってみようと思います。
上記のフォルダというのはテーブルのタイプミスですか。
”月間請求書履歴”と"データ"というテーブルがあるということですか。
"月間請求書履歴"というテーブルがないとエラーになりますが、存在しますか。
グループレベル1ヘッダーにコントロールを作成できました。
ありがとうございました。
CreateGroupLevelメソッドの存在は知りませんでした。
さっそく試してみようと思います。
ありがとうございました。
下記が参考になりませんか。フォームでの場合ですが、レポートでも同様な方法で可能です。
列数が変化するクロス集計クエリと連結するフォーム - hatena chips
列数が変化するクロス集計クエリと連結するフォーム - hatena chips
お勧めはしませんが、どうしてもVBAでグループヘッダーを追加したいという場合は、下記が参考になるかと。
CreateGroupLevel メソッド (Access) | Microsoft Docs
VBAでする理由:
・グロス集計したレコードセットを元にレポートを作成しますので、列見出しが変わります。手作業では大変なのでVBAで作成したいのです。
目的:
・プロジェクトの分析(プロパティ値の表示)
今、自分のプロジェクトのフィールドのプロパティ値、コトントロールのプロパティ値を一覧表にしようとしています。
その時、フィールド名が行見出し、プロパティ名が列見出し、プロパティ値が値になるように、クロス集計しています。
そして、グループレベル1にオブジェクト名を表示させたいのです。
レポートではページヘッダーにプロパティ名を縦長で1行に表示させていますが、とても全部を表示させることはできませんので、重要なプロパティ値、値に変更を加えたプロパティ値のみ表示させています。
この列見出しとしているプロパティ名がプロジェクト毎に変わるので、VBAでレポートを作成したいのです。
ここまではできているのですが、グループレベル1ヘッダーにコントロールを作成できれば、完璧だと思うのです。
よろしくお願いします。
デザインビューでグループヘッダーを追加したり、コントロールを追加するのではなくて、VBAでする理由と目的はなんでしょうか。
事前に追加しておいて、必要に応じてVBAで表示/表示をコントロールするほうがはるかに楽ですし、デザインビューで開く必要がないので安全です。
mayuさん
テーブル設計を見直したサンプルのご提示ありがとうございます。
素朴な質問のつもりでしたが、ここまで懇切丁寧に回答いただき、
情報量にただただ圧倒される次第です。
また、その前段にてmayuさんよりご提示いただいた、
SUM集計関数を用いて元のクエリで抽出できなかったレコードを一括で抽出し
別途対処するというアイディアを参考にして下のクエリを作成しました。
こちらで一応望む結果を得ることができましたので、あまりスマートな方法では
ないと自覚していますが、ひとまずこの質問は解決にしようと思います。
以上、大変参考になるご回答数々いただき感謝致します。ありがとうございました。
※ 続き
結果 ( 一部抜粋 )
※ 続き
データ例
< T_リマインダー >
リマインダーの種別において
・ 日 単位で発生するもの は 1 を入力
・ それ以外のもの ( 週・曜日 ) は 2 を入力
というルールにします
< T_条件 >
F1 ---> 条件ID F5 ---> 週番号_from
F2 ---> リマインダーID F6 ---> 週番号_to
F3 ---> 対象月_from F7 ---> 曜日番号_from
F4 ---> 対象月_to F8 ---> 曜日番号_to
F9 ---> 日番号
※2
月、週、曜日において
連続した値( 毎月、毎週、火~金、4月~6月 など )は
連続した範囲として1行で表現し、
連続しない場合は行を分け、データを個別に登録します。
この部分が、データ登録における一番の難関だと思いますが
データサンプルをよくご覧になれば、構造を理解できるでしょう。
※3
日単位で発生するリマインダにおいて
日番号フィールドに入力する値は、月末は 0
それ以外は 日の数字
※4
曜日や週単位で発生するリマインダにおいて
日番号フィールドに入力する値は 0
テーブルの構造を変更する場合のサンプルを以下に載せておきます。
まず、リマインダーは
・ 日 単位で発生するもの
・ それ以外のもの( 週・曜日 )
の2種に大別できるでしょう。
( 両立しない条件のため )
よって、リマインダの定義テーブルに
種別を管理するフィールドが必要になります。( ※1 )
次に、リマインダーの発生周期は
月、週、曜日、日の組み合わせによることから
条件テーブルに、これらの値を格納するフィールドが必要 ( ※2 )
条件テーブルへデータを登録するにあたり、
行数が増えることに漠然とした不安を感じておられるようなので
行数を抑制できるフィールド構成にします ( ※3 )
特定の日に1度きりで実施されるリマインダと
特定の周期で何度も実施されるリマインダは
入力項目を共通化して統一し、Nullや意味不明の値は許可しない ( ※4 )
※1 ~ ※4 を網羅したテーブル定義
mayuさん
大変に熱のこもったご回答をいただきありがとうございます。
ひとまず、中段にご提示いただいた、元のクエリで抽出されないレコードを集計クエリで別途抽出しユニオンクエリで結合するという考え方を参考にさせていただき、
実際の動作を検証してみたいと思います。
また、独学なため実例を見る機会があまりなく、テーブル設計含めより適した方法を引き続き検討していきたいと思いますので、機会がありましたらぜひよろしくお願い致します。以上、ありがとうございました。
「月」や「日付」の条件をテーブルに追加して長大になるというのは
意味がわかりかねます。
前回の回答で、私はフィールド構成の変更を提案したわけではなく
データの持ち方を変更するよう、示唆したに過ぎません。
したがって、ご自身が考える「 長大にならない 」設計方針と
「月」や「日付」をどのような構成でデータ登録し、
週次や曜日毎に実施するデータと同居させる予定なのか
また、どのような SQL で抽出を行うつもりでいるのか、構想をお聞かせ願えますか。
現状の構成は、以下の問題点が明白ですので
・ 第三者から見て、単一の行からテーブルのデータ構造が把握できない
・ 相関サブクエリというのは、莫大な演算回数が発生するパフォーマンスの悪い SQL である
・ 複雑なサブクエリを複数回発行しても、思ったようにデータが抽出できていない
・ 演算フィールドを左辺に指定して抽出条件を指定しているため、インデックスが効かない
運用も構築も この先 地獄を見る覚悟がおありということでしたら
一応、ご希望の回答はしておきます。
なお、週番号だけを指定するリマインダーが あるのかどうか不明ですが
とりあえず、どちらでもいいように冗長な SQL にしておきます。
以下の結果を ユニオンクエリで rookjimさん記載の SQL と結合すればいいでしょう。
具体的なアドバイスをご希望なら、まずは データベースソフトの扱いにおいて
rookjimさんの方針や考え方は、順番や方向性が真逆である
ということを理解いただかない限り、不毛なやりとりになるでしょう。
のではなく、構築手順は
1. 条件を網羅した適切な構造のテーブルを設計する
2. パフォーマンスや見通しの良い SQL を考える
3. VBAの利用やコントロールの配置は必要最小限に抑え、
シンプルで保守性の高いインターフェース( フォーム・レポート )の構築を目指す
になります。
添付画像における リマインダーID: 1 の内容においても
発生条件が「 第2、第4土曜日 」ですから
フォーム上で [ 指定日 ] [ 日 ] といった項目を ユーザが指定する必要は無いように思いますが
代替値を入力しない限り、テーブル上でそれらの項目は Null になります。
これらの項目を SQLでどう扱うか、見通しが立っていないのでしたら
テーブルの設計から見直す必要があり、当然、フォームも改変を余儀なくされます。
まずは、テーブル設計からやり直す気が有るのか否か、意思表示をお願いします。
mayuさん
つたない質問内容を読み取っていただき、丁寧な回答いただきありがとうございます。
ご指摘いただき、T条件のテーブルの記述の仕方が、望む抽出結果を得るために適さない形式であることがわかりました。
T条件のテーブルが1レコードごとに1条件の構成になっている理由は、ユーザーがくり返し条件を入力するためのフォームを下のように作成したためです。
ご回答いただいたように複数の条件を全て網羅するようにテーブル構成を変更すると、
「月」、「日付」等の並列する条件を追加した際に条件テーブルが長大なものになってしまうため➀については現在のテーブル構成のまま目的の抽出結果を得られる方法を求めております。引き続きご教授いただけますと幸いです。
または
・条件を網羅したテーブルのデータが作成できるようにフォームを再設計する
・T条件のデータを複数の条件を全て網羅するように変換するようクエリを作成する
等で解決できるかと思うのですが、こちらについても具体的な方法をアドバイスいただけますと幸いです。
検討いただき大変有り難く思っております。大変わがままな質問で恐縮ですが
何卒宜しくお願いします。
質問内容 1, 2 両方ともに関連することですが
Tくり返し条件 テーブルの
データ構成に問題があるでしょう。
一意のリマインダーIDを構成する要素は
週番号 + 曜日番号
なのですから
週番号だけ とか、曜日番号だけ という
どちらか1つだけを表現した行を作ってはならないのです。
rookjimさんの例で申し上げるなら
リマインダーID:3 の「 毎週月曜と金曜 」というのは
・ 週番号は 1 または 2 または 3 または 4 または 5
且つ
・ 曜日番号は 2 または 6
であるのに
週番号の入力値を 0 という非該当の数字で表現していることが
SQL文が複雑になり、思ったように抽出できない原因になっています。
T条件
このように
複数の条件( 週 + 曜日 )を全て網羅するようなデータ構成に変更すると
SQL文は以下のように簡潔に記述できて
抽出漏れも解消できます。
質問者です。
テーブルの名前は
Tくり返し条件× → T条件○
でした。
大変失礼致しました。
よろしくお願い致します。
hatena様、本当にありがとうございます。
思いもよらいな現象でビックリしています。
ありがとう御座いました。
下記の設定でどうでしょうか。
値集合ソース
連結列: 1
列数: 3
列幅: 0cm;0.002cm
解説
コンボボックスのボックス部に表示されるのは、列幅0cm以外の最初の列
上記の場合は、2列目がボックス部に表示される。
2列目は列幅が0.002cmなので存在はするがリストではほぼ見えない状態。
リストには3列から表示されてるように見える。
すいません。
選択後にインデントの表示になってるいるので表示がずれてしまいます。
書式か何かで空白のインデント分を調整出来ますでしょうか?
…凄いです。
目からうろこです!!!!!
ツリービューは設定が大変なので本当に助かります。
ありがとうございます。!!
飲食店でしょうか。質問が曖昧過ぎるので具体的に回答はむずかしいです。
Accessはまったくの初めてですか。
だとしたら、まずは、入門書か入門サイトで基本を学習してからでないと難しいと思います。
まずは、テーブル設計から始めてみてください。
下記がテーブル設計については詳しく解説しています。