2017-04-05 11 views
0

私は自分のシートから呼び出すVBAで書かれたUDFを持っています。この関数は3つの引数を取ります。Function CONCATIF(arg1 As Range, arg2 As Boolean, Optional arg3 As Range) As Variant引数の関数の解析

UDFは、それがTRUEまたはFALSEに評価されている前に、すなわち、arg2に傍受し、ARG2のを知っている必要があります。 (最も単純な形で)私を与える、私はApplication.Caller.Formulaを使用してこれを行うには"=CONCATIF(arg1, arg2, arg3)"(または,arg3))または,)のいずれかの代わりに) 私は、単にSplit(Application.Caller.Formula, ",")

私は思いますいくつかの問題がありますを使用して引数2を得ることができますカンマで

  • 分割が私の引数のどれもが、彼らは公式には例えば=SUM(1,IF(CONCATIF(arg1, arg2, arg3)="a",1,0))、入れ子にすることができるので、私はどの項目を知らない
  • に有していてもよい、カンマが含まれていないことを意味しても対処したいです私の分割配列はarg2です。 (これはかなり簡単に修正するべきだと思う:文字列にCONCATIFを見つけて、開始を切り落とし、open/closeまでそれに続くカッコを数えてから、最後を切り捨てる。
  • 引数は数式自体でarg1は範囲を参照することができますが、実際の範囲ではありません
  • トリッキー:CONCATIFは1式で複数回出現することがありますが、標準の文字列検索では常に最初のものを選びます1つの数式が複数ある場合はエラーを返さなければならないので、これを回避する方法は考えられません)

私が望むもの:呼び出し元セルから正しいCONTCATIF()数式を取得し、配列内の3つの文字列として3つの引数を解析する一般的な方法。参考のために、ここに私のコードは(申し訳ありませんが、命名は質問から少し異なっている)

Public Function CONCATIF(checkRange As Range, testFunction As Boolean, Optional concatRange As Range) As Variant 

Dim concatArray() As Variant 
Dim formulaText As String, formulaParts() As String, formulaTest As String 
Dim topLeft As Range, subCell As Range 
Dim newTest As String 
Dim results() As Boolean, result As Boolean 
Dim loopval As Long 
''' 
'input checking 
''' 
If concatRange Is Nothing Then 
    concatArray = checkRange 
ElseIf Not (checkRange.Cells.Count = concatRange.Cells.Count And checkRange.Rows.Count = concatRange.Rows.Count And checkRange.Rows.Count = 1) Then 
    CONCATIF = CVErr(xlErrValue) 
    Exit Function 
Else 
    concatArray = concatRange.Value2 
End If 
''' 
'Extract test function 
''' 
formulaText = Application.Caller.Formula 
formulaParts = Split(formulaText, ",") 'Assumes 1)no commas 2) formula isn't nested 3) formula doesn't contain nested functions 
formulaTest = formulaParts(1) 'get the test function as a string to be evaluated 
Set topLeft = checkRange.Cells(1, 1) 'This is the 'reference' cell - substitute each of the values in the check range for this to test each one 
ReDim results(0) 
On Error GoTo Err 
''' 
'Run test on each of the cells in checkRange 
''' 
For Each subCell In checkRange 
    newTest = Replace(formulaTest, topLeft.Address(0, 0), subCell.Address) 
    If Count(newTest, "(") < Count(newTest, ")") Then 'when optional parameter is missed out, sometimes you get a ,) and sometimes a) after formulaTest, so we must check 
     newTest = Left(newTest, Len(newTest) - 1) 
    End If 
    result = (Evaluate(newTest)) 
skip: 
    results(UBound(results)) = result 
    ReDim Preserve results(UBound(results) + 1) 
Next subCell 
''' 
'Then use array of Booleans for UDF function 
''' 
CONCATIF = "test" 
Exit Function 

Err: 
result = False 'if the evaluate results in an error, it means the input was invalid, so probably won't meet the criteria, therefore can be ignored 
loopval = loopval + 1 
If loopval > checkRange.Cells.Count Then CONCATIF = CVErr(xlErrNA): Exit Function 'exit error loop gracefully if I've missed some edge case 
Resume skip 

End Function 

そして、私のUDFで参照ですこれです:あなたは適切な式パーサーを持っていた場合

Function Count(str As String, chr As String) As Long 'counts the number of instances of a character in a string 
    Count = Len(str) - Len(Replace(str, chr, "")) 
End Function 
+1

を開始することは常に良い習慣です。それが必要ではない場合でも、あなたの質問をできる限り最善にする努力をしていることを示しています。 – Luuklag

+0

あなたのコードを投稿してください。 – User632716

+0

@tomprestonが投稿しましたが、私はすでに質問していたすべてのことを説明してくれたので、どれくらい助けてくれるのかわかりません! – Greedo

答えて

0

あなたが解決することができCONCATIFへの複数の呼び出しを1つの式で処理することを除いて、これらの問題のすべて:CONCATIFのインスタンスが現在呼び出されている100%を見つける方法はわかりません。

様々な式パーサはあなたの周りにありますが、多分適応することができます:あなたのコードを含む、ここに http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html

関連する問題