Re:SALOON & VBA

ACCESS簡易検索ツール(EXCEL VBA)①



'===============(標準モジュール)=====================================
Option Explicit
'+------------------------------------------------------------------------------
'| 共通変数
'| 参照設定:Microsoft Activex Data Object X.X Library と
'| 参照設定:Microsoft ADO Ext.X.X for DDL and Security が必要
'+------------------------------------------------------------------------------
Public Ps_Mdb As String      'ACCESS MDB FILE
Public JetCn As ADODB.Connection 'コネクション
Public JetRs As ADODB.Recordset 'レコードセット
Public ErrMsg As String      'エラーメッセージ
'+------------------------------------------------------------------------------
'| 処理名    :ボタン「TABLE」
'+------------------------------------------------------------------------------
Sub テーブル一覧()
  On Error GoTo Err_Han
  ErrMsg = ""
' 画面固定
  Application.ScreenUpdating = False
  Application.Speech.Speak "TABLE LISTING"
' データベース接続
  Call PS_DbConn
  If ErrMsg <> "" Then GoTo TBL_END
  Dim MyCtg As New ADOX.Catalog
  Dim MyTbl As ADOX.Table
  Dim iRow  As Integer
' ACCESS(ADOX)接続
  MyCtg.ActiveConnection = JetCn
' 項目リストクリア
  Worksheets("COLUMN").Select
  Range(Range("A2:C2"), Selection.End(xlDown)).ClearContents
' テーブルリストクリア
  Worksheets("TBL").Select
  Range(Range("A2:D2"), Selection.End(xlDown)).ClearContents
' データを取得(カタログ情報)
  iRow = 1
  For Each MyTbl In MyCtg.Tables
   If (MyTbl.Type = "TABLE" Or MyTbl.Type = "VIEW") And _
     Left(MyTbl.Name, 1) <> "~" Then
     If UserForm1.TextBox1.Text = "" Or _
      InStr(MyTbl.Name, UserForm1.TextBox1.Text) > 0 Then
      iRow = iRow + 1
      Worksheets("TBL").Cells(iRow, 1).Value = MyTbl.Name
      Worksheets("TBL").Cells(iRow, 2).Value = MyTbl.Type
      Worksheets("TBL").Cells(iRow, 3).Value = MyTbl.DateCreated
      Worksheets("TBL").Cells(iRow, 4).Value = MyTbl.DateModified
     End If
   End If
  Next MyTbl
' リストボックス範囲の変更
  If iRow < 2 Then iRow = 2
  Application.Names("テーブル一覧").RefersTo = "=TBL!$A$2:$A$" & iRow
  Worksheets("TBL").Range("A1").Select
TBL_END:
' オブジェクト消去
  Set MyTbl = Nothing
  Set MyCtg = Nothing
' データベース接続切断(NO COMMIT)
  Call PS_DbDisConn(False)
 
' 画面固定解除
  Application.ScreenUpdating = True
  If ErrMsg <> "" Then
   MsgBox ErrMsg
   Exit Sub
  End If
  Unload UserForm1
  UserForm1.Show
  Exit Sub
Err_Han:
  If ErrMsg = "" Then
   ErrMsg = Err.Description
  End If
  GoTo TBL_END
End Sub
'+------------------------------------------------------------------------------
'| 処理名    :ボタン「COLUMN」
'+------------------------------------------------------------------------------
Sub 項目一覧()
  On Error GoTo Err_Han
  ErrMsg = ""
  If UserForm1.ListBox1.Value = "" Then
   Application.Speech.Speak "You Don't select Tables"
   MsgBox "テーブルが選択されていません!"
   Err.Raise 0
   Exit Sub
  End If
' 画面固定
  Application.ScreenUpdating = False
  Application.Speech.Speak "COLUMN LISTING"
' データベース接続
  Call PS_DbConn
  If ErrMsg <> "" Then GoTo ITEM_END
  Dim stSQL  As String
  Dim iRow  As Integer: iRow = 1
  Dim i    As Integer
  Dim j    As Integer: j = 0
  Dim k    As Integer: k = 0
  Dim m    As Integer
  Dim stTblNo As String: stTblNo = ""
' 選択ありを数え、マークする
  For i = 0 To UserForm1.ListBox1.ListCount - 1
   If UserForm1.ListBox1.Selected(i) Then
     j = j + 1
     Worksheets("TBL").Cells(i + 2, 2).Value = 1  'FLG ON
   Else
     Worksheets("TBL").Cells(i + 2, 2).Value = ""  'FLG OFF
   End If
  Next i
' 項目リストクリア
  Worksheets("COLUMN").Select
  Application.Goto Reference:="項目一覧"
  Selection.ClearContents
  iRow = 1
  For i = 0 To UserForm1.ListBox1.ListCount - 1
   If UserForm1.ListBox1.Selected(i) Then
     If j > 1 Then              '複数テーブル選択か?
      k = k + 1
      stTblNo = "T" & k & "."
     End If
     stSQL = "SELECT * FROM " & UserForm1.ListBox1.List(i)
     Set JetRs = JetCn.Execute(stSQL)
    ' 項目展開
     For m = 0 To JetRs.Fields.Count - 1
      iRow = iRow + 1
      Worksheets("COLUMN").Cells(iRow, 1).Value = stTblNo & JetRs.Fields(m).Name '項目名
      Select Case JetRs.Fields(m).Type                      '項目型
       Case adDate, adDBTimeStamp
         Worksheets("COLUMN").Cells(iRow, 2).Value = "日付/時刻型"
       Case adChar, adLongVarChar, adVarWChar, adLongVarWChar
         Worksheets("COLUMN").Cells(iRow, 2).Value = "テキスト型"
       Case adInteger, adDouble, adNumeric, adSmallInt, adUnsignedTinyInt
         Worksheets("COLUMN").Cells(iRow, 2).Value = "数値型"
       Case adBinary, adVarBinary
         Worksheets("COLUMN").Cells(iRow, 2).Value = "バイナリ型"
       Case adBinary, adCurrency
         Worksheets("COLUMN").Cells(iRow, 2).Value = "通貨型"
       Case adBoolean
         Worksheets("COLUMN").Cells(iRow, 2).Value = "Yes/No型"
       Case Else
         Worksheets("COLUMN").Cells(iRow, 2).Value = JetRs.Fields(m).Type
      End Select
      Select Case Worksheets("COLUMN").Cells(iRow, 2).Value           '項目長
       Case "数値型", "通貨型"
         Worksheets("COLUMN").Cells(iRow, 3).Value = JetRs.Fields(m).Precision & "," _
                              & JetRs.Fields(m).NumericScale
       Case "日付/時刻型", "Yes/No型"
         Worksheets("COLUMN").Cells(iRow, 3).Value = ""
       Case Else
         Worksheets("COLUMN").Cells(iRow, 3).Value = JetRs.Fields(m).DefinedSize
      End Select
     Next m
   End If
  Next i
' リストボックス範囲の変更
  If iRow < 2 Then iRow = 2
  Application.Names("項目一覧").RefersTo = "=COLUMN!$A$2:$C$" & iRow
  Worksheets("COLUMN").Range("A2").Select
ITEM_END:
' データベース接続切断(NO COMMIT)
  Call PS_DbDisConn(False)
' 画面固定解除
  Application.ScreenUpdating = True
  If ErrMsg <> "" Then
   MsgBox ErrMsg
   Exit Sub
  End If
  Unload UserForm1
  UserForm1.Show
  Exit Sub
Err_Han:
  If ErrMsg = "" Then
   ErrMsg = Err.Description
  End If
  GoTo ITEM_END
End Sub
'+------------------------------------------------------------------------------
'| 処理名    :ボタン「SQL実行」
'+------------------------------------------------------------------------------
Sub SQL実行()
  On Error GoTo Err_Han
  ErrMsg = ""
  If UserForm1.TextBox2.Text = "" Then
   Application.Speech.Speak "You don't set SQL"
   MsgBox "SQLが設定されていません!"
   Err.Raise 0
   Exit Sub
  End If
  Dim stSQL As String
  Dim i   As Integer
' 画面固定
  Application.ScreenUpdating = False
' データ取得SQL編集
  stSQL = UserForm1.TextBox2.Text
  If InStr(stSQL, "WHERE") = 0 And _
   InStr(stSQL, "UPDATE") = 0 And _
   InStr(stSQL, "INSERT") = 0 Then
   stSQL = StrConv(stSQL, vbUpperCase)
  End If
  If Left(stSQL, 6) = "SELECT" Then
  ' データベース接続(レコードセットオプション:読み取り専用)
   Call PS_DbConn
   If ErrMsg <> "" Then GoTo DATA_END
  ' データを取得
   Application.Speech.Speak "SELECT EXECUTE"
   Set JetRs = JetCn.Execute(stSQL)
  Else
  ' データベース接続(更新あり)
   Call PS_DbConn(False)
   If ErrMsg <> "" Then GoTo DATA_END
  ' データを更新
   Application.Speech.Speak "UPDATE EXECUTE"
   JetCn.Execute (stSQL)
   GoTo HIST_ADD
  End If
' データシートクリア
  Worksheets("DATA").Select
  Cells.Clear
' 項目名展開
  For i = 0 To JetRs.Fields.Count - 1
   Worksheets("DATA").Cells(1, i + 1).Value = JetRs.Fields(i).Name
   Select Case JetRs.Fields(i).Type
     Case adDate, adDBTimeStamp
      Worksheets("DATA").Cells(2, i + 1).Value = "日付/時刻型"
     Case adChar, adLongVarChar, adVarWChar, adLongVarWChar
      Worksheets("DATA").Cells(2, i + 1).Value = "テキスト型"
     Case adInteger, adDouble, adNumeric, adSmallInt, adUnsignedTinyInt
      Worksheets("DATA").Cells(2, i + 1).Value = "数値型"
     Case adBinary, adVarBinary
      Worksheets("DATA").Cells(2, i + 1).Value = "バイナリ型"
     Case adBinary, adCurrency
      Worksheets("DATA").Cells(2, i + 1).Value = "通貨型"
     Case adBoolean
      Worksheets("DATA").Cells(2, i + 1).Value = "Yes/No型"
     Case Else
      Worksheets("DATA").Cells(2, i + 1).Value = JetRs.Fields(i).Type
   End Select
  Next i
  Rows("1:2").Interior.ColorIndex = 37
' データ展開
  Application.StatusBar = "データ展開中"
  Worksheets("DATA").Range("A3").CopyFromRecordset JetRs
  If Cells(Rows.Count, 1).Value <> "" Then
   Call CSV出力処理
  End If
  Application.StatusBar = False
HIST_ADD:
' 履歴追加
  Worksheets("HIST").Select
  Worksheets("HIST").Rows(1).Select
  Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
  stSQL = Replace(stSQL, vbNewLine & " " & vbNewLine, vbNewLine)
  stSQL = Replace(stSQL, vbNewLine & vbNewLine, vbNewLine)
  Worksheets("HIST").Cells(1, 1).Value = Trim(stSQL)
  Worksheets("HIST").Cells(1, 2).Value = Ps_Mdb
' リストボックス範囲の維持(変えない)
  Application.Names("実行履歴").RefersTo = "=HIST!$A$1:$A$20"
' データシート表示
  ActiveWindow.WindowState = xlNormal
  Worksheets("DATA").Select
  Worksheets("DATA").Range("A1").Select
DATA_END:
' データベース接続切断
  Select Case Left(stSQL, 6)
   Case "UPDATE", "DELETE", "INSERT"
     Call PS_DbDisConn(True)
   Case Else
     Call PS_DbDisConn(False)
  End Select
 
' 画面固定解除
  Application.ScreenUpdating = True
  If ErrMsg <> "" Then
   MsgBox ErrMsg
   Exit Sub
  End If
  If Left(stSQL, 6) = "SELECT" Then
   UserForm1.Hide
  Else
   Unload UserForm1
   UserForm1.TextBox2.Text = stSQL
   UserForm1.Show
  End If
  Exit Sub
Err_Han:
  If ErrMsg = "" Then
   ErrMsg = Err.Description
  End If
  GoTo DATA_END
End Sub
'+------------------------------------------------------------------------------
'| 処理名    :ボタン「SAVE」
'+------------------------------------------------------------------------------
Sub データセーブ()
  Dim FileName As Variant
  FileName = Application.GetSaveAsFilename("DATA.xls", "Excel ブック(*.xls),1")
  If FileName <> False Then 'ダイアログでキャンセルを選ぶとFALSEで抜ける
   Sheets("DATA").Copy
   ActiveWorkbook.SaveAs FileName:=FileName, FileFormat:=xlExcel8, _
              ReadOnlyRecommended:=False, CreateBackup:=False
   ActiveWindow.Close
  End If
End Sub
'+------------------------------------------------------------------------------
'| 処理名    :CSV出力処理
'+------------------------------------------------------------------------------
Sub CSV出力処理()
  Application.Speech.Speak "Do You want to write a CSV file?"
  If MsgBox("検索件数がシート行限界に達しました" & vbNewLine & "CSVに出力しますか?", vbYesNo) = vbNo Then Exit Sub
  Dim FileName As Variant
  FileName = Application.GetSaveAsFilename("DATA.csv", "CSV ファィル(*.csv),1")
  If FileName = False Then Exit Sub 'ダイアログでキャンセルを選ぶとFALSEで抜ける
  Dim outFF  As Integer      ' FreeFile値
  Dim Buf   As String: Buf = ""
  Dim i    As Integer
  Dim j    As Long: j = 0
  outFF = FreeFile
  Open FileName For Output As #outFF
  For i = 0 To JetRs.Fields.Count - 1
   If i > 0 Then Buf = Buf & ","
   Buf = Buf & JetRs.Fields(i).Name
  Next i
  Print #outFF, Buf
  JetRs.MoveFirst
  Do While Not JetRs.EOF
   Select Case JetRs.Fields(0).Type
     Case adDate, adDBTimeStamp, adChar, adLongVarChar, adVarWChar, adLongVarWChar
      Buf = """" & JetRs.Fields(0).Value & """"
     Case Else
      Buf = JetRs.Fields(0).Value
   End Select
   For i = 1 To JetRs.Fields.Count - 1
     Select Case JetRs.Fields(i).Type
      Case adDate, adDBTimeStamp, adChar, adLongVarChar, adVarWChar, adLongVarWChar
        Buf = Buf & ",""" & JetRs.Fields(i).Value & """"
      Case Else
        Buf = Buf & "," & JetRs.Fields(i).Value
     End Select
   Next i
   Print #outFF, Buf
   j = j + 1
   If j = Int(j / 100) * 100 Then
     Application.StatusBar = "CSV RECORD(現在 " & j & "件目)"
   End If
   JetRs.MoveNext
  Loop
  Close #outFF
  Application.Speech.Speak "A CSV file writing is completed"
  MsgBox FileName & vbNewLine & "に " & j & " 件出力しました"
  Application.StatusBar = False
End Sub
'+------------------------------------------------------------------------------
'| 処理名    :データベース接続
'| 処理内容   :データベースに接続する
'| 引数     :(1) (I)  Boolean 読込フラグ
'|                 True=読込のみ,False=更新する
'| 返値     :なし
'| 備考     :実行時エラーは上位処理でハンドル
'+------------------------------------------------------------------------------
Private Sub PS_DbConn(Optional pb_Set As Boolean)
  On Error GoTo Err_Han
  Dim i As Integer
' 共通変数・ホスト、ユーザ、パスワードのいずれかに入力がない場合
  If Ps_Mdb = "" Then
   i = 2
   Do While Worksheets("USER").Cells(i, 1).Value <> ""
     If UserForm1.ComboBox1.Value = Worksheets("USER").Cells(i, 1).Value Then
      Ps_Mdb = Worksheets("USER").Cells(i, 2).Value 'ACCESS MDB FILR
      Exit Do
     End If
     i = i + 1
   Loop
   If Ps_Mdb = "" Then
     ErrMsg = "USERシートにACCESS MDB情報が設定されていません"
    ' 実行時エラーを発生させる
     Err.Raise 0
     Exit Sub
   End If
  End If
' ACCESS接続
  Set JetCn = CreateObject("ADODB.Connection")
  With JetCn
   .Provider = "Microsoft.Jet.OLEDB.4.0"
   If pb_Set Then
    .Mode = adModeRead         ' 読込のみ
   Else
    .Mode = adModeReadWrite      ' 更新あり
   End If
   .ConnectionString = (Ps_Mdb)
   .Open
  End With
' トランザクションの開始
  JetCn.BeginTrans
  Exit Sub
Err_Han:
  ErrMsg = "ACCESS MDB 接続が失敗しました"
  Err.Raise 0
  Exit Sub
End Sub
'+------------------------------------------------------------------------------
'| 処理名    :データベース切断
'| 処理内容   :データベース接続を切断する
'| 引数     :(1) (I)  Boolean トランザクション処理フラグ
'|                 True=Commitする,False=ロールバックする
'| 返値     :なし
'+------------------------------------------------------------------------------
Public Sub PS_DbDisConn(pb_Set As Boolean)
  If ErrMsg <> "" Then Exit Sub
  On Error Resume Next        '実行時エラーを無視
'トランザクション処理フラグ = Trueの場合
  If pb_Set Then
   JetCn.CommitTrans         'トランザクションをコミットする
'トランザクション処理フラグ=Falseの場合
  Else
   JetCn.RollbackTrans        'トランザクションをロールバックする
  End If
' オブジェクト消去
  JetRs.Close
  Set JetRs = Nothing
  JetCn.Close
  Set JetCn = Nothing
  On Error GoTo 0           '実行時エラーハンドリングリセット
End Sub
' 引数 SheetName のシートが実際にあるかチェックする
Function ExistSheet(SheetName) As Boolean
  Dim i As Integer
  ExistSheet = False
  For i = 1 To Sheets.Count
   If StrConv(Sheets(i).Name, vbUpperCase) = StrConv(SheetName, vbUpperCase) Then
     ExistSheet = True
     Exit For
   End If
  Next i
End Function
'+------------------------------------------------------------------------------
'| 処理名    :環境設定
'+------------------------------------------------------------------------------
' シート未設定時(初回のみ)手動実行
Sub 初期シート設定()
  Dim NewWorkSheet As Worksheet
  Const CFont   As String = "HGゴシックM" ' 任意のフォントを設定(お好きなフォント)
  If ExistSheet("DATA") = False Then
   Set NewWorkSheet = Worksheets.Add(after:=Worksheets(Worksheets.Count)) '-- シートが無ければ追加する
   NewWorkSheet.Name = "DATA"
   Cells.Select
   Selection.Font.Name = CFont
   Range("A1").Select
   Set NewWorkSheet = Nothing
  End If
  If ExistSheet("USER") = False Then
   Set NewWorkSheet = Worksheets.Add(after:=Worksheets(Worksheets.Count)) '-- シートが無ければ追加する
   NewWorkSheet.Name = "USER"
   Cells.Select
   Selection.Font.Name = CFont
   Cells(1, 1).Value = "接続先"   ' 見出し(識別名)-- 任意の名称
   Cells(1, 2).Value = "MDB"   ' ACCESS MDB FILE NAME
   Cells(1, 7).Value = "選択idx"  ' 選択記録用(次回表示時も選択を継続)
   Cells(2, 7).Value = 0      ' 先頭が0(初期値)
   Range("A2:E2").Select
   ActiveWorkbook.Names.Add Name:="接続一覧", RefersTo:="=USER!$A$2:$B$2"
   ActiveWorkbook.Names("接続一覧").Comment = "ACCESSの接続情報をコンボボックスに表示する"
   Range("A1").Select
   Set NewWorkSheet = Nothing
  End If
  If ExistSheet("TBL") = False Then
   Set NewWorkSheet = Worksheets.Add(after:=Worksheets(Worksheets.Count)) '-- シートが無ければ追加する
   NewWorkSheet.Name = "TBL"
   Cells.Select
   Selection.Font.Name = CFont
   Cells(1, 1).Value = "TABLE_NAME"   ' 見出し
   Range("A2:A2").Select
   ActiveWorkbook.Names.Add Name:="テーブル一覧", RefersTo:="=TBL!$A$2:$A$2"
   ActiveWorkbook.Names("テーブル一覧").Comment = "テーブル一覧情報をリストボックスに表示する"
   Range("A1").Select
   Set NewWorkSheet = Nothing
  End If
  If ExistSheet("COLUMN") = False Then
   Set NewWorkSheet = Worksheets.Add(after:=Worksheets(Worksheets.Count)) '-- シートが無ければ追加する
   NewWorkSheet.Name = "COLUMN"
   Cells.Select
   Selection.Font.Name = CFont
   Cells(1, 1).Value = "COLUMN_NAME" ' 見出し(項目名)
   Cells(1, 2).Value = "TYPE"    ' 見出し(データタイプ)
   Cells(1, 3).Value = "LENGTH"   ' 見出し(項目長、但し数値型は編集置換する)
   Range("A2:C2").Select
   ActiveWorkbook.Names.Add Name:="項目一覧", RefersTo:="=COLUMN!$A$2:$C$2"
   ActiveWorkbook.Names("項目一覧").Comment = "項目一覧情報をリストボックスに表示する"
   Range("A1").Select
   Set NewWorkSheet = Nothing
  End If
  If ExistSheet("HIST") = False Then
   Set NewWorkSheet = Worksheets.Add(after:=Worksheets(Worksheets.Count)) '-- シートが無ければ追加する
   NewWorkSheet.Name = "HIST"
   Cells.Select
   Selection.Font.Name = CFont
   Range("A2:A20").Select
   ActiveWorkbook.Names.Add Name:="実行履歴", RefersTo:="=HIST!$A$2:$A$20"
   ActiveWorkbook.Names("実行履歴").Comment = "実行履歴をリストボックスに表示する"
   Range("A1").Select
   Set NewWorkSheet = Nothing
  End If
' 既定シートは削除する(削除しなくても可)
  If ExistSheet("Sheet1") Then
   Worksheets("Sheet1").Delete
  End If
  If ExistSheet("Sheet2") Then
   Worksheets("Sheet2").Delete
  End If
  If ExistSheet("Sheet3") Then
   Worksheets("Sheet3").Delete
  End If
End Sub
'(次の記事に続く)
' http://blog.goo.ne.jp/frontflug/e/4b7bd96bb47092935d4356fe710ea65d
名前:
コメント:

※文字化け等の原因になりますので顔文字の投稿はお控えください。

コメント利用規約に同意の上コメント投稿を行ってください。

 

※ブログ作成者から承認されるまでコメントは反映されません。

  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最新の画像もっと見る

最近の「EXCEL VBA」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事