VBA查找近似值

时间:2015-05-09 09:35:43

标签: vba match conditional-statements criteria vlookup

我想执行一个特殊的VLookup,其中找到的值将匹配两个条件:

  1. 发票号必须相同
  2. 从G列中找到的值必须在公差-100到100
  3. 范围内

    准确地说,如果从G栏找到的第一个值(例如-18,007)用于发票编号' 12345678'与第二个标准不匹配(例如-18,007 + 10,000 = -8,007),-8,007超出公差范围,因此请找到' 12345678'的下一个值,直到它符合第二个标准。 这可能吗?

    Vlookup

    以下是我的剧本:

    Sub MyVlookup()
    
        Dim lastrow As Long
        lastrow = Sheets("Sheet1").Range("B" & Rows.Count).End(xlUp).Row
        Set myrange = Range("D:G")
    
        For i = 2 To lastrow
    
            Cells(i, 10) = Application.WorksheetFunction.VLookup(Cells(i, 2), myrange, 4, False)
    
            'This following line is to test the value found is within the tolerance -100 to 100
            If (Cells(i, 10) + Cells(i, 1)) >= 100 Or (Cells(i, 10) + Cells(i, 1)) <= -100 Then
    
                Cells(i, 10).Value = "False" '<----I want to change this line to Lookup the next invoice number in Column D of table2
    
            Else: Cells(i, 10) = Application.WorksheetFunction.VLookup(Cells(i, 2), myrange, 4, False)
    
            End If
    
        Next i
    
    End Sub
    

    修改

    我想要的最终输出: Output

    以下是使用我的修正案的脚本,但需要进行检查:

    Sub MyVlookup2()
    
        Dim myrange As Range
        Dim i As Long, j As Long
        Dim lastrow As Long
        Dim lastrow2 As Long  
        Dim diff As Double
        Const tolerance As Long = 100
        Set myrange = Range("D:G")
        lastrow = Sheets("Sheet1").Range("B" & Rows.Count).End(xlUp).Row
        lastrow2 = Sheets("Sheet1").Range("D" & Rows.Count).End(xlUp).Row
    
        For i = 2 To lastrow
        For j = 2 To lastrow2
             If Cells(i, 2).Value = Cells(j, 4).Value Then
                diff = Cells(i, 1).Value + Cells(j, 7).Value
                   If diff <= tolerance And diff >= -tolerance Then
                      Cells(i, 9).Value = Cells(j, 4).Value
                      Cells(i, 10).Value = Cells(j, 5).Value
                      Cells(i, 11).Value = Cells(j, 6).Value
                      Cells(i, 12).Value = Cells(j, 7).Value
                   Exit For
                End If
             End If
          If j = lastrow2 Then Cells(i, 10).Value = False
        Next j
        Next i
    
     End Sub
    

2 个答案:

答案 0 :(得分:1)

这应该有用(我决定不使用worksheetfunction.vlookup):

Sub MyVlookup2()

Dim myrange As Range
Dim i As Long, j As Long
Dim lastrow As Long
Dim lastrow2 As Long
Dim diff As Double
Const tolerance As Long = 100
Set myrange = Range("D:G")
lastrow = Sheets("Sheet1").Range("B" & Rows.Count).End(xlUp).Row
lastrow2 = Sheets("Sheet1").Range("D" & Rows.Count).End(xlUp).Row

For i = 2 To lastrow
    For j = 2 To lastrow2
        If Cells(i, 2).Value = Cells(j, 4).Value Then
            diff = Cells(i, 1).Value + Cells(j, 7).Value
            If diff <= tolerance And diff >= -tolerance Then
                Cells(i, 10).Value = Cells(j, 7).Value
                Exit For
            End If
        End If
        If j = lastrow2 Then Cells(i, 10).Value = False
    Next j
Next i

End Sub

关于Option Explicit,您应该检查工具&gt;中的复选标记。 选项... ,再也不用担心了。该行将始终自动包含在每个新模块中。 enter image description here

修改

由于您更新了问题,因此如果您不更改第If j = lastrow2 Then Cells(i, 10).Value = False行,则您将找到无法找到匹配项的空白值:

enter image description here

答案 1 :(得分:1)

试试这个通用的 Alookup 代码:



Sub RegisterUDF()
Dim s As String
s = "Approximate lookup similar strings on best consecutive character match basis" & Chr(lO) & vbLf _
& "Lookup_Value = What string to lookup" & Chr(lO) & "Tbl_array = Range to find String"
Application.MacroOptions Macro:="Alookup", Description:=s, Category:=9
End Sub


Sub UnregisterUDF()
Application-MacroOptions Macro:="Alookup", Description:=Empty, Category:=Empty
End Sub


            Function Alookup(Lookup_Value As String, Tbl_Array As Range, Optional col As Integer, Optional MinCharMatch1 As Integer) As String
            'Lookup_Value = What we are searching for
            'Tbl_Array = Range in which Lookup_Value will be searched in. Ideally should be single column
            'Col = Value to the left (negative number) or right (positive number) of the Tbl_Array which would be the answer to the function. Used as offset to Lookup_Value's range in Tbl_Array. _
                   If ommitted, the best match in Tbl_Array is populated as the answer to the function
            'MinCharMatch1 = Least number of characters that should match. If ommitted, defaulted to 6
            
            Dim i As Integer, Str As String, Value As String
            Dim a As Integer, b As Integer, cell As Range
            Dim mincharmatch As Integer
            Dim rng As Range
            
            Lookup_Valuel = UCase(Replace(Lookup_Value, " ", ""))
            Lookup_Valuel = UCase(Replace(Lookup_Valuel, "-", ""))
            Lookup_Valuel = UCase(Replace(Lookup_Valuel, ":", ""))
            Lookup_Valuel = UCase(Replace(Lookup_Valuel, "/", ""))
            Lookup_Valuel = UCase(Replace(Lookup_Valuel, ",", ""))
            
            
            If MinCharMatch1 = 0 Then
            MinCharMatch1 = 6
            End If
            

                For Each cell In Tbl_Array
                cell1 = UCase(Replace(cell, " ", ""))
                cell1 = UCase(Replace(cell1, "-", ""))
                cell1 = UCase(Replace(cell1, ":", ""))
                cell1 = UCase(Replace(cell1, "/", ""))
                cell1 = UCase(Replace(cell1, ",", ""))
    
    
    
    'Check lower len in higer len
    
        If Len(cell1) < Len(Lookup_Valuel) Then
        
        mincharmatch = WorksheetFunction.Min(Len(cell1), MinCharMatch1)
          
                For j = Len(cell1) To mincharmatch Step -1
                    If InStr(Lookup_Valuel, Left(cell1, j)) > 0 Or InStr(Lookup_Valuel, Right(cell1, j)) > 0 Then
                        If Found <> "" Then
                            If j > CInt(Mid(Found, WorksheetFunction.Search("|", Found) + 1, 99)) Then
                            Found = cell.Value2 & "|" & j
                            Set rng = cell
                            End If
                        Else
                            Found = cell.Value2 & "|" & j
                            Set rng = cell
                            
                        End If
                    GoTo nextcell
                    End If
                Next j

        
        Else

         mincharmatch = WorksheetFunction.Min(Len(Lookup_Valuel), Len(cell1), MinCharMatch1)

           
                        For j = Len(Lookup_Valuel) To mincharmatch Step -1
                            If InStr(cell1, Left(Lookup_Valuel, j)) > 0 Or InStr(cell1, Right(Lookup_Valuel, j)) > 0 Then
                            
                                If Found <> "" Then
                                    If j > CInt(Mid(Found, WorksheetFunction.Search("|", Found) + 1, 99)) Then
                                    Found = cell.Value2 & "|" & j
                                    Set rng = cell
                                    End If
                                Else
                    
                                Found = cell.Value2 & "|" & j
                                Set rng = cell
                                End If
                            GoTo nextcell
                            End If
                        Next j


        End If
nextcell:
            
            Next cell
        
                    
        
            If Found <> "" Then
                If col > 0 Then
                Alookup = rng.Offset(0, col - 1).Value2
                ElseIf col < 0 Then
                Alookup = rng.Offset(0, col + 1).Value2
                Else
                Alookup = Left(Found, WorksheetFunction.Find("|", Found) - 1)
                End If
                ' Debug-Print Found
            Else
               
                Alookup = "No Match Found"
                
            End If
            
            
            
        End Function