2013-03-28 7 views
5

जब मैं एक्सेल से समारोह (एक सेल में) कहते हैं:कोड से कॉल किए जाने पर मेरी स्प्रेडशीट फ़ंक्शन अलग-अलग क्यों व्यवहार करती है?

=allVlookup(O24,A:D,3,"") 

VBA

MsgBox allVlookup(Range("O24"), Range("A:D"), 3, "") 

मैं अलग परिणाम प्राप्त के माध्यम से बनाम। एक्सेल से बुलाए जाने पर, मुझे केवल पहला मैच मिलता है, लेकिन जब समान पैरामीटर के साथ वीबीए टेस्ट सब से कॉल किया जाता है (उप-चलाने की अनुमति देने के लिए Range को तर्कों को छोड़कर), मुझे पूर्ण परिणाम मिलते हैं (जो एक से अधिक है) ।

समारोह मैं उपयोग कर रहा हूँ है:

Public Function allVlookup(lookupRange As Range, tableRange As Range, colIndex As Integer, Optional delimiter As String = "") As String 

    Dim c As Range 
    Dim firstAddress As String 
    'MsgBox tableRange.Address ' this is correct 
    'With Sheets(4).Range("A1:C12").Columns(1) 
    'With Range("A1:C12").Columns(1) 

    'this doesn't allow things to work right either (???) 
    'Set tableRange = Range("A:D") 
    'Set lookupRange = Range("O24") 

    'search only the first column for matches 
    With tableRange.Columns(1) 
     Set c = .Find(what:=lookupRange.Value, LookIn:=xlValues) 

     If Not c Is Nothing Then 

      firstAddress = c.Address 

      Do 
       'add the delimiter 
       If (allVlookup <> "") Then 
        allVlookup = allVlookup + delimiter 
       End If 

       'append value to previous value 
       allVlookup = allVlookup + c.Offset(0, colIndex).Value 


       Set c = .FindNext(c) 
       'exit conditions 
       'no match found 
       If (c Is Nothing) Then 
        Exit Do 
        'we're back to start 
       ElseIf (c.Address = firstAddress) Then 
        Exit Do 
       End If 

      Loop 
     End If 
    End With 

End Function 

मैं एक नुकसान में हूँ समझाने के लिए क्यों यह हो रहा है।

आउटपुट को समान होने के लिए मैं क्या कर सकता हूं?

उत्तर

2

कारण यह केवल पहला मैच देता है क्योंकि एक बग की वजह से है। कृपया नीचे link (सेक्शन 5) देखें।

मैंने इसे पहले से ही एक बग के रूप में दायर किया है। यदि आप उपर्युक्त लिंक पढ़ते हैं तो मैंने एक वैकल्पिक कोड भी सुझाया है। उस लिंक मामले में कड़ी कभी मर जाता है से

निकालें (जो ऐसा नहीं होना चाहिए)

.FindNext एक उपयोगकर्ता निर्धारित समारोह में काम नहीं करता अपेक्षा के अनुरूप। आप इसे सामान्य कार्य में उपयोग कर सकते हैं।

कहो चलें हम पत्रक 1 में इस डेटा है: अगर हम एक मॉड्यूल में नीचे दिए गए कोड पेस्ट करें और इसे फिर से चलाने के रूप में हम अपेक्षित परिणाम मिल जाएगा

A1 → Colt 
A2 → Holt 
A3 → Dolt 
A4 → Hello 

और

में
B1 → olt 

अब $A$1:$A$3

Sub Test() 
    Sample Sheets("Sheet1").Range("B1"), Sheets("Sheet1").Range("A1:A4") 
End Sub 

Sub Sample(FirstRange As Range, ListRange As Range) 
    Dim aCell As Range, bCell As Range, oRange As Range 
    Dim ExitLoop As Boolean 
    Set oRange = ListRange.Find(what:=FirstRange.Value, LookIn:=xlValues, _ 
    lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
    MatchCase:=False, SearchFormat:=False) 
    ExitLoop = False 
    If Not oRange Is Nothing Then 
     Set bCell = oRange: Set aCell = oRange 

     Do While ExitLoop = False 
      Set oRange = ListRange.FindNext(After:=oRange) 

      If Not oRange Is Nothing Then 
       If oRange.Address = bCell.Address Then Exit Do 
       Set aCell = Union(aCell, oRange) 
      Else 
       ExitLoop = True 
      End If 
     Loop 
     MsgBox aCell.Address 
    Else 
     MsgBox "Not Found" 
    End If 
End Sub 

लेकिन यह के रूप में यदि आप इस समारोह पेस्ट उम्मीद कार्य नहीं करेगा एक मॉड्यूल में और =FindRange(A1,A1:A5)

कोड केवल आप पाया मूल्य के 1 उदाहरण दे देंगे (सेल C1 में कहते हैं) के रूप में किसी कार्यपत्रक से इसे कहते हैं और बाकी

और इसलिए नतीजा यह है कि आप मिल जाएगा पर ध्यान न दें $ ए $ 2 है !!!

Function FindRange(FirstRange As Range, ListRange As Range) As String 
    Dim aCell As Range, bCell As Range, oRange As Range 
    Dim ExitLoop As Boolean 
    Set oRange = ListRange.Find(what:=FirstRange.Value, LookIn:=xlValues, _ 
    lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
    MatchCase:=False, SearchFormat:=False) 
    ExitLoop = False 
    If Not oRange Is Nothing Then 
     Set bCell = oRange: Set aCell = oRange 

     Do While ExitLoop = False 
      Set oRange = ListRange.FindNext(After:=oRange) 

      If Not oRange Is Nothing Then 
       If oRange.Address = bCell.Address Then Exit Do 
       Set aCell = Union(aCell, oRange) 
      Else 
       ExitLoop = True 
      End If 
     Loop 
     FindRange = aCell.Address 
    Else 
     FindRange = "Not Found" 
    End If 
End Function 

हमें इसे एक अलग कोण से संपर्क करने की आवश्यकता है।

का उपयोग करने के बजाय हम इसका उपयोग करते हैं। फिर से वांछित परिणाम प्राप्त करने तक (फिर से $ 1: $ ए $ 3) प्राप्त करें। नीचे दिए गए कोड को देखें:

Function FindRange(FirstRange As Range, ListRange As Range) As String 
    Dim aCell As Range, bCell As Range, oRange As Range 
    Dim ExitLoop As Boolean 
    Set oRange = ListRange.Find(what:=FirstRange.Value, LookIn:=xlValues, _ 
    lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
    MatchCase:=False, SearchFormat:=False) 
    ExitLoop = False 
    If Not oRange Is Nothing Then 
     Set bCell = oRange: Set aCell = oRange 

     Do While ExitLoop = False 
      Set oRange = ListRange.Find(what:=FirstRange.Value, After:=oRange, LookIn:=xlValues, _ 
      lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
      MatchCase:=False, SearchFormat:=False) 
      If Not oRange Is Nothing Then 
       If oRange.Address = bCell.Address Then Exit Do 
       Set aCell = Union(aCell, oRange) 
      Else 
       ExitLoop = True 
      End If 
     Loop 
     FindRange = aCell.Address 
    Else 
     FindRange = "Not Found" 
    End If 
End Function 
+0

से नहीं कहा जा सकता है, मैं इसे एक बग के साथ रह सकता हूं। परेशान, लेकिन, जानना अच्छा है। – enderland

2

कृपया तर्क के लिए न करें, लेकिन यहां समाधान है जो मुझे एक ही परिणाम देता है। में .Find लाइन बदलें:

Set c = .Find(what:=lookupRange.Value2, after:=.Cells(1), LookIn:=xlValues, LookAt:=xlWhole) 

और इसके अलावा में .FindNext बदलने के लिए:

Set c = .Find(what:=lookupRange.Value2, after:=c, LookIn:=xlValues, LookAt:=xlWhole) 

दलीलों को ध्यान में भी रखें कि tableRange सीमा स्तंभ खिताब होना चाहिए। यदि नहीं, तो परिणाम ऑर्डर पहली नजर में अपेक्षित नहीं होगा।

अंतिम वाक्य के लिए अतिरिक्त (संपादित) स्पष्टीकरण।

| A | B | C | D | 
    --+-----+-----+-----+-----+ 
    1 | ABC 1  2  A 
    2 | ABC 3  4  B 
    3 | ABC 5  6  C 

जब range("A1:D3") में एबीसी की खोज स्तंभ डी आप परिणाम के रूप में मिलेगा से डेटा प्राप्त करने: BCD आप उस प्रकार के टेबल है। ABC प्राप्त करने के लिए पहली पंक्ति में कॉलम शीर्षक होना चाहिए।

+0

यह अच्छी तरह से काम करता प्रतीत होता है - क्या आपके पास सुझाव है कि 'tableRange' के शीर्षक नहीं हैं? – enderland

+0

इसके अलावा, यह क्या है जो इस काम को बनाता है (और मेरे उपयोग का काम नहीं करता है)? शायद। FindNext को UDF – enderland

संबंधित मुद्दे

 संबंधित मुद्दे