いつも大変お世話になっております。
以前より数回ご質問させて頂いておりましたが、この度、大まかな動きが完成したので
データをフロントエンドとバックエンドに分けることと相成りました。
今までは、同ACCESS内のユーザログ保管テーブル T_UserLog に対して下記のように
ログを保管していました。
Public Sub userLog(ByVal PlaceName As String, ByVal ActionName As String)
'行為とユーザをテーブルに保存
Dim DB As DAO.Database: Set DB = CurrentDb
Dim WSH As Object: Set WSH = CreateObject("WScript.Network")
'Set WSH = New IWshRuntimeLibrary.WshNetwork
'それぞれに、ユーザ名とマシン名を取得して代入
Dim PN As String: PN = PlaceName
Dim AN As String: AN = ActionName
'データ書き換え等の都合?により、一度他の変数を経由
'なんかよくわかんないけど、無いとエラー吐いちゃう
DB.Execute "insert into T_UserLog (場所,行為,ユーザー名,マシン名) values('" & PN _
& "','" & AN & "','" & WSH.UserName & "','" & WSH.ComputerName & "')"
'T_UserLogテーブルの、場所、行為、ユーザー名、マシン名に、それぞれデータを記入
End Sub
これらを、パスワード付きのバックエンドデータベース上のテーブルに保管できるようにするため
下記のように変えてみましたが、UserLogをCallすると
「パスワードが正しくありません」とエラーメッセージが出てしまいます。
※パスワード自体は合っています。
Public Sub UserLog(ByVal PlaceName As String, ByVal ActionName As String)
Dim DB As DAO.Database: Set DB = CurrentDb
Dim WSH As Object: Set WSH = CreateObject("WScript.Network")
'Set WSH = New IWshRuntimeLibrary.WshNetwork
'それぞれに、ユーザ名とマシン名を取得して代入
Dim PN As String: PN = PlaceName
Dim AN As String: AN = ActionName
'データ書き換え等の都合?により、一度他の変数を経由
'なんかよくわかんないけど、無いとエラー吐いちゃう
Dim strSQL As String: strSQL = "insert into T_UserLog (場所,行為,ユーザー名,マシン名) values ('" _
& PN & "','" & AN & "','" & WSH.UserName & "','" & WSH.ComputerName & "')"
CurrentDb.Execute strSQL & "T_UserLog IN '' [MS Access; DATABASE=C:\略\MnfctMng_BEDB.accdb;PWD=PASSWORD;];"""
End Sub
元々使っていた DB.execute についても、コピペしてきただけでちゃんと理解できていないので
これをうまいこと変えるやり方がよくわかっていません。(最初のByValとか、途中で変数経由している個所とかも)
たぶんわけわかんないぐらいグチャグチャなのでしょうが、見れば見るほどよくわかんなくなってきてしまって……。
そもそも、今のデータベースの分割が正しいのかどうかも自信なくなってしまって……。
お手数おかけして申し訳ないのですが、ご助力お願いできますでしょうか。
なお、まだ自分のデスクトップ上で動きの確認をしている段階なので、バックエンドもフロントエンドも同じフォルダ内になります。
変更後のVBA(下の方)のDim strSQL行の最後に select * from を加筆し、
と書き直した所、CurrentDb.Execute行に 最後の;が足りないエラーが出てしまいました。
strSQLの内容がまずい気がするんですが、いかがでしょうか…。
コードの記述はちょっと気に掛けてあげると問題にも気づきやすくなります
問題のあるコードそのまま書き換え
INSERT INTO ステートメント
外部ファイルに接続する場合の記述は
VALUESを使った記述の場合「外部ファイルに接続する方法」の記述がありませんね・・・
まぁ、Microsoftの公式資料なんてそんなもんです。きっと似たような記述をすればなんとかなるはず
お試しを
hiroton さん
お早いご返事誠に痛み入ります。
実際に置換してみたところ、うまくいきました・・・!
ありがとうございます!
VBAでSQL文を書いてると、ゴチャついてきちゃいますね。
追加で代入していく方法も今後用いて、着実にミスの無いようにしていきたいです。
また、早速参考にして、UserLogの古い履歴をイイカンジに消す CleanLog にも頑張って適用してみました。下記。
これによって、BEDBの方の古いログも消すことができましたが、これで問題ないでしょうか…。
ログなので別にミスって全消去になってもそこまで問題はないのですが、DELETEを扱うので
すこし心配になってしまって。
ご教示の程宜しくお願い致します。
難しい質問ですねぇ
実行されるクエリが、という意味なら
DB.Execute strSQL
の行でのstrSQL
の中身は問題ないように思いますVBAコードの良し悪しという意味なら突っ込みどころも出てきます
とりあえず、完全にNGなので指摘しますが
RemoveDate
はDate
型の変数です。Format()
は文字列を返します。Date
型の変数に文字列を代入しようとしているので暗黙の型変換が発生します。この行は結局と変わりません。完全に無駄な処理です
他の記述については、好みの問題まで発展しそうな話ので触れないことにしておきます
hirotonさん
ありがとうございます。
元のプログラム文で、日数指定をしてから、「~~以前のデータを削除します」みたいなMSGBOX
を出していたので、formatで文字列に変えてました。
ってことは、strSQL内のWHERE条件も "where 日時<" & RemoveDate & で
わざわざ##囲みしなくても良いんでしょうか…。
それともエラー回避のために念のためつけておくのが安牌でしょうか…。
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さん
申し訳ありません、言葉足らずでした。
RemoveDate = Format(RemoveDate, "yyyy/mm/dd hh:mm") を抜けば、という
考えで勝手に先走ってました…。申し訳ありません。
日付が内部では数値で云々の箇所は、昔に、自作カレンダーフォームの移動関数
のあたりでhatena氏から聞き及んでおりました…!
ご尽力を無駄にしてしまうような形となってしまい申し訳ありません。
ちなみにですけど、テーブルをリンクテーブルにしたらだめなんですかね?
そうすればVBA変えなくていいしクエリとか使ってるならそれもそのままでOKになるし・・・フォルダ構成が変わったとかの時も対応できるし、バッチリだとおもうんですが。
あとACCSESSはデータを消しても容量が減らないので、捨てるデータはたとえば月単位でDB作って書き込み、月が替わったらDB切り替えするとか、そもそも隠す内容でない&検索するとか再利用しないならCSVに吐き出していくとかでも良い気がします。
なおリンクテーブルにするなら参考↓
ACCESSのVBAでリンクテーブルを更新する
朱色さん
ありがとうございます。
大変申し訳ないのですが、私の不勉強故、バックエンドデータベース上のテーブルを参照する場合に「SELECT~ FROM~ 」や「INSERT INTO~ VALUE~」を用いたりすることと、朱色さんが今回説明してくださっているリンクテーブルへの変更云々との違いがよくわかりません。
今回提示している、UserLogに関するVBA以外は変更していませんが、情報の閲覧や編集はできているので、大きな不便は感じていないのですが…。