テキストファイルの行数が必要な理由
VBAでテキストファイルやCSVファイルなどを扱う際に、そのファイルの行数を知りたいことがあります。
その理由には大きく3つあります。
- 単純に行数を知りたいため。
- Excelの最大行数(Range(“A:A”).Rows.Count)と比較するため。
- 高速化のため。
1番目はいいとして、2番目はファイルの内容をシートに貼り付けたい場合にExcelシートの最大行数(Range(“A:A”).Rows.Count)を超えていないかのチェックのためで、3番目は配列の領域確保を事前にファイル行数分行っている方が高速になるためです。
テキストファイルの行数取得方法にはいくつかありますが、ここでは3つ紹介します。
事前設定
以下のサンプルコードではFileSystemObjectとADODBを利用しています。
1つ目と2つ目のサンプルを利用する場合はFileSystemObjectを利用するため、VBA画面のツールメニュー→参照設定 で「Microsoft Scripting Runtime」にチェックを付けてください。
3つ目のサンプルを利用する場合はADODBを利用するため、VBA画面のツールメニュー→参照設定 で「Microsoft ActiveX Data Objects x.x Library」にチェックを付けてください。x.xのバージョンは最大のものを選択してください。
1. 高速にテキストファイル行数を取得する方法
FileSystemObjectのOpenTextFileを追加モードでオープンして最終行にシーク(書き込み位置を移動)させる方法です。その状態のLineプロパティはファイル行数+1の状態になっているため、Lineプロパティから1を引いた値がファイル行数になります。
10万行程度のファイルであれば数ミリ秒程度で取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Function GetLineCount(a_sFilePath) As Long Dim oFS As New FileSystemObject Dim oTS As TextStream Dim iLine '// 引数のファイルが存在しない場合は処理を終了する If (oFS.FileExists(a_sFilePath) = False) Then GetLineCount = -1 Exit Function End If '// 追加モードで開く Set oTS = oFS.OpenTextFile(a_sFilePath, ForAppending) GetLineCount = oTS.Line - 1 End Function |
使い方
1 2 |
Dim iLine iLine = GetLineCount("C:\web\test\a.txt") |
コード説明
2行目 | FileSystemObjectクラスのインスタンス変数を作成するためNewしています。 |
3行目 | FileSystemObjectのメソッドから生成されるTextStreamクラスの変数を宣言しています。ここではまだ使える状態にはなっていません。 |
4行目 | ファイル行数取得用の変数です。 |
6~10行目 | ファイル存在チェックを行い、存在しない場合は-1を返しています。 |
13行目 | OpenTextFileメソッドを追加モードで開き、書き込み位置をファイル終端に移動させています。 |
15行目 | 書き込み位置がファイル終端に移動している状態でのLineプロパティはファイル行数+1を返すため、-1してファイル行数に変換しています。ファイルの最終行が改行のみであっても正しくファイル行数を取得できます。 |
2. テキストファイルを1行ずつ読み込んで行数を取得する方法
FileSystemObjectを使うのは1つ目の方法と同じですが、こちらはファイル行を1行ずつ読み飛ばしてループカウンタからファイル行数を取得する分かりやすい方法です。
処理速度は1つ目よりは遅いですが、10万行程度のファイルであれば10ミリ秒も掛からないでしょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
Function GetLineCount(a_sFilePath) As Long Dim oFS As New FileSystemObject Dim oTS As TextStream Dim iLine iLine = 0 '// 引数のファイルが存在しない場合は処理を終了する If (oFS.FileExists(a_sFilePath) = False) Then GetLineCount = -1 Exit Function End If '// TextStreamオブジェクト作成 Set oTS = oFS.OpenTextFile(a_sFilePath) '// ファイル終端までループ Do While oTS.AtEndOfStream <> True oTS.SkipLine iLine = iLine + 1 Loop GetLineCount = iLine End Function |
使い方
1 2 |
Dim iLine iLine = GetLineCount("C:\web\test\a.txt") |
コード説明
2行目 | FileSystemObjectクラスのインスタンス変数を作成するためNewしています。 |
3行目 | FileSystemObjectのメソッドから生成されるTextStreamクラスの変数を宣言しています。ここではまだ使える状態にはなっていません。 |
4行目 | ファイル行数取得用の変数です。 |
6行目 | ファイル行数変数を0に初期化しています。 |
8~12行目 | ファイル存在チェックを行い、存在しない場合は-1を返しています。 |
15行目 | OpenTextFileメソッドでファイルを開きます。 |
17~21行目 | ファイルの先頭から終端までループし、1行ごとにスキップして行数をカウントします。 |
23行目 | 取得したファイル行数を返します。 |
3. ADODBを使ってテキストファイル行数を取得する方法
ちょっと変わった方法です。ADODBを使ってデータベースのようにファイルの行数を取得します。
処理速度は10万行程度で10数ミリ秒と1つ目のと比べると遅いです。
分かりやすくするためにあえてファイル存在チェックは入れていません。必要な場合は上のコードからFileSystemObjectの変数定義と存在チェック部分をコピペしてください。
1 2 3 4 5 6 7 8 9 10 |
Function GetLineCount(a_sPath, a_sFileName) As Long Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & a_sPath & ";Extended Properties='Text;HDR=NO'" Call rs.Open("SELECT * FROM " & a_sFileName, cn, adOpenStatic, adLockOptimistic, adCmdText) GetLineCount = rs.RecordCount End Function |
使い方
1 2 |
Dim iLine iLine = GetLineCount("C:\web\test\", "a.txt") |
コード説明
2~3行目 | ADODBの接続とレコードセットのインスタンス変数を作成しています。 |
5行目 | 接続先の設定を行っています。 |
7行目 | ファイルの読み込みを行っています。 |
9行目 | RecordCountプロパティでファイル行数を取得しています。 |