[[20160203175950]] 『CSV取込VBAで』(tatsu) ページの最後に飛ぶ

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

 

『CSV取込VBAで』(tatsu)

お世話になっています

以下のマクロを実行したところ、
CSV取込VBAで""が無視されてしまいます
エクセルで,区切りで出力したデータで、セル内に,がある場合
セルが""で囲まれますが、したのVBAで取り込むと""を無視して,でセルに入れてしまいます

例えばCSVが
課長,伊藤,"11,000","2,200"
となっていた場合
取りこむと
課長 伊藤 11,000 2,200 と4つのセルになってほしいのに
課長 伊藤 "11 000" "2 200" と6つのセルになってしまい
後半2セル分が取り込まれない結果になります

どのように修正したらいいか教えていただけないでしょうか
よろしくお願いします

Sub CSVデータ取り込み()

    Dim buf As String
    Dim v As Variant
    Dim 職制 As String, 担当者 As String, 金額1  As String, 金額2 As String
    Dim r As Long
    Dim wrk As Variant

    wrk = Range(Cells(1, 1), Cells(Cells(Rows.Count, 1).End(xlUp).Row, _
          Cells(1, Columns.Count).End(xlToLeft).Column))
    '読み込みファイル指定
    fname = Application.GetOpenFilename()
    Open fname For Input As #1
        Do Until EOF(1)
            Line Input #1, buf
            v = Split(buf, ",")
            r = データ取得(v(0), wrk)
            If r <> 0 Then
                   職制 = v(2)
                   担当者 = v(3)
                   金額1 = v(4)
                   金額2 = v(5)
                      wrk(r, 3) = 職制
                      wrk(r, 4) = 担当者
                      wrk(r, 5) = 金額1
                      wrk(r, 6) = 金額2
            End If
        Loop
    Close #1
    Range(Cells(1, 1), Cells(Cells(Rows.Count, 1).End(xlUp).Row, _
          Cells(1, Columns.Count).End(xlToLeft).Column)) = wrk
    Tool.Show
End Sub

Private Function データ取得(ByVal 取引先コード As String, wrk As Variant) As Long

    Dim r As Long
    For r = 2 To Cells(Rows.Count, 1).End(xlUp).Row
        If wrk(r, 1) = 取引先コード Then
            データ取得 = r
            Exit Function
        End If
    Next r
End Function

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


それは、Splitで
課長,伊藤,"11,000","2,200"が

課長,
伊藤,
"11,
000",
"2,
200"

のように解釈されるからです。

普通に、外部データの取込 - テキストファイルを使う(マクロ記録してそれを修正)
するのが固いですね。

(γ) 2016/02/03(水) 20:48


 ずいぶん前に書いたコードで、実際のCSVファイルが無いので検証不可。

 Sub CSVデータ取り込み()
    Dim buf As String
    Dim v As Variant
    Dim 職制 As String, 担当者 As String, 金額1  As String, 金額2 As String
    Dim r As Long
    Dim wrk As Variant
    wrk = Range(Cells(1, 1), Cells(Cells(Rows.Count, 1).End(xlUp).Row, _
          Cells(1, Columns.Count).End(xlToLeft).Column))
    '読み込みファイル指定
    fname = Application.GetOpenFilename()
    Open fname For Input As #1
        Do Until EOF(1)
            Line Input #1, buf
            v = Split(CleanCSV(buf, Chr(2), Chr(3)), ",")
            'v = Split(buf, ",")
            r = データ取得(v(0), wrk)
            If r <> 0 Then
                   職制 = v(2)
                   担当者 = v(3)
                   金額1 = v(4)
                   金額2 = v(5)
                      wrk(r, 3) = 職制
                      wrk(r, 4) = 担当者
                      wrk(r, 5) = 金額1
                      wrk(r, 6) = 金額2
            End If
        Loop
    Close #1
    With Range(Cells(1, 1), Cells(Cells(Rows.Count, 1).End(xlUp).Row, _
          Cells(1, Columns.Count).End(xlToLeft).Column))
        .Value = wrk
        .Replace Chr(2), ",", 2
        .Replace Chr(3), vbNullString, 2
    End With
    'Tool.Show
End Sub

 Private Function データ取得(ByVal 取引先コード As String, wrk As Variant) As Long
    Dim r As Long
    For r = 2 To Cells(Rows.Count, 1).End(xlUp).Row
        If wrk(r, 1) = 取引先コード Then
            データ取得 = r
            Exit Function
        End If
    Next r
End Function

 Function CleanCSV(ByVal txt As String, ByVal subComma As String, _
    ByVal subDQ As String) As String
    Dim m As Object
    Static RegX As Object
    If RegX Is Nothing Then Set RegX = CreateObject("VBScript.RegExp")
    With RegX
        .Pattern = "(^|,) *(""[^""]+"")(,|$)"
        Do While .test(txt)
            Set m = .Execute(txt)(0)
            txt = Application.Replace(txt, m.firstindex + 1, _
            m.Length, m.submatches(0) & Replace(Replace(m.submatches(1), _
            ",", subComma), """", subDQ) & m.submatches(2))
        Loop
    End With
    CleanCSV = txt
End Function

(seiya) 2016/02/03(水) 23:44


γさん、seiyaさん
回答ありがとうございます
γさん
1万件ほどのデータを取り込み処理する関係上配列変数でデータを取り込み処理する必要があるためマクロ記録はできないのです
seiyaさん
書いていただいたVBAを試したところばっちり取り込めました
いくつか検証しましたが、今のところ問題ないようです
ありがとうございました。さすがに1万件の処理をすべて人力とかありえないですので、、
助かりました
(tatsu) 2016/02/04(木) 11:19

解決されたようでご同慶の至りです。
誤解があるようなので、あえて。

>1万件ほどのデータを取り込み処理する関係上
>配列変数でデータを取り込み処理する必要があるためマクロ記録はできないのです

なにか大きく誤解されているようですね。
# まあ好きなように解釈してもらっていいけど。
# マクロ記録をするほど初心者じゃないよ、と反発されているようですね。
でも違います。

ダミーシートに、「外部データの取込」 - 「テキストファイル」を使って読み込み、
それを一行コードで変数に読み込めばいいだけの話です。
(この作業はかなり汎用性があります。

  ""の有無はもちろん、文字コード対応、列のスキップ、色々な機能も持っています。)

その読み込むコードは、マクロ記録で簡単に得られるという話です。
あとは、その変数に対して順次繰り返し作業するのは、今と同じようにできます。

今回の事象の原因が想像もつかないかたに、
正規表現が理解できるとも思えません。
ブラックボックスが増えただけのことです。
Excelの機能を使って簡便に対応できる方策があるのに残念ですね。

>さすがに1万件の処理をすべて人力とかありえない
誰かそんな提案しているんですか?
マクロ記録 = 手入力 とでも即断しているんでしょうかねえ。

(γ) 2016/02/04(木) 23:38


 >seiyaさん 
 >書いていただいたVBAを試したところばっちり取り込めました 
 >いくつか検証しましたが、今のところ問題ないようです

 そうですか。
 すでに書かれたコードに自前関数で少しデータ加工を加えただけなので、元のコードでの動作が確認されていれば
 想定通り動くはずです。

 もし、最終的に " が必要になったときは

 .Replace Chr(3), vbNullString, 2
 を
 .Replace Chr(3), """", 2
 にすれば、復活します。
(seiya) 2016/02/05(金) 00:05

 >>1万件ほどのデータを取り込み処理する関係上配列変数でデータを取り込み処理する必要があるためマクロ記録はできないのです

 >>さすがに1万件の処理をすべて人力とかありえないですので

 マクロ記録ができない理由というか意味が全くわからないですねぇ。
 実際に操作をやってみられましたか?

(β) 2016/02/05(金) 03:51


γさん、βさん、seiyaさん
コメントいただきありがとうございます

γさん、
>マクロ記録をするほど初心者じゃないよ、と反発されているようですね。
全くそのようなことは考えてはおりません
むしろVBAを知り使い始めて3ヶ月の超初心者です
もちろん、マクロの記録もよく使っています

>ダミーシートに、「外部データの取込」 - 「テキストファイル」を使って読み込み、
>それを一行コードで変数に読み込めばいいだけの話です。
この発想がすぐ出てこない、思いつかないくらい初心者なのです、お恥ずかしい限りです
確かにこのようにすればよかったのですね、申し訳ありませんでした

>>さすがに1万件の処理をすべて人力とかありえない
>誰かそんな提案しているんですか?
>マクロ記録 = 手入力 とでも即断しているんでしょうかねえ。
この発言はγさんに対してのものではなく、
マクロで対応できなければ、私自身で手入力で対応しなければいけないのかな、
そんなことしたくないなー という意味のものでした
ご不快な思いをさせて申し訳ありませんでした

βさんのご指摘も上記理由により、私自身の発想の貧困によるものでした

皆様に教えをいただいているにもかかわらず、私自身の発想の無さや、発言のまずさから
皆様にご不快な思いをさせてしまい、申し訳ありませんでした

エクセルの学校は、本当にいろいろと勉強になるコメントが多く
初心者の私もよく閲覧させていただいていますし
今後とも、皆様には教えを請いたいと思いますので
なにとぞお許しいただきますようお願いいたします

seiyaさん
追加のコード、ありがとうございました
最初に教えていただいたもので問題ないようです
毎月使うことになりそうなので助かりました
ありがとうございました
(tatsu) 2016/02/05(金) 09:05


 念のため。

 r = データ取得(v(0), wrk)

 例えば、検索データv(0)にカンマがあった場合
 例:
 課長,部長

 この場合も
 "課長,部長" となり、変換後は Chr(3)課長Chr(2)部長Chr(3)になっています。

 このままでは、的確な検索ができないので
 Dim temp As String
 temp = v(0)
 If temp Like "*" & Chr(3) & "*" Then temp = Replace(Replace(temp,Chr(3),""), Chr(2), ",")
 r = データ取得(temp, wrk)

 としておいた方がよいでしょう。
 あくまでも念のため...
(seiya) 2016/02/05(金) 09:33

seiyaさん
お返事が遅くなり申し訳ありません
確かに今回は検索データv(0)にカンマはありませんが
今後このデータを別案件で流用する場合こまりますね、

テストでA列に取引先コードとして数値でカンマ付のデータを入れたところ
変数で取り込んだwrkでカンマが抜けてしまいあせりましたが
1A,00zがOKで 1,000がNG だったので気が付きました
数値あつかいで カンマが欠落していたようです
セルの表示形式を文字列にすることで解決できました

ありがとうございます、勉強になりました
(tatsu) 2016/02/08(月) 11:07


コメント返信:

[ 一覧(最新更新順) ]


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