私は自分のシートから呼び出す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
を開始することは常に良い習慣です。それが必要ではない場合でも、あなたの質問をできる限り最善にする努力をしていることを示しています。 – Luuklag
あなたのコードを投稿してください。 – User632716
@tomprestonが投稿しましたが、私はすでに質問していたすべてのことを説明してくれたので、どれくらい助けてくれるのかわかりません! – Greedo