2.2 整列処理を書いてみよう

整列処理を行う処理を書いてみます。「2.1.1 ファイル処理のパターン」で紹介した「集計」「併合」「更新」「照合」などは、その入力となるファイルが特定のキーで整列されていることが前提なので、整列処理は、とても重要な処理です。ExcelのSort機能を利用することにします。

2.2.1 整列のマクロ

手始めとして「整列」のマクロを記録して、それを参考に整列のプロシージャを作ってみます。

まず、以下のようなCSV形式のファイルを「出退勤ログ.csv」という名前で用意して、Excelで開いてみます。

所属,氏名,ID,年月日,出社時刻,退社時刻
営業,河田 次郎,10037,2014/4/1,8:19,18:31
営業,河田 次郎,10037,2014/4/3,8:16,17:31
営業,河田 次郎,10037,2014/4/2,8:39,18:02
技術,山川 太郎,10118,2014/4/2,9:30,18:00
技術,山川 太郎,10118,2014/4/3,8:35,19:42
技術,山中 司朗,10122,2014/4/1,8:46,17:33
技術,山中 司朗,10122,2014/4/2,8:06,18:01
企画,海山 三郎,10123,2014/4/1,8:46,19:30
企画,海山 三郎,10123,2014/4/2,9:03,17:35
総務,野口 五郎,10124,2014/4/1,8:30,18:24
総務,野口 五郎,10124,2014/4/2,8:39,19:03

Excelファイルとして開けたら、[開発]から[マクロの記録]を開始して、[データ]から[並べ替え]を選びます。
図2.2.1-1 図2.2.1-1

[並べ替え]ダイアログボックスで[レベルの追加]をクリックして図のように3つのキーを作り、[OK]をクリックします。
図2.2.1-2 図2.2.1-2

整列が完了したら[記録終了」して、[マクロの表示(Alt+F8)]をしてみます。

Sub Macro6()
'
' Macro6 表の整列(SORT)
'

'
    ActiveWorkbook.Worksheets("出退勤ログ").Sort.SortFields.Clear
    ActiveWorkbook.Worksheets("出退勤ログ").Sort.SortFields.Add Key:=Range("B2:B12"), _
        SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    ActiveWorkbook.Worksheets("出退勤ログ").Sort.SortFields.Add Key:=Range("D2:D12"), _
        SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    ActiveWorkbook.Worksheets("出退勤ログ").Sort.SortFields.Add Key:=Range("E2:E12"), _
        SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    With ActiveWorkbook.Worksheets("出退勤ログ").Sort
        .SetRange Range("A1:F12")
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
End Sub
  1. 先ず、SortFields.Clear メソッドで整列の設定をすべて消去しています。
        ActiveWorkbook.Worksheets("出退勤ログ").Sort.SortFields.Clear
    
  2. 次の3行のSortFields.Add メソッドで、3つのキーを設定しています。
        ActiveWorkbook.Worksheets("出退勤ログ").Sort.SortFields.Add Key:=Range("B2:B12"), _
            SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
        ActiveWorkbook.Worksheets("出退勤ログ").Sort.SortFields.Add Key:=Range("D2:D12"), _
            SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
        ActiveWorkbook.Worksheets("出退勤ログ").Sort.SortFields.Add Key:=Range("E2:E12"), _
            SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    
    レベルごとに3つの設定をしています(Orderは、昇順か降順か。SortOnは、値か、塗りつぶしの色か、文字の色で整列するか。DataOptionは、数値と文字を区別するか)。
    SortOn:=xlSortOnValues		' 値で整列(xlSortOnCellColor,xlSortOnFontColor,xlSortOnIcon)
    Order:=xlAscending          ' 昇順(xlDescending:降順)
    DataOption:=xlSortNormal    ' 数値とテキストを区別する(xlSortTextAsNumbers:区別しない)
    
  3. 最後に整列全体に関する設定をした後、Sort.Apply メソッドで整列を実行しています。
        With ActiveWorkbook.Worksheets("出退勤ログ").Sort
            .SetRange Range("A1:H12")       ' 整列する範囲
            .Header = xlYes                 ' 最初の行にヘッダー情報が含まれているかどうかを指定
            .MatchCase = False              ' 大文字小文字を区別
            .Orientation = xlTopToBottom    ' 整列の方向
            .SortMethod = xlPinYin          ' 整列方法(PinYin:ふりがなを使う、Stroke:ふりがなを使わない)
            .Apply                          ' 現状の設定値に基づいて、セル範囲を整列
        End With
    

これをプロシージャに変更するには、

  1. キーとなる列
  2. 順序
  3. 先頭行を見出しとみなす
を指定すればできそうです。

また、シートの名前は、CSV形式ファイルの名前が使われるので、次のように FileSystemObject の GetBaseName メソッドで取出せますが、CSV形式ファイルをブックとして開いたとき、シートは1つだけですから、Worksheets(1)としても参照可能です。

    Dim fs As Object
    Dim baseName As String
    Dim fname

    fname = "C:\Documents and Settings\user1\My Documents\出退勤ログ.csv"

    Set fs = CreateObject("Scripting.FileSystemObject")
    baseName = fs.GetBaseName(fname)
    MsgBox baseName

整列のキーは値以外使うことは少ないし、その他のオプションは既定値です。こういうパラメータは、デフォルトで設定しておきます。

整列の範囲は、表の先頭セル(A1)からとし、最後のセルの行と列は、SpecialCells メソッドで探せます。

    Dim lastRow As Long
    Dim lastCol As Long
    lastRow = ActiveWorkbook.Worksheets(1).Cells.SpecialCells(xlCellTypeLastCell).Row
    lastCol = ActiveWorkbook.Worksheets(1).Cells.SpecialCells(xlCellTypeLastCell).Column
    MsgBox "Row : " & lastRow & ", Column : " & lastCol
従って、キーの列は以下のように表現できます。
    Dim keyCol    'キーとする列番号
    Range(Cells(2, keyCol), Cells(lastRow, keyCol))    '先頭行を見出しとみなす場合 .Header = xlYes
    Range(Cells(1, keyCol), Cells(lastRow, keyCol))    '先頭行をデータとみなす場合 .Header = xlGuess
開始行は、先頭行を見出しとみなすか、みなさないかによって変わりますが、実は後者のように指定してもちゃんと処理してくれます。 同様に、整列の範囲は以下のように表現できます。
    .SetRange Range(Cells(1, 1), Cells(lastRow, lastCol))

これらのことを組み合わせて、整列のプロシージャを作ってみました。

Sub sortExample()
    Dim cols() As Variant, ordr() As Variant
    cols = Array(4, 5, 2)
    ordr = Array(xlAscending, xlAscending, xlAscending)
    Call Sort(cols, ordr)
End Sub
'
'#####################
'# プロシージャ sort #
'#####################
Sub Sort(ByRef col As Variant, ByRef ordr As Variant)
'シートの整列範囲
    Dim lastRow As Long
    Dim lastCol As Long
    
'   整列処理
    lastRow = ActiveWorkbook.Worksheets(1).Cells.SpecialCells(xlCellTypeLastCell).Row
    lastCol = ActiveWorkbook.Worksheets(1).Cells.SpecialCells(xlCellTypeLastCell).Column
    
    With ActiveWorkbook.Worksheets(1).Sort
        .SortFields.Clear
        .SortFields.Add key:=Range(Cells(1, col(0)), Cells(lastRow, col(0))), order:=ordr(0)
        .SortFields.Add key:=Range(Cells(1, col(1)), Cells(lastRow, col(1))), order:=ordr(1)
        .SortFields.Add key:=Range(Cells(1, col(2)), Cells(lastRow, col(2))), order:=ordr(2)
        .SetRange Range(Cells(1, 1), Cells(lastRow, lastCol))
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With

End Sub

このモジュールを実行するには、以下の手順に従います。

  1. 出退勤ログ.csvを開きます
  2. 開発タブからVisual Basic エディタを開きます
  3. VBAProject(出退勤ログ)を右クリックします
  4. ポップアップメニューから挿入>標準モジュールを選びます
  5. 二つのプロシージャをコピー&ペーストします
パラメータの通り並び替えられることを確認します。

2.2.2 ブックとして開こう

CSV形式のテキストファイルはシステム間のデータ交換によく使われるので、整列が自動化できると便利です。

2.2.1で作成したプロシージャをもっと汎用的にして、CSV形式のテキストファイルをExcelの機能を利用して整列するクラスを作ってみます。そのために手始めとして、2.2.1で用意したCSV形式のテキストファイル「出退勤ログ.csv」をブックとして開くプロシージャを作ってみました。

'
'######################
'# プロシージャ fOpen #
'######################
'ファイル名を引数で受取って、CSV形式ファイルをBookとして開きます。
'
Public Function fOpen(ByVal fnm As String) As Boolean
    Dim infname as String
    infname = fnm
    
    If (fnm = "") Then
        MsgBox "File Name is NULL.", , "fOpen:" & infname
        ioStat = False               '異常終了
        fOpen = False
        Exit Function
    End If
    
On Error GoTo fOpenError
    
    Workbooks.OpenText filename:=infname, _
        DataType:=xlDelimited, comma:=True    ' ファイルを開く
    
    Dim csv_fnm As String
    csv_fnm = fs.getFileName(infname)         ' ファイル名だけを取り出す
    Set fObj = Workbooks(csv_fnm)             ' Workbook オブジェクト


    ioStat = True               '正常
    fOpen = True
Exit Function

fOpenError:
    MsgBox Err.Description & ":" & Err.Number, , "fOpen:" & infname
    ioStat = False               '異常終了
    fOpen = False
End Function
Workbooks.OpenTextメソッドでCSV形式ファイルをブックとして開いています。
    Workbooks.OpenText fileName:=fname, _
        DataType:=xlDelimited, comma:=True    ' ファイルを開く
その後、Workbookオブジェクトを取得して、プログラムで扱えるようにしています。
    csv_fnm = fs.getFileName(fname)           ' ファイル名だけを取り出す
    Set fObj = Workbooks(csv_fnm)             ' Workbook オブジェクト
残りの部分は、textClassのfOpenメソッドと同じです。

2.1.6で作成したテキストファイルを処理するクラスtextClassをcsvClassという名前でコピーして、fopenメソッドを上書きしてやると簡単にcsv形式ファイルを扱うクラスが作れます。

もちろん、その他のメソッドrdNextやwtNextは、そのまま利用できませんが、fcloseメソッドやコンストラクタ、プロパティなどは、そのまま利用できます。

クラスをコピーするには、新しいクラスを作成して、ソースコードをコピー&ペーストしても構いませんが、クラスをエクスポート/インポートする方法もあります。

  1. クラスモジュール「textClass」を右クリックしてメニューから「ファイルのエクスポート」を選び、適当なフォルダに保存します。図2.2.2-1
  2. textClass.clsというテキストファイルができるのでエディタで開き、「VB_Name="csvClass"」と編集し、「csvClass.cls」という名前を付けて保存します。 図2.2.2-2
  3. 再び、クラスモジュールを右クリックしてメニューから「ファイルのインポート」を選びます。
  4. fOpenメソッドを書き換えます。
textClassをエクスポート 図2.2.2-1  VB_NAME属性をcxvClassに変更し、名前を付けて保存 図2.2.2-2

2.2.3 名前を付けて保存しよう

また、整列を行った後、ブックとして開いたCSV形式ファイルに名前を付けて保存すれば、併合(Marge) 、更新(Update)、照合(Matching)などに使えます。

WorkbookオブジェクトのSaveAs メソッドを利用すると、以下のようにファイル形式を指定し、名前を付けて保存できます。 Excelで名前を付けて保存するとき、CSV形式で保存するのと同じです。

'
'#######################
'# プロシージャ fClose #
'#######################
'
'
'
Public Function fClose()
    ' これ以降、エラーが発生したらerrHndlへジャンプ
    On Error GoTo errHndl

    ' 保存先フォルダを選ぶ
    fName = Application.GetOpenFilename( _
         FileFilter:="CSVファイル (*.csv;*.txt), *.csv;*.txt", _
         Title:="整列結果を保存するファイルの名前を指定してください")
    If fName = False Then  Exit Function

    fObj.saveas Filename:=fName, FileFormat:=xlCSV
    fObj.Close SaveChanges:=False
    Exit Function

errHndl:
    ' SaveAsメソッドは同じ名前のファイルがあるとダイアログを表示し、上書き保存するか尋ねてくる。
    ' 「いいえ」「キャンセル」で閉じるとエラー1004が発生する
    If Err.Number = 1004 Then
        MsgBox "ファイルの上書き保存がキャンセルされました。" & vbCrLf _
            & "編集を継続できます。" & vbCrLf _
            & "必要なら名前を付けて保存してください。"
    Else
        MsgBox Err.Description & ":" & Err.Number
    End If

End Function

GetOpenFilenameメソッドは、Windowsのフォルダとファイルを指定するダイアログを呼び出します。

キャンセルボタンがクリックされるとfNameには文字列でなく論理値Falseが返されます。fNameには、文字列と論理値のどちらが代入されてもいいようにVariant型で宣言しておきます。

    ' 保存先フォルダを選ぶ
    fName = Application.GetOpenFilename( _
         FileFilter:="CSVファイル (*.csv;*.txt), *.csv;*.txt", _
         Title:="整列結果を保存するファイルの名前を指定してください")
    If fName = False Then  Exit Function

GetOpenFilenameメソッドで受け取ったファイル名をsaveasメソッドに渡して、CSV形式で名前を付けて保存します。

CSV形式ではなく、ブックとして保存することも考えられます。saveas メソッドのパラメータに "FileFormat:=xlNormal" とすれば、Excel のブックとして保存できます。

    fObj.saveas Filename:=fName, FileFormat:=xlCSV

Close メソッドのパラメータに "SaveChanges:=False"としているのは、既に名前を付けて保存しているので、閉じるときには保存する必要がないからです。

    fObj.Close SaveChanges:=False

On Error文を使って、予期しないエラーが発生した時の処理を書いています。このFunctionではファイル名を付けて保存するメソッドSaveAsを呼んでいますが、同じ名前のファイルがあると上書き保存するか尋ねるダイアログボックスを表示します。利用者がそのダイアログを「いいえ」か「キャンセルで」閉じた時は、システムエラーで通知されるので、それをキャッチして処理するためにOn Error文を使っています。システムエラーが発生したらGoTo分文で指定したラベルの次の文に実行が移ります。SaveAsメソッドのダイアログボックスが「いいえ」か「キャンセルで」閉じられたときは、エラー「1004」が発生するのでその場合の対応をMsgBoxで表示しています。それ以外のシステムエラーだった場合は、エラーメッセージを表示しています。

    On Error GoTo errHndl 
    .
    .
        Exit Function
    errHndl:
    .
    .
    End Function

以上の例を実行してみればわかるように、ファイル名と保存場所を操作者に尋ねています。自動で保存して、次のステップに進むように作ることもできます。

'########################
'# プロシージャ fClose  #
'########################
'ファイルを閉じます。
'
Public Function fClose() As Boolean
    ' これ以降、エラーが発生したらerrHndlへジャンプ
    On Error GoTo errHndl

    ' 出力ファイル名の既定値を作る
    Dim tempfname As String, outfname As String, fs as Object
    Set fs = CreateObject("Scripting.FileSystemObject")
    tempfname = fs.GetTempName
    outfname = Environ("TEMP") & "\" & fs.GetBaseName(tempfname) & ".csv"    ' "%temp%フォルダの一時ファイル名を生成

    ' 変更が保存されていなければ、規定の名前で保存
    If Not fObj.Saved Then
        fObj.SaveAs filename:=outfname, FileFormat:=xlCSV
    End If

    fObj.Close SaveChanges:=False   ' 保存せずに閉じる

    ioStat = True               '正常
    fClose = True
Exit Function
errHndl:
    MsgBox Err.Description & ":" & Err.Number
    ioStat = False               '異常終了
    fClose = False
End Function
出力ファイル名の既定値を作るために、GetTempNameメソッドで一時ファイル名を取得しています。拡張子として.tmpがつくので、GetBaseNameメソッドでベース名を取り出して、改めて拡張子.csvを付け加えています。一時フォルダの名前を環境変数TEMPからEnviron関数で取り出して、一時ファイルのフルパスを作成しています。

2.2.4 クラスを作ろう

前節までのことをヒントに2.1.6 で作った textClass と同じように、csvClass を作ってみます。2.1.1節の図を再掲します。ここで作るクラスは、CSV形式のファイルを開き、Excelの整列機能を利用して整列を行い、CSV形式として別の名前を付けて保存するのが目的です。

図2.1.1-4   図2.1.1-4

データを特定のキーで整列しておくことによって、併合や更新、照合処理が可能になります。

このクラスには、

  1. CSVファイルをブックとして開く
  2. データの範囲を調べ、指定されたキーで整列する
  3. 整列されたブックをCSV形式のテキストファイルとして保存する
  4. というような機能を持たせることにします。将来的には、ランダム検索や置き換えなどの機能も付け加えてみたいと思います。

以上の機能を実現するには、どんな情報を与えてやる必要があるか、もう少し整理してみます。

  1. 先ず、目的となるファイルを教えてやる必要があります
  2. 整列結果を保存するファイルも指定できるようにします
    出力ファイル名が指定されなかったらファイル名を作成して保存する機能も持たせます
  3. 次に、キー項目となる列を列番号で指定できるようにします
  4. キー項目ごとに昇順で整列するか降順で整列するか指定できるようにします
  5. 1行目を見出しとみなすか、データとみなすか指定できるようにします
  6. エラーの発生を知らせる情報も必要です

次のようなプロパティを用意して、以上の情報を呼び出し元と交換します。もっと細かい指定が必要なこともあるかもしれませんが、既定値にしておき、必要になったらその都度プロパティを追加することにします。

表2.2.4-1 必要なプロパティ
No.プロパティ名プロパティ意味
1.inFileName入力ファイル整列するCSV形式ファイルのフルパスを保存します
2.outFileName出力ファイル名保存するCSV形式ファイルのフルパスを保存します
3.sKeyキー列番号整列キーとする列の番号を配列の参照渡しで指定します
4.sOrder整列の順序昇順か降順かを指定します。これもキー列番号に応じて配列で渡します
5.sHeader見出しの扱い1行目を見出しとみなすか、データとみなすか指定できるようにします
6.ioStatusステータス入出力動作の状態を保存します。正常に整列処理が終わったときは、True とします。
処理が正常に終わらなかったときは、False とします。

次に、必要なメソッドについて考えてみます。

このクラスには、以下のような処理が必要です。

  1. ファイルを開いて準備します
  2. 設定したプロパティに従って整列を開始します
  3. 整列の結果をCSV形式のテキストファイルとして保存します

表2.2.4-2 必要なメソッド
No.メソッド機能
 .Class_Initialize()オブジェクトの初期値を設定するときに使用します。
 .Class_Terminate()オブジェクトがアンロードされたあとに実行する処理を記述します。通常は不要です。
1.Sortプロパティに従って、ファイルを開き、整列(ソート)を実行し、名前を付けて保存します。
2.fOpenCSV形式のテキストファイルを開きます。
3.fClose整列の結果をCSV形式のテキストファイルとして保存します。

2.2.4.1 内部変数を用意しておこう

以上のようにプロパティとメソッドを作って、少しずつコードを書いてみます。まず、プロパティを保存するためのプライベートな変数や定数などを定義します。ローカル変数はクラスの外からアクセスできない変数です。

'################
'# ローカル変数 #
'################
'# ファイル名
Private infname     As Variant      ' 入力ファイル名をフルパスで保存しておきます。
Private outfname    As Variant      ' 出力ファイル名をフルパスで保存しておきます。
'
'# 整列キーのオプションは3つまで指定できるように準備。さらに必要なときは配列の次元数を増やす。
Private sortKey(2) As Variant       ' キー列番号(A列:1,B列:2,C列:3……)
Private sortSortOn(2) As Variant    ' 値で整列(xlSortOnValues,xlSortOnCellColor,xlSortOnFontColor,xlSortOnIcon)
Private sortOrder(2) As Variant     ' 整列の順序(xlAscending:昇順,xlDescending:降順)
Private sortDataOpt(2) As Variant   ' 数値とテキストの区別(xlSortNormal:区別する, xlSortTextAsNumbers:区別しない)

'# 整列のオプション
Private csvHeader As Variant        ' 最初の行にヘッダー情報が含まれているかどうかを指定
Private csvMatchCase As Boolean     ' 大文字小文字を区別
Private csvOrientation As Variant   ' 整列の方向
Private csvSortMethod As Variant    ' 整列方法(xlPinYin:ふりがなを使う、xlStroke:ふりがなを使わない)
'
'# 入出力ステータス
Private ioStat As Boolean           ' 入出力が正常なとき True
'
'# オブジェクト変数
Private fs      As Object           ' FileSystemオブジェクト
Private fObj    As Object           ' ブックのオブジェクト

最後の2行はファイルを扱うオブジェクトを保存する変数(オブジェクト変数)です。

2.2.4.2 プロパティを書こう

前節で定義したローカル変数に呼出し元プロシージャからアクセスできるようにプロパティプロシージャを書いて行きましょう。

先ず、ファイル名です。ファイル名は、オープンメソッドで与えるので実際は必要ないでしょう。

'
'#############################
'#プロパティ 入力ファイル名 #
'#############################
'オープンメソッドで与えられるので実際は利用しない
Public Property Get inFileName() As Variant
    inFileName = infname
End Property
Public Property Set inFileName(ByVal param As Variant)
    infname = param
End Property

次に、出力ファイル名です。整列した結果を保存するファイルの名前です。ファイルをクローズするfClose()メソッドを呼ぶ前に設定する必要があります。コンストラクタClass_Initialize()で、テンポラリフォルダのファイル名を生成して既定値を与えておきます。呼出し元から設定されなかった場合、fClose()メソッドは既定値で保存してファイルを閉じます。ファイルを保存した後、このプロパティから整列結果のファイル名を取り出せます。

'
'#############################
'#プロパティ 出力ファイル名 #
'#############################
Public Property Get outFileName() As Variant
    outFileName = outfname
End Property
' 既定値としてコンストラクタで%temp%フォルダの一時ファイル名を生成するので、
' 呼出し元で設定する必要はない
Public Property Set outFileName(ByVal param As Variant)
    outfname = param
End Property

整列キーです。キーは配列で渡します。ローカル変数は3つまで指定できるように用意しています。配列のプロパティは設定方法が少し異なっています。

'
'##############################
'#プロパティ sKey()          #
'##############################
' キー列番号(A列:1,B列:2,C列:3……)
'
Public Property Let sKey(ByVal ix As Long, ByVal param As Variant)
    sortKey(ix) = param
End Property
Public Property Get sKey(ByVal ix As Long) As Variant
    sKey = sortKey(ix)
End Property

昇順で整列するか降順で整列するか指定するオプションです。整列キーと同じく配列で渡します。添え字も整列キーと同じ値を使います。

'###############################
'#プロパティ sOrder()         #
'###############################
' 整列の順序(xlAscending:昇順,xlDescending:降順)
Public Property Set sOrder(ByVal ix As Long, ByVal param As Variant)
    sortOrder(ix) = param
End Property
Public Property Get sOrder(ByVal ix As Long) As Variant
    sOrder = sortOrder(ix)
End Property

最初の行が見出し行かどうかを指定する整列のオプションです。

'#############################
'#プロパティ sHeader        #
'#############################
Public Property Set sHeader(ByVal param As Variant)
    csvHeader = param
End Property
以上で整列に関するオプションのプロパティは終わりです。他にも整列のオプションはありますが、既定値をコンストラクタで指定しておき、必要になったらプロパティを追加して呼出し元から設定できるように改修することにします。

最後は、ステータスです。入出力の結果を呼出し元に与える情報なので、Get だけ書いておけば良いでしょう。

'#########################
'#プロパティ ステータス #
'#########################
Public Property Get ioStatus() As Boolean
    ioStatus = ioStat
End Property

2.2.4.3 コンストラクタとデストラクタ

2.2.4.3.1 コンストラクタ

まずは、コンストラクタから書いてみます。コンストラクタには引数を渡せないので、オブジェクト内のローカル変数の初期化だけ行います。ファイル名は、環境変数から一時フォルダのパスを取出し、ファイルシステムオブジェクトから一時ファイル名に使えるランダムな文字列を貰って、結合しています。

'################
'#コンストラクタ#
'################
'オブジェクト内のローカル変数を初期化する。
'ファイル名は、デフォルトで一時フォルダのファイル名をランダムに生成する。
'
Private Sub Class_Initialize()
    ' 出力ファイル名の既定値を作る
    Dim tempfname As String
    Set fs = CreateObject("Scripting.FileSystemObject")
    tempfname = fs.GetTempName
    outfname = Environ("TEMP") & "\" & fs.GetBaseName(tempfname) & ".csv"   '%temp%フォルダの一時ファイル名を生成"
    
    ' 整列キーの既定値
    Dim ix As Integer
    For ix = 0 To UBound(sortKey)
        sortKey(ix) = -1            ' -1のときは設定なし
        sortSortOn(ix) = xlSortOnValues
        sortOrder(ix) = xlAscending
        sortDataOpt(ix) = xlSortNormal
    Next ix
    sortKey(0) = 1                  ' キー列の既定値はA列
    
    csvHeader = xlYes               ' 最初の行にヘッダー情報が含まれているかどうかを指定
    csvMatchCase = False            ' 大文字小文字を区別
    csvOrientation = xlTopToBottom  ' 整列の方向
    csvSortMethod = xlPinYin        ' 整列方法(PinYin:ふりがなを使う、Stroke:ふりがなを使わない)
    
    ioStat = True                   '正常
End Sub

2.2.4.3.2 デストラクタ

デストラクタは、オブジェクトがアンロードされたあとに実行されます。デストラクタは書かなくても問題ありません。

'##############
'#デストラクタ#
'##############
'デストラクタは、オブジェクトがアンロードされたあとに実行されます。
Private Sub Class_Terminate()
End Sub

2.2.4.4 メソッドを書こう

2.2.4.4.1 fOpen メソッド

ファイル名と入出力モードを引数で受取って、ファイルをテキストストリームとして開きます。ファイル名が空文字列""で、入出力モードが書込みモードのときは一時ファイルを作成することにします。
書込みモードの場合は、ファイルを新規作成してから開きます。

'#################
'#メソッド fOpen #
'#################
'ファイル名を引数で受取って、CSV形式ファイルをBookとして開きます。
'
Public Function fOpen(ByVal fnm As String) As Boolean
    ' ファイル名がなければ、異常終了
    If (fnm = "") Then
        MsgBox "File Name is NULL.", , "fOpen:csvClass" & fnm
        ioStat = False
        fOpen = False
        Exit Function
    End If

On Error GoTo fOpenError
    infname = fnm

    Workbooks.OpenText filename:=infname, _
        DataType:=xlDelimited, comma:=True    ' ファイルを開く

    Dim csv_fnm As String
    csv_fnm = fs.getFileName(infname)         ' ファイル名だけを取り出す
    Set fObj = Workbooks(csv_fnm)             ' Workbook オブジェクト

    ioStat = True               '正常
    fOpen = True
Exit Function

fOpenError:
    MsgBox Err.Description & ":" & Err.Number, , "fOpen:csvClass" & infname
    ioStat = False               '異常終了
    fOpen = False
End Function

2.2.4.4.2 fClose メソッド

ファイルを閉じます。

'###################
'#メソッド fClose #
'###################
'ファイルを閉じます。
'
Public Sub fClose()
On Error GoTo fCloseError    ' エラーが発生したならばfCloseErrorへジャンプ

    fobj.Close

    IOStat = True       '正常終了
    ErrStat = False


Exit Sub

fCloseError:
    IOStat = False      '異常終了
    ErrStat = True
    MsgBox Err.Description & ":" & Err.Number, , "fClose:txtClasss:" & FName
End Sub

2.2.4.4.3 csvSort メソッド

設定されたプロパティをもとに、整列します。

'############################
'# プロシージャ csvSort     #
'############################
' 整列処理
Function csvSort() As Boolean
'シートの整列範囲
    Dim lastRow As Long	' シートの最後の行
    Dim lastCol As Long	' シートの最後の列
    Dim ix As Long		' 整列キーオプション配列の添え字
    
    ' 整列するシートの範囲を決めるために、シートの最後の行と列を求める
    lastRow = ActiveWorkbook.Worksheets(1).Cells.SpecialCells(xlCellTypeLastCell).Row
    lastCol = ActiveWorkbook.Worksheets(1).Cells.SpecialCells(xlCellTypeLastCell).Column
    
    With fObj.Worksheets(1).Sort	' CSV形式ファイルを開いているのでシートは1つだけ
        .SortFields.Clear			' 整列オブジェクトの設定を初期化
        
        For ix = 0 To UBound(sortKey)	' 整列キーオプションをせってする
            If sortKey(ix) = -1 Then Exit For	' 整列キー列の値が負ならば終わり
            .SortFields.Add key:=Range(Cells(1, sortKey(ix)), Cells(lastRow, sortKey(ix))), _
                SortOn:=sortSortOn(ix), order:=sortOrder(ix), _
                DataOption:=sortDataOpt(ix)
        Next ix
        .SetRange Range(Cells(1, 1), Cells(lastRow, lastCol))	' 整列の範囲
        .Header = csvHeader				' 1行目をタイトル行とするか
        .MatchCase = csvMatchCase		' 大文字、小文字を区別するか
        .Orientation = csvOrientation	' 整列の方向
        .SortMethod = csvSortMethod		' 整列方法(xlPinYin:ふりがなを使う、xlStroke:ふりがなを使わない)
        .Apply							' 整列実行
    End With

End Function

2.2.5 クラスを呼び出してみよう

「出退勤ログ.csv」を整列してみます。標準モジュールにテストドライバを作成します。テストドライバは、まず、出社時刻の昇順に整列します。次にID、年月日、出社時刻の昇順に整列します。整列した結果は、一時フォルダに保存します。ファイル名は自動で作られるので、ファイル名を表示します。

'#######################################
'# 整列テストドライバ sortExample2() #
'#######################################
'指定された「出退勤ログファイル.csv」を整列します。
'出社時刻の昇順に並べ変えます。
'一時フォルダに保存されたファイルの名前を表示します。
'ID、年月日、出社時刻の昇順に並べ変えます。
'一時フォルダに保存されたファイルの名前を表示します。
'
Sub sortExample2()
    '# csvClassのインスタンス化
    Dim syuttaikinlog As csvClass
    Set syuttaikinlog = New csvClass    ' 新しいcsvClassのインスタンス(オブジェクト)作ります
    
    syuttaikinlog.sKey(0) = 5           '整列キーを1つ設定
    
    If syuttaikinlog.fOpen("C:\Users\muneyoshi\Documents\VBA4Excel\出退勤ログ.csv") = False Then Exit Sub
    syuttaikinlog.csvSort               ' 整列
    syuttaikinlog.fClose                ' 結果を一時フォルダに保存して閉じる
    If syuttaikinlog.ioStatus = False Then Exit Sub
    
    ' 保存ファイル名を表示
    MsgBox syuttaikinlog.outFileName
    
    Set syuttaikinlog = New csvClass    ' 新しいcsvClassのインスタンス(オブジェクト)作ります
    '整列オプションの配列
    syuttaikinlog.sKey(0) = 3           ' 第1整列キーをC列とする
    syuttaikinlog.sKey(1) = 4           ' 第2整列キーをD列とする
    syuttaikinlog.sKey(2) = 5           ' 第3整列キーをE列とする
    
    If syuttaikinlog.fOpen("C:\Users\muneyoshi\Documents\VBA4Excel\出退勤ログ.csv") = False Then Exit Sub
    syuttaikinlog.csvSort               ' 整列
    syuttaikinlog.fClose                ' 結果を一時フォルダに保存して閉じる
    If syuttaikinlog.ioStatus = False Then Exit Sub
    
    ' 保存ファイル名を表示
    MsgBox syuttaikinlog.outFileName
End Sub

プログラムの流れが理解できたら、実行してみます。csvClassは、こちらからダウンロードできます。