比较字母数字数据,Excelsorting时忽略连字符

我正在学习Excel VBA编程,目前我正试图解决Excel如何对包含文本的单元格进行sorting的问题。

我在工作簿中有两张纸,每张都有自己的一列电子邮件地址以及其他数据。 我将引用Sheet1中的Column1和Sheet2中的Column2,其中只有列1可能具有重复的电子邮件地址列出。

我需要确定列1中的电子邮件是否在列2中find,并且每次这是真的,必须运行某些代码。

最初,我用两个嵌套的Do While循环解决了这个问题,其中外部循环从上到下遍历Column1中的每个单元,名为Cell1,而内部循环则比较Cell1和Column2中的每个单元,名为Cell2,也是从上到下如果发现相同的值,则尽早退出内部循环。

为了使效率更高,我想按升序对每列进行sorting,并且让每个Cell1只查看Column2,直到Cell2中的string的值大于Cell1中的string的值,并且当下一个Cell1被迭代时它将从最后一个循环停止的Cell2继续,因为较早的Cell2值都小于Cell1,并且不能有相同的值。

我想到的代码是通过Column1中每个单元格的外部循环,以及一个内部循环,如下所示:

'x1 is the row number of Cell1 'x2 is the row number of Cell2 'below is the code for the internal loop looking through Column2 Do While Sheets(2).Cells(x2, 1).Value <> 0 If LCase(Sheets(1).Cells(x1, 1).Value) < LCase(Sheets(2).Cells(x2, 1).Value) Then Exit Do ElseIf LCase(Sheets(1).Cells(x1, 1).Value) = LCase(Sheets(2).Cells(x2, 1).Value) Then '... code is run Exit Do End If x2 = x2 + 1 Loop 

我现在遇到的问题是,电子邮件可以使用连字符( – )和撇号('),而Excelsorting列时忽略它们,VBA在比较字母数字值时不会忽略它们。 如果我有:

  AB 1 Noemi Noemi 2 no-reply no-reply 3 notify notify 

代码将A1与B1进行比较,并看到A1=B1 ,然后A2与B1,看到A2<B1 ,然后跳到A3。

我的第一个问题是,我可以强制Excelsorting包括连字符和撇号在内的字母数字文本吗?

如果没有,到目前为止,我只想通过查看Cell1和Cell2来解决这个问题,不pipe他们是否具有TRUE,然后使用新variables从Cell1和Cell2中提取没有连字符的文本,撇号,并继续在内部循环中使用这些新值。

我的第二个问题是,如果可能,我怎样才能学会以更高效的方式解决这个问题?

让我知道,如果我不清楚,我会重写一些事情,并且我会提供您可能提供的任何帮助。

编辑:

为了进一步说明,Mircosoft本身认识到Excel在sorting时忽略了破折号和撇号:

http://office.microsoft.com/en-001/excel-help/default-sort-orders-HP005199669.aspx http://support.microsoft.com/kb/322067

如果昨天有人问我,我会同意大卫对Excel的预期结果的看法。 不过经过实验,我不得不同意德克。

排序示例

A列包含我用于testingDirk索赔的未分类值。

B列已经进行了常规的Excelsorting。 正如你所看到的,列不是ASCII / Unicode序列,因为“单引号”应该在“连字符”之前出现在“字母a”之前。

Excel使用代字符(〜)作为Find的转义字符,所以我想知道它是否会为Sort执行相同的操作。 AdjustedSort1将“单引号”replace为“单引号”和“连字符”replace为“波浪号连字符”,对“单引号”和“连字符”进行sorting并恢复。 结果显示在C列中。序列更好,但不是ASCII / Unicode,因为“aa-b”在“aa'c”之前。

D列使用了几年前我写的VBA Shell Sort例程。 如果你的列表非常大,你可能会更好地search网页的“VBA快速sorting”,但我的sorting应该给合理大小的列表可接受的性能。

 Sub AdjustedSort1() With Worksheets("Sheet2").Columns("C") .Replace What:="'", Replacement:="~'", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, _ SearchFormat:=False, ReplaceFormat:=False .Replace What:="-", Replacement:="~-", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, _ SearchFormat:=False, ReplaceFormat:=False .Sort Key1:=Range("C2"), Order1:=xlAscending, Header:=xlYes, _ OrderCustom:=1, MatchCase:=False, _ Orientation:=xlTopToBottom, DataOption1:=xlSortNormal .Replace What:="~~-", Replacement:="-", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, _ SearchFormat:=False, ReplaceFormat:=False .Replace What:="~~'", Replacement:="'", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, _ SearchFormat:=False, ReplaceFormat:=False End With End Sub Sub AdjustedSort2() Dim Inx As Long Dim RngValue As Variant Dim RowLast As Long Dim ColValue() As String With Worksheets("Sheet2") RowLast = .Cells(Rows.Count, "D").End(xlUp).Row ' Load values from column D excluding header RngValue = .Range(.Cells(2, "D"), .Cells(RowLast, "D")).Value ' Copy values from 2D array to 1D array ReDim ColValue(LBound(RngValue, 1) To UBound(RngValue, 1)) For Inx = LBound(RngValue, 1) To UBound(RngValue, 1) ColValue(Inx) = RngValue(Inx, 1) Next ' Sort array Call ShellSort(ColValue, UBound(ColValue)) ' Copy values back to 2D array For Inx = LBound(ColValue) To UBound(ColValue) RngValue(Inx, 1) = ColValue(Inx) Next ' Copy values back to column D .Range(.Cells(2, "D"), .Cells(RowLast, "D")).Value = RngValue End With End Sub Public Sub ShellSort(arrstgTgt() As String, inxLastToSort As Integer) ' Coded 2 March 07 ' Algorithm and text from Algorithms (Second edition) by Robert Sedgewick ' The most basic sort is the insertion sort in which adjacent elements are compared ' and swapped as necessary. This can be very slow if the smallest elements are at ' end. ShellSort is a simple extension which gains speed by allowing exchange of ' elements that are far apart. ' The idea is to rearrange the file to give it the property that taking every h-th ' element (starting anywhere) yields a sorted file. Such a file is said to be ' h-sorted. Put another way, an h-sorted file is h independent sorted files, ' interleaved together. By h-sorting for large value of H, we can move elements ' in the array long distances and thus make it easier to h-sort for smaller values of ' h. Using such a procedure for any sequence of values of h which ends in 1 will ' produce a sorted file. ' This program uses the increment sequence: ..., 1093, 364, 121, 40, 13, 4, 1. This ' is known to be a good sequence but cannot be proved to be the best. ' The code looks faulty but it is not. The inner loop compares an ' entry with the previous in the sequence and if necessary moves it back down the ' sequence to its correct position. It does not continue with the rest of the sequence ' giving the impression it only partially sorts a sequence. However, the code is not ' sorting one sequence then the next and so on. It examines the entries in element ' number order. Having compared an entry against the previous in its sequence, it will ' be intH loops before the next entry in the sequence in compared against it. Dim intNumRowsToSort As Integer Dim intLBoundAdjust As Integer Dim intH As Integer Dim inxRowA As Integer Dim inxRowB As Integer Dim inxRowC As Integer Dim stgTemp As String intNumRowsToSort = inxLastToSort - LBound(arrstgTgt) + 1 intLBoundAdjust = LBound(arrstgTgt) - 1 ' Set intH to 1, 4, 13, 40, 121, ..., 3n+1, ... until intH > intNumRowsToSort intH = 1 Do While intH <= intNumRowsToSort intH = 3 * intH + 1 Loop Do While True If intH = 1 Then Exit Do ' The minimum value on entry to this do-loop will be 4 so there is at least ' one repeat of the loop. intH = intH \ 3 For inxRowA = intH + 1 To intNumRowsToSort stgTemp = arrstgTgt(inxRowA + intLBoundAdjust) inxRowB = inxRowA Do While True ' The value of element inxRowA has been saved. Now move the element intH back ' from row inxRowA into this row if it is smaller than the saved value. Repeat ' this for earlier elements until one is found that is larger than the saved ' value which is placed in the gap. inxRowC = inxRowB - intH If arrstgTgt(inxRowC + intLBoundAdjust) <= stgTemp Then Exit Do arrstgTgt(inxRowB + intLBoundAdjust) = arrstgTgt(inxRowC + intLBoundAdjust) inxRowB = inxRowC If inxRowB <= intH Then Exit Do Loop arrstgTgt(inxRowB + intLBoundAdjust) = stgTemp Next Loop End Sub 

将所有的“ – ”replace为“^”,然后Excel不会像“ – ”那样忽略“^”。

然后可以将“^”replace回“ – ”。