「みんな教えて! 選手権!!」開催のお知らせ

VB初心者です。
以下のように文字列を分割したいのですが

<やりたいこと>
MOJI="A","B","C,D,E"

ARRAY(0)="A"
ARRAY(1)="B"
ARRAY(2)="C,D,E"


ARRAY=SPLIT(MOJI,",") ではだめですよね。
何か、簡単なやり方はありますか?

よろしくお願いします。

A 回答 (5件)

大概の場合はうまくいくと思います。


Function csv(source) As Variant
Dim reg As New RegExp
Dim mc As MatchCollection
Dim buf
Dim i
Dim bobj As Object
Dim arry()

If Len(source) > 0 And Left(source, 1) <> "," Then
buf = buf & ","
Else
csv = ""
Exit Function
End If
reg.Pattern = "(""[^""]*""),|([^""]*),"
reg.Global = True
Set mc = reg.Execute(source)
If mc.Count <> 0 Then
reg.Pattern = ",$"
ReDim arry(mc.Count)
For i = 0 To mc.Count - 1
arry(i) = reg.Replace(mc(i), "")
Next
End If
csv = arry
End Function
    • good
    • 0
この回答へのお礼

ありがとうございます。
試してみます。

お礼日時:2011/02/07 17:50

補足の説明が。

。。回答者の意図を分かってないですね。

VB6で
> MOJI="A","B","C,D,E"
は文法エラーです。この時点でVB6の文法で文字列を
理解していない事になります。ダブルクォーテーションは
文法として意味を持ちます。

データのダブルクォーテーションと、VB6の文法の
ダブルクォーテーションを区別して説明して下さい。

「CSV形式でデータの中にカンマを含む場合」でいいですか?
VB6の文法としてそのようなデータを変数に入れるなら、
MOJI = """A"",""B"",""C,D,E"""
となります。
変数、MOJI に「"A","B","C,D,E"」というデータを入れる
という意味です。ダブルクォーテーションが文法としての
意味を持っているため、2つ重ねてエスケープします。

ここで、CSV形式は「データ中にカンマを含まない場合」
はダブルクォーテーションで囲まないでも成り立つ事が
重要です。
CSV形式のデータを正しく読み取るには、データとして
「A,B,"C,D,E"」も「A」「B」「C,D,E」と解釈できる
必要があります。更に「データ中にダブルクォーテーション
を含む場合」も許可されています。「A,B,"C,""D,E"」は
「A」「B」「C,"D,E」と解釈します。
http://www.kasai.fm/wiki/rfc4180jp

理解した上で説明しなおしてください。
    • good
    • 0

配列に入れて添え字何個か数える?。



プログラミング的にいうと区切りを数える、でも解決します。
『","』の出現数=2

1バイトずつ見て、2バイト前、1バイト前とともに判定する。
配列ARRAYの知識いりません。
    • good
    • 0

簡単なやり方はありません。


憶えておくと便利な正規表現を使います。

【理論】

(1)引用符で囲まれた部分を配列に記録
(2)引用符で囲まれた部分を非表示文字で置換
(3)カンマで分割
(4)分割した内容に置換文字があれば
  配列に記録した元の文字列で復元

【プログラム例】

Function 分割(ByVal MOJI)
Dim 編集後文字列
Dim 正規表現
Dim 一致集合
Dim 要素
Dim 添字
Dim 分割配列
ReDim 引用符内部(0)

'正規表現オブジェクトをインスタンス化する
Set 正規表現 = CreateObject("VBScript.RegExp")
'置換対象を「全て」にする
正規表現.Global = True
'引用符で囲まれた文字列を示す正規表現パターン
正規表現.Pattern = """.*?"""
'上記に一致する集合を得る
Set 一致集合 = 正規表現.Execute(MOJI)
'引用符で囲まれた部分を記録する配列の要素数を初期化
添字 = -1
'一致集合から一つずつ取り出して配列に記録する
For Each 要素 In 一致集合
    '要素数をインクリメントする
    添字 = 添字 + 1
    '配列の要素数を以前の内容を残して拡張する
    ReDim Preserve 引用符内部(添字)
    '拡張した要素に記録
    引用符内部(添字) = 要素
Next
'引用符で囲まれた部分をBackSpaceで置換する
編集後文字列 = 正規表現.Replace(MOJI, vbBack)
'カンマで区切る
分割配列 = Split(編集後文字列, ",")
'検出/置換の範囲を「最初だけ」にする
正規表現.Global = False
'BackSpaceの正規表現パターン
正規表現.Pattern = "\x08"
'復元用添字を初期化する
添字 = -1
'分割した配列を一つずつ処理する
For 要素 = 0 To UBound(分割配列)
    'データにBackSpaceが含まれる限りループする
    Do While 正規表現.Test(分割配列(要素))
        '復元用添字をインクリメントする
        添字 = 添字 + 1
        'BackSpaceを復元する
        分割配列(要素) = _
           正規表現.Replace(分割配列(要素), _
           引用符内部(添字))
    Loop
Next
'戻り値として配列を返す
分割 = 分割配列
End Function

【実行例】

Dim MOJI, 結果, 要素
MOJI = """A"",""B"",""C,D,E"""
結果 = 分割(MOJI)
Debug.Print MOJI
For Each 要素 In 結果
    Debug.Print 要素
Next


尚、引用符内に引用符を置く可能性がある場合は
先にその部分(二重引用符とかエスケープ指定)を
置換しておいてから同じ操作を行います。
正規表現は以下を参照してください。
http://msdn.microsoft.com/ja-jp/library/cc392487 …
    • good
    • 1
この回答へのお礼

ありがとうございます。
試してみます。

お礼日時:2011/02/07 17:50

簡単なコード(split関数)ではむつかしいですね。

レベル(優先度)をつけて一遍には出来ないでしょう。
Instr関数で文字の出現位置を順次探り、抽選順位を判別ロジックで組まないといけないように思う。
しかし当初の文字列の内容があいまいなので下記補足を乞う。
ーーー
>VB初心者です
VBA、VB6,VB.NETのうちのどれですか?
>MOJI="A","B","C,D,E"
これをそのままコード(代入文)として載せるとエラーになると思う。
実際に動く、プログラムの代入文の表現ではどうなりますか?内容を正確に知りたいため。
分割単位の意味が不明のところが出るようにおもう。
代入する特はARRAY(0)="A"でも、Msgbox で表示すると A であり、本当はAと表示したいのか、”A"と表示したいのか
質問では紛らわしいから。
ーーー
Arrayという変数は、別にArray関数というのがあり、紛らわしいので避けるべきでしょう。
--
単なる思い付きで疑問に思った例ですか?
実際に実務などしていて、ぶつかった例ならもう少し詳しく、直面したケースを広く教えてください。

この回答への補足

回答ありがとうございます。
細くしますと
VB6
で、例がよくなかったですね。
MOJI="A","B","C,D,E"

TempAry(0) = "A" "A"の文字列として扱いたい。
TempAry(1) = "B"
TempAry(2) = "C,D,E"
で分割した配列の個数を知りたいのですが?

たとえば、
MOJI="A","B","C"

TempAry=Aplit(MOJI,",")
UBOUND(TempAry) → 2ですよね、上記も同様のことがしたいのですが?

すいません、簡単に書きすぎました。

よろしお願いします。

補足日時:2011/02/07 14:37
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報