VBAと日々のこぼれ話

  1. VBA

【VBA】CSVを1行ずつ処理したい

CSVデータをワークへ入れずに1行ずつ処理したい

私自身はインプットファイルの読み込み後、一旦、Excelシートやテーブルにデータを入れ、そこからデータ取得することが主です。

これは処理内容が複雑になることが多いのでデータを中間テーブル(ワーク)に初めから入れておいた方が便利からなのですが、場合によってはそれをしたくないというニーズもあるようですのでこんな方法もあるよと。

前提事項

CSVファイルフォーマット

CSVファイルのフォーマットが綺麗(※)であれば、ファイルをOPEN⇒1行読み込み⇒Split(項目分割)のうちの少なくともSplit処理を書かなくて良い分、楽だし処理速度も速いかな?と思います。

・・・正規表現でのsplit、書かなくて良いなら書きたくないのです。

※CSVフォーマットについては、色々と存在していてこれという明確なルールがはっきりとしていないそうで。
少なくともIETFのRFC 4180のDefinition of the CSV Format辺りを網羅出来ていることかなぁ。
CSVについては、RFC 7111(RFC4180の更新版)も一緒に目を通すと良いよ!

少し具体的(ざっくり)に言うと
・一行、一データ
・項目の区切り文字がカンマ(tsvならTabといった区切り文字)で統一
・値内の「”」は「””」とエスケープ
・値内に改行コードやカンマがあれば「”」で値を囲む等。

この辺りは、RFC4180曰く殆どのCSVフォーマットに共通だそう。

事前準備

インプットデータ(test.csv)の中身

商品コード,商品名,単価,最終仕入日
0001,ピーナッツ(殻付き),1320.6,2018/5/14
1000,充電式電池,804,2018/3/20
0567,ビニール傘,520,2017/12/22

Schema.iniへの設定内容

[test.csv]
ColNameHeader=True
Format=CSVDelimited
Col1=商品コード Text
Col2=商品名 Text
Col3=単価 Double
Col4=最終仕入日 Date

その他準備

Schema.iniについてやADO利用のための参照設定は下の記事も参考にしてください。
また、今回のサンプルコードは参照設定不要で作成しています。

(参考元の記事もいずれもう少し丁寧に書き直したい。読み返すと不親切極まりない)

サンプルコード

実施していることは、非常にシンプルで

①CSVファイルの情報が定義されたSchema.ini通りにCSVファイルを開く(CSVファイルに接続)
②CSVファイルを上から1行ずつ、左の項目から書き出す
③②をファイルの終わりまで繰り返す

①のファイルを開く際の条件にSQLクエリを足せば、いつぞや話したExcelシートに対してSQLが発行できるようにCSVファイルにもSQL発行することが可能ですが、
今回は愚直にイミディエイトウィンドウに書き出しています。

【スポンサーリンク】



ポイント

ISAMフォーマットのオプションは設定しなくて良い

以前に話していたISAMフォーマット(下記の記事を参照)にはオプション設定ができます。

オプションでは、ヘッダーと接続モードに関する設定が可能なのですが、ISAMフォーマットがTextである場合、設定不要です。
というか、設定しても言うことをきいてくれないことがあるので初めから書かないが正しいです。

ISAMフォーマットのオプション設定やそのバグについてはこのブログで説明の途中(続けてもマニアックすぎて需要があるのか)なのですが、実は、TextへのADO接続(DAO接続)は、オプションやレジストリの設定が効かない場合があります。

言うことを聞いてくれない理由は今のところずばり解説してくれているものが見つけられていないのですが、ひとまずCSV等へADO接続する際は、Schema.iniを使ってきちんと設定することで言い聞かせる(回避する)というのが実情です。

よって、ISAMフォーマットの部分は必須のフォーマット指定で構いません。

ヘッダー情報について

CSVファイルにヘッダの情報はありませんが、どうして各フィールド名が取得できるかと言うと、Schema.iniでファイルの情報定義を行っておりここから取得しています。

サンプルデータのようにCSVファイル内にデータしかない場合は気にしなくても良いのですが、CSVファイルの1行目にヘッダ情報(フィールド名)があるような場合は注意が必要です。

サンプルコードでは、CSV1行目からデータが設定されているとみなした作りにしています。
ですので、1行目にヘッダーが設定してある場合は、1行ずつ書き出しを行っている部分のロジックを改修、、、しても良いですがそれは結構手間です。

ですので、そんな場合は、Schema.iniの「ColNameHeader=False」を「ColNameHeader=True」としてください。

すると、CSVの1行目はヘッダとみなされデータとしては無視されます。

先ほどもお話ししたようにフィールド名などのCSVファイルの定義情報は、Schema.iniの定義情報を利用するので「ColNameHeader」の設定で取得できなくなることはありません。

おまけ

文字コード設定について

Schema.iniへの文字コードの設定は、ANSIかOEMの二択という公式ドキュメント(2017年)があります。

ですが、そもそも日本語環境下ではSchema.iniによる文字コードの設定はあまり意味のない設定だと思っているので、省略してこのサンプルコードの前提としてShift-JISのCSVファイルと書いておこうと思いました。

サンプルのSchema.iniにも文字コード設定は記載していません。
(日本版Officeの場合(設定言語に依存だったかも)、Excelは基本的に文字コードはShift-JISと認識される)

ですが、試しにUnicode (UTF-8)の文字コードファイルを作成して、Schema.iniで文字コード(コードページ)を指定してみるときちんと判定している模様。

(私が発見したわけでなく、他の方のブログでもよく設定されている)

仕様が変わったのかなぁ。この辺り、保証できないのでご注意ください。

文字コード設定したい場合は、「CharacterSet=ANSI(または文字コードページ)」のように設定してください。

例)コードページ
Shift-JIS=932
UTF-8=65001

【スポンサーリンク】



VBAの最近記事

  1. 【VBA】CSVを1行ずつ処理したい

  2. Excelシートの最終行を取得したい その1

  3. 【VBA】未だに苦手としていること

  4. 【VBA】モジュール先頭に記述する4種類のOption キーワード ステートメント

  5. 【VBA】同じ階層体系のフォルダを量産したい

関連記事

【スポンサーリンク】




PAGE TOP