Microsoft Access 掲示板

ユーザログ保管のVBAを、PWD付バックエンドDBに保管させたい

9 コメント
views
4 フォロー

いつも大変お世話になっております。
以前より数回ご質問させて頂いておりましたが、この度、大まかな動きが完成したので
データをフロントエンドとバックエンドに分けることと相成りました。

今までは、同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とか、途中で変数経由している個所とかも)
たぶんわけわかんないぐらいグチャグチャなのでしょうが、見れば見るほどよくわかんなくなってきてしまって……。
そもそも、今のデータベースの分割が正しいのかどうかも自信なくなってしまって……。
お手数おかけして申し訳ないのですが、ご助力お願いできますでしょうか。

なお、まだ自分のデスクトップ上で動きの確認をしている段階なので、バックエンドもフロントエンドも同じフォルダ内になります。

ゲッキョク駐車場
作成: 2021/04/07 (水) 10:37:12
最終更新: 2021/04/07 (水) 10:40:15
通報 ...
1
ゲッキョク駐車場 2021/04/07 (水) 11:07:42 修正 cb55f@f6500

変更後のVBA(下の方)のDim strSQL行の最後に select * from を加筆し、

  Dim strSQL As String: strSQL = "insert into T_UserLog (場所,行為,ユーザー名,マシン名) values ('" _
  & PN & "','" & AN & "','" & WSH.UserName & "','" & WSH.ComputerName & "') select * from "
  
  CurrentDb.Execute strSQL & "T_UserLog IN '' [MS Access; DATABASE=C:\略\MnfctMng_BEDB.accdb;PWD=PASSWORD;];"""

と書き直した所、CurrentDb.Execute行に 最後の;が足りないエラーが出てしまいました。
strSQLの内容がまずい気がするんですが、いかがでしょうか…。

2
hiroton 2021/04/07 (水) 11:40:44 bb98d@f966d

コードの記述はちょっと気に掛けてあげると問題にも気づきやすくなります

問題のあるコードそのまま書き換え

Dim strSQL As String
strSQL = strSQL & "insert into T_UserLog (場所,行為,ユーザー名,マシン名)"
strSQL = strSQL & " values ('" & PN & "','" & AN & "','" & WSH.UserName & "','" & WSH.ComputerName & "')"
strSQL = strSQL & " T_UserLog IN '' [MS Access; DATABASE=C:\略\MnfctMng_BEDB.accdb;PWD=PASSWORD;];"""
CurrentDb.Execute strSQL

INSERT INTO ステートメント

外部ファイルに接続する場合の記述は

複数のレコードを追加するクエリは、次のとおりです。

INSERT INTO target [(field1[, field2[, ...]])] [IN externaldatabase]
SELECT [source.]field1[, field2[, ...]
FROM tableexpression

1 つのレコードを追加するクエリは、次のとおりです。

INSERT INTO target [(field1[, field2[, ...]])]
VALUES (value1[, value2[, ...])

VALUESを使った記述の場合「外部ファイルに接続する方法」の記述がありませんね・・・

まぁ、Microsoftの公式資料なんてそんなもんです。きっと似たような記述をすればなんとかなるはず

INSERT INTO target [(field1[, field2[, ...]])] [IN externaldatabase]
VALUES (value1[, value2[, ...])

Dim strSQL As String
strSQL = strSQL & "insert into T_UserLog (場所,行為,ユーザー名,マシン名)"
strSQL = strSQL & " IN '' [MS Access;DATABASE=C:\略\MnfctMng_BEDB.accdb;PWD=PASSWORD;]"
strSQL = strSQL & " values ('" & PN & "','" & AN & "','" & WSH.UserName & "','" & WSH.ComputerName & "')"
CurrentDb.Execute strSQL

お試しを

3
ゲッキョク駐車場 2021/04/07 (水) 14:20:03 cb55f@f6500

hiroton さん
お早いご返事誠に痛み入ります。
実際に置換してみたところ、うまくいきました・・・!
ありがとうございます!
VBAでSQL文を書いてると、ゴチャついてきちゃいますね。
追加で代入していく方法も今後用いて、着実にミスの無いようにしていきたいです。

また、早速参考にして、UserLogの古い履歴をイイカンジに消す CleanLog にも頑張って適用してみました。下記。

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

これによって、BEDBの方の古いログも消すことができましたが、これで問題ないでしょうか…。
ログなので別にミスって全消去になってもそこまで問題はないのですが、DELETEを扱うので
すこし心配になってしまって。
ご教示の程宜しくお願い致します。

4
hiroton 2021/04/07 (水) 17:08:36 bb98d@f966d

難しい質問ですねぇ
実行されるクエリが、という意味ならDB.Execute strSQLの行でのstrSQLの中身は問題ないように思います


VBAコードの良し悪しという意味なら突っ込みどころも出てきます

とりあえず、完全にNGなので指摘しますが

RemoveDate = Format(RemoveDate, "yyyy/mm/dd hh:mm")

RemoveDateDate型の変数です。Format()は文字列を返します。Date型の変数に文字列を代入しようとしているので暗黙の型変換が発生します。この行は結局

RemoveDate = RemoveDate

と変わりません。完全に無駄な処理です

他の記述については、好みの問題まで発展しそうな話ので触れないことにしておきます

6
ゲッキョク駐車場 2021/04/08 (木) 09:26:19 cb55f@f6500 >> 4

hirotonさん
ありがとうございます。

元のプログラム文で、日数指定をしてから、「~~以前のデータを削除します」みたいなMSGBOX
を出していたので、formatで文字列に変えてました。

ってことは、strSQL内のWHERE条件も "where 日時<" & RemoveDate & で
わざわざ##囲みしなくても良いんでしょうか…。
それともエラー回避のために念のためつけておくのが安牌でしょうか…。

7
hiroton 2021/04/08 (木) 14:09:01 3ea36@f966d >> 4

それともエラー回避のために念のためつけておくのが安牌でしょうか…。

RemoveDateDim RemoveDate As Dateと宣言している(date型で宣言している)ので「#」は必須です(ないと困ったことになります)

Dim d As Date
d = date
Debug.print d & ""

こういう処理(date型を文字列にして出力する)と

2021/04/08

日付(+時刻)っぽい文字に変わります

問題のコードも

strSQL = strSQL & "where 日時<#" & RemoveDate & "#"

が実際に処理されるときはRemoveDateが日付っぽい文字に変わるのでそれをSQL文上での日付データとして扱うためには「#」で囲む必要があります。これを怠ると、例えば

where 日時<2021/4/8

のようなSQL文になるので、「2021/4/8」=「2021÷4÷8」=「63.15625」

where 日時<63.15625

が実行されます。やばいですね

ちなみにdate型というのはコンピュータの内部では数値データです。
Date Data Type (Visual Basic)
つまり、上のSQLは

where 日時<#1900/03/03 3:45:00#

と同じです。SQL構文として問題のない文なので動きます。でも、これでは意図した通りの結果は得られませんよね?ちょーやばいです。エラーを出してくれたほうがマシです

8
ゲッキョク駐車場 2021/04/08 (木) 16:19:14 cb55f@f6500 >> 4

hirotonさん

申し訳ありません、言葉足らずでした。
RemoveDate = Format(RemoveDate, "yyyy/mm/dd hh:mm") を抜けば、という
考えで勝手に先走ってました…。申し訳ありません。

日付が内部では数値で云々の箇所は、昔に、自作カレンダーフォームの移動関数
のあたりでhatena氏から聞き及んでおりました…!

ご尽力を無駄にしてしまうような形となってしまい申し訳ありません。

5
朱色 2021/04/07 (水) 20:19:08 db0eb@4c730

ちなみにですけど、テーブルをリンクテーブルにしたらだめなんですかね?
そうすればVBA変えなくていいしクエリとか使ってるならそれもそのままでOKになるし・・・フォルダ構成が変わったとかの時も対応できるし、バッチリだとおもうんですが。
あとACCSESSはデータを消しても容量が減らないので、捨てるデータはたとえば月単位でDB作って書き込み、月が替わったらDB切り替えするとか、そもそも隠す内容でない&検索するとか再利用しないならCSVに吐き出していくとかでも良い気がします。

なおリンクテーブルにするなら参考↓
ACCESSのVBAでリンクテーブルを更新する

9
ゲッキョク駐車場 2021/04/08 (木) 16:30:23 cb55f@f6500 >> 5

朱色さん
ありがとうございます。

大変申し訳ないのですが、私の不勉強故、バックエンドデータベース上のテーブルを参照する場合に「SELECT~ FROM~ 」や「INSERT INTO~ VALUE~」を用いたりすることと、朱色さんが今回説明してくださっているリンクテーブルへの変更云々との違いがよくわかりません。

今回提示している、UserLogに関するVBA以外は変更していませんが、情報の閲覧や編集はできているので、大きな不便は感じていないのですが…。