- 締切済み
VBAでCSVファイルをインポートする方法について
VBAでCSVファイルをインポートする方法について OS:ウィンドウズXP Access Version:2000 AccessVBAでcsvファイルをインポートするマクロを作っています。 現在、インポート定義を利用して、データ型を指定したインポートができているのですが、1点だけ問題があり、質問します。 インポートするcsvファイルのA列にIDが入力されています。 そのA列の末尾に、ID(数値型)ではない「<b>32</b><br />」という値が入っています。 Accessのテーブルでは、このIDのフィールドは数値型で管理している為、この1レコードだけ エラーとなり、エラーテーブルが作られ、また、インポート先のテーブルには空のレコードができてしまいます。 この末尾の行については、IDではない「<b>32</b><br />」以外は何もデータが入っていない為、 インポートする必要がありません。 もし可能であれば、csvファイルのA列(Accessテーブルでは数値型のIDというフィールド)が数値ではない場合、 その行のインポートをスキップするような処理がVBAで作成できるとよいのですが、可能でしたら教えてもらえないでしょうか。 ※以下はVBAを作成する為に仮に用意し、読込を行っているcsvファイルと、VBAソースになります。 ○csvファイル名:インポート用csvファイル.csv 内容: ID,テキスト1,テキスト2,テキスト3,テキスト4,メモ1,メモ2, 1,a,A,z,Z,あ,ん, 2,b,B,y,Y,い,を, 3,c,C,x,X,う,わ, 4,d,D,w,W,え,ろ, 5,e,E,v,V,お,れ, 6,f,F,u,U,か,る, 7,g,G,t,T,き,り, 8,h,H,s,S,く,ら, 9,i,I,r,R,け,よ, 10,j,J,q,Q,こ,ゆ, <b>32</b><br />,,,,,, ○VBAソース Dim FN As String Dim Res As Integer WizHook.Key = 51488399 Res = WizHook.GetFileName(0, "", "", "", FN, "", _ "csvファイル(*.csv)|*.csv", 0, 0, 4, True) WizHook.Key = 0 If Res = 0 Then DoCmd.TransferText , "csvインポート定義", "インポートテーブル", FN MsgBox "csvファイルをインポートしました", vbOKOnly End If
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- nda23
- ベストアンサー率54% (777/1415)
>If IsNumeric(A(1)) Option Base を特に指定しない限り、配列の底は0です。 行中に区切り文字がなければ要素数=1なので、配列範囲外に なります。 データ中に改行があったり、引用符で囲まれるという条件は 先にお知らせください。引用符があるということはデータ中に カンマ(項目の区切りでない)がある可能性があります。 Line Input は1行(改行までの)読み込みなので、改行を 含むデータがあるとすると、オカシクなります。 もし、項目数とDBフィールドが(の属性も)分かっているなら、 ファイルをフィルタリングせずに直接書き込む方が早いかも。 Const 項目数 As Long = 7 Dim 列 As Long Dim 項目 As Variant Dim RS As Dao.Recorset Set RS = CurrentDb.OpenRecordset("hoge") ’テーブルを開く == 中略 == Do Until EOF(1) Input #1, 項目 If VarType(項目) = vbString Then If Not EOF(1) Then Line Input #1, 項目 Else RS.AddNew RS.Fields(0) = 項目 For 列 = 2 To 項目数 If EOF(1) Then Exit For Input #1, 項目 RS.Fields(列 - 1) = 項目 Next RS.Update End If Loop RS.Close Close #1
- nda23
- ベストアンサー率54% (777/1415)
方法は二つあります。 一つはファイル読み込み→レコード挿入をVBAで記述する ものです。もう一法はファイルをVBAでフィルタリング してからインポートするものです。 「インポートの定義」があることを考えると、2番目の 方法の方が安全かと思います。 以下はフィルタリングの例 Dim T$, W$, A W = "C:\~\wk.csv" ’★フィルタリング後のファイル名 Open FN For Input As #1 Open W For Output As #2 Do Until EOF(1) Line Input #1, T A = Split(T, ",") If IsNumeric(A(0)) Then Print #2, T '★先頭項目が数字の場合のみ出力 End If Loop Close DoCmd.TransferText , "csvインポート定義", "インポートテーブル", W
補足
回答いただきありがとうございます。 早速試してみたところ、仮のcsvファイルの先頭行を削除すると、うまく動作しています。 ※先頭行:ID,テキスト1,テキスト2,テキスト3,テキスト4,メモ1,メモ2, こちらの先頭行はインポート定義でフィールド名として使用している為、レコードとして読込は行っていません。 また、EOFやIsNumericについても解説されているサイトを見てみました。 そこで質問で挙げた仮データではなく実際に使用するcsvファイルの読み込みように編集したところ、 実行時エラー '9': インデックスが有効範囲にありません。というエラーが発生しました。 実際に使うcsvファイルの形式を用いて、新たに簡易のcsvファイルを用意したところ、 同様のエラーが発生しましたので、伺いたく新たな簡易csvファイルの内容を記載させていただきます。 ○csvファイル名:インポート用簡易csvファイル2.csv → ファイルを開くダイアログを用いて開き、ファイル名を変数FNへ格納しています。 ・csvとしてExcelで開いた場合 A列 B列 1行目 ID text 2行目 1 aa bb cc 3行目 2 dd ee ff ・メモ帳で開いた場合 "ID","text", "0001","aa bb cc", "0002","dd ee ff", ※本番で使用するcsvファイルは、区切り文字が「"」と「,」であることや セル内で改行を行っているフィールドがあり、メモ帳で開くとbbとccの間の 空白行があったことが本エラーの原因ではないかと思っているのですが、 これらの原因を回避する方法が分からず困っています。 また、先頭行のIDというのも数値ではないので、 そこですでにエラーになっているのかも?という気もしていますが、 まだAccessをはじめたばかりでこれ以上詳しくは分かりませんでした。 よろしければ原因と対策を判断いただけないでしょうか? 以下は現在編集したソースです。 Dim FN As String Dim Res As Integer Dim T$, reFile$, A WizHook.Key = 51488399 Res = WizHook.GetFileName(0, "", "", "", FN, "", _ "csvファイル(*.csv)|*.csv", 0, 0, 4, True) WizHook.Key = 0 If Res = 0 Then reFile = Dir(FN) & "\Filetering" & FN ’★フィルタリング後のファイル名 Open FN For Input As #1 Open reFile For Output As #2 Do Until EOF(1) Line Input #1, T A = Split(T, ",") If IsNumeric(A(1)) Then Print #2, T '★先頭項目が数字の場合のみ出力 End If Loop Close DoCmd.TransferText , "csvインポート定義", "インポートテーブル", reFile MsgBox "csvファイルをインポートしました", vbOKOnly End If