Public Sub CleanLog(Day As Integer)
'上記で登録したユーザーAccessデータを、いい感じの古さの物から削除
Dim RemoveDate As Date: RemoveDate = DateAdd("d", -Day, Now)
'今の日にちから、●●日前 を特定する関数
RemoveDate = Format(RemoveDate, "yyyy/mm/dd hh:mm")
'特定した日付を、xxxx/xx/xx xx:xx の形に整える
Dim DB As DAO.Database: Set DB = CurrentDb
Dim strSQL As String
strSQL = strSQL & "delete from T_UserLog "
strSQL = strSQL & "IN '' [MS Access; PWD=PASSWORD; DATABASE=C:\略\MnfctMng_BEDB.accdb;] "
strSQL = strSQL & "where 日時<#" & RemoveDate & "#"
DB.Execute strSQL
'上記の日時からのデータをすべて削除する
End sub
レポートで6ヶ月分のカレンダー表示 - hatena chips
上記の テーブル「T_月」に 0 から 11 までの数値を入力すれば12ヶ月分のデータが出力されます。
それを元にレポートを作成すればいいでしょう。
あとは、上記のリンク先の方法を理解して応用してください。
ページ関係の制御はメインレポート側で行いますので、サブフォームにはページという概念はないです。
レポートヘッダーかグループヘッダーを使ってください。
ということなら、まずは週マスターテーブルを作成すると管理が楽になりそうです。
例えば下記のような感じです。
テーブル名 T_週
フォームはメイン/サブフォーム形式にして、
メインフォームは上記のテーブルをレコードソースにして、サブフォームは勤務時間管理用のテーブルをレコードソースにします。「週ID」フィールドも勤務時間管理テーブルに持たせます。
サブフォームのヘッダーかフッターにテキストボックスを配置してコントロールソースに下記の式を設定すれば、
勤務時間計や勤務時間が8時間以上の回数を表示できます。
=Sum([退勤時間]-[出勤時間]) * 24
=Sum(IIf((([退勤時間]-[出勤時間]) * 24)>=8, 1, 0))
テーブルを開いてそこで直接更新しても、テーブルやテーブルのフィールドではイベントが発生しないので、自動でフィールドBに計算結果を代入することはできません。
フィールドAを更新したときに自動でフィールドBも更新するには、テーブルと連結した入力フォームを作成する必要があります。
フォーム上では、フィールドと連結したテキストボックスで入力することになります。
テキストボックスの更新後処理イベントを使うことになります。
以上の説明で理解いただけたでしょうか。
不明な点があれば、具体的に質問してください。
フィールドA→テキストボックス→フィールドBとするのですか?
フィールドA→フィールドBではなにか不具合がありますか?
どちらでもお好みでいいと思います。
単価×個数 というような単純な式ならクエリにする場合が多いですね。
フォームや他のレポートでも使いまわせますので。
複雑な式で、そのレポートのみでしか使用しない場合はレポート上のテキストボックスのコントロールソースに式を設定する場合もあります。デザインビューですぐに確認できますし、修正もそこで完了します。
しかし、たいていは入力フォームでも計算結果を表示させる場合が多いので、共通のクエリにしてクエリで式を設定する方が多いですね。
目的次第だと思います。
入力した直後に結果を格納したいのなら、テーブルと連結した入力フォームを作成して、フィールドAと連結したテキストボックスの更新後処理のイベントでフィールドBに計算結果を格納することになります。
レポートを選択すれば幅は表示されます。ただし、変更はデザインビューにする必要があります。
レイアウトで数値指定で幅を設定できましたっけ?
プロパティ見てたけど見つけられませんでした
いつも迅速、ご丁寧なご返事をありがとうございます。
参考にして頑張りたいと思います。
用紙の幅-左右の余白 が印刷範囲の幅というように計算するか、
プレビューのさせて、はみ出たら狭くする、足らなければ広くするというようにレポート幅を調整することになりますね。
例えば、A4縦なら用紙幅210mm 左右余白が各15mmなら 210-(15*2)=180mm が印刷範囲の幅になります。
項目のレイアウトによって、印刷設定で2ページ印刷にするか、列数2にするか、レポート幅を用紙幅の2倍にするか、を選択します。
そこで、クエリに代入コーナーを設け、2021/3と入力したら、」
の意味が、
クエリのデザインビューで、フィールド欄に、[]で囲んだ式を入力しており、プレビューするときにダイアログが開きそこに日付を入力するとその日付で抽出されるということでしょうか。
この場合、フィールド欄に入力した式をパラメーターといい、パラメーターを含むクエリのことをパラメータクエリといいます。
基本的な用語ですので覚えておきましょう。
現状は、商品一覧クエリに
[日付指定【例:2021/3】]
というパラメーターが設定してあり、商品一覧レポート(メインレポート)のレコードソースになっている。この商品一覧クエリからさらに集計クエリを作成して、商品別集計クエリ(サブレポート)のレコードソースにしている。
この場合、それぞれがパラメータークエリになりますので、2回入力を要求されます。
上記のような状況だと理解しました。
対処法ですが、パラメーターの式にはフォームのテキストボックスを参照する式にすることができます。そうすると、フォームを開いてテキストボックスに日付を入力してからレポートを開けば、パラメーターダイアログか開くことはないです。
設定する式は、下記のような書式になります。
Forms!フォーム名!テキストボックス名
テキストボックスなら設定で日付選択カレンダーを表示させたりすることが出来ますし、そのフォームにレポートを開くコマンドボタンを配置しておけば、より使いやすいものになります。
朱色さん
ありがとうございます。
大変申し訳ないのですが、私の不勉強故、バックエンドデータベース上のテーブルを参照する場合に「SELECT~ FROM~ 」や「INSERT INTO~ VALUE~」を用いたりすることと、朱色さんが今回説明してくださっているリンクテーブルへの変更云々との違いがよくわかりません。
今回提示している、UserLogに関するVBA以外は変更していませんが、情報の閲覧や編集はできているので、大きな不便は感じていないのですが…。
hirotonさん
申し訳ありません、言葉足らずでした。
RemoveDate = Format(RemoveDate, "yyyy/mm/dd hh:mm") を抜けば、という
考えで勝手に先走ってました…。申し訳ありません。
日付が内部では数値で云々の箇所は、昔に、自作カレンダーフォームの移動関数
のあたりでhatena氏から聞き及んでおりました…!
ご尽力を無駄にしてしまうような形となってしまい申し訳ありません。
RemoveDate
をDim RemoveDate As Date
と宣言している(date型で宣言している)ので「#」は必須です(ないと困ったことになります)こういう処理(date型を文字列にして出力する)と
日付(+時刻)っぽい文字に変わります
問題のコードも
が実際に処理されるときは
RemoveDate
が日付っぽい文字に変わるのでそれをSQL文上での日付データとして扱うためには「#」で囲む必要があります。これを怠ると、例えばのようなSQL文になるので、「2021/4/8」=「2021÷4÷8」=「63.15625」
が実行されます。やばいですね
ちなみにdate型というのはコンピュータの内部では数値データです。
Date Data Type (Visual Basic)
つまり、上のSQLは
と同じです。SQL構文として問題のない文なので動きます。でも、これでは意図した通りの結果は得られませんよね?ちょーやばいです。エラーを出してくれたほうがマシです
hirotonさん
ありがとうございます。
元のプログラム文で、日数指定をしてから、「~~以前のデータを削除します」みたいなMSGBOX
を出していたので、formatで文字列に変えてました。
ってことは、strSQL内のWHERE条件も "where 日時<" & RemoveDate & で
わざわざ##囲みしなくても良いんでしょうか…。
それともエラー回避のために念のためつけておくのが安牌でしょうか…。
ちなみにですけど、テーブルをリンクテーブルにしたらだめなんですかね?
そうすればVBA変えなくていいしクエリとか使ってるならそれもそのままでOKになるし・・・フォルダ構成が変わったとかの時も対応できるし、バッチリだとおもうんですが。
あとACCSESSはデータを消しても容量が減らないので、捨てるデータはたとえば月単位でDB作って書き込み、月が替わったらDB切り替えするとか、そもそも隠す内容でない&検索するとか再利用しないならCSVに吐き出していくとかでも良い気がします。
なおリンクテーブルにするなら参考↓
ACCESSのVBAでリンクテーブルを更新する
難しい質問ですねぇ
実行されるクエリが、という意味なら
DB.Execute strSQL
の行でのstrSQL
の中身は問題ないように思いますVBAコードの良し悪しという意味なら突っ込みどころも出てきます
とりあえず、完全にNGなので指摘しますが
RemoveDate
はDate
型の変数です。Format()
は文字列を返します。Date
型の変数に文字列を代入しようとしているので暗黙の型変換が発生します。この行は結局と変わりません。完全に無駄な処理です
他の記述については、好みの問題まで発展しそうな話ので触れないことにしておきます
hiroton さん
お早いご返事誠に痛み入ります。
実際に置換してみたところ、うまくいきました・・・!
ありがとうございます!
VBAでSQL文を書いてると、ゴチャついてきちゃいますね。
追加で代入していく方法も今後用いて、着実にミスの無いようにしていきたいです。
また、早速参考にして、UserLogの古い履歴をイイカンジに消す CleanLog にも頑張って適用してみました。下記。
これによって、BEDBの方の古いログも消すことができましたが、これで問題ないでしょうか…。
ログなので別にミスって全消去になってもそこまで問題はないのですが、DELETEを扱うので
すこし心配になってしまって。
ご教示の程宜しくお願い致します。
早速のご返事誠にありがとうございます。
試してみたいと思います。
コードの記述はちょっと気に掛けてあげると問題にも気づきやすくなります
問題のあるコードそのまま書き換え
INSERT INTO ステートメント
外部ファイルに接続する場合の記述は
VALUESを使った記述の場合「外部ファイルに接続する方法」の記述がありませんね・・・
まぁ、Microsoftの公式資料なんてそんなもんです。きっと似たような記述をすればなんとかなるはず
お試しを
変更後のVBA(下の方)のDim strSQL行の最後に select * from を加筆し、
と書き直した所、CurrentDb.Execute行に 最後の;が足りないエラーが出てしまいました。
strSQLの内容がまずい気がするんですが、いかがでしょうか…。
解決しました!!
リレーション先登録されている社員番号と一致しないせいでエラーが出ていました・・・
同じように登録するとエラーなしで表示されました!
お手数をお掛けし申し訳ありません。
レコードソースのパラメータはそのまま参照できます。
テキストボックスを2つ配置して、コントロールソースにそれぞれ下記のように設定すればOKです。
=[はじまりの日付【例:2021/3/1】]
=[終わりの日付【例:2021/4/2】]
このクエリを実行するとエラーは表示されますか?または、レコードが表示されませんか?
素人がググっただけですが、社員番号がnullになるものが無くても、LEFT JOINの結果、組み合わせでnullになっているせいとか?
hiroton様
回答いただき誠にありがとうございます。
私も原因がそれだと思い探したのですが社員番号がnullになるのはありませんでした。。。
SELECT 社員マスタ.社員番号, 社員マスタ.氏名, 社員マスタ.入社年月日, 社員マスタ.生年月日, 全社員住所歴マスタ.郵便番号,
全社員住所歴マスタ.都道府県, 全社員住所歴マスタ.市区町村, 全社員住所歴マスタ.番地,
全社員住所歴マスタ.[マンション等], ([全社員住所歴マスタ].[都道府県] & ([全社員住所歴マスタ].[市区町村]) & [全社員住所歴マスタ].[番地] & ([全社員住所歴マスタ].[マンション等])) AS 全住所,
DateDiff("yyyy",[生年月日],Date())+(Format([生年月日],"mmdd")>Format(Date(),"mmdd")) & "歳" AS 年齢, 全社員住所歴マスタ.登録日
FROM 社員マスタ LEFT JOIN 全社員住所歴マスタ ON 社員マスタ.社員番号 = 全社員住所歴マスタ.社員番号
WHERE (((全社員住所歴マスタ.登録日)=DMax("登録日","全社員住所歴マスタ","社員番号 =" & [全社員住所歴マスタ].[社員番号])) AND ((社員マスタ.退職の有無)=False));
[全社員住所歴マスタ].[社員番号]
がnullになるレコードがあるのでは?高さに応じて上位置を少し小さくすることになるかと。その辺はトライ&チェックが微調整するしかないかなと思います。
例えばヘッダーや詳細の一番下におきたいときにはどうすればいいのでしょうか?
数値指摘での位置合わせは、どうもその要素の真ん中が基準になっているような、気がします
おー!気が付きませんでした
線に見えるけど細い四角なんですね
調整もしやすそうです!
大変参考になりました!
Accessのレポートで罫線はなかなか難しいですね。
細線とか1ポイントとか設定しても、プリンターによって太さが異なったりします。
直線コントロールの代わりに四角形コントロールで、境界線は透明、背景色を黒にして、高さをいろいろ変更すると細かく調整できます。
下記は、直線コントロールの幅、四角形コントロールの高さを変更したものをプレビューで500%ズームしたもののキャプチャーです。
設計する手間やコード量が増えるという意味です。
再請求や修正・削除が無制限にできるという自由度と引き換えに、作成する時間がかかるし、メンテナンスも大変そうです。
一度、作成してしまえばいいですが。
インボイス制度がもうすぐ始まるそうですが、請求書の発行者もなんからの形で控えを保存しておく必要があるそうです。
下記で議論してますのでご参考に。
請求書をPDFで保存するかどうか Microsoft Access 掲示板 - zawazawa
hirotonさんへ
「クロス集計クエリからレポート印刷」に関して最初の設計図と現状は大幅に変わってしまいました。
アクセスでクロス集計表を作る場合は列と値は1つしか設定できないという認識がありました。
現状は最終的にクロス集計表としての複数の列と値を設定できるようになり求める設計図が大幅に広がってしまいました。
「クロス集計クエリからレポート印刷」というトピックへの書き込みはこれで最後にします。
一か月近い期間のアドバイスありがとうございました。
また機会がありましたらよろしくお願いします。
頭で考えれば単純な処理なんですが体系立てるのはなかなかむずかしいみたいですね
削除請求書番号に記載するにしても、用意したフィールドよりも削除が発生するかもしれない(常識的に考えれば2つも用意すれば十分でしょうけど)といった不安もありますね
履歴テーブルをつくるとそれなりのコストがかかるというのはどういった意味でしょうか?
保存容量や動作の軽さに影響するという意味ですか?
いっそ削除したものは、データベースには残さずに請求書発行時にPDFとして写しを作成し、確認用としてとっておく、とかが楽なのかもしれないと思ってきました
起こる確率の低いイレギュラーなことばかり考えてしまい、全然進まなくなるのが悪い癖ですね
その要件は、昔からなかなか難しい要件の一つです。
いろいろな方法があると思います。
請求した通りに間違いなく、遅れもなく入金してくれれば問題はないのですが、いろいろイレギュラーなことがありますからね。
期限までに入金してくれなかったり、
一部だけ入金してきたり、
まとめて入金してきたり、
たまに、余分に入金してきたり、
・・・
こちら側にも、入力間違いとか、ありますしね。
これらのイレギュラーにも柔軟に対応できるようにするには、ある程度データに冗長性を持たせることになりますね。
自分もそのような設計にすると思います。
あと、入金日も持たせるかな。
期限をすぎても、入金されない場合は、再請求する必要がありますので、
再請求時の請求書番号も必要になりますね。
品番に再請求が発生するなら、別テーブルに履歴として保存しておく必要があるかも知れません。
これは、当然そうすべきでしょうね。
売上テーブルに、請求書番号、削除請求書番号、というフィールドを持たせるか、
別テーブルにして履歴をすべて残すか、ですね。
履歴には上記の再請求も含めて残すといいでしょう。
再請求や修正/削除がどの程度発生するかによってどちらかに決めることになると思います。
別テーブルで履歴を残すというのはそれなりにコストがかかりますので、それに見合うかどうか、検討してください。
区切りをどこで付けるかというのは悩みどころですが、そろそろ質問を分けたほうがよさそうです
当初の質問として
とあり、それに対してデータベース的なアプローチ(クエリ・SQLを駆使してデータ整形)で回答を付けました。ACCESS的なアプローチで連番を振ったり、処理速度的に厳しいところをVBAで対応したりもしましたが、元データに依存するような部分はなかったと思います。
言葉にすると「大きなデータをページ毎のデータに整形する方法」ですね
追加の質問は元データから項目が追加されてきているし、「各ページのデータができた後のレポート表示のしかた」といった感じで最初の質問からは内容が離れてきているので、改めて必要な内容(データ構造、レポートの表示イメージ等)を整理した上で新たな質問にしてください
[テキスト122]~[テキスト125]は適切な名前で運用するか、
[テキスト122]→n0ケース数表示
等、注釈を追記するようにしてください(質問者以外中身のわからないモノでは回答しにくいです)
それと、コードはなるべくコピペで提示するようにしましょう。いろいろ捗ります
コードブロック
下記の MessageBoxTimeoutA を使う方法はどうでしょうか。
自動的にメッセージボックスを閉じるならWSHは使わない!messageboxtimeoutAを使う | タケイチの備忘録
Accessに関する情報交換の掲示板ですが、どの辺がAccessと関係ありますか。
AccessのVBAで実現したいという話ですか。
AccessからWSHを呼び出すという話ですか。