分岐処理について

studio

#1

複数のExcelファイルの中に特定の文字があるExcelとないExcelがある場合の分岐処理のやり方をご教示いただけないでしょうか?


#2

30個ぐらいのExcelを繰り返し処理をしようと思っていますが、分岐処理のやり方でつまずいています


#3

質問があっさりしていて私が理解しきれていない部分ありますが、
だいたいこんな感じのフローを想定しているのではないかと思います。
いかがでしょう。

で、個人的に「ExcelでできることはExcelでやらせたほうが早い」派なので、
Excelシートに特定文字があるかどうかは、[Invoke VBA]アクティビティを使って、
こんなVBAコードを呼んじゃえば良いと思ってます。


’引数で渡された文字列がアクティブシートにあればTrue,なければFalseを返すVBAコード
Function FindString(strString as string) as Boolean

dim rngFind as Range

set rngFind = Activesheet.Cells.Find( strString)
If rngFind is nothing then
FindString = false
else
FindString = True
end If

End Function



エクセルの操作
#4

Invoke VBAはセキュリティの関係で、あまり使わない方がよい(使えるように設定すること自体にリスクがある)ので難しいところですね。

かといって代案が、というともう、ExcelのGUIを直接操作して検索するか、VB.NETコードでごりごり書くしかなく。前者は割と時間がかかる上に、調節も面倒だなぁ、という感じで。

凄まじい力技ですが、以下のコードでExcel側の設定にあまり依存せず、「Excelファイルのシート内に該当の文字があるか」は検索できます。
(Invoke Codeアクティビティを使います。引数の設定は画像を参照してください)

Dim InvokeProp As Func(Of Object, String, Object(), Object) = _
    Function(target As Object, ParamName As String, Args As Object()) As Object
        Return target.GetType().InvokeMember(ParamName, Reflection.BindingFlags.GetProperty Or Reflection.BindingFlags.Instance, Nothing, target, Args)
    End Function

Dim InvokeMethod As Func(Of Object, String, Object(), Object) = _
    Function(target As Object, ParamName As String, Args As Object()) As Object
        Return target.GetType().InvokeMember(ParamName, Reflection.BindingFlags.InvokeMethod Or Reflection.BindingFlags.Instance, Nothing, target, Args)
    End Function

Dim ReleaseObj As Action(Of Object) = _
    Sub(target As Object)
        Runtime.InteropServices.Marshal.ReleaseComObject(target)
    End Sub

Ret = False
Dim xlApp As Object = CreateObject("Excel.Application")
Dim xlBooks As Object = InvokeProp(xlApp, "WorkBooks", Nothing)
Dim xlBook As Object = InvokeMethod(xlBooks, "Open", New Object(0) {TargetFile})

Dim xlSheets As Object = InvokeProp(xlBook, "WorkSheets", Nothing)
Dim sheetCount As Int32 = CType(InvokeProp(xlSheets, "Count", Nothing), Int32)

For n As Integer = 1 To sheetCount
    Dim xlSheet As Object = InvokeProp(xlBook, "WorkSheets", New Object(0) {n})
    Dim xlCells As Object = InvokeProp(xlSheet, "Cells", Nothing)
    Dim xlFind As Object = InvokeMethod(xlCells, "Find", New Object(0) {SearchText})
    Ret = Ret Or (Not IsNothing(xlFind))

    If Not IsNothing(xlFind) Then
        ReleaseObj(xlFind)
    End If

    ReleaseObj(xlCells)
    ReleaseObj(xlSheet)
Next

ReleaseObj(xlSheets)

InvokeMethod(xlBook, "Close", New Object(0) {False})
ReleaseObj(xlBook)
ReleaseObj(xlBooks)

InvokeMethod(xlApp, "Quit", Nothing)
ReleaseObj(xlApp)


#5

悩ましいですね。選択肢としては、
①セキュリティを気にしつつVBAで逃げる
②コードのメンテナンスを気にしつつVB.netのコードで対処
③ワークフローのメンテナンスを気にしつつExcelの操作(GUI)で対応する
④業務フロー自体を変更して、UiPathの外側で対処する
ですかね。

ちなみに③だと、「Excelシート開く」→「シートを全部選択状態にする」→「Ctrl-Fで検索ダイアログ開く」→「ダイアログに文字列入力」→「すべて検索ボタンクリック」→「検索条件に一致するデータが見つかりません」ダイアログが出たら検索文字列なし」という操作をアクティビティを並べて実施することになりますかね。できなくはなさそうですが・・・・という感じです

@yukkir さま、いかがでしょうか?


#6

yukinoさん、Honokaさん
ご返信ありがとうございます。
InvokeVBAはセセキュリティの問題があるとのことですのでInvokeCodeを試してみたいと思います。
いろいろなご提案ありがとうございました。
進捗がありましたらご報告させていただきます。


#7

お世話になっております。
UiPathではなくVBAの方で作成しました。