[[20180119083931]] 『特定行からのCSV取り込み』(もも) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『特定行からのCSV取り込み』(もも)

お世話になっております。

全くのVBA初心者です。CSVファイルの取り込みのVBAは出来ましたが、余分なデータまで取り込まれていました。
特定行からCSVファイルを取り込みたいのですがうまくいきません。

お知恵をお借りできないでしょうか?

< 使用 Excel:Excel2013、使用 OS:Windows7 >


 行単位なので有ればいったん取り込んでから特定行前の行を削除してはどうか。
(ねむねむ) 2018/01/19(金) 09:59

一部、ねむねむさんとかぶったけどそのまま投稿します。

こんにちは。

偉そうな言い方になっていたら恐縮ですが、回答者はこの掲示板に文字で書いて頂いた情報しかわかりません。
ですので特定行って言われてもそれがどこにあるのか知りません。(どうやって特定行だって判断するのか条件を知りません)それをわかるように説明してください

アプローチ方法はいくつかあると思いますけど、自分がぱっと思いついたのは以下2つです。

作戦1
取り込んでから要らないデータを削除する。

作戦2 ← 今回はこちらをイメージされてると思われます。
CSV(テキストファイル)の特定行が何行目からなのか調べて、その行以降を読み込む。
(もこな2) 2018/01/19(金) 10:07


 作戦2を採る場合には
 Open ファイル名 For Input As #ファイル番号
 で対象CSVを開きLine Inputなどで変数に取り込んで中身のチェック、それによりセルに書きこむ、という形になる。
(ねむねむ) 2018/01/19(金) 10:28

ねむねむ さん もこな2 さん
の 作戦2をコードにすると
("Sheet1")A列に行頭5文字が12350以外を書き出します。

Sub main()

    Const fnm As String = "D:\excel\test.csv"
    Dim buf(), i As Long, rowcnt As Long, sh01 As Worksheet
    Set sh01 = Worksheets("Sheet1")
    rowcnt = 1: i = 0
    Open fnm For Input As #1
    Do While Not EOF(1)
        ReDim Preserve buf(i)
        Line Input #1, buf(i)
        If Left(buf(i), 5) <> 12350 Then
            sh01.Cells(rowcnt, 1).Value = buf(i)
            rowcnt = rowcnt + 1
        End If
        i = i + 1
    Loop
    Close #1

でしょうか
外してましたら。突っ込みお願いいたします。 ^^;

(隠居じーさん) 2018/01/19(金) 10:55


メモ帳で投稿内容を推敲してる間にすばらしい回答ついてますが、せっかくなので投稿します。

テキストファイルとして1行ずつ読み込む方法はこちらが参考になりそうです。
http://officetanaka.net/excel/vba/file/file08b.htm

また、何行目からCSV読み込みたいという場合には、QueryTables.Add 関数を使うというアプローチもありそうです。
https://www.tipsfound.com/vba/18014

例として・・・
>こんにちは,今日も,いい天気ですね
>明日も,晴れると,いいですね
>明後日の,天気は,なんでしょうか
みたいなCSVがあったとして、
明日も〜で始まる行以降を取り込みたいのであれば、こんなコードでいけるとおもいます。

Sub Sample()
'==変数の宣言とか

    Dim buf As String, n As Long, i As Long
    Dim New_SH As Worksheet

'==処理1(テキストファイルとして開いて条件に合致する行を探す)

    Open "C:\test\Data.csv" For Input As #1
        Do Until EOF(1)
            Line Input #1, buf
            n = n + 1
            If buf Like "明日も*" Then
                i = n '←見付かったら別の変数に行を格納
                Exit Do
            End If
        Loop
    Close #1

'==処理2(処理1で行がみつかっていたら、ブックにシートを追加して、そこに取り込む)

    If i = 0 Then Exit Sub '「i」が初期値のままだったら終了
    Set New_SH = Worksheets.Add
    With New_SH
        With .QueryTables.Add _
            (Connection:="TEXT;C:\test\DATA.CSV", Destination:=.Range("$A$1"))
            .TextFileCommaDelimiter = True   ' カンマ区切り
            .RefreshStyle = xlOverwriteCells ' セルに上書き
            .TextFileStartRow = i 'データの読込開始行をセット
            .Refresh ' データを表示
            .Delete ' CSV との接続を解除
        End With
    End With

End Sub
(もこな2) 2018/01/19(金) 11:54


すみません。説明が変でした。

(誤)テキストファイルとして開いて
(正)OPENメソッドで開いて

こちらのほうが適切ですね。。。
他にツッコミどころがあればお願いします。
(もこな2) 2018/01/19(金) 12:09


 他の回答者さんの言われている通り、「特定行」の定義がイマイチなので
 1.決まった行以降の取込み
 2.決まった文字列を含む行以降の取込み
 で考えてみました。

 FSOを使って一旦配列に格納後に処理しています。
 TEST1は13行目以降の取込み、TEST2は「12345」の文字列を含む行以降の取込みです。

 Sub TEST1()

    Const CSVPath As String = "C:\test\DATA.CSV"
    Const DataChoiceRow As Long = 13 '取込み開始行

    Dim FSO As Object, i As Long, Data, CSVFile, n As Long

    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set CSVFile = FSO.OpenTextFile(CSVPath, 1)
    Data = Split(CSVFile.ReadAll, vbCrLf)
    CSVFile.Close
    For i = DataChoiceRow - 1 To UBound(Data)
        n = n + 1: Range("A" & n).Value = Data(i)
    Next i
    Set FSO = Nothing    

 End Sub

 Sub TEST2()

    Const CSVPath As String = "C:\test\DATA.CSV"
    Const DataFindStr As String = "12345" '検索文字列

    Dim FSO As Object, i As Long, Data, CSVFile, n As Long, c As Long

    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set CSVFile = FSO.OpenTextFile(CSVPath, 1)
    Data = Split(CSVFile.ReadAll, vbCrLf)
    CSVFile.Close
    For i = 0 To UBound(Data)
        If InStr(Data(i), DataFindStr) > 0 Then
            For c = i To UBound(Data)
                n = n + 1: Range("A" & n).Value = Data(c)
            Next c
            Exit For
        End If
    Next i
    Set FSO = Nothing

 End Sub
(ろっくん) 2018/01/19(金) 12:42

お世話になっております。

説明不足の中ご対応いただいありがとうございました。

特定の行からの取り込みになります。

勉強不足で皆様の構文を解読するのに時間がかかりますが

先んじてお礼させていただきます。
(もも) 2018/01/19(金) 13:25


 「特定の行」の条件はありますか?
 条件によりコードが変わりますし、より良いコードが捻出されるかもしれませんよ。
(ろっくん) 2018/01/19(金) 13:40

実験してるうちに、解決したのかもしれないけど、せっかくなので投稿します。

>ろっくんさん の他の回答者さんの言われている通り、「特定行」の定義がイマイチなので〜 を拝見して
>(隠居じーさん)さんのコードを拝見して

そうですよね・・「特定行から」って言うのを特定行「以降」って読みましたけど、特定行を「抜き出して」という意味にも取れますよね。

ということで、別のファイルに抜き出してから質問者さんのコードで取り込む方法も考えてみました。

Sub Sample2()
'==変数の宣言とか

    Dim buf As String
    Dim tmp_FilePath As String
        tmp_FilePath = ThisWorkbook.Path & "\tmp.csv"

'==処理1(条件に合致するものだけtmp.csvに書き出す)

    Open "C:\test\Data.csv" For Input As #1
    Open tmp_FilePath For Output As #2
        Do Until EOF(1)
            Line Input #1, buf
            If buf Like "明日も*" Then Print #2, buf
        Loop
    Close #2
    Close #1

'==処理2(質問者さんのコードでcsv取込)

    Call 質問者さんコード(tmp_FilePath)

End Sub

Sub 質問者さんコード(パス As String)
'省略
Ene Sub
(もこな2) 2018/01/19(金) 13:47


 特定文字のある行だけを抽出する場合はこんな感じでも。
 (エラー処理してないです。。)

 Sub TEST3()

    Const CSVPath As String = "C:\test\DATA.CSV"
    Const DataFindStr As String = "12345" '検索文字列

    Dim FSO As Object, i As Long, Data, CSVFile, n As Long
    Dim ExtractData

    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set CSVFile = FSO.OpenTextFile(CSVPath, 1)
    Data = Split(CSVFile.ReadAll, vbCrLf)
    CSVFile.Close
    ExtractData = Filter(Data, DataFindStr)

    For n = 0 To UBound(ExtractData)
         Range("A" & n + 1).Value = ExtractData(n)
    Next n

    Set FSO = Nothing

 End Sub
(ろっくん) 2018/01/19(金) 14:15

お世話になっております。

特定の行は23行目だと思うのですが、測定結果が書き出されたCSVファイルが有ります。
CSVファイルを取り込んだら、測定結果以外に測定条件まで測定結果上部に取り込まれてしまいました。

測定結果がおそらく23行目からかと思いますが、確実とは言えず
測定結果が記載されているところから取り込みをしたかったのです。

測定結果は下記のようにはじまります。
x y z
1  2 3
5  4 6
・ ・ ・

と7000行くらい続きます。

わかりにくくて申し訳ありません。

(もも) 2018/01/19(金) 15:55


>測定結果がおそらく23行目からかと思いますが、確実とは言えず
みなさんがコメントされてるとおり、まさにココが肝です。
ももさんは、どうやってココがそうだ って特定してますか?

CSVファイルをメモ帳で開いてみて、23行目あたりがどうなってるか見てみましょう。
たとえば、「x,y,z」ってなってるが行あって、それを根拠に特定しているのであれば、それが検索キーです。

私のコードでいえば
If buf = "x,y,z" Then
と直せば、いけるとおもいます。

きになるのが、
>x y z
>1  2 3
>5  4 6
>・ ・ ・
>と7000行くらい続きます。
と仰っているので、まさかとはおもいますが、
23行目あたりが、「x,y,z」、その次の行が、「1,2,3」、さらにその次がその次の行が、「5,4,6」ってなってたらその箇所って特定できるわけではないですよね?
それでも探せますけど、そういう条件ならそうと言わないと回答者はももさんのパソコン見えてませんから、なかなか明確な回答を返すのは難しいです。

何行続いているかは、エクセルの行数超えなければ関係ないです。

ちなみに、たとえば「1,000」みたいに、項目単位でみたときにカンマが含まれるものはないですか?
難しくいうと、カンマを文字として扱ってるデータはないですか?
もし、そういうデータがある場合は、先に言っておかないと、カンマは区切りの意味でしか使ってないって解釈して回答してしまうので、ご注意ください。
※「1000」 を 書式で 「1,000」って表示させてるなら問題ないです。しつこいようですが、カンマを文字として扱ってる場合にトラブルの原因になります。

(お小言みたいになってすみません。)

(もこな2) 2018/01/19(金) 16:35


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.