整列処理を行う処理を書いてみます。「2.1.1 ファイル処理のパターン」で紹介した「集計」「併合」「更新」「照合」などは、その入力となるファイルが特定のキーで整列されていることが前提なので、整列処理は、とても重要な処理です。ExcelのSort機能を利用することにします。
手始めとして「整列」のマクロを記録して、それを参考に整列のプロシージャを作ってみます。
まず、以下のような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
[並べ替え]ダイアログボックスで[レベルの追加]をクリックして図のように3つのキーを作り、[OK]をクリックします。
図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
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
レベルごとに3つの設定をしています(Orderは、昇順か降順か。SortOnは、値か、塗りつぶしの色か、文字の色で整列するか。DataOptionは、数値と文字を区別するか)。
SortOn:=xlSortOnValues ' 値で整列(xlSortOnCellColor,xlSortOnFontColor,xlSortOnIcon) Order:=xlAscending ' 昇順(xlDescending:降順) DataOption:=xlSortNormal ' 数値とテキストを区別する(xlSortTextAsNumbers:区別しない)
With ActiveWorkbook.Worksheets("出退勤ログ").Sort
.SetRange Range("A1:H12") ' 整列する範囲
.Header = xlYes ' 最初の行にヘッダー情報が含まれているかどうかを指定
.MatchCase = False ' 大文字小文字を区別
.Orientation = xlTopToBottom ' 整列の方向
.SortMethod = xlPinYin ' 整列方法(PinYin:ふりがなを使う、Stroke:ふりがなを使わない)
.Apply ' 現状の設定値に基づいて、セル範囲を整列
End With
これをプロシージャに変更するには、
また、シートの名前は、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
このモジュールを実行するには、以下の手順に従います。
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メソッドやコンストラクタ、プロパティなどは、そのまま利用できます。
クラスをコピーするには、新しいクラスを作成して、ソースコードをコピー&ペーストしても構いませんが、クラスをエクスポート/インポートする方法もあります。
図2.2.2-1
図2.2.2-2
また、整列を行った後、ブックとして開いた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.1.6 で作った textClass と同じように、csvClass を作ってみます。2.1.1節の図を再掲します。ここで作るクラスは、CSV形式のファイルを開き、Excelの整列機能を利用して整列を行い、CSV形式として別の名前を付けて保存するのが目的です。
図2.1.1-4
データを特定のキーで整列しておくことによって、併合や更新、照合処理が可能になります。
このクラスには、
以上の機能を実現するには、どんな情報を与えてやる必要があるか、もう少し整理してみます。
次のようなプロパティを用意して、以上の情報を呼び出し元と交換します。もっと細かい指定が必要なこともあるかもしれませんが、既定値にしておき、必要になったらその都度プロパティを追加することにします。
| No. | プロパティ名 | プロパティ | 意味 |
|---|---|---|---|
| 1. | inFileName | 入力ファイル | 整列するCSV形式ファイルのフルパスを保存します |
| 2. | outFileName | 出力ファイル名 | 保存するCSV形式ファイルのフルパスを保存します |
| 3. | sKey | キー列番号 | 整列キーとする列の番号を配列の参照渡しで指定します |
| 4. | sOrder | 整列の順序 | 昇順か降順かを指定します。これもキー列番号に応じて配列で渡します |
| 5. | sHeader | 見出しの扱い | 1行目を見出しとみなすか、データとみなすか指定できるようにします |
| 6. | ioStatus | ステータス | 入出力動作の状態を保存します。正常に整列処理が終わったときは、True とします。 処理が正常に終わらなかったときは、False とします。 |
次に、必要なメソッドについて考えてみます。
このクラスには、以下のような処理が必要です。
| No. | メソッド | 機能 |
|---|---|---|
| . | Class_Initialize() | オブジェクトの初期値を設定するときに使用します。 |
| . | Class_Terminate() | オブジェクトがアンロードされたあとに実行する処理を記述します。通常は不要です。 |
| 1. | Sort | プロパティに従って、ファイルを開き、整列(ソート)を実行し、名前を付けて保存します。 |
| 2. | fOpen | CSV形式のテキストファイルを開きます。 |
| 3. | fClose | 整列の結果をCSV形式のテキストファイルとして保存します。 |
以上のようにプロパティとメソッドを作って、少しずつコードを書いてみます。まず、プロパティを保存するためのプライベートな変数や定数などを定義します。ローカル変数はクラスの外からアクセスできない変数です。
'################ '# ローカル変数 # '################ '# ファイル名 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行はファイルを扱うオブジェクトを保存する変数(オブジェクト変数)です。
前節で定義したローカル変数に呼出し元プロシージャからアクセスできるようにプロパティプロシージャを書いて行きましょう。
先ず、ファイル名です。ファイル名は、オープンメソッドで与えるので実際は必要ないでしょう。
'
'#############################
'#プロパティ 入力ファイル名 #
'#############################
'オープンメソッドで与えられるので実際は利用しない
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
まずは、コンストラクタから書いてみます。コンストラクタには引数を渡せないので、オブジェクト内のローカル変数の初期化だけ行います。ファイル名は、環境変数から一時フォルダのパスを取出し、ファイルシステムオブジェクトから一時ファイル名に使えるランダムな文字列を貰って、結合しています。
'################
'#コンストラクタ#
'################
'オブジェクト内のローカル変数を初期化する。
'ファイル名は、デフォルトで一時フォルダのファイル名をランダムに生成する。
'
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
デストラクタは、オブジェクトがアンロードされたあとに実行されます。デストラクタは書かなくても問題ありません。
'############## '#デストラクタ# '############## 'デストラクタは、オブジェクトがアンロードされたあとに実行されます。 Private Sub Class_Terminate() End Sub
ファイル名と入出力モードを引数で受取って、ファイルをテキストストリームとして開きます。ファイル名が空文字列""で、入出力モードが書込みモードのときは一時ファイルを作成することにします。
書込みモードの場合は、ファイルを新規作成してから開きます。
'#################
'#メソッド 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
ファイルを閉じます。
'###################
'#メソッド 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
設定されたプロパティをもとに、整列します。
'############################
'# プロシージャ 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
「出退勤ログ.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は、こちらからダウンロードできます。