Access (VBA)

Access VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 7 Professional : Access 2010)
CSVファイルの結合 Workbooks.OpenText関数について
投稿日時: 18/01/04 19:39:06
投稿者: 馬車道停留所

こんにちは。
 
バッチファイルを使わずに、VBAで特定のフォルダ内にあるCSVファイルを結合しようとしています。
CSVをエクセルに貼り付ける際に、文字列が数字に置き換わってしまい、頭の0が取れてしまうことを回避するために、CSVファイルをテキスト形式で開いて貼り付けたいと思っています。
 
今のところ、「Set sBook = xlApp.Workbooks.OpenText(strDir & strFnm, Origin:=932, Comma:=True)」の箇所で、エラーが表示されてしまいます。
 
ご教授お願いします。
 
Private Sub GetCSVFiles_Click()
    Dim strDir As String
    Dim strFnm As String
    Dim xlApp As Excel.Application
    Dim mBook As Excel.Workbook
    Dim sBook As Excel.Workbook
    Dim mSht As Excel.Worksheet
    Dim sSht As Excel.Worksheet
    Dim v As Variant
    Dim oFlow As Boolean
     
    Set xlApp = New Excel.Application
    xlApp.Visible = True
    ' 新しいブックを追加
    Set mBook = xlApp.Workbooks.Add
    Set mSht = mBook.Worksheets(1)
      
    With Application.CurrentDb
    Let strDir = Left(.Name, Len(.Name) - Len(Dir(.Name)))
           End With
    strFnm = Dir(strDir & "*.csv")
    ' ファイルがあるだけループ
    Do While strFnm <> ""
    Set sBook = xlApp.Workbooks.OpenText(strDir & strFnm, Origin:=932, Comma:=True)
    ' 特定シートのみ結合
        Set sSht = sBook.Worksheets("testdata")
            ' 1回目
            If mSht.Cells(1) = Empty Then
            sSht.Range("A1").CurrentRegion.Copy
                    mSht.Cells(1, 1) _
                   .PasteSpecial Paste:=xlPasteValuesAndNumberFormats
                    Let xlApp.CutCopyMode = False
            Else
               ' 2回目から
            With sSht.Range("A1").CurrentRegion
                   .Resize(.Rows.Count - 0).Offset(0).Copy
            End With
                    mSht.Cells(mSht.Range("A1").CurrentRegion.Rows.Count + 1, 1) _
                   .PasteSpecial Paste:=xlPasteValuesAndNumberFormats
                    Let xlApp.CutCopyMode = False
            End If
        sBook.Close False
        If oFlow Then Exit Do
        strFnm = Dir()
    Loop
    xlApp.DisplayAlerts = False
             
    ' 一つに纏えたCSVファイルの保存
        mBook.SaveAs FileName:=strDir & "Output", FileFormat:=xlCSV, Local:=True
     
    ' 終了処理
    mBook.Close False
    xlApp.DisplayAlerts = True
    xlApp.Quit
End Sub

回答
投稿日時: 18/01/05 10:29:56
投稿者: Suzu

こんにちは。
 
すみません。
 
目的は何なのでしょうか。
AccessにCSVファイルを取り込む事が目的なのでしょうか。
 
であれば、
1. 1つめの CSVファイル を ワークテーブルに取り込む Docmd.TransferText メソッド
2. 2つめの CSVファイル を 先と同じワークテーブルに取り込む Docmd.TransferText メソッド
 
で済む話しなのでは?
 
 
処理速度向上を狙って CSV ファイルを連結したいのであれば、
コマンドプロンプトのバッチを使うのがお手軽だと思うのですが ダメな理由は何でしょう。
 
 
わざわざ Excel を介しているので
・処理速度が【遅く】なってしまう。
・文字列が数字に置き換わってしまい、頭の0が取れてしまうこと が起きる原因となっている。
という事は ご理解 されていらっしゃいますでしょうか。

投稿日時: 18/01/05 11:48:10
投稿者: 馬車道停留所

Suzuさん
 
ご連絡ありがとうございます。
 
第一の目的は、複数のCSVを一つに結合することです。
第二の目的は、一つに結合したCSVを、一回の作業で、アクセスに取り込む事です。
 
バッチファイルも作成し、そちらはうまく動きますが、
VBAで作成したい理由は、プログラム実行時に、結合するファイルの中身が、一瞬でも確認出来るからです。
 
ご指摘の通り、エクセルに貼り付ける段階で、元のCSVの日付形式や、文字列形式が崩れてしまうので、日付の方は、なんとか、フォーマットする事で、解消出来たのですが、CSVをエクセルに、テキスト形式で貼り付ける事が知識不足で出来ておりません。

回答
投稿日時: 18/01/05 16:39:36
投稿者: Suzu

すみません。
 

引用:
第一の目的は、複数のCSVを一つに結合することです。
第二の目的は、一つに結合したCSVを、一回の作業で、アクセスに取り込む事です。

 
なぜ、一つに纏めてAccessに取り込まなければならないのか。 その理由をご説明願いたいのです。
 
しかも、動作に時間のかかる EXCELを使用しなければならないのか。
こちらに関しては
引用:
プログラム実行時に、結合するファイルの中身が、一瞬でも確認出来るからです。

 
が理由だと推測する事はできるのですが、
 
確認できたとして、どうなるの?
 
途中で止める仕組みを組み込んでいる訳でもないのですよね。
それとも、特定の箇所を確認すれば良いのでしょうか。であればその内容を組み込んでしまっても良いと思いますが。。
 
と言っても始まらないので。。
 
直接の原因としては
WorkBooks.OpenText は 戻り値としてオブジェクトを返さないメソッドです。
 
なので
 
引用:
Dim obj As Excel.Workbook
 
Workbooks.OpenText Filename:="C:\DATA\TEST.csv", Origin:=932, Comma:=True
For Each obj In Workbooks
  If obj.Name = "TEST.CSV" Then Exit For
Nex

 
の様に開いた後に、走査します。
 
 
以下、私見です。
-----------------------------------------------------------------------------------------------
1ファイルづつユーザーに確認させる様にしたとして
表示されるのは、ほんの数秒。
 
使うユーザーとしては、
特定セルのみを確認すれば良いならともかく
複数セルを確認できる訳がなく、ただの負担にしかなりませんから、
確認画面を実装する事は、プログラムを提供するが側の自己満足としか思えません。
 
バッチファイルが出来ているのであれば
引用:
Dim ShellObject As Object
Set ShellObject = CreateObject("WScript.Shell")
ShellObject.Run "バッチファイル", 1, True
Docmd.TransferText 〜〜

充分と思いますよ。

回答
投稿日時: 18/01/05 17:26:33
投稿者: sk

引用:
Set sBook = xlApp.Workbooks.OpenText(strDir & strFnm, Origin:=932, Comma:=True)

引用:
の箇所で、エラーが表示されてしまいます。

エラー自体に関しては Suzu さんが指摘されている通り。
( OpenText メソッドは Function プロシージャではなく Sub プロシージャ)
 
----------------------------------------------------------------------------
 
xlApp.Workbooks.OpenText FileName:=strDir & strFnm, Origin:=932, Comma:=True
Set sBook = xlApp.Workbooks(2)
 
----------------------------------------------------------------------------
 
OpenText メソッドを実行する時点で開かれているブックの数が
常に 2 個であるならば、上記のようなコードでも充分でしょう。
 
引用:
' 一つに纏えたCSVファイルの保存
mBook.SaveAs FileName:=strDir & "Output", FileFormat:=xlCSV, Local:=True

また、ファイル結合処理を実行しようとした時点で
既に Output.csv が存在していた場合、そのファイルも
結合の対象に含まれることになるため、同名のファイルが
存在しないかどうかを検査し、OpenText メソッドによって
開かれるファイルから除外することが必要であるはず。
 
引用:
バッチファイルを使わずに、VBAで特定のフォルダ内にある
CSVファイルを結合しようとしています。

CSV ファイルを結合する手段に関しては
Excel を含めて色々あるとして
(個人的には Excel を間にかますのはお奨め出来ませんが)
 
引用:
CSVをエクセルに貼り付ける際に、文字列が数字に置き換わってしまい、
頭の0が取れてしまうことを回避するために、CSVファイルを
テキスト形式で開いて貼り付けたいと思っています。

例示されたコードでは、OpenText メソッドを実行する際に
引数 FieldInfo の設定が行なわれていません。
 
そのままでは同様に、数字のみで構成された文字列等が
数値型のデータに変換されて前ゼロが取れるという結果となるでしょう。

投稿日時: 18/01/05 22:44:18
投稿者: 馬車道停留所

Suzuさん
 
なぜ、一つに纏めてAccessに取り込まなければならないのか。 その理由をご説明願いたいのです。 
 
しかも、動作に時間のかかる EXCELを使用しなければならないのか。 
 
⇒その方法しか知らないからと言うのが答えです。
 
確認できたとして、どうなるの? 
 
⇒バッチでの処理と中身に違いがないか確認したい思いもありましたが、実用的ではないですね。
 
途中で止める仕組みを組み込んでいる訳でもないのですよね。 
 
⇒はい。ないです。
 
それとも、特定の箇所を確認すれば良いのでしょうか。であればその内容を組み込んでしまっても良いと思いますが。
 
⇒結合する際に、ちゃんと末尾に貼り付けされているか、レコード数がもれなく、付加されていっているかみたい程度でした。
 
直接の原因としては 
WorkBooks.OpenText は 戻り値としてオブジェクトを返さないメソッドです。 
 
⇒そうなんですね。
 ありがとうございます。
 
⇒確かに、バッチファイルの処理だけで充分ですね。
 そう言われてみると、自己満足だったかもしれません。

投稿日時: 18/01/05 22:56:14
投稿者: 馬車道停留所

skさん
 
( OpenText メソッドは Function プロシージャではなく Sub プロシージャ) 
 
⇒ありがとうございます。
 
また、ファイル結合処理を実行しようとした時点で 既に Output.csv が存在していた場合、そのファイルも 結合の対象に含まれることになるため、同名のファイルが 存在しないかどうかを検査し、OpenText メソッドによって 開かれるファイルから除外することが必要であるはず。 
 
⇒ご指摘の通りです。
 
CSV ファイルを結合する手段に関しては Excel を含めて色々あるとして (個人的には Excel を間にかますのはお奨め出来ませんが) 
 
例示されたコードでは、OpenText メソッドを実行する際に 引数 FieldInfo の設定が行なわれていません。 
 
⇒確かに、調べて見たのですが、複雑過ぎて、短時間では、理解に困り、断念しました。
 
そのままでは同様に、数字のみで構成された文字列等が 数値型のデータに変換されて前ゼロが取れるという結果となるでしょう。
 
⇒ご指摘の通りです。

投稿日時: 18/01/05 22:57:26
投稿者: 馬車道停留所

皆様からいただいた助言を踏まえ、今回は、バッチ処理で対応する事とします。
ご回答いただいた皆様ありがとうございました。

投稿日時: 18/01/06 19:36:26
投稿者: 馬車道停留所

ありがとうございました。