ExcelVBA覚書 CSV読込とSchema.ini

CSVファイルを読み込むときに、ADODBを使って読み込むやり方というのがあって、これには
1,ADODB.Streamを使う
2,ADODB.CommandとADODB.RecordSetのGetStringを使う(SELECT * FROM [{ファイル名}])
という2種類の方法があるというので、サンプルを実行してみたら、
1より2のほうが若干処理が速い。
ただ、2には落とし穴があって、それは
★勝手に型を変えてしまう
★読み込み方によっては正しくすべてのデータが取り込めない
ということだと分かった。

前0がついていようが数値にしよるし、日付は勝手に日付型でシートに出力されてしまうは、設定の仕方によっては思い通りのデータ取込ができなくなってしまう。

ってかさ、こんないい加減なサンプル送ってくんなよ!!
(他のところで実行時エラー起きてるし・・・)

ってなことであったが、どうすれば改善できるのか知らない私。
いろいろやってみて途方に暮れたところでGoogle先生の厄介になってみたら、

Schema.ini使うんです!

みたいな記事発見。で、「ADODB Schema.ini」で検索をかける。
ふむふむ、取り込む列の型とか、文字エンコードとか、このファイルの中で指定してあげればよいのだね!
————-
[{ファイル名}]
ColNameHeader=False
CharacterSet=65001
Format=CSVDelimited
Col1=列1 Text
Col2=列2 Text
Col3=列3 Text
Col4=列4 Text
Col5=列5 Text
—————
{ファイル名}は実際に読み込むファイル名(パスはなしで、ファイル名だけでいい)
ColNameHeader は、ヘッダー有無。(Trueはあり)
Format=CSVDelimited は、CSV形式(カンマ区切り)
CharacterSet=65001 は文字エンコードがUTF-8である。(S-JISなら932)
下に読み取り用のサンプルソースをつけているが、そこでCharacterSetを指定しているので,iniには必要ない。
(どちらかに設定があればOK)
Col1=*** の *** は、列のタイトル、その右のTextが型

【VBA】ADOを使用してテキストファイル(CSV)をDB操作する方法のまとめ

を参照したところ、型は整数はShortやLong、日付はDateと記載されている。
Char型で50文字なら、「Char Width 50」といったように記載されているので、固定長であればこういう記載になるのかと思う。
(試してはいない)

で、このSchema.iniをcsvファイルのあるフォルダパスと同じところに入れておくのだが、

チョイ待ち!!

読み込むcsvファイルが常に同じところに置かれているとは限らんではないか!
ということになった。
そう、読み込むCSVは、ダイアログで選ばせるのだ・・・
となると、csvと同じところにschema.iniを配置させねばファイルの意味がないし、いや、そもそもダイアログで選ぶファイル名もSchema.iniで定義したファイル名と異なっていたら読み込んでくれへんやん!!!

と、また1つ問題が生じてしまった。
ということで、最終的には、

a) 一時保存用のフォルダを作る
b) a)で作ったフォルダにSchema.iniを入れる
c) ダイアログで選択されたCSVファイルを a)で作成したフォルダに固定のファイル名にコピーする
  (固定のファイル名というのが、Schema.iniに定義する{ファイル名}と同じになるように)
d) c)のコピーされたほうのファイルをADODBでSELECTして読み込む
e) 読込が終わったら、c)のコピーされたほうのファイルを削除

として、どの場所にあっても、同じフォーマットで取り込まれるようにしたのだった。
ってなると、ADODB.Streamを使うより時間がかかってしまったので、結局Streamのほうが速い!という結論に至った。

とはいえ、CSVファイルの全データが取得できなかった点も、Schema.ini、Properties(“Extended Properties”)や、GetStringメソッドを見直して何とかとりあえずうまく行くようにはなった。
Officeは2016。

    Dim con As ADODB.Connection
    Dim cmd As ADODB.Command
    Dim rs  As ADODB.Recordset

    Set con = New ADODB.Connection
    With con
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .Properties("Extended Properties") = "Text;CharacterSet=65001;"    '65001=UTF-8 ,932=SJIS
        .Open {csvファイルのあるフォルダパス}
    End With
    Set cmd = New ADODB.Command
    Set cmd.ActiveConnection = con
    cmd.CommandText = "SELECT * FROM [{CSVファイル名}] "
    Set rs = New ADODB.Recordset
    rs.CursorType = adOpenStatic
    rs.Open cmd
    
    Dim dmp As String
    dmp = rs.GetString(adClipString, , ",", vbCrLf, "")  '行はCRLF, 列はカンマで区分するという設定に
    rs.MoveFirst
    Do Until rs.EOF
        '****** 1行分の処理を記載 ***********  
        rs.MoveNext
    Loop
   
  ’どばっとExcelに貼りつけるなら、Range.CopyFromRecordsetメソッドで 
    ' Activesheet.Cells(1,1).CopyFromRecordset rs            みたいな感じ

   rs.Close
    Set rs = Nothing
    Set cmd = Nothing
    con.Close
    Set con = Nothing

GetString メソッド (ADO)

中途半端なサンプルを送りつけられたせいで悩んだが、かえっていい勉強になったわぃ!
ということにしておこう。

Add a Comment

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

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