2012-06-15 18:29:24 +0000 2012-06-15 18:29:24 +0000
14
14
Advertisement

Confronto di stringhe di testo simili in Excel

Advertisement

Attualmente sto cercando di riconciliare i campi “Nome” da due fonti di dati separate. Ho un certo numero di nomi che non hanno una corrispondenza esatta ma sono abbastanza vicini da essere considerati abbinati (esempi qui sotto). Avete qualche idea su come posso migliorare il numero di corrispondenze automatiche? Sto già eliminando le iniziali di mezzo dai criteri di corrispondenza.

=IFERROR(IF(LEFT(SYSTEM A,IF(ISERROR(SEARCH(" ",SYSTEM A)),LEN(SYSTEM A),SEARCH(" ",SYSTEM A)-1))=LEFT(SYSTEM B,IF(ISERROR(SEARCH(" ",SYSTEM B)),LEN(SYSTEM B),SEARCH(" ",SYSTEM B)-1)),"",IF(LEFT(SYSTEM A,FIND(",",SYSTEM A))=LEFT(SYSTEM B,FIND(",",SYSTEM B)),"Last Name Match","RESEARCH")),"RESEARCH")

Formula di corrispondenza attuale:

Advertisement
Advertisement

Risposte (7)

12
12
12
2012-06-15 18:51:25 +0000

Potreste considerare di usare il Microsoft Fuzzy Lookup Addin .

Dal sito MS:

Panoramica

Il Fuzzy Lookup Add-In per Excel è stato sviluppato da Microsoft Research ed esegue la corrispondenza fuzzy di dati testuali in Microsoft Excel. Può essere usato per identificare righe duplicate all'interno di una singola tabella o per unire righe simili tra due tabelle diverse. L'abbinamento è robusto per un'ampia varietà di errori tra cui errori di ortografia, abbreviazioni, sinonimi e dati aggiunti o mancanti. Per esempio, potrebbe rilevare che le righe “Mr. Andrew Hill”, “Hill, Andrew R.” e “Andy Hill” si riferiscono tutte alla stessa entità sottostante, restituendo un punteggio di somiglianza con ogni corrispondenza. Mentre la configurazione predefinita funziona bene per un'ampia varietà di dati testuali, come i nomi dei prodotti o gli indirizzi dei clienti, la corrispondenza può anche essere personalizzata per specifici domini o lingue.

6
6
6
2012-06-15 19:47:53 +0000

Io cercherei di usare questa lista (solo la sezione inglese) per aiutare ad eliminare le abbreviazioni comuni.

Inoltre, potresti considerare di usare una funzione che ti dirà, in termini esatti, quanto sono “vicine” due stringhe. Il seguente codice proviene da here e grazie a smirkingman .

Option Explicit
Public Function Levenshtein(s1 As String, s2 As String)

Dim i As Integer
Dim j As Integer
Dim l1 As Integer
Dim l2 As Integer
Dim d() As Integer
Dim min1 As Integer
Dim min2 As Integer

l1 = Len(s1)
l2 = Len(s2)
ReDim d(l1, l2)
For i = 0 To l1
    d(i, 0) = i
Next
For j = 0 To l2
    d(0, j) = j
Next
For i = 1 To l1
    For j = 1 To l2
        If Mid(s1, i, 1) = Mid(s2, j, 1) Then
            d(i, j) = d(i - 1, j - 1)
        Else
            min1 = d(i - 1, j) + 1
            min2 = d(i, j - 1) + 1
            If min2 < min1 Then
                min1 = min2
            End If
            min2 = d(i - 1, j - 1) + 1
            If min2 < min1 Then
                min1 = min2
            End If
            d(i, j) = min1
        End If
    Next
Next
Levenshtein = d(l1, l2)
End Function

Quello che farà è dirvi quante inserzioni e cancellazioni si devono fare a una stringa per arrivare all'altra. Cercherei di mantenere questo numero basso (e i cognomi dovrebbero essere esatti).

5
Advertisement
5
5
2015-10-09 14:26:12 +0000
Advertisement

Ho una formula (lunga) che puoi usare. Non è così ben affinata come quelle sopra - e funziona solo per il cognome, piuttosto che per il nome completo - ma potreste trovarla utile.

Quindi se avete una riga di intestazione e volete confrontare A2 con B2, mettete questo in qualsiasi altra cella di quella riga (per esempio, C2) e copiate fino alla fine.

=IF(A2=B2, “ESATTO”,IF(SUBSTITUTE(A2,“-”,“ ”)=SUBSTITUTE(B2,“-”,“ ”), “Trattino”,IF(LEN(A2)>LEN(B2),IF(LEN(A2)>LEN(SUBSTITUTE(A2,B2,“”), “Stringa intera”,IF(MID(A2,1, 1)=MID(B2,1,1),1,0)+IF(MID(A2,2,1)=MID(B2,2,1),1,0)+IF(MID(A2,3,1)=MID(B2,3,1),1,0)+IF(MID(A2,LEN(A2),1)=MID(B2,LEN(B2),1),1,0)+IF(MID(A2,LEN(A2)-1,1)=MID(B2,LEN(B2)-1,1),1, 0)+IF(MID(A2,LEN(A2)-2,1)=MID(B2,LEN(B2)-2,1),1,0)&“°”),IF(LEN(B2)>LEN(SUBSTITUTE(B2,A2,“”)), “Stringa intera”,IF(MID(A2,1,1)=MID(B2,1,1),1,0)+IF(MID(A2,2,1)=MID(B2,2,1),1, 0)+IF(MID(A2,3,1)=MID(B2,3,1),1,0)+IF(MID(A2,LEN(A2),1)=MID(B2,LEN(B2),1),1,0)+IF(MID(A2,LEN(A2)-1,1)=MID(B2,LEN(B2)-1,1),1,0)+IF(MID(A2,LEN(A2)-2,1)=MID(B2,LEN(B2)-2,1),1,0)&“°”))))

Questo restituirà:

  • EXACT - se è una corrispondenza esatta
  • Hyphen - se è una coppia di nomi a doppia barra ma uno ha un trattino e l'altro uno spazio
  • Whole string - se tutto un cognome è parte dell'altro (ad esempio, se uno Smith è diventato un French-Smith)

Dopo di che vi darà un grado da 0° a 6° a seconda del numero di punti di confronto tra i due. (cioè, 6° si confronta meglio).

Come ho detto è un po’ approssimativo, ma si spera che vi porti all'incirca nel campo giusto.

2
2
2
2016-06-23 06:12:19 +0000

Stavo cercando qualcosa di simile. Ho trovato il codice qui sotto. Spero che questo aiuti il prossimo utente che viene a questa domanda

Restituisce il 91% per Abracadabra / Abrakadabra, il 75% per Hollywood Street/Hollyhood Str, il 62% per Firenze/Francia e 0 per Disneyland

Direi che è abbastanza vicino a quello che volevi :)

Public Function Similarity(ByVal String1 As String, _
    ByVal String2 As String, _
    Optional ByRef RetMatch As String, _
    Optional min_match = 1) As Single
Dim b1() As Byte, b2() As Byte
Dim lngLen1 As Long, lngLen2 As Long
Dim lngResult As Long

If UCase(String1) = UCase(String2) Then
    Similarity = 1
Else:
    lngLen1 = Len(String1)
    lngLen2 = Len(String2)
    If (lngLen1 = 0) Or (lngLen2 = 0) Then
        Similarity = 0
    Else:
        b1() = StrConv(UCase(String1), vbFromUnicode)
        b2() = StrConv(UCase(String2), vbFromUnicode)
        lngResult = Similarity_sub(0, lngLen1 - 1, _
        0, lngLen2 - 1, _
        b1, b2, _
        String1, _
        RetMatch, _
        min_match)
        Erase b1
        Erase b2
        If lngLen1 >= lngLen2 Then
            Similarity = lngResult / lngLen1
        Else
            Similarity = lngResult / lngLen2
        End If
    End If
End If

End Function

Private Function Similarity_sub(ByVal start1 As Long, ByVal end1 As Long, _
                                ByVal start2 As Long, ByVal end2 As Long, _
                                ByRef b1() As Byte, ByRef b2() As Byte, _
                                ByVal FirstString As String, _
                                ByRef RetMatch As String, _
                                ByVal min_match As Long, _
                                Optional recur_level As Integer = 0) As Long
'* CALLED BY: Similarity *(RECURSIVE)

Dim lngCurr1 As Long, lngCurr2 As Long
Dim lngMatchAt1 As Long, lngMatchAt2 As Long
Dim I As Long
Dim lngLongestMatch As Long, lngLocalLongestMatch As Long
Dim strRetMatch1 As String, strRetMatch2 As String

If (start1 > end1) Or (start1 < 0) Or (end1 - start1 + 1 < min_match) _
Or (start2 > end2) Or (start2 < 0) Or (end2 - start2 + 1 < min_match) Then
    Exit Function '(exit if start/end is out of string, or length is too short)
End If

For lngCurr1 = start1 To end1
    For lngCurr2 = start2 To end2
        I = 0
        Do Until b1(lngCurr1 + I) <> b2(lngCurr2 + I)
            I = I + 1
            If I > lngLongestMatch Then
                lngMatchAt1 = lngCurr1
                lngMatchAt2 = lngCurr2
                lngLongestMatch = I
            End If
            If (lngCurr1 + I) > end1 Or (lngCurr2 + I) > end2 Then Exit Do
        Loop
    Next lngCurr2
Next lngCurr1

If lngLongestMatch < min_match Then Exit Function

lngLocalLongestMatch = lngLongestMatch
RetMatch = ""

lngLongestMatch = lngLongestMatch _
+ Similarity_sub(start1, lngMatchAt1 - 1, _
start2, lngMatchAt2 - 1, _
b1, b2, _
FirstString, _
strRetMatch1, _
min_match, _
recur_level + 1)
If strRetMatch1 <> "" Then
    RetMatch = RetMatch & strRetMatch1 & "*"
Else
    RetMatch = RetMatch & IIf(recur_level = 0 _
    And lngLocalLongestMatch > 0 _
    And (lngMatchAt1 > 1 Or lngMatchAt2 > 1) _
    , "*", "")
End If

RetMatch = RetMatch & Mid$(FirstString, lngMatchAt1 + 1, lngLocalLongestMatch)

lngLongestMatch = lngLongestMatch _
+ Similarity_sub(lngMatchAt1 + lngLocalLongestMatch, end1, _
lngMatchAt2 + lngLocalLongestMatch, end2, _
b1, b2, _
FirstString, _
strRetMatch2, _
min_match, _
recur_level + 1)

If strRetMatch2 <> "" Then
    RetMatch = RetMatch & "*" & strRetMatch2
Else
    RetMatch = RetMatch & IIf(recur_level = 0 _
    And lngLocalLongestMatch > 0 _
    And ((lngMatchAt1 + lngLocalLongestMatch < end1) _
    Or (lngMatchAt2 + lngLocalLongestMatch < end2)) _
    , "*", "")
End If

Similarity_sub = lngLongestMatch

End Function
1
Advertisement
1
1
2015-10-30 10:56:53 +0000
Advertisement

Questo codice scansiona la colonna a e la colonna b, se trova qualche somiglianza in entrambe le colonne la mostra in giallo. Potete usare il filtro a colori per ottenere il valore finale. Non ho aggiunto questa parte nel codice.

Sub item_difference()

Range("A1").Select

last_row_all = Range("A65536").End(xlUp).Row
last_row_new = Range("B65536").End(xlUp).Row

Range("A1:B" & last_row_new).Select
With Selection.Interior
    .Pattern = xlSolid
    .PatternColorIndex = xlAutomatic
    .Color = 65535
    .TintAndShade = 0
    .PatternTintAndShade = 0
End With

For i = 1 To last_row_new
For j = 1 To last_row_all

If Range("A" & i).Value = Range("A" & j).Value Then

Range("A" & i & ":B" & i).Select
With Selection.Interior
    .Pattern = xlSolid
    .PatternColorIndex = xlAutomatic
    .ThemeColor = xlThemeColorDark1
    .TintAndShade = 0
  .PatternTintAndShade = 0
End With

End If
Next j
Next i
End Sub
1
1
1
2016-09-14 12:14:05 +0000

Anche se la mia soluzione non permette di identificare stringhe molto diverse, è utile per la corrispondenza parziale (substring match), ad esempio “questa è una stringa” e “una stringa” risulterà come “matching”:

basta aggiungere “*” prima e dopo la stringa da cercare nella tabella.

Solita formula:

  • vlookup(A1,B1:B10,1,0)
  • cerca.vert(A1;B1:B10;1;0)

diventa

  • vlookup(“*” & A1 & “*”,B1:B10;1,0)
  • cerca. vert(“*” & A1 & “*”;B1:B10;1;0)

“&” è la “versione breve” per concatenate()

1
Advertisement
1
1
2015-02-05 02:42:16 +0000
Advertisement

Potete usare la funzione di similarità (pwrSIMILARITY) per confrontare le stringhe e ottenere una percentuale di corrispondenza tra le due. Potete fare attenzione alle maiuscole e alle minuscole oppure no. Dovrete decidere quale percentuale di corrispondenza è “abbastanza vicina” per le vostre esigenze.

C'è una pagina di riferimento a http://officepowerups.com/help-support/excel-function-reference/excel-text-analyzer/pwrsimilarity/ .

Ma funziona abbastanza bene per confrontare il testo nella colonna A con la colonna B.

Advertisement

Domande correlate

6
13
9
10
9
Advertisement
Advertisement