[[20140903104551]] 『エクセルとアクセスを活用していたのですが、アク』(あや) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『エクセルとアクセスを活用していたのですが、アクセスが廃止になりました』(あや)

 エクセルVBA
 アクセスクエリ
 アクセスVBA
 を使って、集計をしております

 今回、アクセスが廃止されることになり
 対応方法を考えています
 (出来る限り現状は変えず回避方向で…)

 集計作業の内容
 エクセルのデータファイルを、
 1エクセル側からアクセスのインポートファンクションを呼び出し
 2アクセスVBAでインポート
 3アクセスクエリで結合や抽出条件を指定し 必要なデータに成形
 4エクセル側からアクセスのエクスポートファンクションを呼び出し
 5アクセスVBAでエクセルに出力

 (実際の記述)
 1エクセル側からアクセスのインポートファンクションを呼び出し

   ’エクセル モジュールに記述
    'Accessにインポート&★チェック.xlsにエクスポート
     strAccessPath = ThisWorkbook.Path & "\チェック.mdb"

     Set objAccess = CreateObject("Access.Application")
     objAccess.Opencurrentdatabase strAccessPath

     objAccess.Run "Fnインポート"
     objAccess.Run "Fnエクスポート"    ☆

     objAccess.closecurrentdatabase
     objAccess.Quit
     Set objAccess = Nothing

 2アクセスVBAでインポート

   ’アクセスモジュールに記述
   Function Fnインポート()
   On Error GoTo エラー

       Dim Active_mdb As String   
       Dim varac As Variant
       Dim varxls As Variant

       Active_mdb = CurrentProject.Path

       varac = "tbl_チェック"
       varxls = Active_mdb & "\チェック.xls"

       DoCmd.DeleteObject acTable, varac
       DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel9, _
                                     varac, varxls, True, "チェック!"

       Exit Function

   エラー:

       MsgBox "予期せぬエラーが発生しました。" & Chr(13) & _
              "エラー番号:" & Err.Number & Chr(13) & _
              "エラー内容:" & Err.Description, vbCritical
   End Function

 3アクセスクエリで結合や抽出条件を指定し 必要なデータに成形
  クエリデザインビューでテーブル結合や抽出条件を指定

 4エクセル側からアクセスのエクスポートファンクションを呼び出し
 (1エクセル側からアクセスのインポートファンクションを呼び出し)の☆部分

 5アクセスVBAでエクスポート

   Function Fnエクスポート()

   On Error GoTo エラー

       Dim Active_mdb As String
       Dim varac As Variant
       Dim varxls As Variant

       Active_mdb = CurrentProject.Path

       varxls = Active_mdb & "\★チェック.xls"

       DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, _
           "qry_作業1", varxls, True

       Exit Function

   エラー:

       MsgBox "予期せぬエラーが発生しました。" & Chr(13) & _
              "エラー番号:" & Err.Number & Chr(13) & _
              "エラー内容:" & Err.Description, vbCritical

   End Function

 (伝わりにくい部分がいくつかあるかと思います…)
 こんな形でアクセスを使用しているのですが
 アクセスがなくなることにより、
 アクセスのクエリを活用している部分を他の動きで代用する必要があり

 クエリを代用するものでわたしが思いつくのは
 エクセルのVLOOKUPをマクロで再現したり、かなと思いますが
 たくさんのクエリを使っているため、
 良い方法はないかなと考えております

 アクセスがなくても、エクセルからデータベースを動かすなど…?
 幅広く教えていただけると勉強になります

 *説明不足があるかと思いますので、
 そのときはご指示下さい

< 使用 Excel:Excel2010、使用 OS:WindowsXP >


Accessのクエリは、VBAのようにちょっとした計算や整形をSQLに含めて便利です。
クエリがクエリをテーブル扱いして参照、なんて事も簡単にできてしまいます。

しかし、移植にはこれらが仇になってしまうので、新たに標準のSQL文やVBAの処理で作り直すしかないかと思います。
クエリの性能に依存した処理をしているほど、移植は大変になるでしょう。
(移植より、新たな処理を考えたほうが早いかもしれませんね)

VBAでは、ADODB.Connection 等を使用して、MDBだけでなく、シートやCSVをDB扱いすることもできます。
Accessに慣れているのでしたら、集計が必要な場合に、SQL文で処理する方法もありますので、調べてみてください。
(Excel2010のようなので、.Provider = "Microsoft.ACE.OLEDB.12.0" なんかも検索候補に)
(???) 2014/09/03(水) 16:26


サンプル仕様編

 >アクセスがなくても、エクセルからデータベースを動かす

 あやさんの投稿から、ファイルは、Office2003以前のバージョンで管理されていたものを
 Excel2010でアクセスなしで管理する ということでしょうか?

 よって、同じ仕様をアクセスアプリを使った場合と対比できるようにサンプル仕様を明確にしたいと思います。

 仕様は、Excelファイルとmdbファイルでデータのやり取りを行い、結果を新たなExcelファイルに作成する
 という内容です。

 ファイル構成

     sample1.xls      ---->    sample2.xls
     dbsamp.mdb

     VBAsamp.xls   ---- VBAコードがあるExcelファイル(サンプルデータ作成コードと仕様実行コード)

  sample1.xls  Sheet1に以下のようなデータを用意します。

    A    B      C    D
 1  会員番号   氏名          出身    血液型
 2     1       奥田 美香   東京都    A型
 3      2       榎田 道子   東京都    AB型
 4      3       吉野 佳代子 埼玉県    O型
 5      4       新田 恵利   埼玉県    O型
 6      5       中島 美春   東京都    A型
 7      6       樹原亜紀     神奈川県  AB型
 8      7       友田 麻美子 東京都    A型

 Dbsamp.mdb

 tbl1 というテーブルとqry1というクエリを用意します。

 tbl1 は、以下のようなデータを用意します。

 会員番号       備考
  1             週間文春タバコフォーカス事件にて脱退
  2             週間文春タバコフォーカス事件にて脱退
  3             週間文春タバコフォーカス事件にて脱退
  4             初期メンバーの中で最も活躍。在籍中にボンド/キャニオンからソロデビュー
  5            「なかじ」の愛称で親しまれる
  6             ニャンギラスの一員として活躍。妙に背が高い
  7             週間文春タバコフォーカス事件にて脱退

 尚、フィールド構成は、

   会員番号   数値型  主キー
   備考          テキスト型

 なっています。

 qry1   内容は、以下のsqlです。

 SELECT table1.会員番号, table1.氏名, table1.出身, table1.血液型, tbl1.備考 FROM table1 LEFT JOIN tbl1 ON table1.会員番号 = tbl1.会員番号;

 尚、上記のtable1とは、sample1.xlsのSheet1のデータをインポートするテーブルです。

 qry1により、table1とtbl1の同じ会員番号のデータを結合します。

 その結果をsample2.xlsのqry1というシートに出力するという仕様です。
 正常に作動すれば、sample2.xlsのqry1というシートには、

    A    B      C    D     E
 1  会員番号   氏名          出身    血液型      備考
 2     1       奥田 美香   東京都    A型         週間文春タバコフォーカス事件にて脱退
 3      2       榎田 道子   東京都    AB型       週間文春タバコフォーカス事件にて脱退
 4      3       吉野 佳代子 埼玉県    O型         週間文春タバコフォーカス事件にて脱退
 5      4       新田 恵利   埼玉県    O型         初期メンバーの中で最も活躍。在籍中にボンド/キャニオンからソロデビュー
 6      5       中島 美春   東京都    A型        「なかじ」の愛称で親しまれる
 7      6       樹原亜紀     神奈川県  AB型       ニャンギラスの一員として活躍。妙に背が高い
 8      7       友田 麻美子 東京都    A型         週間文春タバコフォーカス事件にて脱退

 という結果が得られるはずです。

 次投稿にて、サンプルデータを作成するコードを提示します。

(ichinose) 2014/09/06(土) 20:35


*サンプルデータ作成編

 新規ブックの標準モジュール(Module1)に以下のDB作成プログラムパック

 '==============================================================================
 Private cat As Object 'ADOX.Catalog
 Function create_cat(flnm As String) As Long
    On Error Resume Next
    Set cat = CreateObject("ADOX.Catalog")
    cat.Create "Provider=Microsoft.jet.OLEDB.4.0;" & _
        "Data Source=" & flnm
    create_cat = Err.Number
    On Error GoTo 0
 End Function
 '=================================================================
 Function get_cn() As Object
   Set get_cn = cat.ActiveConnection
 End Function
 '=================================================================
 Function cr_cmd(text As String, nm As String) As Long
    On Error Resume Next
    cr_cmd = 0
    cat.Views.Delete nm
    Err.Clear
    Dim cmd As Object
    Set cmd = CreateObject("adodb.command")
    cmd.CommandText = text
    cat.Views.Append nm, cmd
    cr_cmd = Err.Number
    On Error GoTo 0
 End Function
 '===================================================================
 Sub close_cat()
    On Error Resume Next
    cat.ActiveConnection.Close
    Set cat = Nothing
    On Error GoTo 0
 End Sub

 標準モジュール(Module2)に

 '=====================================================================
 Option Explicit
 Sub mk_smp_data()
    mk_xls
    mk_mdb
 End Sub
 '==========================================================================
 Sub mk_xls()
    On Error Resume Next
    Kill ThisWorkbook.Path & "\sample1.xls"
    On Error GoTo 0
    With Workbooks.Add
       .Worksheets(1).Name = "Sheet1"
       With .Worksheets(1)
          .Range("a1:d1").Value = Array("会員番号", "氏名", "出身", "血液型")
          .Range("a2:d8").Value = Evaluate("{1,""奥田美香"",""東京都"",""A型"";2,""榎田道子"",""東京都"",""AB型"";" & _
              "3,""吉野佳代子"",""埼玉県"",""O型"";4,""新田恵利"",""埼玉県"",""O型"";" & _
              "5,""中島美春"",""東京都"",""A型"";6,""樹原亜紀"",""神奈川県"",""AB型"";" & _
              "7,""友田麻美子"",""東京都"",""A型""}")
       End With

       If Val(Application.Version) > 11 Then
          .SaveAs ThisWorkbook.Path & "\sample1.xls", 56
       Else
          .SaveAs ThisWorkbook.Path & "\sample1.xls"
       End If
       .Close
    End With
 End Sub
 '==================================================================================
 Sub mk_mdb()
    Dim sql_str As String
    Dim retcode As Long
    Dim cn As Object
    Dim biko As Variant
    Dim g0 As Long
    On Error Resume Next
    Kill ThisWorkbook.Path & "\dbsamp.mdb"
    On Error GoTo 0
    If create_cat(ThisWorkbook.Path & "\dbsamp.mdb") = 0 Then
       Set cn = get_cn
       sql_str = _
             "CREATE TABLE tbl1 (会員番号 integer CONSTRAINT tkey PRIMARY KEY ,備考 varchar(255));"
       cn.Execute sql_str
       biko = Array("週間文春タバコフォーカス事件にて脱退", "週間文春タバコフォーカス事件にて脱退", "週間文春タバコフォーカス事件にて脱退", _
            "初期メンバーの中で最も活躍。在籍中にボンド/キャニオンからソロデビュー", "「なかじ」の愛称で親しまれる", "ニャンギラスの一員として活躍。妙に背が高い", _
            "週間文春タバコフォーカス事件にて脱退")
       For g0 = LBound(biko) To UBound(biko)
          sql_str = " INSERT INTO tbl1 " _
                        & "(会員番号,備考) VALUES " _
                        & "(" & (g0 + 1) & ",'" & biko(g0) & "');"
          cn.Execute sql_str
       Next
       cr_cmd "SELECT Table1.会員番号, 氏名, 出身, 血液型, 備考 FROM table1 LEFT JOIN tbl1 ON table1.会員番号 = tbl1.会員番号;", "qry1"
       close_cat
    End If
 End Sub

 一度、適当なフォルダに保存(VBAsamp.xls)してから、mk_smp_dataを実行してみてください。

 上記ブックを保存したフォルダにsample1.xlsとdbsamp.mdbが作成されるはずです。

 作成されていたなら、前投稿のようなデータが作成されているか 確認してください。

 確認が出来たなら、dbsamp.mdbの標準モジュールにアクセスを使って以下のコードを
 作成してください。

 Option Compare Database
 Option Explicit
 Function Fnインポート()
     On Error Resume Next
         Dim Active_mdb As String
         Dim varac As Variant
         Dim varxls As Variant
         Active_mdb = CurrentProject.Path
         varac = "table1"
         varxls = Active_mdb & "\sample1.xls"
         DoCmd.DeleteObject acTable, varac
         Err.Clear
         DoCmd.TransferSpreadsheet acImport, 8, varac, varxls, True, "Sheet1!"
         If Err.Number <> 0 Then
            MsgBox Err.Description & "  :  " & Err.Number
         End If
     On Error GoTo 0
 End Function
 Function Fnエクスポート()
         On Error Resume Next
         Dim Active_mdb As String
         Dim varac As Variant
         Dim varxls As Variant
         Active_mdb = CurrentProject.Path
         varxls = Active_mdb & "\sample2.xls"
         DoCmd.TransferSpreadsheet acExport, 8, _
             "qry1", varxls, True
         If Err.Number <> 0 Then
            MsgBox Err.Description & "  :  " & Err.Number
         End If
 End Function

 これは、あやさんが投稿されたものと殆ど同じコードをサンプル仕様用に変えたものです。

 尚、アクセスがない場合は、上記のコードは、入れられません。

 アクセスアプリを使った場合との対比はできませんが、ExcelVBAで仕様の実行は可能です。

 では、次投稿にて、サンプル仕様を実行するコードです。

(ichinose) 2014/09/06(土) 21:03 訂正


*サンプル仕様コード編

 では、実際の実行コードです。先にサンプルデータ作成プロフラムを入れたVBAsamp.xlsの
 標準モジュール(Module3)にADO関連I/Oパック

 '==========================================================================
 Option Explicit
 Private cn As Object
 '==========================================================================
 Function open_db(dbpath As String, Optional prv As Long = 0) As Long
    On Error GoTo err_open_db
    open_db = 0
    Set cn = CreateObject("ADODB.Connection")
    If prv = 0 Then
       cn.ConnectionString = "provider=Microsoft.jet.OLEDB.4.0;" & "Data Source=" & dbpath
    Else
       cn.ConnectionString = "Provider=Microsoft.Ace.OLEDB.12.0;" & "Data Source=" & dbpath
    End If
    cn.Open
    On Error GoTo 0
    Exit Function
 err_open_db:
    MsgBox Error(Err.Number) & Err.Number
    open_db = Err.Number
 End Function
 '==========================================================================
 Sub close_db()
    On Error Resume Next
    cn.Close
    Set cn = Nothing
    On Error GoTo 0
 End Sub
 '==========================================================================
 Function execute_sql(sql As String, Optional grs As Object = Nothing, Optional er As Boolean = False) As Long
    On Error GoTo err_sql
    close_rs grs
    execute_sql = 0
    If grs Is Nothing Then
       cn.Execute sql
    Else
       grs.Open sql, cn, 2, 2
    End If
    On Error GoTo 0
    Exit Function
 err_sql:
    If er Then MsgBox Err.Description & "  :  " & Err.Number
    execute_sql = Err.Number
 End Function
 '==========================================================================
 Sub close_rs(grs As Object)
    On Error Resume Next
    grs.Close
 End Sub

 別の標準モジュール(Module4)に

 '==========================================================================
 Option Explicit
 Sub test1()
    Dim straccesspath As String
    Dim objaccess As Object
    'エクセル モジュールに記述
    'Accessにインポート&★チェック.xlsにエクスポート
     straccesspath = ThisWorkbook.Path & "\dbsamp.mdb"
     Set objaccess = CreateObject("Access.Application")
     objaccess.Opencurrentdatabase straccesspath
     objaccess.Run "Fnインポート"
     objaccess.Run "Fnエクスポート"
     objaccess.closecurrentdatabase
     objaccess.Quit
     Set objaccess = Nothing
 End Sub
 '==========================================================================
 Sub test2()
    Dim rs As Object
    Dim sql As String
    On Error Resume Next
    Kill ThisWorkbook.Path & "\sample2.xls"
    On Error GoTo 0
    If open_db(ThisWorkbook.Path & "\dbsamp.mdb") = 0 Then
       sql = "drop Table table1;"
       execute_sql sql
       sql = "select * into table1 from [Excel 8.0; HDR=Yes;Database=" & ThisWorkbook.Path & "\sample1.xls" & "].[Sheet1$]"
       execute_sql sql
       Set rs = CreateObject("adodb.recordset")
       execute_sql "select * into [Excel 8.0; HDR=Yes;Database=" & ThisWorkbook.Path & "\sample2.xls" & "].[qry1] from qry1;", , True
       Call close_db
    End If
 End Sub

 以上です。test1,test2を実行してみてください。どちらでも同じ結果(sample2.xls)が得られることを
 確認してください。

 test2は、本当なら、一度、mdbにsample1.xlsをインポートしなくても(Table1を作らない)
 可能でしたが、今回は、test1と同じような方法で行いました。

 尚、dbsamp.mdbに前投稿でのVBAコードを記述しなければ、test1は、エラーになります。
 test2は、dbsamp.mdbにvbaコードがなくても作動します。

 以上です。Excel2002、2010で確認しました。

 うまくいくようなら、ADOの研究をしてみてください。

 ただ、アクセスがないと メンテナンスは大変ですよ!!

(ichinose) 2014/09/06(土) 22:02


 ???さん ichinoseさん ありがとうございます
 理解・検証にお時間くださいm(_ _)m

(あや) 2014/09/08(月) 10:13


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.