"Meinten Sie ..."-Korrektur durch Zählen von Unterschieden

    • VBA: Excel

    Es gibt 1 Antwort in diesem Thema. Der letzte Beitrag () ist von petaod.

      "Meinten Sie ..."-Korrektur durch Zählen von Unterschieden

      Servus zusammen,
      in vielen Fällen ist es möglich, dass der Nutzer nach einem String gefragt wird und er dabei einen Tippfehler macht. Google fragt einen dann "Meinten Sie ...".
      Ich habe etwas Ähnliches in VBA realisiert.

      Für die Methode wird ein Array namens Dictionary angelegt in das man alle Begriffe hineinschreibt, die als Input erlaubt sind.
      Wenn man die Methode DidYouMeanDictionary aufruft, vergleicht er den der Methode übergebenen String mit jedem einzelnen Eintrag im Array Dictionary und zählt die Unterschiede. Die Methode gibt dann denjenigen Eintrag aus Dictionary zurück, der dem Input am ähnlichsten ist (also am wenigsten Unterschiede aufweist).

      Prinzipiell können beliebige Strings in beliebiger Anzahl mit den üblichen Methoden in das Array Dictionary geladen werden, hier ist (weil ich es in meinem Anwendungsfall so brauche) eine Methode LoadMonthsToDictionary, die die 12 Monate in das Array lädt mit dabei. Am Besten ist es jedoch, wenn der Anwendungsfall bereits auf wenige Begriffe reduziert ist, dann ist die Treffergenauigkeit auch höher.

      Bekannte Issues:
      -Wenn sich der Input und das Vergleichswort in der Länge unterscheiden, kann es unter Umständen zu falschen Angaben in der Statistik kommen, wenn man printStats auf true setzt.

      Hier der Source-Code (Unter Excel 2013 ausführlich getestet):

      Visual Basic-Quellcode

      1. Public Dictionary() As String
      2. Function countDifferences(str1 As String, str2 As String) As Long
      3. 'Counts the differences between str1 and str2 (different chars, removed chars, added chars)
      4. Dim lngC1CharLength As Long
      5. Dim CHARCHANGECOUNT As Long
      6. CHARCHANGECOUNT = 0
      7. For i = 1 To Application.WorksheetFunction.Max(Len(str1), Len(str2))
      8. If Len(str1) < Len(str2) Then
      9. If InStr(1, Mid(str2, i, 1 + Len(str2) - Len(str1)), Mid(str1, i, 1), vbTextCompare) = 0 Then
      10. CHARCHANGECOUNT = CHARCHANGECOUNT + 1
      11. End If
      12. ElseIf Len(str1) > Len(str2) Then
      13. If InStr(1, Mid(str2, Application.WorksheetFunction.Max(1, i - (Len(str1) - Len(str2))), 1 + Len(str1) - Len(str2)), Mid(str1, i, 1), vbTextCompare) = 0 Then
      14. CHARCHANGECOUNT = CHARCHANGECOUNT + 1
      15. End If
      16. Else
      17. If Mid(str1, i, 1) <> Mid(str2, i, 1) Then
      18. CHARCHANGECOUNT = CHARCHANGECOUNT + 1
      19. End If
      20. End If
      21. Next
      22. countDifferences = CHARCHANGECOUNT + Application.WorksheetFunction.Max(Len(str2) - Len(str1), 0)
      23. End Function
      24. Public Sub LoadMonthsToDictionary(Optional BeVerbose As Boolean = False)
      25. 'Loads a sample dictionary consisting of the german names for the months of a year.
      26. Dictionary = Split("Januar, Februar, März, April, Mai, Juni, Juli, August, September, Oktober, November, Dezember", ", ")
      27. If BeVerbose = True Then
      28. Debug.Print "Loaded the following words to the dictionary:"
      29. For Each word In Dictionary
      30. Debug.Print " " & word
      31. Next
      32. End If
      33. End Sub
      34. Public Function DidYouMeanDictionary(text As String, Optional printStats As Boolean = False) As String
      35. 'Compares text with every word in the dictionary using the countDifferences-function and returns the most similar word.
      36. 'This only works properly for single words.
      37. On Error GoTo Fehler
      38. Dim MinDiff, MinDiffIndex
      39. Dim DictString As String, DiffString As String
      40. MinDiff = countDifferences(text, Dictionary(0))
      41. MinDiffIndex = 0
      42. DictString = Dictionary(0) & " "
      43. DiffString = FormatNumber(countDifferences(text, Dictionary(i)), Len(Dictionary(i))) & " "
      44. For i = 1 To UBound(Dictionary)
      45. If MinDiff > countDifferences(text, Dictionary(i)) Then
      46. MinDiff = countDifferences(text, Dictionary(i))
      47. MinDiffIndex = i
      48. End If
      49. DictString = DictString & Dictionary(i) & " "
      50. DiffString = DiffString & FormatNumber(countDifferences(text, Dictionary(i)), Len(Dictionary(i))) & " "
      51. Next i
      52. DidYouMeanDictionary = Dictionary(MinDiffIndex)
      53. If printStats = True Then
      54. Debug.Print ""
      55. Debug.Print "Analysis stats: Differences between " & text & " and ..."
      56. Debug.Print DictString
      57. Debug.Print DiffString
      58. Debug.Print ""
      59. Debug.Print "Chars to be added to get from " & text & " to " & Dictionary(MinDiffIndex) & ": " & Application.WorksheetFunction.Max(Len(Dictionary(MinDiffIndex)) - Len(text), 0)
      60. Debug.Print "Chars to be removed to get from " & text & " to " & Dictionary(MinDiffIndex) & ": " & Application.WorksheetFunction.Max(Len(text) - Len(Dictionary(MinDiffIndex)), 0)
      61. Debug.Print "Chars to be exchanged to get from " & text & " to " & Dictionary(MinDiffIndex) & ": " & Application.WorksheetFunction.Max(MinDiff - Application.WorksheetFunction.Max(Len(text) - Len(Dictionary(MinDiffIndex)), 0) - Application.WorksheetFunction.Max(Len(Dictionary(MinDiffIndex)) - Len(text), 0), 0)
      62. Debug.Print ""
      63. End If
      64. Exit Function
      65. Fehler:
      66. Err.Raise 1234, "CountDifferences", "No Dictionary is specified. Please specify a dictionary by filling the global array 'Dictionary' with values." & vbCrLf & vbCrLf & "Exact error description:" & vbCrLf & Err.Description
      67. End Function
      68. Public Function FormatNumber(num As Double, length As Long) As String
      69. 'Adds zeros in front of the number num sothat it meets the given length.
      70. For i = 1 To length - Len(CStr(num))
      71. FormatNumber = FormatNumber & " "
      72. Next i
      73. FormatNumber = FormatNumber & CStr(num)
      74. End Function


      Viele Grüße,
      vatbub