はじめに
この投稿は、RPAツールのUiPathで「Excelで「表示されている」シート/列/行を取得」する方法についての投稿です。
「Excel操作を.NETのコードでやってみよう」シリーズです。他の投稿はこちら。
Excel操作で困ることがある
UiPathでExcel操作をする際に「どうやって実現すれば良いのだろう」と困ることがあります。
例えば今回の「表示されているシートだけを取得したい」といったケースです。
この手の課題は「一度知ってしまえば、その後は横展開すれば解決できる」ものなので、
自分が知っているナレッジを、整理も含めて投稿していこうと思います。
標準では「非表示」も取得してしまう
エクセルには
- 非表示シート
- 非表示列
- 非表示行
がありますが、UiPath標準アクティビティでは「表示/非表示の関係なく、全て取得」します。
そのため「非表示は相手にしたくない」ケースでは困ることがあります。
例えば、以下の業務要件があったとします。
- 「2021年売上.xlsx」内には「商品ID」別のシートがある(シート名が商品IDになっている)
- 各シートの商品IDで、当月売上データをWebシステムからスクレイピングし、シートに貼り付ける
- 廃盤の古い商品は「シートが非表示になっている」ので、そのシートは更新しなくて良い
この場合、UiPathの標準アクティビティの「UiPath.Excel.Activities.ExcelGetWorkbookSheets」でシートの一覧を取得して、ループしながら売上データをWEBから取得すると思いますが、標準アクティビティでは「非表示のシートも取得」してしまいます。
オプションで「非表示シートを含めない」があれば良いのですが、残念ながらありません。
標準アクティビティ以外で「非表示を取得しない」方法は、以下があります。
No | 方法 | デメリット/懸念 |
---|---|---|
1 | VBAのコードを書いて、Invoke VBAで取得する | VBA実行セキュリティ設定が必要 |
2 | .NETのコードを書いて、Invoke Codeで取得する | UiPath標準外なので、現場によっては使用NG |
3 | .NETのコードでInvoke Code | 書くのが難しい? |
1.2はデメリット/懸念があるので、出来るなら、3の「.NETのコードでInvoke Code」が良いと思います。
以下で紹介します。
.NETで、表示中のシート名のみを取得する
以下は、Excelブック内のシートで「表示中のシート名」を取得するVB.NETのコードです。
※ 非表示のシートは取得しません
'// 対象エクセルファイルのパスを指定
Dim bookPath As String = "C:\temp\exceltest.xlsx"
'// ファイルを読み込み
Dim sheetNameList As New List(Of String)
Dim ap As New Microsoft.Office.Interop.Excel.Application
Dim wb As Microsoft.Office.Interop.Excel.Workbook
Dim ws As Microsoft.Office.Interop.Excel.Worksheet
Try
'// ブックを開く
wb = ap.Workbooks.Open(IO.path.GetFullPath(bookPath))
'// シートループ
For idx As Integer = 1 To wb.Sheets.Count
ws = CType(wb.Sheets(idx), Microsoft.Office.Interop.Excel.Worksheet)
'// 表示状態を確認して、リストに格納
If ws.Visible = Microsoft.Office.Interop.Excel.XlSheetVisibility.xlSheetVisible Then
sheetNameList.Add(ws.Name)
End If
Next
wb.Close
Catch ex As Exception
Console.writeLine(ex.ToString)
Throw(ex)
Finally
'// ブックを閉じる
If Not(wb Is Nothing) Then wb = Nothing
ap = Nothing
End Try
呼び出し可能なxamlファイルにしたものを用意しました。以下からダウンロードできます。
[github.com] GetVisibleSheetNameList.xaml
.NETで、表示中の列名のみを取得する
以下は、Excelシート内で「表示中の列名(列番号)」を取得するVB.NETのコードです。
※ 非表示の列名/列番号は含まない
※ 匿名関数「func_ConvColumNumberToName」で、列番号を列名に変換しています
'// -------------------------------------------
'// 関数定義:列番号を列名に変換
'// -------------------------------------------
Dim func_ConvColumNumberToName As Func(Of Integer, String) = _
Function(columnIndex As Integer) As String
Dim colLetter As String = String.Empty
Dim modNum As Integer = 0
Dim divEnd As Integer = columnIndex
While divEnd > 0
modNum = (divEnd - 1) Mod 26 '// 26 = A-Z
colLetter = Chr(65 + modNum) & colLetter '// char(65) = A
divEnd = CInt((divEnd - modNum) \ 26)
End While
Return colLetter
End Function
'// -------------------------------------------
'// 対象エクセルファイルのパス・シート名・最大取得列
Dim bookPath As String = "C:\temp\exceltest.xlsx"
Dim sheetName As String = "Sheet1"
Dim columnNumberMax As Integer = 99
Dim columnNameList As New List(Of String)
Dim ap As New Microsoft.Office.Interop.Excel.Application
Dim wb As Microsoft.Office.Interop.Excel.Workbook
Dim ws As Microsoft.Office.Interop.Excel.Worksheet
Try
'// ブックを開く
wb = ap.Workbooks.Open(IO.path.GetFullPath(bookPath))
'// シートループ
For idx As Integer = 1 To wb.Sheets.Count
ws = CType(wb.Sheets(idx), Microsoft.Office.Interop.Excel.Worksheet)
If ws.Name = sheetName Then
'// 列ループ
For idxCol As Integer = 1 To columnNumberMax
'// 表示状態を確認して、リストに格納
If Not(CBool(
ws.Range(ws.Cells(1, idxCol), ws.Cells(1, idxCol)).EntireColumn.Hidden)) Then
columnNameList.Add(func_ConvColumNumberToName(idxCol))
End If
Next
Exit For
End If
Next
wb.Close
Catch ex As Exception
Console.writeLine(ex.ToString)
Throw(ex)
Finally
'// ブックを閉じる
If Not(wb Is Nothing) Then wb = Nothing
ap = Nothing
End Try
呼び出し可能なxamlファイルにしたものを用意しました。以下からダウンロードできます。
[github] GetVisibleRowNumberList.xaml
引数は以下のようになっています。
※ in_columnNumberMax は「取得する列番号の最大値」指定です。
.NETで、表示中の行番号のみを取得する
以下は、Excelシート内で「表示中の行番号」を取得するVB.NETのコードです。
※ 非表示の行番号は含まれません
'// 対象エクセルファイルのパス・シート名・最大取得行を指定
Dim bookPath As String = "C:\temp\exceltest.xlsx"
Dim sheetName As String = "Sheet1"
Dim rowNumberMax As Integer = 99
'// ファイルを読み込み
Dim rowNumberList As New List(Of String)
Dim ap As New Microsoft.Office.Interop.Excel.Application
Dim wb As Microsoft.Office.Interop.Excel.Workbook
Dim ws As Microsoft.Office.Interop.Excel.Worksheet
Try
'// ブックを開く
wb = ap.Workbooks.Open(IO.path.GetFullPath(bookPath))
'// シートループ
For idx As Integer = 1 To wb.Sheets.Count
ws = CType(wb.Sheets(idx), Microsoft.Office.Interop.Excel.Worksheet)
If ws.Name = sheetName Then
'// 行ループ
For idxRow As Integer = 1 To rowNumberMax
'// 表示状態を確認して、リストに格納
If Not(CBool(
ws.Range(ws.Cells(idxRow,1), ws.Cells(idxRow,1)).EntireRow.Hidden)) Then
rowNumberList.Add(idxRow.ToString)
End If
Next
Exit For
End If
Next
wb.Close
Catch ex As Exception
Console.writeLine(ex.ToString)
Throw(ex)
Finally
'// ブックを閉じる
If Not(wb Is Nothing) Then wb = Nothing
ap = Nothing
End Try
呼び出し可能なxamlファイルにしたものを用意しました。以下からダウンロードできます。
[github] GetVisibleRowNumberList.xaml
引数は以下のようになっています。
※ in_rowNumberMax は「取得する列番号の最大値」指定です。
おわりに
シート・列・行で「非表示分は取得したくない」という時に、引き出しの一つとして、役に立てばと思います。
最後までお読みいただき、ありがとうございました。