2012-03-11 91 views
0

我有一个单元格范围在Excel中,多列宽和多行长。有些单元格是空白的。我想合并(使用VBA)非空白单元格到列表中,删除重复,并按字母顺序排序。在Excel范围内合并数据,删除空白和重复

例如,给定该输入(其中a破折号表示为这个问题为目的的空单元):

- - A D - 
C - - A - 
- - B - D 
- - - - - 
A - - E - 

以下排序输出产生:

A 
B 
C 
D 
E 

如示例输入显示,范围中的某些行和列可能包含所有空白单元格。

+0

的可能重复(http://stackoverflow.com/questions/5890257/populate-unique-values-in [在从Excel VBA阵列填充唯一值] -to-VBA的阵列从-Excel文件)。这[已经回答](http://stackoverflow.com/a/5896692/119775)。 – 2012-03-12 12:54:40

回答

5

这是一种方法。

CODE(试验和测试)

Option Explicit 

Sub Sample() 
    Dim ws As Worksheet 
    Dim LastRow As Long, lastCol As Long, i as Long 
    Dim Rng As Range, aCell As Range 
    Dim MyCol As New Collection 

    '~~> Change this to the relevant sheet name 
    Set ws = Sheets("Sheet21") 

    With ws 
     LastRow = .Cells.Find(What:="*", After:=.Range("A1"), _ 
     Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _ 
     SearchDirection:=xlPrevious, MatchCase:=False).Row 

     lastCol = .Cells.Find(What:="*", After:=.Range("A1"), _ 
     Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByColumns, _ 
     SearchDirection:=xlPrevious, MatchCase:=False).Column 

     Set Rng = .Range("A1:" & Split(.Cells(, lastCol).Address, "$")(1) & LastRow) 

     'Debug.Print Rng.Address 
     For Each aCell In Rng 
      If Not Len(Trim(aCell.Value)) = 0 Then 
       On Error Resume Next 
       MyCol.Add aCell.Value, """" & aCell.Value & """" 
       On Error GoTo 0 
      End If 
     Next 

     .Cells.ClearContents 

     For i = 1 To MyCol.Count 
      .Range("A" & i).Value = MyCol.Item(i) 
     Next i 

     '~~> OPTIONAL (In Case you want to sort the data) 
     .Columns(1).Sort Key1:=.Range("A1"), Order1:=xlAscending, Header:=xlGuess, _ 
     OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _ 
     DataOption1:=xlSortNormal 
    End With 
End Sub 

快照

enter image description here

随访

我刚刚意识到加入3个线条更使得吨他的代码甚至比上面的代码更快。

Option Explicit 

Sub Sample() 
    Dim ws As Worksheet 
    Dim LastRow As Long, lastCol As Long, i As Long 
    Dim Rng As Range, aCell As Range, delRange As Range '<~~ Added This 
    Dim MyCol As New Collection 

    '~~> Change this to the relevant sheet name 
    Set ws = Sheets("Sheet1") 

    With ws 
     '~~> Get all the blank cells 
     Set delRange = .Cells.SpecialCells(xlCellTypeBlanks) '<~~ Added This 

     '~~> Delete the blank cells 
     If Not delRange Is Nothing Then delRange.Delete '<~~ Added This 

     LastRow = .Cells.Find(What:="*", After:=.Range("A1"), _ 
     Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, _ 
     SearchDirection:=xlPrevious, MatchCase:=False).Row 

     lastCol = .Cells.Find(What:="*", After:=.Range("A1"), _ 
     Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByColumns, _ 
     SearchDirection:=xlPrevious, MatchCase:=False).Column 

     Set Rng = .Range("A1:" & Split(.Cells(, lastCol).Address, "$")(1) & LastRow) 

     'Debug.Print Rng.Address 
     For Each aCell In Rng 
      If Not Len(Trim(aCell.Value)) = 0 Then 
       On Error Resume Next 
       MyCol.Add aCell.Value, """" & aCell.Value & """" 
       On Error GoTo 0 
      End If 
     Next 

     .Cells.ClearContents 

     For i = 1 To MyCol.Count 
      .Range("A" & i).Value = MyCol.Item(i) 
     Next i 

     '~~> OPTIONAL (In Case you want to sort the data) 
     .Columns(1).Sort Key1:=.Range("A1"), Order1:=xlAscending, Header:=xlGuess, _ 
     OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _ 
     DataOption1:=xlSortNormal 
    End With 
End Sub 

HTH

西特

+0

我会说,这是做到这一点的方式。 +1如果需要,您可以在临时工作表上进行排序并重新加载到数组中。 – 2012-03-11 16:18:41

+2

+1好的解决方案。尽管我总是在'SpecialCells'中使用错误测试,但是如果不存在的话。同样,它最好存在测试单元,而不是直接用'FInd'设置行和列。 – brettdj 2012-03-12 02:01:44

+0

用'specialcells'处理错误的好处。我总是包括它。不知道为什么我错过了这里:) – 2012-03-12 08:12:13