TOP

Ricerca fuzzy per LibreOffice Calc

FUZZYLOOKUP() Descrizione

Conosciamo tutti la famosa funzione VLOOKUP() che ci aiuta a combinare i dati di tabelle diverse. Tuttavia, questa funzione presenta uno svantaggio significativo: non può combinare valori simili, ovvero se c'è un errore nella parola, non ci sarà alcuna corrispondenza.

Per poter combinare valori approssimativi, possiamo creare la nostra funzione. Chiamiamolo FuzzyLookup().

Immaginiamo di avere due elenchi. Entrambi hanno approssimativamente gli stessi elementi, ma possono essere scritti in modo leggermente diverso. Il compito è trovare per ciascun elemento del primo elenco l'elemento più simile del secondo elenco, ovvero implementare una ricerca per il testo massimamente simile più vicino.

La grande domanda, in questo caso, è cosa considerare come criterio di “somiglianza”. Solo il numero di caratteri corrispondenti? Il numero di partite consecutive? È opportuno considerare maiuscole e minuscole o gli spazi? Cosa fare con la diversa disposizione delle parole in una frase? Ci sono molte opzioni e non esiste un'unica soluzione: per ogni situazione l'una o l'altra sarà migliore dell'altra.

Nel nostro caso, implementiamo l'opzione più semplice: ricerca in base al numero massimo di corrispondenze di caratteri. Non è perfetto, ma funziona abbastanza bene per la maggior parte delle situazioni.


Codice BASIC per la funzione FuzzyLookup

Per aggiungere la funzione FuzzyLookup, apri il menu Tools - Macros - Edit Macros..., seleziona Module1 e copia il seguente testo nel modulo:


Function FuzzyLOOKUP(LookupValue As String, SrcTable As Variant, Optional SimThreshold As Single) As String 
  'moonexcel.com.ua
  Dim Str       As String  
  Dim CellArray As Variant
  Dim StrArray  As Variant
  
  If IsMissing(SimThreshold) Then SimThreshold  = 0
  
  Str      = LCase(LookupValue)
  StrArray = Split(Str)
  StrExt   = UBound(StrArray)  
            
  For Each Cell In SrcTable
                          
    CellArray = Split(LCase(Cell))
    CellExt   = UBound(CellArray)    	    
    CellRate  = 0
	
    'Controlliamo ogni parola nella frase di ricerca
    For x = 0 To StrExt 
    
      StrWord = StrArray(x)	  
      If Len(StrWord) = 0 Then GoTo continue_x
	  MaxStrWordRate = 0
	  
      'Controlliamo ogni parola nella cella successiva dalla tabella dei valori originale
      For i = 0 To CellExt
        
        CellWord = CellArray(i)
		If Len(CellWord) = 0 Then GoTo continue_i
   
        FindCharNum = OccurrenceNum(StrWord, CellWord)
        StrWordRate = FindCharNum / Max(Len(StrWord),Len(CellWord))
		
        If StrWordRate > MaxStrWordRate Then MaxStrWordRate = StrWordRate
		continue_i:
      Next i		    
		    		    
      CellRate = CellRate + MaxStrWordRate
	  continue_x:
    Next x               
        
    'Manteniamo la migliore corrispondenza
    If CellRate > MaxCellRate Then    
      MaxCellRate = CellRate
      BestCell    = Cell          
       
      FindCharNum = OccurrenceNum(Str, Cell)
      SimRate     = FindCharNum / Max(Len(Str),Len(Cell))
    End If       
        
  Next Cell
    
  IF SimRate >= SimThreshold Then 
    IF SimThreshold = -1 Then
      ReturnValue = BestCell + " (" + Format(SimRate, "0.00") + ")"
    ElseIf SimThreshold = -2 Then
      ReturnValue = Format(SimRate, "0.00")
    Else
      ReturnValue = BestCell
    End If
  Else 
    ReturnValue = ""
  End If    
  
  FuzzyLOOKUP = ReturnValue
End Function


Function OccurrenceNum(ByVal SourceString As String, ByVal TargetString As String)
  For i = 1 To Len(SourceString)	         		        	        
    'Stiamo cercando l'occorrenza di ciascun simbolo
    Position = InStr(1, TargetString, Mid(SourceString, i, 1), 1)  
    'Aumentiamo il contatore delle coincidenze
    If Position > 0 Then		  
      Count = Count + 1
      'Rimuovi il simbolo trovato
      TargetString = Left(TargetString, Position - 1) + Right(TargetString, Len(TargetString) - Position)   
    End If
  Next i    
  OccurrenceNum = Count
End Function


Function Max(ByVal value1 As Variant, ByVal value2 As Variant)  
  If value1 > value2 Then
	Result = value1
  Else
	Result = value2
  End If
  Max = Result
End Function

Successivamente, chiudi Macro Editor e torna al foglio di lavoro LibreOffice Calc: ora puoi utilizzare la nostra nuova funzione FuzzyLookup().