Accessのノウハウ(フォーム上でのエクスポート設定)
「ファイルのインポート・エクスポートをフォーム上で実行する」の
その2 エクスポート 版です。
インポートの項で、フォームの作り方・フォーマットテーブルとの連携の仕方・クエリの名前付け等について
お話しましたので、
エクスポートについては、まずは、モジュールサンプルを提示します。
フォームとモジュールサンプル
こんなフォームを作るとします。
レコードソースは、インポートと同じ T_Formatです。

***********************************
エクスポートボタンをクリックした時のサンプル モジュールです。

Functionプロシージャ CheckFile
ふぁ
1.エクスポートの構文
①Excelの時
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, “Q_302_指定日付分を抽出”, myDir & myFN, True
↑これは、拡張子が xlsx の時
xls の時は、acSpreadsheetTypeExcel8
(注意1)
②CSVの時
DoCmd.TransferText acExportDelim, , “Q_302_指定日付分を抽出”, myDir & myFN, True
(この場合は、カンマ区切り、ヘッダーあり)
③出力フォルダと出力ファイル名
ちなみに、myDir & myFN は こんな風に組み合わせます。
miDir D:\OneDrive\ドキュメント\Accessブログ\
myFN Sample.xlsx , Sample.xls , Sample.csv
以下のように年月(日)を組み合わせるケースも多いです。
myFN = Format(Date,”yyyymmdd”) & “_提出データトレース結果.xls”
↓
20200401_提出データトレース結果.xls のように出力されます。
(注意1)Excelの型が合ってないとき、
例えば、本来xlsxなのに 拡張子を xls としたときは、エラーとなります。
「破損している」とか「拡張子」があっていないなどのメッセージが出ます。
④Excelファイルのシート名
シート名を指定したいときは、
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel8, “Q_12クエリ名”, myDir & myFN, True,”シート名”
と入力しますが、そのままで問題無いときは、シート名は指定しないことが多いです。
その場合、シート名がクエリ名になります。
その方が、問題が起きたときトレースしやすい(=クエリ名がわかるので、そこから追いかけやすい)
2.エクスポートの前の 色々なチェック
①フォルダの存在チェック
存在チェックだけでなく、「子フォルダが無い時は作る」という選択肢も作っておくと便利です。
MKDirで子フォルダが作れます。ただし、親フォルダが無いとエラーになります。
(いちばん簡単な書き方は以下だが、親フォルダが無いとエラーになる)
If Dir(myDir,vbDirectory)=”” Then
MkDir myDir
End If
親フォルダ全て作るには、
・一つずつフォルダの存在を見るモジュールを作るか
・HCreateDirectoryExというAPIを使うか
という方法はありますが、
私の経験上、Accessの定例出力では一つ下の階層を作りたいケースが殆どなので
MKDirで、ほぼ用は足りると思っています。
(例)\Accessブログ\振込状況トレース\20200401\Hurikomi_check.xlsx とか
※ちなみに最近勉強中のPythonだと os.mkdir() os.makedirs()の2種類でこなせて便利な様子
②ファイルの存在チェック
ファイル名の存在チェックと、上書きするかの選択肢の処理が必要です。
これが無いと既に同名のファイルがあると、エラーになります。
このチェックは、あちこちで使うので、別途Functionプロシージャを作って読み込んでいます。
Dir で 存在をチェックして、
もしファイルがあれば、上書きするか聞いて、
上書きOKなら
Kill で 削除します
③出力ファイル名
出力ファイル名は以下のパターンが多いと思います。
A.常に固定のファイル名 Hurikomi_Check.xlsx 別のシステムに受け渡しをするケース
B.ファイル名の前に年月(日)をつける 20200401Hurikomi_check.xlsx
C.ファイル名の後に年月(日)をつける Hurikomi_check20200401.xlsx
Aの場合は、フォルダ名に年月(日)をつけるケースが多いです。
2①の例で上げた様なパターンですね。(20200401\Hurikomi_check.xlsx )
Bは、一度に複数のファイルをエクスポートする時に向いています。
時系列でエクスポートできるので、不要になった時に、まとめて削除しやすいです。
BとCのタイプが混在していると、結構不便なのでご注意ください。
例 以下のようになってしまい、
20200401未納者連絡.xlsx
20200402未納者連絡.xlsx
振込チェック20200401.xlsx
振込チェック20200402.xlsx
振込チェック20200401.xlsx
20200401未納者連絡.xlsx
を「ひとかたまり」に出来なくなってしまいます。
3.出力の際のフォームとクエリの組み合わせ
出力するときは、フォーム上で日付を指定して、その日付でクエリを絞り込み、出力するファイル名に日付もつけておく、なんていうパターンが多いです。
サンプルを表示しておきます。
ちなみに、エクスポート項目には、以下を含めた方がいいです。
①フォームで指定した条件(この場合、日付)
正しく抽出しているかどうか、「ファイルの中で確かめられるように」しておくことは結構大事です。
これがないと、間違って抽出しても気づかず、処理を進めてしまうことが結構あります。
そして最終段階で、数字がおかしいと気づく事が…(悲)
②名称だけでなく、その名称の元となるコード
例えば、部署名だけでなく、部署コードも含めないと、後でもう一度並び替えようと思ったときに
困ることがあります。
エクスポートのフォームの設定

フォームとクエリの連携

エクスポート結果

4.実際のモジュールのコード
いちおうコード貼っておきますね。テキストベースになってしまうので見にくいですが、
コピぺして、インデント等を整えれば、みやすくなるはず。
エクスポートボタンのモジュール
Private Sub cmd_Export2_Click()
Dim myDir As String
Dim myFN As String
Dim myBtn_Make_Path As Boolean
'フォーム上に書き込みがあるかチェック
If IsNull(Me.txt_Export) Then
MsgBox "フォルダパスを入力してください"
Me.txt_Export.SetFocus
Exit Sub
End If
'出力フォルダが見つからなかったら、フォルダを作る指定のラジオボタン
'デフォルトは True
myBtn_Make_Path = Me.Botton_Make_Path
'フォーム上に書き込まれた出力フォルダ名
myDir = Me.txt_Export
'出力フォルダ名の最後に\が無ければ\をつける
If Right(myDir, 1) <> "\" Then
myDir = myDir & "\"
End If
'出力フォルダがなければ作る
'出力フォルダが見つからなかったら、フォルダを作る
'そういう ラジオボタンを作っておく
'Botton_Make_Path =デフォルトは True
'出力フォルダの存在チェック
If Dir(myDir, vbDirectory) = "" Then
If myBtn_Make_Path = True Then
'出力フォルダが無くて、
'かつ「フォルダ無ければ作るボタン」があれば子フォルダを作る
'ただしMkDirは親フォルダが無いとエラーになる
On Error GoTo myError
MkDir myDir
On Error GoTo 0
Else
MsgBox "出力フォルダが見つかりません"
Me.txt_Export.SetFocus
Exit Sub
End If
End If
'親フォルダ全て作るには、
'一つずつフォルダの存在を見て作るか
'SHCreateDirectoryExというAPIを使うか
'という方法はあるけれど Accessの出力ではもう一つ下の階層を作りたいケースが殆どなので
'MKDirで、ほぼ用は足りる
'ファイル名に年月をつける
'何度も出力する場合は、年月日を前にしておいた方が、まとまった並び順になる
myFN = Format(Date, "yyyymmdd") & "_振込状況トレース結果.xlsx"
'例えば、画面に表示されている日付をセットするときは、
myFN = Format(textDate, "yyyymmdd") & "_振込状況トレース結果.xlsx"
'ファイルの存在チェック用のFunctionプロシージャ(関数)で処理
' CheckFile(パス名+ファイル名)
'ファイルの存在をチェックして、存在していたら上書きするかMSG
'上書きYesなら、上書き そうでなければ終了
If CheckFile(myDir & myFN) = False Then
Exit Sub
End If
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, "Q_302_指定日付分を抽出", myDir & myFN, True
'ちなみに acSpreadsheetTypeExcel8 なら出力ファイル名は 「.xls」
'これがずれていると、Excelを開くとき「ファイルが壊れている」の表示が出る
MsgBox "終わり"
Exit Sub
myError:
MsgBox "親フォルダが無いため、出力フォルダの作成が作成できませんでした"
Me.txt_Export.SetFocus
Exit Sub
End Sub
ファイルの存在チェックのモジュール(存在していたら上書きするか確認。OKなら削除しておく)
Function CheckFile(myFilePath As String) As Boolean
'同名のファイルがあるかチェック。あれば削除
If Dir(myFilePath) = "" Then
CheckFile = True
Else
myBtn = MsgBox("同名のファイルがあります。再作成してよろしいですか?" _
& vbCrLf & vbCrLf & _
"ファイル名:" & Dir(myFilePath), _
vbYesNoCancel + vbExclamation, "要確認")
If myBtn = vbYes Then
On Error GoTo Kill_Error
Kill myFilePath
On Error GoTo 0
CheckFile = True
Else
MsgBox "中止"
CheckFile = False
End If
End If
Exit Function
Kill_Error:
MsgBox Err.Number & vbCrLf & Err.Description
CheckFile = fale
End Function
日付変換前処理のモジュール(「2020.4.1」を「2020/4/1」のカタチに変換する)
Function hiduke(keyDate As String) As Date Dim myArray() As String '日付が「.」で区切られているので、配列型にする myArray = Split(keyDate, ".") '年、月、日に分ける hiduke = DateSerial(myArray(0), myArray(1), myArray(2)) End Function


