下図のような既存のワークシートがあるとします。
前提条件
- 対象データは「会社データ」という名前のワークシートにあるとします。
- 対象のワークシートには1つ以上の空行を挟んで2つのテーブル(カテゴリテーブル、会社テーブル)があるとします。
- いずれのテーブルも開始行・開始列が変わる可能性があるとします(プログラムでテーブルの場所を探す)。
- 最初のテーブルの列タイトルは変わる可能性がありますが、列順は変わらないとします(列位置から対象データを探す)。
- 2つ目のテーブルの列タイトルは変わりませんが、列順は変わる可能性があるとします(列タイトルから対象データを探す)。
処理内容
カテゴリ名のリストと会社名のリストを抽出します。
コード
呼び出し側(Main など)
Dim categories As New List(Of String) Dim companies As New List(Of String) Call カテゴリ名と会社名を取得("D:\test\会社データ.xlsx", categories, companies) '取得したリストを好きなように処理しましょう Console.WriteLine(vbCrLf & "===== カテゴリ =====") For Each category As String In categories Console.WriteLine(category) Next Console.WriteLine(vbCrLf & "===== 会社 =====") For Each company As String In companies Console.WriteLine(company) Next
「カテゴリ名と会社名を取得」関数
Private Sub カテゴリ名と会社名を取得(targetFileFullname As String, categories As List(Of String), companies As List(Of String)) '対象ファイルを開いてワークブックを取得 Dim wb = new XLWorkbook(targetFileFullname) 'シート名からワークシートを取得 Dim ws = wb.Worksheet("会社データ") Const categoryIdColNum As Integer = 1 'カテゴリID の列の位置 Const categoryNameColNum As Integer = 2 'カテゴリ名の列の位置 '使用されている最初の1行全体を取得(これには未使用の列範囲も含まれている)。 Dim firstRowUsed = ws.FirstRowUsed '使用されている最初の1行全体の範囲から、使用されている範囲のみを求める(不要な列範囲を取り除く) Dim categoryRow = firstRowUsed.RowUsed '現在、タイトル行を指している '対象範囲を次の行に移動する(ここからデータ行) categoryRow = categoryRow.RowBelow 'カテゴリ ID の列に ID が記入されている限り、行を順に処理してカテゴリ名を取得していく While categoryRow.Cell(categoryIdColNum).IsEmpty = False Dim categoryName As String = categoryRow.Cell(categoryNameColNum).GetString categories.Add(categoryName) categoryRow = categoryRow.RowBelow End While '会社テーブルを取得する方法はいろいろあります。 'ここでは直接的なやり方をしてみましょう。 '他の方法としては、たとえば、row.IsEmpty が真である限りループ処理して '会社テーブルの最初の行を見つけることもできます。 '会社テーブルの開始位置になり得る最初のアドレスを取得 '(現在 categoryRow はカテゴリテーブルの1つ下の行を指している) Dim firstPossibleAddress = ws.Row(categoryRow.RowNumber).FirstCell.Address '会社テーブルの終了位置になり得る最後のアドレスを取得 Dim lastPossibleAddress = ws.LastCellUsed.Address '会社テーブルが存在し得る範囲から、使用されている範囲を取得する Dim companyRange = ws.Range(firstPossibleAddress, lastPossibleAddress).RangeUsed '取得した範囲をテーブルとして扱う(列タイトルを使用するため) Dim companyTable = companyRange.AsTable '会社名のリストを取得 ' → 会社テーブルのデータ範囲の行を取得 ' → 行を順次処理して「会社名」列の値をリストにして返す ' → companies に格納 companies.AddRange( companyTable.DataRange.Rows _ .Select(Function(companyRow) companyRow.Field("会社名").GetString) _ .ToList ) End Sub
実行結果