Access (VBA)

Access VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Pro : Microsoft 365)
csvのレコードとフィールド名を取得したい
投稿日時: 25/01/17 09:57:26
投稿者: kazz

お世話になります。
 
Cドライブ直下に月次.csvがあります。
フィールド1列目が「会計年度」、6列目が「1ヶ月目発生」、
2行目以降はレコードという構成です。
 
単票フォームのテキストボックス「txtFilePath」に、C:\月次.csvと
表示されおり、コマンドボタンを押下した時に、
テキストボックス「txt会計年度」に上記csv「会計年度」の
レコード1行目を転記、テキストボックス「txtヶ月目」にフィールド名
「1ヶ月目発生」を転記させたいのですが方法がわかりません。
 
ご教示お願いいたします。

回答
投稿日時: 25/01/17 11:44:37
投稿者: sk

引用:
Cドライブ直下に月次.csvがあります。
フィールド1列目が「会計年度」、6列目が「1ヶ月目発生」、
2行目以降はレコードという構成です。

2 〜 5 列目の列見出しについて触れられていませんが、
そもそもその CSV ファイルは(データベースとしての)
テーブルの体を成しているのでしょうか。
 
引用:
テキストボックス「txt会計年度」に上記csv「会計年度」の
レコード1行目を転記、テキストボックス「txtヶ月目」にフィールド名、
「1ヶ月目発生」を転記させたい

雰囲気的に、あたかも Excel ワークシートで作成された定型帳票を
無理やり CSV ファイルとして出力したかような印象を受けるのですが。
 
つまりここでの「1ヶ月目発生」というのは本来『フィールド名』ではなく、
何らかの事象が発生した時期を表す『値』なのではないかと。

投稿日時: 25/01/17 13:39:24
投稿者: kazz

skさん、ありがとうございます。
  
2 〜 5 列目の列見出しについて触れられていませんが、
そもそもその CSV ファイルは(データベースとしての)
テーブルの体を成しているのでしょうか。
 
列見出しについて説明しますと、1列目から順番に、
「会計年度」「部門コード」「部門名」「科目コード」「科目名」「1ヶ月目発生」、
6列で構成されています。
 
テキストボックス「txt会計年度」に上記csv「会計年度」の
レコード1行目を転記、テキストボックス「txtヶ月目」にフィールド名、
「1ヶ月目発生」を転記させたい
雰囲気的に、あたかも Excel ワークシートで作成された定型帳票を
無理やり CSV ファイルとして出力したかような印象を受けるのですが。
つまりここでの「1ヶ月目発生」というのは本来『フィールド名』ではなく、
何らかの事象が発生した時期を表す『値』なのではないかと。
 
このcsvは会計ソフトから下記の条件で出力しています。
・タイトル出力「あり」※列見出しの事です
・レコード長「可変長」
・区切文字「カンマ」
・文字コード「ANSI」
 
「1ヶ月目発生」はcsvの列見出しです。csvの2行目以降に、
金額(数値型)がレコードがあります。
この列は、1ヶ月目発生、2ヶ月目発生、3ヶ月目発生・・・と
出力する月によって列見出しが変動します。
 
以上のような構成となっています。

回答
投稿日時: 25/01/17 15:47:00
投稿者: sk

引用:
列見出しについて説明しますと、1列目から順番に、
「会計年度」「部門コード」「部門名」「科目コード」「科目名」「1ヶ月目発生」、
6列で構成されています。

引用:
「1ヶ月目発生」はcsvの列見出しです。csvの2行目以降に、
金額(数値型)がレコードがあります。
この列は、1ヶ月目発生、2ヶ月目発生、3ヶ月目発生・・・と
出力する月によって列見出しが変動します。

ならば、とりあえず考えられる方法としては
次のようなものが挙げられます。
 
・Open ステートメントを使用して CSV ファイルを直接読み込み、
 1 行目の 6 列目の値と 2 行目の 1 列目の値を取得するコードを作成する。
 (文字コードが UTF-8 であるファイルを扱う場合は ADODB.Stream オブジェクトを使用する)
 
・その CSV ファイルを参照先とするリンクテーブルを一時的に作成しておき、
 DAO.Recordset オブジェクトを使用してそのテーブルをレコードセットとして開き、
 「 6 列目のフィールドの名前」と「先頭のレコードの[会計年度]の値」を
 取得するコードを作成する。
 
・ADODB.Connection オブジェクトおよび ADODB.Recordset オブジェクトを
 使用してその CSV ファイルを直接レコードセットとして開き、
 「 6 列目のフィールドの名前」と「先頭のレコードの[会計年度]の値」を
 取得するコードを作成する。
 
・オートメーションによって Excel アプリケーションを起動して
 その CSV ファイルを開き、展開されたワークシートの
 「 F1 セルの値」と「 A2 セルの値」をそれぞれ取得するコードを作成する。
 
どの方法を用いるべきかは、レコードによって[会計年度]の値が異なるのか
(=確実に 1 件目のレコードを参照する必要があるのか)、
ただ「 6 列目のフィールドの名前」と「先頭のレコードの[会計年度]の値」を
取得するだけでよいのか、そこから派生して同じ CSV ファイルを用いた
別の処理を実行する必要があるのか(必要があるなら、それはどのような処理なのか)
などによるでしょう。
 
引用:
単票フォームのテキストボックス「txtFilePath」に、C:\月次.csvと
表示されおり、コマンドボタンを押下した時に、
テキストボックス「txt会計年度」に上記csv「会計年度」の
レコード1行目を転記、テキストボックス「txtヶ月目」にフィールド名、
「1ヶ月目発生」を転記

例えば 4 番目の手法を採用する( Excel を仲介させる)であれば、
コマンドボタンの[クリック時]イベントで次のようなプロシージャを
実行します。
 
(フォームモジュール)
----------------------------------------------------------
Private Sub コマンドボタン名_Click()
On Error GoTo Err_コマンドボタン名_Click

    Dim strFilePath As String
    
    strFilePath = Trim(Nz(Me![txtFilePath].Value, ""))
    
    If strFilePath = "" Then
        MsgBox "ファイルパスが指定されていません。", _
               vbExclamation, _
               "ファイル参照エラー"
        Exit Sub
    End If
    
    If Not strFilePath Like "*.csv" Then
        MsgBox "CSVファイルを指定して下さい。", _
               vbExclamation, _
               "ファイル参照エラー"
        Exit Sub
    End If
    
    If Dir(strFilePath) = "" Then
        MsgBox "指定されたパス'" & strFilePath & "'に該当するファイルが見つかりません。", _
               vbExclamation, _
               "ファイル参照エラー"
        Exit Sub
    End If
    
    Dim xlsApp As Object                'Excel.Application
    Set xlsApp = CreateObject("Excel.Application")
    
    Dim xlsBook As Object               'Excel.Workbook
    Set xlsBook = xlsApp.Workbooks.Add
    
    Dim xlsWorksheet As Object          'Excel.Worksheet
    Set xlsWorksheet = xlsBook.Worksheets(1)
    
    Dim xlsQueryTable As Object         'Excel.QueryTable
    Dim strConnectString As String
    
    With xlsWorksheet
        strConnectString = "TEXT;" & strFilePath
        Set xlsQueryTable = .QueryTables.Add(Connection:=strConnectString, _
                                             Destination:=.Cells(1, 1))
    End With
    
    Dim aryColumnDataTypes() As Long
    Dim lngColumn As Long
    
    For lngColumn = 0 To 5
        ReDim Preserve aryColumnDataTypes(0 To lngColumn)
        aryColumnDataTypes(lngColumn) = 2
    Next
    
    With xlsQueryTable
        .Name = "temp"
        .FieldNames = False
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = False
        .RefreshOnFileOpen = False
        .RefreshStyle = 1               'xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = False
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 932
        .TextFileStartRow = 1
        .TextFileParseType = 1          'xlDelimited
        .TextFileTextQualifier = 1      'xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = False
        .TextFileSemicolonDelimiter = False
        .TextFileCommaDelimiter = True
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = aryColumnDataTypes
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With
    
    Me![txt会計年度].Value = xlsWorksheet.Cells(2, 1).Value
    Me![txtヶ月目].Value = xlsWorksheet.Cells(1, 6).Value
    
Exit_コマンドボタン名_Click:
On Error Resume Next

    Set xlsQueryTable = Nothing
    Set xlsWorksheet = Nothing
    xlsBook.Close False
    Set xlsBook = Nothing
    xlsApp.Quit
    Set xlsApp = Nothing
    
    Exit Sub

Err_コマンドボタン名_Click:

    Dim strErrTitle As String
    Dim strErrMsg As String

    strErrTitle = "実行時エラー (" & Me.Name & ".コマンドボタン名_Click)"
    strErrMsg = Err.Number & ": " & Err.Description

    Debug.Print strErrTitle
    Debug.Print strErrMsg

    MsgBox strErrMsg, vbCritical, strErrTitle

    Resume Exit_コマンドボタン名_Click
End Sub
----------------------------------------------------------

投稿日時: 25/01/20 13:45:06
投稿者: kazz

skさん、
 
・Open ステートメントを使用して CSV ファイルを直接読み込み、
 
Openステートメントを色々調べながら試したところ、
求めたい結果を得ることができました。
 
またエクセルを利用したコードまで書いていただき、
ありがとうございます。
サンプルコードとして保存させていただきました。
 
ありがとうございました。
 
Private Sub コマンド20_Click()
    Dim buf As String
    Dim tmp As Variant
    Dim lngCnt As Long
    Dim lngNendo As Variant
    Dim strKagetume As String 'csvのフィールド6列目、〇ヶ月目のこと
     
    Open Me.txtFileName For Input As #1
    lngCnt = 1
    Do Until EOF(1)
        Line Input #1, buf
        temp = Split(buf, ",")
        If lngCnt = 1 Then
            strKagetume = temp(5)
        ElseIf lngCnt = 2 Then
            lngNendo = temp(0)
        ElseIf lngCnt = 3 Then
            Exit Do
        End If
        lngCnt = lngCnt + 1
    Loop
     
    Me.txt会計年度 = lngNendo
    Me.txtヶ月目 = strKagetume
    Close #1
End Sub

投稿日時: 25/01/21 16:26:44
投稿者: kazz

skさん、
先に進むことができました。
解決とさせていただきます。
ありがとうございました。