DAO のオブジェクトモデルでは
フォームのセッションで参照された Database オブジェクトも
Workspace オブジェクトの下位オブジェクトであり、
上位オブジェクトが Close メソッドを呼び出した時点で
それに連なる下位オブジェクトの参照は全て破棄されることになります。
Private Sub cmd_ReSet_Click()
Dim wks As DAO.Workspace
On Error GoTo ErrorHandler
Me.Painting = False
Me.RecordSource = vbNullString
Set wks = Access.Application.DBEngine.Workspaces(0)
MsgBox wks.Databases.Count '★★★
wks.BeginTrans
With wks.Databases(0)
.Execute "DELETE FROM M_USER"
.Execute "INSERT INTO M_USER SELECT * FROM W_USER"
.Close
End With
wks.CommitTrans
wks.Close 'この行は不要
ExitProc:
Set wks = Nothing
Me.RecordSource = "M_USER"
Me.Painting = True
Exit Sub
ErrorHandler:
wks.Rollback
MsgBox Err.Description
Resume ExitProc
End Sub
SELECT 製品名, Nz([当月末在庫],0)-Nz([当月入庫],0)+Nz([当月出庫],0) AS 前月在庫, Nz([当月入庫],0) AS 入庫, Nz([当月出庫],0) AS 出庫, Nz([入庫の合計],0)-Nz([出庫の合計],0) AS 当月末在庫
FROM Q当月まで入出庫 LEFT JOIN Q当月入出庫 ON Q当月まで入出庫.製品ID = Q当月入出庫.製品ID;
SELECT Q当月まで入出庫.製品名, Nz([在庫],0)-Nz([当月入庫],0)+Nz([当月出庫],0) AS 前月在庫, Nz([当月入庫],0) AS 入庫, Nz([当月出庫],0) AS 出庫, Nz([入庫の合計],0)-Nz([出庫の合計],0) AS 当月末在庫
FROM Q当月まで入出庫 LEFT JOIN Q当月入出庫 ON Q当月まで入出庫.製品ID = Q当月入出庫.製品ID;
Public Function 月初(申請日 As Variant) As Variant
If IsNull(申請日) Then Exit Function
月初 = DateSerial(Year([申請日]), Month([申請日]) + 1, 1)
Do
Select Case Weekday(月初)
Case vbMonday To vbFriday
If IsNull(DLookup("祝日名", "T_祝日", "日付=#" & 月初 & "#")) Then
Exit Do
End If
End Select
月初 = 月初 + 1
Loop
End Function
PARAMETERS [Forms]![フォーム1]![表示月] DateTime;
SELECT 製品ID, Sum(出庫) AS 当月出庫, Sum(入庫) AS 当月入庫
FROM Q入出庫明細のクロス集計クエリ
WHERE 入出庫日 Between DateSerial(Year([Forms]![フォーム1]![表示月]),Month([Forms]![フォーム1]![表示月]),1) And DateSerial(Year([Forms]![フォーム1]![表示月]),Month([Forms]![フォーム1]![表示月])+1,1)-1
GROUP BY 製品ID;
Q当月まで入出庫
PARAMETERS [Forms]![フォーム1]![表示月] DateTime;
SELECT Q入出庫明細のクロス集計クエリ.製品ID, Sum(出庫) AS 出庫の合計, Sum(入庫) AS 入庫の合計, 製品.製品名
FROM Q入出庫明細のクロス集計クエリ LEFT JOIN 製品 ON Q入出庫明細のクロス集計クエリ.製品ID = 製品.製品ID
WHERE 入出庫日<=DateSerial(Year([Forms]![フォーム1]![表示月]),Month([Forms]![フォーム1]![表示月])+1,1)-1
GROUP BY Q入出庫明細のクロス集計クエリ.製品ID, 製品.製品名;
それぞれ必要に応じた日付の範囲(where条件)で出庫、入庫を合計します。
具体的にはフォーム1の表示月に「2019/12/1」と入っていれば
上は「Between #2019/12/1# And #2019/12/31#」、
下は「<= #2019/12/31#」
となるような条件になっています。 Q当月まで入出庫では必要に応じて製品の情報を加えておきます。
SELECT Q当月まで入出庫.製品名, Nz([在庫],0)-Nz([当月入庫],0)+Nz([当月出庫],0) AS 前月在庫, Nz([当月入庫],0) AS 入庫, Nz([当月出庫],0) AS 出庫, Nz([入庫の合計],0)-Nz([出庫の合計],0) AS 当月末在庫
FROM Q当月まで入出庫 LEFT JOIN Q当月入出庫 ON Q当月まで入出庫.製品ID = Q当月入出庫.製品ID;
'フォーム 開くとき
Private Sub Form_Open(Cancel As Integer)
Dim i As Integer
For i = 1 To 42
Me("T" & i).OnClick = "=SetDate(" & i & ")"
Next
Me.cmdPrev.OnClick = "=MoveMonth(-1)"
Me.cmdNext.OnClick = "=MoveMonth(1)"
Me.txtDate = Date 'この行を修正
SetCalendar
End Sub
Q入庫 SQL
SELECT 入庫.入庫日 AS 入出庫日, 製品.製品ID, 入庫詳細.入庫数量 AS 入出庫数, "入庫" AS 入出庫区分
FROM (入荷先 INNER JOIN 入庫 ON 入荷先.入荷先ID = 入庫.入荷先ID) INNER JOIN (製品 INNER JOIN 入庫詳細 ON 製品.製品ID = 入庫詳細.製品ID) ON 入庫.入庫ID = 入庫詳細.入庫ID;
Q出庫 SQL
SELECT 出庫.出庫日 AS 入出庫日, 製品.製品ID, 出庫詳細.出庫数量 AS 入出庫数, "出庫" AS 入出庫区分
FROM 製品 INNER JOIN ((出荷先 INNER JOIN 出庫 ON 出荷先.出荷先ID = 出庫.出荷先ID) INNER JOIN 出庫詳細 ON 出庫.出庫ID = 出庫詳細.出庫ID) ON 製品.製品ID = 出庫詳細.製品ID;
SELECT 入庫.入庫日 AS 入出庫日, 製品.製品ID, 入庫詳細.入庫数量 AS 入出庫数, "入庫" AS 入出庫区分
FROM (入荷先 INNER JOIN 入庫 ON 入荷先.入荷先ID = 入庫.入荷先ID) INNER JOIN (製品 INNER JOIN 入庫詳細 ON 製品.製品ID = 入庫詳細.製品ID) ON 入庫.入庫ID = 入庫詳細.入庫ID
UNION ALL SELECT 出庫.出庫日 AS 入出庫日, 製品.製品ID, 出庫詳細.出庫数量 AS 入出庫数, "出庫" AS 入出庫区分
FROM 製品 INNER JOIN ((出荷先 INNER JOIN 出庫 ON 出荷先.出荷先ID = 出庫.出荷先ID) INNER JOIN 出庫詳細 ON 出庫.出庫ID = 出庫詳細.出庫ID) ON 製品.製品ID = 出庫詳細.製品ID;
画像にあるレポート「合計残高試算表」には日付が入っていませんが出力する必要がありますか?
選択クエリの集計を使い日付フィールドの集計を「Where 条件」にして抽出条件を指定すれば、日付範囲でデータが抽出され、かつ、借方、貸方のグループ化ができると思いますが
クエリで日付の抽出がうまくできているならVBAはDoCmd.OpenReportメソッドでレポートを開くだけでしょう
(VBA側で日付を抽出するような何かは行いません)
何をどうやってそうなったのか、どう使いたいのかさっぱりわかりません
各レコードの借方、貸方のデータが一致していませんが、「合計残高試算表」では借方、貸方のデータを「勘定科目」として一致するもので残高を計算させたいように見えます
このクエリを基にレポートを作成しようとしているならば、その部分から見直したほうがいいです。クエリのデータ(出力結果)ではなく、SQLビューのSQL文や、元にしているデータ(テーブル)の構造を提示してください
hiroton様
確認取れました。ありがとうございました。
hiroton様
ご回答ありがとうございます。
確認してみます。
はい。閉じてはいけません。
フォームの Recordset オブジェクトにアプローチ可能な状態では
同時に、上位オブジェクト Database のインスタンスも生成されています。
DAO のオブジェクトモデルでは
フォームのセッションで参照された Database オブジェクトも
Workspace オブジェクトの下位オブジェクトであり、
上位オブジェクトが Close メソッドを呼び出した時点で
それに連なる下位オブジェクトの参照は全て破棄されることになります。
# 提示いただいた cmd_ReSet_Click のコードに
# タイプライブラリ 及び オブジェクト間の上下関係・階層構造を明示しました。
cmd_Count ボタンを押した直後に cmd_ReSet ボタンを押すと
★★★ の実行結果において
1つだけに思える Database オブジェクトの数が
実際は
( フォームで生成された )カレントデータベースの別インスタンス
( Workspaceのインスタンス生成と共に参照された )カレントデータベースの開いているコピー
の2つになっていて
共に wks オブジェクト変数の管理下になっていることが確認できるでしょう。
あぁ、すみません
回答前に少し修正を入れたらミスってました
「在庫」ではなく「当月末在庫」でした
基にしたクエリから持ってきているフィールドではなく、クエリで作ったフィールドをさらに同じクエリで参照しています
当月の在庫と当月の入出庫から逆算して前月の在庫を出しているという計算です
ちなみに一番最初のフィールドを
Q当月まで入出庫.製品ID
にするか製品名
にするか迷った挙句中途半端な形になってましたのでそこも修正してあります(レポートのレコードソースにするつもりだったので「製品名」でいいかと思いますが、さらに情報を追加したいとなったときのために製品IDも入れておいたほうがやりやすいかなぁとも思ってます)
中身を見ましたが、これだけの内容をすべて解読するのはさすがにできません。
今回の質問に関係のあるオブジェクト(テーブル、クエリ、フォーム)のみ残して、テーブルデータも現象を再現できる最低限のものにして、それを再度送ってもらえませんか。
どのフォームでどのように操作して、どのように想定通りにならないか、説明してもらえませんか。
すいません。
いただいたレポート用ソースのSQLですが[在庫]を有効なフィールドまたは式として認識できませんと表記されてしまいました。
SELECT Q当月まで入出庫.製品名, Nz([在庫],0)-Nz([当月入庫],0)+Nz([当月出庫],0) AS 前月在庫, Nz([当月入庫],0) AS 入庫, Nz([当月出庫],0) AS 出庫, Nz([入庫の合計],0)-Nz([出庫の合計],0) AS 当月末在庫
FROM Q当月まで入出庫 LEFT JOIN Q当月入出庫 ON Q当月まで入出庫.製品ID = Q当月入出庫.製品ID;
この[在庫]というのはQ当月まで入出庫、Q当月入出庫には入っていないものだと思うのですが…
のりさん、すみません。ファイルが届いているのに気が付きませんでした。
夜にファイルの中身を見させていただきます。しばらくお待ちください。
おはようございます
hatena さま ファイルは届きましたでしょうか?
下記でどうですか。
"日付=#" & 申請日 & "#"
を"日付=#" & 月初 & "#"
に変更しただけです。動作確認はしてませんので、動作確認は十分にしてください。
いくつか書式の違うレポートを作りたいということですね。
表示に差異はあっても元にするデータは同じなのでユニオンクエリ→クロス集計クエリの流れは基本的なデータの整形としてよくとる手です。
(最初から入出庫テーブルにしてしまえばユニオンクエリをやらなくていい分楽できますが)
2枚目の画像(月別在庫表)については新たに提示した手順のほうでうまくできると思います。
1枚目の画像(商品毎入出庫履歴)はちょっと複雑で、集計と明細が含まれた形なのでサブレポートを組み込むのが楽な方法かと思います。
(改ページを考えたときに先頭行をどうするか等で変わってくると思います)
前月末在庫は最後のクエリで計算されていますので、これを基にレポートを作成して、製品IDでグループ化、改ページの設定をすれば製品ごとのページが出来上がります。
明細部分はQ入出庫明細のクロス集計クエリから日付を条件にデータを抽出したデータをサブレポートにして製品IDでリンクして表示させるという形です。
最後の「合計」は吹き出しの説明がコピペになっていませんか?ちょっとよくわかりませんが見た目からすると「当月出庫数の合計」ですかね?レポートで合計する方法もまずは調べてみてください。
写真が横になって申し訳ありませんがこのようなものができればと考えていました。<a
連絡が遅くなり申し訳ございません。
何とかできるかと軽い気持ちで考えてみましたら思ったようなものができず、どうしたものかと悩んでおり遠のいておりました。
回答していただいたものでやってみます。
少々、お時間をくだされば幸いです。
回答ありがとうございます。
本当に望み通りのデータが抽出されました。
感謝の気持ちでいっぱいです。
本当にありがとうございます。
その後いかがでしょうか。
レポートで「集計実行」を使うと簡単だと言いましたが、実はこの方法には問題点があります。
とのことだったのでとりあえず形にしてから再修正を、と思っていましたが、(自分の方法のままでは)形にならなさそうな気がしてきたので追記を入れておきます。(ホントはQA形式で進めていきたかったのですが)
まず、レポートの表示を次のように考えることとします。
2019年12月
次に、レポートに表示する月はフォーム上で入力することとします。
・フォーム名:フォーム1
・フォーム1上のテキストボックス:表示月
表示月には表示したい月の1日を入力することとします。(2019年12月のレポートを表示したい場合は2019/12/1)
当月入出庫のデータ、当月在庫用のデータを作る
Q入出庫明細のクロス集計クエリを元に次のクエリを作成します。
Q当月入出庫
Q当月まで入出庫
それぞれ必要に応じた日付の範囲(where条件)で出庫、入庫を合計します。
具体的にはフォーム1の表示月に「2019/12/1」と入っていれば
上は「
Between #2019/12/1# And #2019/12/31#
」、下は「
<= #2019/12/31#
」となるような条件になっています。
Q当月まで入出庫では必要に応じて製品の情報を加えておきます。
クロス集計クエリを使う場合、フォーム上の値を使うためにはパラメーターの設定が必要です。
SQLビューであれば一番上に入っている1行ですが、デザインビューであればデザインビュー上側の適当な位置で右クリックして表示されるポップアップメニューから「パラメーター」を選択して設定できます。
レポート用のソースを作る
上の2つのクエリを基にさらにクエリを発行します。
ところどころにあるNz関数はデータがなかった時に別な値に置き換える関数です。
データがなかった時の値は
Null
になりますがNull
が含まれた計算は結果がNull
になるという特性がありますので、例えば12月の出庫がない製品の在庫を計算しようと在庫+入庫+出庫(Null)
を単純にしてしまうと計算結果がNull(画面上では表示なし)になってしまいます。このクエリを表示すれば、上に挙げたレポートの表示形式のデータが表示されますので、このクエリを基にレポートを作成すれば完成です。
ありがとうございます
さっそく試してみます!
カレンダーフォーム(F_Calendar)の開く時のイベントプロシージャを下記のように書き換えてください。
上記の修正でこちらもエラーなく表示することだできるようになります。
ありがとうございます
無事表示することができました
インポートはするときにオートナンバー型の主キーを追加して取り込みます。
次に、それをもとに下記のように変換します。
データ量か多くて手入力がたいへんなら更新クエリかVBAを使います。
Accessのテーブルとしてはこの形にしておきます。
上記のテーブルからクロス集計クエリで簡単に希望のレイアウトに変換できます。
テーブル自体を下記のようにしてしまうと、データベースとしては使いものになりません。
そこまでできたら、次は下記の手順で。
まず、クロス集計クエリで日付での抽出は、下記のように設定してください。
フィールド: 日付
集計: Where条件
抽出条件: Between #019/01/04# And #2019/01/16#
このクエリを保存します。
新規にクエリを作成して、元のデータテーブル追加して日付に抽出条件を設定します。
さらに上記で作成したクロス集計クエリを追加して必要なフィールドを表示させます。
2つのテーブルとクエリは結合はしません。
このクエリを開けばご希望の結果になります。
回答頂きありがとうございます。
教えて頂いた通りに作成してみました。
下記の流れで作成し、作成例の形と同じようになりました。
作成の流れ
クエリのデザインビューを開く
↓
フィールドを借方、借方金額のみにする
↓
集計にして、借方をグループ化、借方金額を合計にする
↓
クロス集計にする
↓
一番左のフィールドに式1:1と入力
↓
行列の入れ替えを式1→行見出し、借方→行見出し、借方金額→値にする
作成結果
式1:仮払金:現金:支払手形:諸口:消耗品:通信費:買掛金:売掛金:売上:普通預金:旅費交通費
1:20000:150000:5000:20000:4000:10000:25000:180000:3500:147000:0
※借方と借方金額の項目と数値の違いはご容赦ください。
一度にせずにひとつずつして作成していけば割と簡単にできるのでは。
まず、下記の集計クエリを作成してみましょう。
hirotonさま
ありがとうございます
先週末にファイルは送りました
ややこしく構成しているので 解読に時間がかかるのかも…
rs(i).Nameで SUBまたはFUCTIONが定義されていませんとなります
RS 認識させるところからやってみます
hatenaさん指摘のようにもう少し詳細が必要に思います
サブフォームのレコードソースをクロス集計クエリにしていて横にスクロールさせている(そのスクロールの初期位置を変えたい)と想像しての回答なのでこの前提が間違っていると回答も明後日の方向になってしまいますね
横スクロールさせたいなら
setfocus
で縦スクロールさせたいならfindfirst
でとなると思いますhirotonさま
ありがとうございます
やってみましたがダメでした
むずかしです・・・
エスパーしてみる
※試していません
こういうの?
もう少し具体的な情報を提示してください。
テーブルのフィールド構成、データ例、それをどこ(フォーム?)でどのように表示たいのか、など。
この掲示板は画像もアップロードできますので、現状のフォームの画像をアップロードするとか。
呈示されている情報だけでは、まったくイメージがつかめません。
そちらのフォームの構成が不明ですし、やろうとしていることも複雑そうです。
文章を何度か読んでみましたが、状況が把握できません。
現状のファイルをファイル送信フォームより送信してもらえませんでしょうか。
それをみながら質問の読んだら理解できるかもしれません。
ありがとうございます
無事うまく標準することができました
(おわび:回答で、クロス集計クエリとすべきところを集計クエリとしていました。わかりにくかったと思います。無事に進んでいるようで何よりです)
大元になる明細ができたら月ごとの集計を作ります。
入出庫日を各月になるように変換する必要がありますが、クエリでは「入出庫区分」を作ったように、計算結果をデータとするフィールドを出力することができます。
Q入出庫明細のクロス集計クエリを元に新しくクエリを作り製品ID,出庫,入庫フィールドと、「年月: format([入出庫日],"yyyymm")」フィールドを作成します。
このクエリ(選択クエリ)で集計機能を使い、製品IDと年月でグループ化、出庫と入庫を合計すれば各製品IDの月ごとの出庫と入庫が出来上がります。
後は、このクエリを基にレポートを作成すれば、>> 2の通り製品IDごとに各月の在庫まで表示できるでしょう。
どのような方法を考えているのか、レポートをどの程度扱えるのかわからないので今回もここまで
Format([入出庫日],"yyyymm")
の解説今回、月ごとの集計を出したということで、日付データから月データを作ります。
日付から月を取り出す関数としては
month([日付])
がありますが、データベースが運用されれば年も跨ぐでしょう。2019年の11月の数字と2020年のそれが合算されたらまずいでしょうから、「年」の情報も含んだ「年月」フィールドにします。format関数そのものについては調べてみてください。
今回は、例えば「2019/12/01」という日付のデータを「201912」のように変換する使い方になっています。
余談
いまさらですが、テーブル構造が先に出ていたのでユニオンクエリを使って~と進めましたが、入出庫ぐらいなら最初から一つのテーブルでいいんじゃないかと思います。
(最初から入出庫区分を付けたテーブルで管理し、必要に応じて入出庫区分='出庫'等のクエリを発行する)
そのほかのテーブルについても入庫・出庫で分かれていますが、内容は同じものになるのでしょう。
これらについてはむしろ、入庫であるか、出庫であるかという区分も必要ないように見えるのでデータを分けてしまうのは良くないでしょう。
このように行いました。
TRANSFORM Sum(Q入出庫明細.入出庫数) AS 入出庫数のカウント
SELECT Q入出庫明細.製品ID, Q入出庫明細.入出庫日
FROM Q入出庫明細
GROUP BY Q入出庫明細.製品ID, Q入出庫明細.入出庫日
PIVOT Q入出庫明細.入出庫区分;
Q入出庫明細のクロス集計クエリを選択し、行見出しを製品IDと入出庫日をし、列見出しを入出庫区分に選択。値を集計するフィールドを入出庫数にし、集計方法を合計を選択すればよろしいでしょうか?
>> 5
誤字脱字がありました。大変申し訳ありません。
Q出庫 SQL→ Q出庫明細 SQL
Q入庫 SQL→ Q入庫明細 SQL
無題 → Q入出庫明細 SQL
です。
hiroton 様
返信が遅くなり申し訳ございません。
上記4番で躓いてしまいました。
1から3迄は以下のように行いました。
Q入庫 SQL
SELECT 入庫.入庫日 AS 入出庫日, 製品.製品ID, 入庫詳細.入庫数量 AS 入出庫数, "入庫" AS 入出庫区分
FROM (入荷先 INNER JOIN 入庫 ON 入荷先.入荷先ID = 入庫.入荷先ID) INNER JOIN (製品 INNER JOIN 入庫詳細 ON 製品.製品ID = 入庫詳細.製品ID) ON 入庫.入庫ID = 入庫詳細.入庫ID;
Q出庫 SQL
SELECT 出庫.出庫日 AS 入出庫日, 製品.製品ID, 出庫詳細.出庫数量 AS 入出庫数, "出庫" AS 入出庫区分
FROM 製品 INNER JOIN ((出荷先 INNER JOIN 出庫 ON 出荷先.出荷先ID = 出庫.出荷先ID) INNER JOIN 出庫詳細 ON 出庫.出庫ID = 出庫詳細.出庫ID) ON 製品.製品ID = 出庫詳細.製品ID;
SELECT 入庫.入庫日 AS 入出庫日, 製品.製品ID, 入庫詳細.入庫数量 AS 入出庫数, "入庫" AS 入出庫区分
FROM (入荷先 INNER JOIN 入庫 ON 入荷先.入荷先ID = 入庫.入荷先ID) INNER JOIN (製品 INNER JOIN 入庫詳細 ON 製品.製品ID = 入庫詳細.製品ID) ON 入庫.入庫ID = 入庫詳細.入庫ID
UNION ALL SELECT 出庫.出庫日 AS 入出庫日, 製品.製品ID, 出庫詳細.出庫数量 AS 入出庫数, "出庫" AS 入出庫区分
FROM 製品 INNER JOIN ((出荷先 INNER JOIN 出庫 ON 出荷先.出荷先ID = 出庫.出荷先ID) INNER JOIN 出庫詳細 ON 出庫.出庫ID = 出庫詳細.出庫ID) ON 製品.製品ID = 出庫詳細.製品ID;
事前にインポートするためのテーブルを作成しておきます。
フィールドのデータ型は適切なものに設定しておきます。
数値なら数値型、日付なら日付型、テキストならテキスト型というように。
このテーブルにインポートします。
エクセルの方も同じ列には同じ種類のデータでないと正確にインポートはできません。日付とテキストが混在してるなどはNGです。
ありがとうございます。インポートの勉強をしてみます。
ちなみにインポートすると数字もアルファベットも短いテキストになるのでしょうか?それともエクセルの書式を文字列にしてからインポートするようなのでしょうか?
試してから結果をUPさせていただきます。
そうなると思います。私はエクセルデータをリンクテーブルで使用することはないので推測ですが。
エクセルのデータにリンクしても参照のみで更新はできないので、データベースとしての意味は少ないと思います。
アクセスのテーブルにエクセルデータをインポートして使用するのがいいと思います。