AccessVBAにてファイル入出力ダイアログを表示

まだAccessでマッチョにコードを書き始める前は
Accessでファイル入出力ダイアログを呼ぶときに、microsoftOfficeやExcelのオブジェクトを参照設定して呼び出しいました。

だけれど、それだとOfficeのバージョンが開発環境と異なる場合にエラーになっちゃうんですね。
そこで、あれこれ調べていると隠しオブジェクトのWizHookを使うことによって
参照設定無しでダイアログが呼べることを発見。

以下はダイアログの関数。戻り値はファイルパス。

※下記のソースを使用する場合はあくまで自己責任になります。

'=============================================================================================================
Function GetFileName(Optional hwndOwner As Long, Optional AppName As String, Optional DlgTitle As String, _
                       Optional OpenTitle As String, Optional strFile As String, Optional InitialDir As String, _
                       Optional Filter As String, Optional FilterIndex As Long, Optional View As F_gnfView, _
                       Optional flags As F_gfnFlags, Optional fOpen As F_gfnFOpen = gfnFOpenOpen) As String
'◆機能 :   コモンダイアログ呼び出し(「ファイルを開く」、「名前をつけて保存」)
'◆引数 :   hwndOwner   =ダイアログのオーナーとなるオブジェクトのハンドルを渡します。
'           AppName     =実行アプリケーションの名前を指定します。
'           DlgTitle    =ダイアログのウィンドウタイトルに表示する文字列を指定します。
'                        省略時は既定のタイトル(「ファイルを開く」あるいは「名前を付けて保存」)が表示されます。
'           OpenTitle   =実行用コマンドボタンの標題に当たる文字列を指定します。
'                        省略時は既定の標題(「開く」あるいは「保存」)が表示されます。
'           strFile     =出力用引数です。選択したファイルのフルパスが格納されます。
'           InitialDir  =ダイアログの初期表示ディレクトリを指定します。
'                        省略時はカレントディレクトリが表示されます。
'           Filter      =[ファイルの種類] リストボックスに設定する一覧を指定します。
'                        形式は「表示用文字列 1|拡張子 1|表示用文字列 2|拡張子 2|...」の繰り返しになります。
'                        区切り記号「|」は Chr$(0) あるいは定数 vbNullChar でも構いませんが、
'                        VB では「|」を使った方が簡単でしょう。
'                        なお表示用文字列の中の拡張子を括る括弧を誤って全角文字で指定すると、実行されません。
'           FilterIndex =初期表示時に [ファイルの種類] リストボックスの何行目を既定で選択するかをインデックス番号で指定します。
'                        先頭行は 0 から開始します。
'           View        =ファイル一覧の表示スタイルを指定します。
'                        0=詳細、1=プレビュー、2=プロパティ、3=一覧です。
'                        View 引数は単独では機能せず、flags 引数に &H40 を指定して初めて有効になります。
'           flags       =ダイアログの動作を指定するオプション値をビットフラグで指定します。
'                        これは Win32 API で使用される OPENFILENAME 構造体の Flags と微妙に異なります。
'                        現時点で判明しているオプションについては、参考資料を参照
'                 View = 0 , flags = 0  : Viewを直前に実行したタイプと同じにする
'                 View = 0 , flags = 64 : [詳細]
'                 View = 1 , flags = 64 : [プレビュー]
'                 View = 2 , flags = 64 : [プロパティ]
'                 View = 3 , flags = 64 : [一覧]
'                 View = 0 , flags = 32 , fOpen = True : フォルダ選択モード
'                 View = 0 , flags = 1  , fOpen = False : 読み取り専用ファイルの選択を不可にし、上書き確認
'                 View = 0 , flags = 8  , fOpen = True  : 複数ファイル選択可。ファイル名間はタブで区切られる
'           fOpen       =ダイアログの種別を指定します。
'                        True を設定すると [ファイルを開く] になり、
'                        False を指定すると [名前を付けて保存] になります。
'◆戻値 :  ファイルが選択された場合はそのファイルのパス名(strFile)、キャンセルされた場合は空文字("")
'=============================================================================================================
    Dim lngResult As Long
    
    '初期化
    If hwndOwner = 0 Then
        hwndOwner = Application.hWndAccessApp
    End If
    
    If AppName = "" Then
        AppName = "Microsoft Access"
    End If
    
    If Filter = "" Then
        Filter = "すべてのファイル (*.*)|*.*"
    End If
    
    'WizHook 有効化
    WizHook.Key = 51488399
    'WizHook の GetFileName を呼び出し
    lngResult = WizHook.GetFileName(hwndOwner, AppName, DlgTitle, OpenTitle, strFile, InitialDir, Filter, FilterIndex, View, flags, fOpen)
    ' WizHook 無効化
    WizHook.Key = 0

    If lngResult = -302 Then
        F_GetFileName = ""
    Else
        F_GetFileName = strFile
    End If
End Function


そんでもって、下記はinputboxに入力した名前にてテーブルを生成しつつ任意のcsvファイル取り込むコード

Sub testcode()

Dim cn As New ADODB.Connection
Dim cn2 As ADODB.Connection
Dim rs As New ADODB.Recordset
Dim str_sql As String
Dim file_name As String
Dim Update_Date As Date
Dim DAO As DAO.Database
Dim tdfNew As TableDef
Dim drs As DAO.Recordset
Dim count As Integer
Dim i As Integer
Dim ck_flg As Boolean
Dim path As String
Dim tmp_path As String
Dim Array_file_name As Variant
Dim FNo As Long
Dim txtData As String
Dim tb_name As String

Set cn = CurrentProject.Connection



 'ファイル名を取得
 tmp_path = get_tmp_path()
    file_name = GetFileName(0, _
                        "" & "", _
                        "取込", _
                        "取込", _
                        "", _
                        Nz(tmp_path, ""), _
                        gfnFilter_csv, _
                        0, _
                        gfnViewDetail, _
                        8, _
                        gfnFOpenOpen)
    '--2-2.ファイルの出力
    file_name = Replace(file_name, Chr(9), ",")
  Array_file_name = Split(file_name, ",")
                                                            
    If Trim(Array_file_name(0)) <> "" Then 'ファイル名が未選択か
        path = GetPath(Array_file_name(0)) 'パス名の取得
        Call set_tmp_path(path)
               
    Else
    
         Exit Sub
    End If
    

'一行目を読み込む
FNo = FreeFile
tb_name = InputBox("テーブル名を決めてください", "入力")


Open file_name For Input As #FNo
    'ファイルの1行目の項目名部分を読み込む
    'フォーマットチェック
    Line Input #FNo, txtData
    arrData = Split(txtData, ",")


        '新しい TableDef オブジェクトを作成します。
    Set db = CurrentDb
        Set tdfNew1 = db.CreateTableDef(tb_name)


            ' フィールドを作成し、新しい TableDef オブジェクトに追加します。
            ' これは、TableDef オブジェクトを このデータベース上の
            'TableDefs コレクションに追加する前に行う必要があります。

For i = 0 To UBound(arrData)
    tdfNew1.Fields.Append tdfNew1.CreateField(arrData(i), dbText, 255)

Next i
            ' 新しい TableDef オブジェクトをデータベースに追加します。
            db.TableDefs.Append tdfNew1


    Set db = Nothing
    Set tdfNew = Nothing

'w1取込
rs.Open tb_name, cn, adOpenDynamic, adLockOptimistic
        '実際のデータ部分(2行目)からの処理
        Do While Not EOF(FNo)
            Line Input #FNo, txtData    '行単位
            arrData = Split(txtData, ",")
            
            If rs.Fields(0).Name = arrData(0) Then 'フィールド名=データの値なら取り込まない

            
            Else
                rs.AddNew
                    For i = 0 To UBound(arrData)
                            If Nz(arrData(i), "") = "" Then
                                rs.Fields(i) = Null
                            Else
                                rs.Fields(i) = Replace(arrData(i), """", "")
                            End If
                    Next i
                rs.Update
            End If
        Loop
           
    Close #FNo

    Set rs = Nothing


End Sub