【Excel VBA】固定長ファイル分割ツール

■固定長ファイル

1行の長さが一定であるファイルを固定長ファイルという。

一般的に桁数や行数でデータ項目を判断し、それぞれ区分けしたデータをインプットとして読み込む。

■固定長ファイル(例)

固定長ファイルの例を示す。

▼INPUTDATA.txt

1202108077
5A00300030
5B00310034
5B00360037
5A00330034
5C00310032
5D00200019
5D00240020
5C00450040
5F00330030
5B00300030
5C00460049
5A00320030
5E00320032
5F00370039
5A00390032
5D00290028
5C00280025
5B00280028
5A00270030
9000000019

■固定長ファイルのレイアウト

一般的に固定長ファイルを扱う場合は、固定長ファイルに対応するファイルレイアウトが存在する。

上記「INPUTDATA.txt」のファイルレイアウトは以下の通り

▼ヘッダー行のレイアウト

項目桁数備考
レコード区分1値が「1」の場合はヘッダーレコード
日付8YYYYMMDD形式
曜日11:日曜日
2:月曜日
3:火曜日
4:水曜日
5:木曜日
6:金曜日
7:土曜日

▼データ行のレイアウト

項目桁数備考
レコード区分1 値が「5」の場合はデータレコード
品種1
高さ4
重さ4

▼フッター行のレイアウト

項目桁数備考
レコード区分1 値が「9」の場合はフッターレコード
データ件数9データレコードの件数

■固定長ファイル分割ツールの仕様

固定長ファイル分割ツールの仕様を以下の通り示す。

(1)[Main]シートにファイル名(フルパス)を指定し、【分割】ボタン押下で処理を開始する。

(2) ヘッダー/データ/トレーラシートを初期化する。

なお、各シートの1行目は項目説明欄のため、初期化せずに残す。

▼ヘッダーシート

▼データシート

▼フッターシート

(3)レイアウトシートからヘッダー/データ/フッターシートの区切り桁数を取得。

(4)「 INPUTDATA.txt 」を1行ずつループ処理し、各シート(ヘッダー/データ/フッター)へ分割した項目を貼り付けていく。

■サンプルコード

' シート名の定数
Private Const SHTNAME_MAIN      As String = "Main"
Private Const SHTNAME_HEADER    As String = "ヘッダー"
Private Const SHTNAME_DATA      As String = "データ"
Private Const SHTNAME_FOOTER   As String = "フッター"
Private Const SHTNAME_LAYOUT    As String = "レイアウト"

' Mainシートの定数
Private Const INPUT_LOW As Integer = 3  ' 固定長ファイル名読み込み行
Private Const INPUT_COL As Integer = 4  ' 固定長ファイル名読み込み列

' ヘッダー/データ/フッターシート共通定数
Private Const START_LOW         As Integer = 2      ' 分割した固定長ファイル表示開始行
Private Const START_COL         As Integer = 1      ' 分割した固定長ファイル表示開始行

' レイアウトシートの定数
Private Const START_BYTE_LOW    As Integer = 3      ' 区切りバイト数表示行
Private Const START_BYTE_HCOL   As Integer = 3      ' ヘッダー区切りバイト数表示列
Private Const START_BYTE_DCOL   As Integer = 5      ' データ区切りバイト数表示列
Private Const START_BYTE_FCOL   As Integer = 7      ' フッター区切りバイト数表示列


' ヘッダー/データ/フッターシートの初期化関数
Private Sub Init_Sheets(ShtHeader As Worksheet, ShtData As Worksheet, ShtFooter As Worksheet)

    ' ヘッダー/データ/フッターシートの初期化
    ShtHeader.Range("2:1048576").ClearContents
    ShtData.Range("2:1048576").ClearContents
    ShtFooter.Range("2:1048576").ClearContents

End Sub


' レイアウトシートから区切り桁数を取得する関数
Private Function InpuFLayOut(ShFLayOut As Worksheet, bunkatsu_col As Integer) As Integer()
    
    Dim layout()    As Integer  ' 戻り値用の配列
    Dim irow        As Integer  ' 行カウンタ
    Dim i           As Integer  ' 配列用カウンタ
        
    ' 初期値をセット
    irow = START_BYTE_LOW
    i = 0
    
    ' レイアウトシートで作業
    With ShFLayOut
        
        ' 対象(ヘッダー/データ/フッター)の表示区切り桁数分繰り返し
        Do Until .Cells(irow, bunkatsu_col).Value = ""
            
            ReDim Preserve layout(i)
        
            ' 区切り桁数を配列へ格納
            layout(i) = .Cells(irow, bunkatsu_col).Value
            
            ' インクリメント
            irow = irow + 1
            i = i + 1
        Loop
        
    End With

    ' 戻り値を設定
    InpuFLayOut = layout()

End Function


' 分割処理
Private Sub Bunkatsu(InputSheet As Worksheet, layout() As Integer, startrow As Integer, strLine As String)
    
    Dim icol            As Integer  ' 列カウンタ
    Dim i               As Integer  ' 配列用カウンタ
    Dim startbyte       As Integer  ' 区切り開始桁数を格納する変数
    Dim bunkatsubyte    As Integer  ' 区切り桁数を格納する変数
    
    ' 作業シートにフォーカス
    With InputSheet
                
        ' 初期値を設定
        icol = START_COL
                    
        ' 分割区切り桁数開始位置の初期化
        startbyte = layout(0)
                    
        ' 分割区切り桁数の要素数分ループ処理
        For i = 0 To UBound(layout)
                        
            ' 分割区切り桁数表示行の値をセット
            bunkatsubyte = layout(i)
                        
            ' 固定長ファイルの値を分割して、セルに値を入れる
            .Cells(startrow, icol).Value = Mid(strLine, startbyte, bunkatsubyte)
                        
            ' 分割区切り桁数開始位置をインクリメント
            startbyte = startbyte + bunkatsubyte
                    
            ' 列カウンタをインクリメント
            icol = icol + 1
                    
        Next
                           
    End With
        
End Sub


' 分割ボタン押下時の処理(メイン処理)
Public Sub Click_Btn_Bunkatsu()
    
    ' 変数宣言
    Dim ShtMain         As Worksheet            ' Mainシートの変数
    Dim ShtHeader       As Worksheet            ' ヘッダーシートの変数
    Dim ShtData         As Worksheet            ' データシートの変数
    Dim ShtFooter      As Worksheet            ' フッターシートの変数
    Dim ShFLayOut       As Worksheet            ' レイアウトシートの変数
    Dim FileName        As String               ' Mainシートのファイル名を格納する変数
    Dim fso             As Object               ' ファイルオブジェクトの変数
    Dim openfile        As Object               ' ファイルの中身を格納する変数
    Dim strLine         As String               ' ファイルを1行ずつ格納するようの変数
    Dim HiRow           As Integer              ' ヘッダーシート用行カウンタ
    Dim DiRow           As Integer              ' データシート用行カウンタ
    Dim FiRow           As Integer              ' フッターシート用行カウンタ
    Dim HLayOut()       As Integer              ' ヘッダー用区切り桁数を格納する配列
    Dim DLayOut()       As Integer              ' データ用区切り桁数を格納する配列
    Dim FLayOut()       As Integer              ' フッター用区切り桁数を格納する配列
    
    ' エラーハンドリング
    On Error GoTo Click_Btn_Bunkatsu_ERROR
    
    Set ShtMain = Sheets(SHTNAME_MAIN)          ' Mainシートを格納
    Set ShtHeader = Sheets(SHTNAME_HEADER)      ' ヘッダーシートを格納
    Set ShtData = Sheets(SHTNAME_DATA)          ' データシートを格納
    Set ShtFooter = Sheets(SHTNAME_FOOTER)    ' フッターシートを格納
    Set ShFLayOut = Sheets(SHTNAME_LAYOUT)      ' レイアウトシートを格納
    
    ' ヘッダー/データ/フッターシートの初期化
    Call Init_Sheets(ShtHeader, ShtData, ShtFooter)
    
    ' 初期値の設定
    HiRow = START_LOW
    DiRow = START_LOW
    FiRow = START_LOW
    
    ' レイアウトシートからヘッダー/データ/フッターシートの区切り桁数を取得
    HLayOut() = InpuFLayOut(ShFLayOut, START_BYTE_HCOL)
    DLayOut() = InpuFLayOut(ShFLayOut, START_BYTE_DCOL)
    FLayOut() = InpuFLayOut(ShFLayOut, START_BYTE_FCOL)
    
    ' ファイル名(フルパスを取得)
    FileName = ShtMain.Cells(INPUT_LOW, INPUT_COL).Value
    
    ' FileSystemObjectのインスタンス
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    ' 固定長ファイルを開く
    Set openfile = fso.opentextfile(FileName)
    
    ' 固定長ファイルの最終行までループ処理
    Do Until openfile.AtEndOfStream = True
        
        ' 1行を文字列に格納
        strLine = openfile.ReadLine
        
        ' 1バイト目が「1」ならばヘッダーシートに分割
        If Mid(strLine, 1, 1) = 1 Then
                       
            ' 分割処理呼び出し
            Call Bunkatsu(ShtHeader, HLayOut(), HiRow, strLine)
                       
            ' ヘッダーシート用行カウンタをインクリメント
            HiRow = HiRow + 1
        
        ' 1バイト目が「5」ならばデーターシートに分割
        ElseIf Mid(strLine, 1, 1) = 5 Then
            
            ' 分割処理呼び出し
            Call Bunkatsu(ShtData, DLayOut(), DiRow, strLine)
                    
            ' データシート用行カウンタをインクリメント
            DiRow = DiRow + 1
        
        ' 1バイト目が「9」ならばフッターシートに分割
        ElseIf Mid(strLine, 1, 1) = 9 Then
                        
            ' 分割処理呼び出し
            Call Bunkatsu(ShtFooter, FLayOut(), FiRow, strLine)
            
            ' フッターシート用行カウンタをインクリメント
            FiRow = FiRow + 1
        
        End If
        
    Loop
    
    ' 完了メッセージを出力
    MsgBox "分割完了"

    GoTo Click_Btn_Bunkatsu_EXIT


' エラーハンドリング
Click_Btn_Bunkatsu_ERROR:

    ' エラーメッセージを出力
    MsgBox Err.Description
    

' 終了時の共通処理
Click_Btn_Bunkatsu_EXIT:
    
    ' 終了処理
     Set ShtMain = Nothing
     Set ShtHeader = Nothing
     Set ShtData = Nothing
     Set ShtFooter = Nothing
     Set fso = Nothing
     Set openfile = Nothing
     Set ShFLayOut = Nothing
     
End Sub

■実行結果

▼【分割】ボタン押下時

▼ヘッダーシート

▼データシート

▼フッターシート

コメント