Takenoff Labs

Lotus Notes/Domino に関する Tips や、クラシックの名曲などを紹介します

[Notes/Domino] CSVの1行を取得する方法(項目内改行対応版)

(2017/10/16 全面的に書き換えました)

CSVの規則によると、引用符(ダブルクォーテーション)内では、改行を入れていいことになっています。が、Line Input では改行までを1行として読み込むので、これに対応しようと思うとちょっと面倒なことになります。そんな面倒を解消するため、手軽に扱える関数を作ってみました。

説明 CSVの1行を取得して配列化(項目内改行対応版)
構文 GetCSVLine(Byval intFno As Integer, Byval strDelim As String, Byval strQuote As String) As Variant
引数 [in,---]intFno ... ファイル番号
[in,---]strDelim ... デリミタ
[in,---]strQuote ... 引用符
戻り値 CSVの1行分を配列化した値

※CSVのルールに反したデータは想定していません。より厳密にやるなら、エラーチェックなどを入れてください。

ソースコード

Public Function GetCSVLine(ByVal intFno As Integer, _
ByVal strDelim As String, ByVal strQuote As String) As Variant
    Dim strCsv   As String
    Dim strRet() As String
    Dim strBuf   As String
    Dim bln1st   As Boolean
    Dim blnQuote As Boolean
    
    strBuf = ""
    bln1st = True
    
    Do
        If EOF(intFno) Then
            If strBuf <> "" Then
                Call AryPush(strRet, strBuf)
            End If
            Exit Do
        End If
        
        Line Input #intFno, strCsv
        
        Do Until strCsv = ""
            Select Case Left(strCsv, 1)
            Case strQuote
                If bln1st = True Then
                    blnQuote = True
                    bln1st   = False
                Else
                    If blnQuote = True Then
                        If Left(strCsv, 2) = strQuote & strQuote Then
                            strBuf = strBuf & strQuote
                            strCsv = Mid(strCsv, 2)
                        Else
                            blnQuote = False
                        End If
                    Else
                        strBuf = strBuf & strQuote
                    End If
                End If
            Case strDelim
                If blnQuote = True Then
                    strBuf = strBuf & strDelim
                Else
                    Call AryPush(strRet, strBuf)
                    strBuf = ""
                    bln1st = True
                End If
            Case Else
                strBuf = strBuf & Left(strCsv, 1)
                bln1st = False
            End Select
            strCsv = Mid(strCsv, 2)
        Loop
        
        If blnQuote = True Then
            strBuf = strBuf & Chr(13) & Chr(10)
        ElseIf strBuf <> "" Then
            Call AryPush(strRet, strBuf)
        End If
        
    Loop Until blnQuote = False
    
    If AryIsUninit(strRet) = True Then
        Call AryPush(strRet, "")
    End If
    
    GetCSVLine = strRet
End Function

Public Sub AryPush(varAry As Variant, varVal As Variant)
    Dim intMax As Integer
    
    If IsArray(varAry) = False Then
        Exit Sub
    End If
    
    On Error GoTo ERR_INIT
    intMax = UBound(varAry) + 1
    On Error GoTo 0
    
    ReDim Preserve varAry(intMax)
    varAry(intMax) = varVal
    Exit Sub
    
ERR_INIT:
    intMax = 0
    ReDim varAry(0)
    Resume Next
End Sub

Public Function AryIsUninit(varAry As Variant) As Boolean
    Dim intMin As Integer
    
    On Error GoTo ERR_INIT
    intMin = LBound(varAry)
    On Error GoTo 0
    
    AryIsUninit = False
    Exit Function
    
ERR_INIT:
    AryIsUninit = True
    Exit Function
End Function

使い方

Dim varAry As Variant
Dim intFno As Integer
intFno = FreeFile()
Open "C:\test.csv" For Input As #intFno
Do Until EOF(intFno)
    varAry = GetCSVLine(intFno, ",", |"|)
    '処理
Loop
Close #intFno
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

トラックバック

トラックバックはありません

コメント

コメントはありません

※コメントは承認制となっております。管理者が承認するまで表示されません。申し訳ありませんが、投稿が表示されるまでしばらくお待ちください。





(以下のタグが使えます)
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

For spam filtering purposes, please copy the number 3345 to the field below:

^
×