3
1

More than 3 years have passed since last update.

【UiPath】Excel - 表示されているシート/列/行だけを取得(非表示分は取得しない)

Last updated at Posted at 2021-03-16

はじめに

この投稿は、RPAツールのUiPathで「Excelで「表示されている」シート/列/行を取得」する方法についての投稿です。

「Excel操作を.NETのコードでやってみよう」シリーズです。他の投稿はこちら。

Excel操作で困ることがある

UiPathでExcel操作をする際に「どうやって実現すれば良いのだろう」と困ることがあります。
例えば今回の「表示されているシートだけを取得したい」といったケースです。

この手の課題は「一度知ってしまえば、その後は横展開すれば解決できる」ものなので、
自分が知っているナレッジを、整理も含めて投稿していこうと思います。

標準では「非表示」も取得してしまう

エクセルには

  • 非表示シート
  • 非表示列
  • 非表示行

がありますが、UiPath標準アクティビティでは「表示/非表示の関係なく、全て取得」します。
image.png
そのため「非表示は相手にしたくない」ケースでは困ることがあります。
例えば、以下の業務要件があったとします。

- 「2021年売上.xlsx」内には「商品ID」別のシートがある(シート名が商品IDになっている)
- 各シートの商品IDで、当月売上データをWebシステムからスクレイピングし、シートに貼り付ける
- 廃盤の古い商品は「シートが非表示になっている」ので、そのシートは更新しなくて良い

この場合、UiPathの標準アクティビティの「UiPath.Excel.Activities.ExcelGetWorkbookSheets」でシートの一覧を取得して、ループしながら売上データをWEBから取得すると思いますが、標準アクティビティでは「非表示のシートも取得」してしまいます。
062613263396366316535302e706e67.png

オプションで「非表示シートを含めない」があれば良いのですが、残念ながらありません。
image.png

標準アクティビティ以外で「非表示を取得しない」方法は、以下があります。

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

引数は以下のようになっています。
image.png

.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

引数は以下のようになっています。
image.png
※ 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

引数は以下のようになっています。
image.png
※ in_rowNumberMax は「取得する列番号の最大値」指定です。

おわりに

シート・列・行で「非表示分は取得したくない」という時に、引き出しの一つとして、役に立てばと思います。
最後までお読みいただき、ありがとうございました。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1