ExcelVBAとAccessの連携 第1回 Excelからデータベースへの接続

ExcelVBAとAccessの連携 第1回 Excelからデータベースへの接続

だいぶ前からまとめてみたいとは思っていたのですが、書きたいことのボリュームがどんどん増えてゆき、シリーズものになってしまいました…。できるだけ分かりやすく書けるようがんばります!


関連記事

この連載がもっと実用的なサンプルで書籍になりました!

連携させるメリット

小規模なデータ量ならExcelだけでもなんとかなるし、Accessだって単体でアプリケーションも作れます。が、敢えてAccessのデータベースをExcelから操作する(私にとっての)メリットについて。

グラフ化が容易

私は、出産前は検査の仕事をしておりまして、1/1000mm単位の膨大な量の測定データを毎日毎日Excelに溜め込んでいました。Excelにデータを格納すると、グラフのテンプレートさえ作っておけば、自動でグラフに描写されていくので便利なんです。

でも、データを溜めれば溜めるほどファイルサイズは大きく、動作も重くなる…。結局、ある程度の期間でファイルを新規にし、またそこへデータを溜めていく日々。どうなのこれ…。

そこで、

  1. まずはExcelの測定用シート上にデータを入力
  2. データをAccessのデータベースへ格納
  3. データを見たいときはAccessからExcelのグラフ用シートへ読み込み

という方式へたどり着きました。Excel自体にデータは格納されないので、ファイルサイズは増えないし動きもサクサク。いろんな条件で絞り込んでデータを読み込めるから、前より便利になりました!

ExcelのVBAは勉強しやすい

MicroSoftOfficeにはどれもVBAが使えますが、ExcelVBAが一番ユーザーが多いんじゃないかな、と、思っています。

もちろんAccessも多いと思うんですが、使えるようになるまでの敷居がなかなか高く、ライトユーザーさんに敬遠される…(;´Д`) Excelからだととっつきやすく、ユーザーが多いということは、それだけ勉強している人も多くて、ネット上でも情報が抱負です。

中小企業の強い味方

私の会社もそうですが、業務ソフトの自社開発は使用面でも金額面でも非常にメリットが大きいです。Excel+Accessでかなり実用的なものもつくれちゃいます。

2016/6/29追記:このページをたくさんの方にご覧にいただいたおかげで、貴重な体験をさせていただきました…! 参考書選びの選択肢のひとつにしていただけたら光栄です(*´∀`*)

Accessでテーブルを用意

というわけで、AccessではVBAを使わずに、データベースのテーブル設計だけやっておきます。

130307-1

テーブルとは、こんな感じのものです。フィールドの名前と型(数値とか、文字列とか)を指定しておいて、そこへレコードを登録していきます。

フィールドには必ず1つ以上のキーと呼ばれる重複しないデータの入るフィールドを設定する必要があります。

この例なら、男か女かではひとつのレコードを特定できませんよね。名前も、同じ人がいるかもしれないのでキーにはできません。必ずひとつでないとならないので、IDや番号などを設定することが多いです。

ADOとSQL文を使ってExcelから読み書き

データベースへ読み書きするには、SQLという言語を使います。ExcelVBAでSQL文はそのままでは認識できないので、string型で宣言した変数に文字列としてSQL文を書いておいて、それをADOというインタフェースを使ってAccessを操作する…という感じです。

ADOというのはActiveX Data Objectsの略で、Microsoftが提唱しているデータアクセスのための技術だとか。アプリケーション、言語などに依存しないため使い勝手がよいらしいです!

基本コード

参照設定は使わない方法で書いてみたので、できるだけ幅広い環境で動けばいいなと思ってます。

参照設定の有無の違いについては、こちらの記事もご参照ください。

Sub sample()
  Dim DBpath As String 'ファイル名
  Dim adoCn As Object 'ADOコネクションオブジェクト
  Dim adoRs As Object 'ADOレコードセットオブジェクト
  Dim strSQL As String 'SQL文

  DBpath = "C:\sample.mdb" '接続するファイル(~2003)のフルパス
  'DBpath = "C:\sample.accdb" '接続するファイル(2007~)のフルパス
  Set adoCn = CreateObject("ADODB.Connection") 'ADOコネクションオブジェクトを作成
  Set adoRs = CreateObject("ADODB.Recordset") 'ADOレコードセットオブジェクトを作成
  adoCn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & DBpath & ";" 'Access(~2003)ファイルを開く
  'adoCn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & DBpath & ";" 'Accessファイル(2007~)を開く


  strSQL = "ここにSQL文を入れます" 'SQL文をString形式になるように

  '書込・編集・削除の場合----------------------------------
  adoCn.Execute strSQL 'SQLを実行
  '--------------------------書込・編集・削除の場合ここまで

  '読込の場合----------------------------------------------
  adoRs.Open strSQL, adoCn 'SQLを実行して対象をRecordSetへ

  '出力方法1-スタートのセルを指定して一気に貼り付け
  Range("A1").CopyFromRecordset adoRs

  '出力方法2-ひとつひとつ貼り付け
  i = 1 'スタート行
  Do Until adoRs.EOF 'レコードセットが終了するまで処理を繰り返す
    Cells(i, 1) = adoRs!フィールド名1
    Cells(i, 2) = adoRs!フィールド名2
    Cells(i, 3) = adoRs!フィールド名3
    i = i + 1 '行をカウントアップする
    adoRs.MoveNext '次のレコードに移動する
  Loop
  '--------------------------------------読込の場合ここまで


  adoRs.Close 'レコードセットのクローズ(読込した場合のみ)
  adoCn.Close 'コネクションのクローズ
  Set adoRs = Nothing 'オブジェクトの破棄
  Set adoCn = Nothing
End Sub
  1. 宣言(2~5行)
  2. 接続・セット(7~12行)
  3. 処理(15~36行)
  4. 切断(39~42行)

というのが一連の流れかなという感じです。処理部分(15~36行)だけ変えれば汎用的に使えそう。

7,8行目のAccessファイル名指定と、11,12行目のファイルを開くところですが、Accessのバージョンが2003までと2007以降で書き方が変わってきます。

Excelへの出力については、一気にズバっと貼り付けする方法と、カスタマイズしながら貼り付けできる(量が多いと遅そう)方法があるみたいですね。両方書いてみましたが、用途によって使い分ければ良さそうです。

2017/5/19追記

うわー! 今更だけど2番めの貼付け方法でフィールド名を変数にできるんじゃないかー! と気がついたので追記します。

  '出力方法2-ひとつひとつ貼り付け
  Dim outputCell as Range: outputCell = Range("A1") '基点セル指定
  Dim row As Integer: row = outputCell.Row '行取得
  Dim col As Integer: col = outputCell.Column '列取得
  Dim field As Object, i As Integer
  Do Until adoRs.EOF 'レコードセットが終了するまで処理を繰り返す
    i = 0
    For Each field In adoRs.Fields 'フィールドの数だけ繰り返す
      Cells(row, col + i) = adoRs(field.Name)
      i = i + 1
    Next
    row = row + 1 '行をカウントアップする
    adoRs.MoveNext '次のレコードに移動する
  Loop

CopyFromRecordsetのほうが楽なんですが、書式設定とか消えちゃうことがあって後者を使うことが多かったのに、いままで気がつかなかった…、これならSQLさえ組めば行けるからめっちゃ便利じゃん…!

次回は、具体的に「こんなモノをつくるぞ」という提示をして、実際にAccess+Excelで動くプログラムを作って解説してみたいと思っています。よろしければお付き合いください。

参考

公開日:2013/03/07
更新日:2017/05/19

9件のコメント

  1. 曾 進 より:

    素晴らしい内容だと思います。
    サンプルプログラム(Excel+MDB)一式をダウンロードできますでしょうか?

    • *you より:

      曾進さん、コメントありがとうございます。

      だいぶ前に書いた記事でして、Officeのバージョンが変わったりなどして今現在用意できるDLサンプルが無く、申し訳ありません。産休明けて落ち着いたら検討してみようかと思います!

  2. ラム より:

    エクセルは2013、アクセスは2016ですが問題ありませんか?

    • *you より:

      ラムさん、コメントありがとうございます。

      その組み合わせは試したことがないので確実なことは言えないのですが、バージョンが違うもの同士でも動いた経験はあります。バックアップを確実にとって検証してみるのが良いと思います。

  3. とも より:

    今回、ExcelVBAからAccessのデータベースにアクセスすることになり今回のページが大変役に立ち助かりました。
    小規模の会社からの依頼なんですが複数PCからExcelVBAのフォーム画面から入力してAccessへ更新するという内容なんですが複数PCからの更新はどのようにしたらいいのでしょうか?
    また、Accessは破損しやすいと聞いているのでバックアップもVBA側からしたいのですがその方法などがあればアドバイスして頂きたいのですが・・・。
    お時間があるときに教えてください。

    • *you より:

      ともさん、コメントありがとうございます。

      私は仕事では、Accessファイルをネットワークフォルダに入れておいて、つながっている複数のPCから更新しています。ただしAccessの仕様上、多数の人間が頻繁に、同時・大量に書き換えるような目的のシステムではないことが前提です。

      バックアップは、ネットワークフォルダの中身を毎日同じ時間に別ドライブへ、というツールを使っているのでVBAでやったことはありません。やるならFileCopyステートメントで別ドライブへコピーとかでしょうか。

      なお、最適化も定期的に行ったほうが良いと思います。私はたまーに中身をチェックして手動で行うので自動化したことはないのですが、Excelからでもできるようですので、一応参考記事のリンクを貼っておきます。

      Excelって頑張ればなんでもできちゃうのですが、「そこまでExcelでやらなくても」ってところまでやってしまうと、制約が多くなって逆に使いにくくなっちゃうケースもよくあります。複数人で運用する場合、ルールが守られないことには回らないので、別のツールを使ったり、部分的には手動にしたほうが結果的に楽だったりということもあるので、いろんな方法を検討してみてください。

  4. とも より:

    youさん、ありがとうございます^^
    もう少し聞きたいことがあるのですが
    アクセスでレコードレックというのは可能なんでしょうか??
    可能ならレコードロックされているかどうかのチェックなどはどうやればいいのでしょうか??
    何度も質問してしまい申し訳ありません。
    お時間があるときに教えてください

  5. とも より:

    youさん
    ありがとうございます。
    2~3台で稼働ということでしたからたぶん大丈夫かと思っています。
    教えて頂いたサイトを参考に頑張ってみます^^
    本当にありがとうございました♪


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)