- PR -

CSVファイルからの取込編集ができない。

投稿者投稿内容
cats
大ベテラン
会議室デビュー日: 2002/11/29
投稿数: 221
お住まい・勤務地: 東京
投稿日時: 2003-12-08 08:50
CSV読込み用クラス。(""内の改行には対応していません)
コード:
C#
namespace Utility
{
    public class CSV 
    {
        public static string[] GetCSV(string s)
        {
            ArrayList a = new ArrayList();
            int i = 0, j;
            string t;
            StringBuilder h = new StringBuilder();
            while (i < s.Length) 
            {
                bool b = s[i] == '"';
                if (b) ++i;
                j = s.IndexOf(b ? '"' : ',', i);
                if (j < 0) j = s.Length;
                t = s.Substring(i,j-i);
                if (b && j < s.Length-1 && s[j+1] == '"') 
                {
                    h.Append(t);
                    h.Append('"');
                    i = j+1;
                } 
                else 
                {
                    a.Add(h + t);
                    h.Length = 0;
                    i = j + (b?2:1);
                }
            }
            return (string[])a.ToArray(Type.GetType("System.String"));
        }
    }
}

VB.NET
Namespace Utility
    Public Class CSV
        Public Shared Function GetCSV(ByVal s As String) As String()
            Dim a As ArrayList = New ArrayList()
            Dim i As Integer = 0, j As Integer
            Dim t As String
            Dim h As StringBuilder = New StringBuilder()
            While (i < s.Length)
                Dim b As Boolean = (s.Chars(i) = """"c)
                If (b) Then
                    i += 1
                    j = s.IndexOf(""""c, i)
                Else
                    j = s.IndexOf(","c, i)
                End If
                if (j < 0) then j = s.Length
                t = s.Substring(i, j - i)
                If (b AndAlso j < s.Length - 1 AndAlso s.Chars(j + 1) = """"c) Then
                    h.Append(t)
                    h.Append(""""c)
                    i = j + 1
                Else
                    h.Append(t)
                    a.Add(h.ToString)
                    h.Length = 0
                    i = j + 1
                    If (b) Then i += 1
                End If
            End While
            GetCSV = CType(a.ToArray(Type.GetType("System.String")), String())
        End Function
    End Class
End Namespace

ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-12-08 10:27
ども、ほむらです。
----------------
なな氏へ
引用:

取り込み自体は出来ているのですが
それをカンマ編集で配列に入れる時、データにカンマがある場合、
うまく配列に入ってくれないというのが今回の問題なんです。


カンマ編集=データの分解
でいんでしょうか?
つまり、分解が思ったように行かないということ?
エクセルで出力されるCSVファイルでよければ正規表現を使用するとわりと簡単に
分解できるようです。。(Perlでしか作ったことありませんが^^;;;;)

順序しては
1.ファイルの内容をバッファへ取り込み
2.区切り文字を先頭にして引用符の有無2パターンの最短マッチ(レコードの抽出)
3.各レコードの最後に区切り文字を追加
4.1レコードずつクォーテーションを含む形で列に分解(最短マッチ)
5.クォーテーションの置換
こんな感じでした。。
コツは正規表現が左から右に解釈されるということと最短マッチを利用することです。
Perl形式ですが正規表現を載せておきます。(RegExpでもつかえるはずです)
参考になるかな?
コード:

レコードの抽出
pattern = /^((?:,?(?:\"[.\n]*?\"|[.\n]*?))+)$/
MULTILINE ON, GLOBAL ON

レコードの分解
Pattern = /((?:\"[.\n]*?[^\"]\")[ \t]*|(?:[.\n]*?)),/
MULTILINE OFF, GLOBAL ON
ちなみに、[ \t]*はなくてもいいです。データ間の空白を無視しているだけですので(笑


# レコード抽出の正規表現が間違えていたので修正

オリジナルのコードものせておきます
ただ、パッケージが別々の関係で
関数名がたぶってしまっています^^;;;
コード:

#CSVファイルの内容からレコードの抽出
sub split($@)
{
my $self = shift;
my $csvDATA = shift || return [];
my $sepCHAR = shift || ',';
my $quoteCHAR = shift || '"';
return ($csvDATA =~ m/^((?:$sepCHAR?(?:$quoteCHAR.*?$quoteCHAR|.*?))+)$/msg);
}

# 1レコード分のCSVデータを分解
sub split($@)
{
my $self = shift;
my $work = shift || ''; # CSV形式の1レコードの文字列
my $sepCHAR = shift || ','; # 区切り文字
my $quoteCHAR = shift || '"'; # 引用符
return 0 if( $work eq '' );


$work .= $sepCHAR; # レコードの最後に , を追加
my @result = ($work =~ m/((?:$quoteCHAR.*?[^$quoteCHAR]$quoteCHAR)[ \t]*|(?:.*?))$sepCHAR/sg); # とりあえず列の取り出し;
######################
# レコードのデータに
# 引用符 が含まれていた場合
# 引用符 を はずして 引用符二個で一つに変換する
if( $work =~ m/$quoteCHAR/ ){
my $count = 0;
foreach $work ( @result ){
#######################
# 取り出した列の整形
$work = '' if( !defined($work) || $work eq "$quoteCHAR$quoteCHAR" ); # ""のみはデータ無しで空白に置換
$work =~ s/$quoteCHAR(.+)$quoteCHAR/$1/s; # " で囲まれていた場合 "を取り外す
$work =~ s/$quoteCHAR$quoteCHAR/$quoteCHAR/g; # "" は " に変換
$result[ $count ++ ] = $work; # 変換後の結果で更新
}
}
return @result;
}



#後方参照の$1が消えてしまっていたので全角に修正

[ メッセージ編集済み 編集者: ほむら 編集日時 2003-12-08 10:33 ]

[ メッセージ編集済み 編集者: ほむら 編集日時 2003-12-08 11:30 ]

スキルアップ/キャリアアップ(JOB@IT)