Option Explicit
Public Values As Range
Public Bin1 As ListObject, Bin2 As ListObject
Public Sub KutCells(target As Range)
Set Values = target
Set Bin1 = Values.ListObject
Values.Font.Color = vbRed
End Sub
Public Sub MoveCells(target As Range)
Set Bin2 = target.ListObject
Call AddDummy 'see NOTE below
Call PutInOrder(Union(Values, Bin2.DataBodyRange), Bin2)
Call PutInOrder(Bin1.DataBodyRange, Bin1)
Call DeleteDummy
Call CleanUp
End Sub
Function IsTable(rng) As Boolean
Dim t As Boolean, cel As Range
On Error Resume Next
t = True
For Each cel In rng
If cel.ListObject Is Nothing Then t = False
If Not Intersect(cel, cel.ListObject.HeaderRowRange) Is Nothing Then t = False
If Err.Number > 0 Then t = False
Next
IsTable = t
End Function
Public Sub PutInOrder(rng As Range, aBin As ListObject)
Dim cel As Range
Application.ScreenUpdating = False
With aBin
'move everything to first column for sorting
For Each cel In rng
.Range.Offset(.Range.Rows.Count).Resize(1, 1) = cel
cel.ClearContents
Next cel
.Range.Sort key1:=.Range.Cells(1, 1), order1:=xlAscending, Header:=xlYes
.Range.Font.Color = 0
End With
Call ThreeColumns(aBin)
End Sub
Public Sub DeleteEmptyRows(aBin As ListObject)
On Error Resume Next
Dim r As Long
For r = aBin.DataBodyRange.Rows.Count To 1 Step -1
If aBin.DataBodyRange.Cells(r, 1) = "" Then aBin.DataBodyRange.Rows(r).Delete
Next r
End Sub
Public Sub ThreeColumns(aBin As ListObject)
Dim nCount As Long, w As Object, rng As Range, cel As Range
Dim R1 As Long, R2 As Long, R3 As Long
'how many items in each column
Call DeleteEmptyRows(aBin)
nCount = aBin.DataBodyRange.Rows.Count
If nCount >= 6 Then
R1 = CInt(nCount / 3)
R3 = R1 + 1
R2 = nCount - R1 - R3
Set cel = aBin.DataBodyRange.Cells(1, 1)
'move to column 2
Set rng = cel.Offset(R1).Resize(R2)
cel.Offset(, 1).Resize(R2).Value = rng.Value
rng.ClearContents
'move to column 3
Set rng = cel.Offset(R1 + R2).Resize(R3)
cel.Offset(, 2).Resize(R3) = rng.Value
rng.ClearContents
End If
'delete empty rows
Call DeleteEmptyRows(aBin)
End Sub
Sub CleanUp()
Set Values = Nothing
Set Bin1 = Nothing
Set Bin2 = Nothing
End Sub
[COLOR=#ff0000]' NOTE
' code below included to force one additional value into each bin
' .DataBodyRange throws an error if the table is empty
' this lazy workaround avoids that problem[/COLOR]
Public Sub AddDummy()
Bin1.Range.Offset(Bin1.Range.Rows.Count).Resize(1, 1) = "ZZZZZZ"
Bin2.Range.Offset(Bin2.Range.Rows.Count).Resize(1, 1) = "ZZZZZZ"
End Sub
Public Sub DeleteDummy()
Dim cel As Range
For Each cel In Union(Bin1.DataBodyRange, Bin2.DataBodyRange)
If cel = "ZZZZZZ" Then cel.ClearContents
Next cel
End Sub