Option Explicit
Public TargetListBox As MSForms.ListBox
Private SourceListArray() As Variant
Public LatestListArray As Variant
Private i As Long
Private j As Long
Private Sh(1) As Worksheet
Private DimensionNumber As Long
Private Sub Class_Initialize()
DimensionNumber = 1
End Sub
Public Sub InitializeList(ByVal source_list_array As Variant, _
Optional column_number_autofit As Boolean = False, _
Optional column_width_autofit As Boolean = False)
Dim temp As Variant
If IsArray(source_list_array) Then
temp = source_list_array
Else
temp = Array(source_list_array)
End If
TargetListBox.List = temp
temp = WorksheetFunction.Transpose(temp)
If UBound(temp, 2) <> 1 Then
temp = WorksheetFunction.Transpose(temp)
DimensionNumber = 2
End If
ReDim SourceListArray(UBound(temp) - 1, UBound(temp, 2) - 1)
For i = 0 To UBound(SourceListArray)
For j = 0 To UBound(SourceListArray, 2)
SourceListArray(i, j) = temp(i + 1, j + 1)
Next
Next
LatestListArray = SourceListArray
If column_number_autofit Then
TargetListBox.ColumnCount = UBound(LatestListArray, 2) + 1
End If
If column_width_autofit Then
TargetListBox.ColumnWidths = ColumnWidthValue
End If
End Sub
Public Sub UpdateList(ByVal list_array As Variant)
Dim temp As Variant
If IsArray(list_array) Then
temp = list_array
Else
temp = Array(list_array)
End If
TargetListBox.List = temp
LatestListArray = temp
End Sub
Public Sub ResetList()
UpdateList SourceListArray
End Sub
Public Property Get SelectedIndex() As Variant
Dim Dict As Object
Set Dict = CreateObject("Scripting.Dictionary")
For i = 0 To TargetListBox.ListCount - 1
If TargetListBox.Selected(i) Then
Dict(i) = True
End If
Next
SelectedIndex = Dict.keys
End Property
Public Function SelectedCount() As Long
SelectedCount = UBound(SelectedIndex) + 1
End Function
Public Function SelectedValues() As Variant
Dim arr() As Variant
If SelectedCount = 0 Then
arr = Array()
Else
Dim Counter As Long: Counter = 0
Select Case DimensionNumber
Case 1
ReDim arr(SelectedCount - 1)
For i = 0 To TargetListBox.ListCount - 1
If TargetListBox.Selected(i) Then
arr(Counter) = TargetListBox.List(i)
End If
Next
Case 2
ReDim arr(SelectedCount - 1, UBound(LatestListArray, 2))
For i = 0 To TargetListBox.ListCount - 1
If TargetListBox.Selected(i) Then
For j = 0 To UBound(arr, 2)
arr(Counter, j) = TargetListBox.List(i, j)
Next
Counter = Counter + 1
End If
Next
End Select
End If
SelectedValues = arr
End Function
Public Sub SelectAll()
For i = 0 To TargetListBox.ListCount - 1
TargetListBox.Selected(i) = True
Next
End Sub
Public Sub UnselectAll()
For i = 0 To TargetListBox.ListCount - 1
TargetListBox.Selected(i) = False
Next
End Sub
Public Sub ReverseSelection()
For i = 0 To TargetListBox.ListCount - 1
TargetListBox.Selected(i) = Not TargetListBox.Selected(i)
Next
End Sub
Public Function FindAll(faWhat As Variant, _
Optional target_column As Long = -1, _
Optional faLookAt As Excel.XlLookAt = xlPart, _
Optional faMatchCase As Boolean = False, _
Optional faMatchByte As Boolean = False) As Variant
Dim Dict As Object
Set Dict = CreateObject("Scripting.Dictionary")
Dim WhatArray As Variant
If IsArray(faWhat) Then
WhatArray = faWhat
Else
WhatArray = Array(faWhat)
End If
Dim LoopIndex As Variant
Dim temp As String
For Each LoopIndex In WhatArray
If Not faMatchCase Then
LoopIndex = StrConv(LoopIndex, vbUpperCase)
End If
If Not faMatchByte Then
LoopIndex = StrConv(LoopIndex, vbWide)
End If
If faLookAt = xlPart Then
LoopIndex = "*" & LoopIndex & "*"
End If
For j = 0 To UBound(LatestListArray, 2)
If target_column = -1 Or target_column = j Then
For i = 0 To UBound(LatestListArray)
temp = LatestListArray(i, j)
If Not faMatchCase Then
temp = StrConv(temp, vbUpperCase)
End If
If Not faMatchByte Then
temp = StrConv(temp, vbWide)
End If
If temp Like LoopIndex Then
Dict(i) = True
End If
Next
End If
Next
Next
FindAll = Dict.keys
FindAll = SortArray(FindAll)
End Function
Public Sub FindAndSelectAll(faWhat As Variant, _
Optional target_column As Long = -1, _
Optional faLookAt As Excel.XlLookAt = xlPart, _
Optional faMatchCase As Boolean = False, _
Optional faMatchByte As Boolean = False)
Call UnselectAll
Dim arr As Variant
arr = FindAll(faWhat, target_column, faLookAt, faMatchCase, faMatchByte)
TargetListBox.MultiSelect = fmMultiSelectMulti
Dim LoopIndex As Variant
For Each LoopIndex In arr
TargetListBox.Selected(LoopIndex) = True
Next
End Sub
Public Sub FindAndUpdateList(faWhat As Variant, _
Optional target_column As Long = -1, _
Optional faLookAt As Excel.XlLookAt = xlPart, _
Optional faMatchCase As Boolean = False, _
Optional faMatchByte As Boolean = False)
Dim arr As Variant
arr = FindAll(faWhat, target_column, faLookAt, faMatchCase, faMatchByte)
If UBound(arr) = -1 Then Exit Sub
Dim temp() As Variant
ReDim temp(UBound(arr), UBound(SourceListArray, 2))
Dim LoopIndex As Variant
i = 0
For Each LoopIndex In arr
For j = 0 To UBound(temp, 2)
temp(i, j) = LatestListArray(LoopIndex, j)
Next
i = i + 1
Next
LatestListArray = temp
Call UpdateList(LatestListArray)
End Sub
Public Function RegExpAll(raPattern As Variant, _
Optional target_column As Long = -1, _
Optional raIgnoreCase As Boolean = False) As Variant
Dim Dict As Object
Set Dict = CreateObject("Scripting.Dictionary")
Dim myReg As Object
Set myReg = CreateObject("VBScript.RegExp")
myReg.Pattern = raPattern
myReg.IgnoreCase = raIgnoreCase
Dim temp As String
On Error GoTo er:
For j = 0 To UBound(LatestListArray, 2)
If target_column = -1 Or target_column = j Then
For i = 0 To UBound(LatestListArray)
temp = LatestListArray(i, j)
If myReg.Test(temp) Then
Dict(i) = True
End If
Next
End If
Next
RegExpAll = Dict.keys
RegExpAll = SortArray(RegExpAll)
Exit Function
er:
RegExpAll = Array()
End Function
Public Sub RegExpAndSelectAll(raPattern As Variant, _
Optional target_column As Long = -1, _
Optional raIgnoreCase As Boolean = False)
Call UnselectAll
Dim arr As Variant
arr = RegExpAll(raPattern, target_column, raIgnoreCase)
TargetListBox.MultiSelect = fmMultiSelectMulti
Dim LoopIndex As Variant
For Each LoopIndex In arr
TargetListBox.Selected(LoopIndex) = True
Next
End Sub
Public Sub RegExpAndUpdateList(raPattern As Variant, _
Optional target_column As Long = -1, _
Optional raIgnoreCase As Boolean = False)
Dim arr As Variant
arr = RegExpAll(raPattern, target_column, raIgnoreCase)
If UBound(arr) = -1 Then Exit Sub
Dim temp() As Variant
ReDim temp(UBound(arr), UBound(SourceListArray, 2))
Dim LoopIndex As Variant
i = 0
For Each LoopIndex In arr
For j = 0 To UBound(temp, 2)
temp(i, j) = LatestListArray(LoopIndex, j)
Next
i = i + 1
Next
LatestListArray = temp
Call UpdateList(LatestListArray)
End Sub
Private Function SortArray(arr As Variant, _
Optional sort_order As Excel.XlSortOrder = xlAscending) As Variant
Dim aryList As Object
Dim s As Variant
Set aryList = CreateObject("System.Collections.ArrayList")
Dim LoopIndex As Variant
For Each LoopIndex In arr
Call aryList.Add(LoopIndex)
Next
Select Case sort_order
Case xlAscending
Call aryList.Sort
Case xlDescending
Call aryList.Sort
Call aryList.Reverse
End Select
SortArray = aryList.ToArray
End Function
Public Property Get ColumnWidthArray() As Variant
Dim arr() As Variant
ReDim arr(UBound(LatestListArray, 2))
Dim temp As Double
For j = 0 To UBound(LatestListArray, 2)
For i = 0 To UBound(LatestListArray)
temp = LenB(StrConv(LatestListArray(i, j), vbFromUnicode)) * TargetListBox.Font.Size * 0.7
If arr(j) < temp Then
arr(j) = temp
End If
Next
Next
ColumnWidthArray = arr
End Property
Public Property Get ColumnWidthValue() As String
ColumnWidthValue = Join(ColumnWidthArray, ";")
End Property
Public Function Levenshtein(ByVal string1 As String, ByVal string2 As String) As Long
Dim i As Long
Dim j As Long
Dim string1_length As Long
string1_length = Len(string1)
Dim string2_length As Long
string2_length = Len(string2)
Dim distance() As Long
ReDim distance(string1_length, string2_length)
For i = 0 To string1_length
distance(i, 0) = i
Next
For j = 0 To string2_length
distance(0, j) = j
Next
For i = 1 To string1_length
For j = 1 To string2_length
If Asc(Mid$(string1, i, 1)) = Asc(Mid$(string2, j, 1)) Then
distance(i, j) = distance(i - 1, j - 1)
Else
distance(i, j) = Application.WorksheetFunction.Min _
(distance(i - 1, j) + 1, _
distance(i, j - 1) + 1, _
distance(i - 1, j - 1) + 1)
End If
Next
Next
Levenshtein = distance(string1_length, string2_length)
End Function
Public Function MatchRatio(ByVal string1 As String, ByVal string2 As String) As Double
Dim ⊿ As Long
⊿ = Levenshtein(string1, string2)
MatchRatio = (Len(string1) - ⊿) / Len(string1)
End Function
Public Function MatchRatioAll(mrWhat As Variant, _
Optional target_column As Long = -1) As Variant
Dim arr() As Variant
ReDim arr(1 To (UBound(LatestListArray) + 1) * (UBound(LatestListArray, 2) + 1) + 1, _
1 To 5)
arr(1, 1) = "行番号"
arr(1, 2) = "列番号"
arr(1, 3) = "指定文字"
arr(1, 4) = "比較文字"
arr(1, 5) = "一致率%"
Dim temp As String
Dim Counter As Long: Counter = 2
For j = 0 To UBound(LatestListArray, 2)
If target_column = -1 Or target_column = j Then
For i = 0 To UBound(LatestListArray)
temp = LatestListArray(i, j)
arr(Counter, 1) = i
arr(Counter, 2) = j
arr(Counter, 3) = mrWhat
arr(Counter, 4) = temp
arr(Counter, 5) = Format(MatchRatio(CStr(mrWhat), temp) * 100, "0.0")
Counter = Counter + 1
Next
End If
Next
MatchRatioAll = Sort2DArray(arr, xlYes, 5, xlDescending)
End Function
Public Function Sort2DArray(source_array As Variant, _
Optional header As XlYesNoGuess = xlYes, _
Optional target_column_index As Variant = 1, _
Optional sort_order As Excel.XlSortOrder = xlAscending) As Variant
On Error GoTo er:
Application.ScreenUpdating = False
Set Sh(0) = ActiveSheet
If Sh(1) Is Nothing Then
Set Sh(1) = Sheets.Add
Sh(0).Activate
End If
Sh(1).Cells.Clear
Sh(1).Range("A1").Resize(UBound(source_array), UBound(source_array, 2)) = source_array
Dim Tb As ListObject
Set Tb = Sh(1).ListObjects.Add(xlSrcRange, Sh(1).UsedRange, , header)
Dim ColumnIndex As Long
Select Case IsNumeric(target_column_index)
Case True
ColumnIndex = target_column_index
Case Else
On Error Resume Next
ColumnIndex = Tb.ListColumns(target_column_index).Index
If ColumnIndex = 0 Then ColumnIndex = 1
On Error GoTo 0
End Select
If Tb.ListColumns.Count > ColumnIndex Then
ColumnIndex = 1
End If
Tb.Sort.SortFields.Clear
Tb.Sort.SortFields.Add Key:=Cells(1, ColumnIndex), _
Order:=sort_order
With Tb.Sort
.header = header
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Sort2DArray = Tb.Range
Application.ScreenUpdating = True
Exit Function
er:
Sort2DArray = Array()
Application.ScreenUpdating = True
End Function
Private Sub Class_Terminate()
Dim DisplayAlertsState As Boolean
DisplayAlertsState = Application.DisplayAlerts
If Not Sh(1) Is Nothing Then
Application.DisplayAlerts = False
Sh(1).Delete
Application.DisplayAlerts = DisplayAlertsState
End If
End Sub