csvとかさー

なんか最近やけにcsvファイルをexcel vbaで処理なんてことがあって、たいていはあるcsvからデータを読んでなんかしらの変換加えて新たに作ったcsvの方へ書き込む。という処理なので、なんかうまいこと出来ないかなーと考えてたのね。
これがCとかだと処理内容の関数用意しといて関数へのポインタ使ってどーたらすると綺麗に作れそうな気もするのですがVBAだしな。
VBAでexcelで読んだcsv(例としてcsvtest.csv)

に入っている、bbb、cccという項目のデータを足して、新たに作ったcsvの2つ目の項目として書き込む

を処理する流れとしては、
1) excelでcsvを読む→ファイル名のシートが出来る(csvtest.csv)…excelにやらす
2) 新規にワークシート追加して、シート名をつける→destcsvというシートとする
Shetts.Add
Activesheets.Name=”destcsv”
3) testcsvのほうから読み出す項目名のセル(桁)を探す→scol()という変数にいれとく
for i=1 to 1000
 Select case Sheets(“csvtest”).Cells(1,i)
  Case “bbb”:
   scol(0) = i
  Case “ccc”:
   scol(1) = i
  Case “”:
   exit for
 End Select
next
4) destcsvのほうへ書き込む項目名を作って、その行を決める→dcolという変数にいれとく
Sheets(“destcsv”).Cells(1,2) = “fff”
dcol = 2
5) testcsvのほうから読んできて、足してdestcsvのほうへ書き込む
for i=2 to 1000
 Sheets(“destcsv”).Cells(i,dcol) = _
  Sheets(“testcsv”).Cells(i,scol(0))+Sheets(“testcsv”).Cells(i,scol(1))
next
ってかんじかしら。ただ最後のループは終了条件が書いてないので、データがあろうとなかろうと1000行まで作業してしまうのね。
んで今回はなんとなくPushとPopという名で関数作ってみた。
作った関数は、
CsvSetRead(読み出すシート名, 項目名 [, 配列]) …[, 配列]は省略すると 0
  戻り値は項目のある桁。もし項目名がなければ0を返す
CsvSetWrite(書き込むシート名, 項目名, 項目を書き込む桁 [, 配列])
  もし書き込むシート名にあたるシートがなければ勝手に新規シートを追加します。
CsvPrep(読み出すシート名, 項目名, 書き込むシート名, 項目名, 項目を書き込む桁 [,配列])
  内部でcsvsetreadとwriteを連続して呼んでるだけ
PopCsv([配列]) …戻り値が-9999でデータ終了
PushCsv(データ [,配列])
戻り値は当然variant型。
これでさっきの処理を書くと、
Call CsvPrep(“csvtest”, “bbb”, “destcsv”, “fff”, 2)
Call CsvSetRead(“csvtest”, “ccc”, 1)
For i = 1 To 200
  j = PopCsv()
 If (j = -9999) Then Exit For
  PushCsv (j + PopCsv(1))
Next
こんなかんじ。これでも2項目から読んで1項目へ書いているので若干煩雑(?)ですが、一項目から読んで一項目へ書き込む、たとえばある項目の文字を半角にして書き込むとかいう処理なら、
Call CsvPrep(“csvtest”, “bbb”, “destcsv”, “fff”, 2)
For i = 1 To 200
  j = PopCsv()
 If (j = -9999) Then Exit For
 PushCsv (StrConv(j, vbNarrow))
Next
こんなので。
今後はちょっと楽が出来るかなー。

おすすめ