• ベストアンサー

Excel→Access ADO接続 

お世話になります ■ExcelからAccessに接続し社員Noを入力すると氏名が表示するように したいのですが。 ■Access側 社員管理.mdb 社員DB ID|社員No|社員名| 社員Noで検索させます 社員Noはランダムです 例:0001002200 例2:aあ0021aう001 ■Excel側 C5以下社員No入力欄(セル結合していますC5:J5) K5以下社員名表示欄(セル結合していますK5:X5) 社員No入力後Accessから値を取り出し社員名に名前が値が飛ぶようにしたい 社員No入力してもヒットしない場合は決められたエラー文字を入力させたい。 宜しくお願いいたします。 尚、Excelファイルすべてのワークシートに適用させたい 分かる方、宜しくお願い申し上げます

質問者が選んだベストアンサー

  • ベストアンサー
  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.5

#2, 4 です。連投すみません。 ThisWorkbook モジュールでやる場合の参考コードです。違いは、  ・SQL で問い合わせする手法になっています  ・複数セルが一度に更新された場合も対応します ぐらいですけど、都度 DB に問い合わせているので処理速度は遅いですね。 ご参考までということで。  # ご紹介した URL もじっくり目を通してみて下さい Option Explicit ' // データベース周りの定数 Private Const DB_CONNECTION_STR  As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" Private Const DB_FILEPATH     As String = "C:\社員管理.mdb" ' // mdbのフルパス Private Const DB_NOTFOUND_MESSAGE As String = "Not Found."   ' // エラー時 Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)   ' // Require: Microsoft ActiveX Data Objects 2.x Library   Dim cn  As ADODB.Connection   Dim rs  As ADODB.Recordset   Dim rCode As Range   Dim r   As Range   Dim sql  As String   Dim sCode As String   Dim sRet As String   On Error Resume Next   Set rCode = Range(Sh.Cells(5, "C"), Sh.Cells(Rows.Count, "C"))   Set rCode = Intersect(Target, rCode)   Set rCode = Intersect(rCode, Sh.UsedRange)   If rCode Is Nothing Then Exit Sub   On Error GoTo Err_   ' // データベースに接続   Set cn = CreateObject("ADODB.Connection")   cn.Open DB_CONNECTION_STR & DB_FILEPATH   ' // データベース問い合わせ   Set rs = CreateObject("ADODB.Recordset")   For Each r In rCode.Cells     sCode = Trim$(r.Text)     If Len(sCode) Then       sql = ""       sql = sql & "SELECT [社員名]"       sql = sql & " FROM [社員DB]"       sql = sql & " WHERE [社員No] ='" & sCode & "'"       sql = sql & " ORDER BY [ID]"       rs.Open sql, cn, adOpenKeyset, adLockReadOnly       ' // 結果を出力       If rs.EOF Then         sRet = DB_NOTFOUND_MESSAGE       Else         sRet = rs.Fields(0).Value       End If       rs.Close     Else       sRet = ""     End If     Cells(r.Row, "K").Value = sRet   Next r Bye_:   On Error Resume Next   Set rCode = Nothing   rs.Close: Set rs = Nothing   cn.Close: Set cn = Nothing   Exit Sub Err_:   MsgBox Err.Description, vbCritical   Resume Bye_ End Sub

その他の回答 (6)

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.7

#5 です。 すみません。#5 のコードを少し訂正しておきます。 Cells(r.Row, "K").Value = sRet   ↓ このままだと、Change イベントが多重発生するので、もしお試しに なるのであれば、For ループの前あたりの適当な場所に   Application.EnableEvents = False を入れてイベントの再発を抑止し、ラベル Bye_: 以下あたりの適当 なところに   Application.EnableEvents = True を追加して下さい。

BSR123
質問者

お礼

ありがとうございます 思っていたように動きました 感動しました ありがとうございます

noname#140971
noname#140971
回答No.6

1、VBエディタを開く。 2、挿入(I)-標準モジュール(M) をクリック。 3、Const pubCNNSTRING~End Functionまでをコピペ。 以上で DBLookup関数が使えるようになります。 その後、DBLookup関数の使い方を[イミディエイト]でテストされたし。 なお。 Private Sub CommandButton1_Click()   Me.Cells(1, 1) = DBLookup("SELECT EName FROM Employee WHERE ENo='A100'") End Sub これで、エクセルのセルに表示できます。 ところで、質問者のやり方は、テーブル全体からサーチする方法。 DBLookup関数は、SELECT文で条件を指定して1レコードの一つの列のみを抽出する方法。 通常は、後者のやり方です。 Private Sub CommandButton1_Click()   Me.Cells(1, 1) = DLookup("EName", "Employee", "ENo='A100'") End Sub と、Access では DLookup関数なるものが提供されています。 DBLookup関数は、このDLookup関数のADOバージョンみたいなものです。

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.4

#2 です。正直 DB 周りの処理は久ぶりなので、間違ってたら誰か突っ込み 入れて下さい^^; Seek はインデックスを利用した検索です。検索するフィールドにインデックス が設定されている必要がありますが、この点は OK ですか?  参考URL: http://www.accessclub.jp/ado/17.html もしインデックスが設定されていないのであれば、Find メソッドの方を利用 しなければなりません。 前提ですけども、当初のご質問本文にあるとおり、 > 社員管理.mdb     <--- mdbファイル名 > 社員DB        <--- テーブル名 > ID|社員No|社員名|   <--- フィールド構成 とします。補足頂いた内容を修正するとこんな感じ。 Sub SetShainmei(ByVal Target As Range)      ' // 要参照設定: Microsoft ActiveX Data Objects 2.x Library      Const cstDbPath   As String = "C:\社員管理.mdb" '// mdbのフルパス   Const cstTblName  As String = "社員DB"     '// テーブル名   Const cstfldName  As String = "社員名"     '// フィールド名      Dim cn       As New ADODB.Connection   Dim rs       As New ADODB.Recordset   Dim sCriteria    As String      If Target.Column <> 3 Or Target.Row < 5 Or Target.Count > 1 Then     Exit Sub   End If   cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & cstDbPath   rs.Open cstTblName, cn, adOpenKeyset, adLockOptimistic   sCriteria = "[社員No] = '" & Target.Value & "'"   rs.Find sCriteria, , adSearchForward   If Not rs.EOF Then     Target.Offset(0, 8).Value = rs.Fields(cstfldName)   Else     Target.Offset(0, 8).Value = "Not Found!"   End If   rs.Close: Set rs = Nothing   cn.Close: Set cn = Nothing End Sub 余談ですけど、、 > --------------------かくシート貼り付け-------------------- > Private Sub Worksheet_Change(ByVal Target As Range) >  SetShainmei Target > End Sub 全てのシートが対象となるのであれば、ThisWorkbook モジュールの Workbook_SheetChange イベントで良いのでは?

回答No.3

http://www.happy2-island.com/vbs/cafe02/capter00506.shtml 基本的なマクロについては分かるのでしょうか MDBは誰が作ったのでしょうか MDBに接続はできるでしょうか SQL SELECTはできるでしょうか どこまでできて どこがわからないのでしょうか この方法はあなたの発案ですか MDBである必要はありますか

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.2

参考URL: VBA応用(ADOでデータを取得する http://www.asahi-net.or.jp/~ef2o-inue/vba_o/sub05_130_030.html 具体的にどの点がわからないのですか?

BSR123
質問者

お礼

お返事ありがとうございます 補足内容よろしくお願いします

BSR123
質問者

補足

お返事ありがとうございます 下記を動かそうとしているのですが動かなくて困っています データー型が違うのとprimarykeyではないのですが・・ 修正できますか? --------------------モジュール-------------------- Sub SetShainmei(Target As Range)  Const cstDbPath As String = "mdbのフルパス"  Const cstTblName As String = "テーブル名"  Const cstfldName As String = "フィールド名"  Dim cn As New ADODB.Connection  Dim rs As New ADODB.Recordset  If Target.Column <> 3 Or Target.Row < 5 Or Target.Rows.Count > 1 Or Target.Columns.Count > 1 Then   Exit Sub  End If  cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & cstDbPath  rs.Open cstTblName, cn, adOpenKeyset, adLockReadOnly, adCmdTableDirect  rs.Index = "primarykey"  rs.Seek Target.Value, adSeekFirstEQ  If Not rs.EOF Then   Target.Offset(0, 8) = rs.Fields(cstfldName)  Else   Target.Offset(0, 8) = Null  End If  rs.Close: Set rs = Nothing  cn.Close: Set cn = Nothing End Sub --------------------かくシート貼り付け-------------------- Private Sub Worksheet_Change(ByVal Target As Range)  SetShainmei Target End Sub

noname#140971
noname#140971
回答No.1

<C:\Temp\Db1.mdb!Employee> ID__ENo___EName 1___A100__鈴木 一郎 2___A101__中村 主水 [イミディエイト] ? DBLookup("SELECT EName FROM Employee WHERE ENo='A100'") 鈴木 一郎 ? IIF(Len(DBLookup("SELECT EName FROM Employee WHERE ENo='A111'")), "Found!", "Not Found!") Not Found! これな、エクセルからAccessのデータベースにアクセスするテスト結果です。 上記の2つのテストで質問には答えているかと思います。 Option Explicit Const pubCNNSTRING = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Temp\db1.mdb" Public Function DBLookup(ByVal strSQL As String) As Variant On Error GoTo Err_DBLookup    Dim DataValue    Dim rst As ADODB.Recordset    Set rst = New ADODB.Recordset    With rst      .Open strSQL, _         pubCNNSTRING, _         adOpenStatic, _         adLockReadOnly      If Not .BOF Then        .MoveFirst        DataValue = .Fields(0)      End If    End With Exit_DBLookup: On Error Resume Next    rst.Close    Set rst = Nothing    DBLookup = DataValue & ""    Exit Function Err_DBLookup:    MsgBox "SELECT 文の実行時にエラーが発生しました。(DBLookup)" & Chr$(13) & Chr$(13) & _       "・Err.Description=" & Err.Description & Chr$(13) & _       "・SQL Text=" & strSQL, _       vbExclamation, " 関数エラーメッセージ"    Resume Exit_DBLookup End Function なお、通常は、pubCNNSTRING は外部テキストファイル(xxxxx.ini)などに定義して読み込ませるかと思います。

BSR123
質問者

お礼

お返事ありがとうございます

BSR123
質問者

補足

当方初心者です 省略されては分かりません 尚、 Option Explicit Const pubCNNSTRING = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Temp\db1.mdb" モジュール上記場所指定しなおしてもうごきません 宜しくお願いします