Excel将一列按“最大”排序为最小的字符串

时间:2016-08-09 08:43:15

标签: excel vba sorting

我试图通过一个包含大文本长度的列对每个excel文件进​​行排序。这样,使用数据服务作业导入SQL时,数据不会被截断。我意识到Excel读取前8行或16行,并根据它确定字段的长度,我的很多文本被剪切为255个字符。

我尝试将一个文件作为实验,并将列设置为399 varchar,这是其中一个文件中最长字符串的长度。我在DS作业映射中设置的字段大小无关紧要,经历的字符串长度设置字段大小。

我已经创建了一小段VBA来循环遍历每个文件并按最大到最小的文本进行排序,它正在循环并且正在做某事但是没有从最大到最小排序。

不确定它是否是空单元格或导致它的原因,但是我设法为一个文件手动执行此操作 - 从最大到最小排序 - 现在它从不说最大到最小,只有A> Z由于某种原因。

我对代码有一个问题,就像我提到的那样,它没有排序,2)我有一个关于处理多个文件和确定最大字段长度的问题。我不知道DS作业是否会改变字段大小,如果遇到另一个文本长度大于最后一个文件的文件?我用一个文件完成了这个,但这并没有告诉我,唯一的方法是尝试正确排序多个文件,然后针对每个文件运行作业。

这是我正在尝试进行排序的循环。我找到名为“sort Me”的列作为示例,然后对其应用排序。

 For i = 1 To lastcol

        With wb.ActiveSheet
            ColChar = colLtr(i)
            rangestr = ColChar & "1:" & ColChar & "" & MaxRowCount
             If .range(ColChar & 1).Value = "Sort Me" Then
                range(rangestr).Sort key1:=range(rangestr), order1:=xlDescending, Orientation:=xlSortRows, Header:=xlYes
            End If
        End With

    Next i

我有一个从列号创建列字符的函数。我循环遍历每一列,直到我点击我想要的那个然后尝试排序。 rangestr变量是我想要排序的范围。

编辑:为了澄清我希望文本字段在最顶部最长,最短在底部,有空,一些工作表没有文本。像这样:

"This is the longest piece of text to be a top"
"This is shorter piece of text"
"This is even shorter"

主要是至少要首先正确完成排序。寻求如何正确地做到这一点的建议。

非常感谢

安德鲁

2 个答案:

答案 0 :(得分:1)

Excel具有强大的内置排序功能,我最好用它们的实际速度而不是重新发明轮子

如果您需要一个新的(和临时的)字段 - 其中包含文本长度 - 我还会使用“帮助”字段方法和代码,如下所示:

Sub SortIt(dataRng As Range, headerStrng As String)
    Dim f As Range, helpRng As Range
    Dim colsOffset As Long

    With dataRng
        Set f = .Rows(1).Find(what:=headerStrng, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False) '<--| look for wanted header column
        If f Is Nothing Then Exit Sub '<--| if no header found, then no job to do!

        Set helpRng = .Resize(, 1).Offset(, .Parent.UsedRange.Columns(.Parent.UsedRange.Columns.Count).Column - .Columns(1).Column + 1) '<--| set a helper range in first column outside worksheet used range and occupying data range same rows
        With helpRng
            colsOffset = .Column - f.Column + 1 '<--| calculate column offset from "header" column to "helper" range
            .FormulaR1C1 = "=len(RC[-" & colsOffset - 1 & "])" '<--| fill "helper" range with corresponding "header" cells number of characters. they will be eventually cleared
        End With
        .Resize(, helpRng.Column - .Columns(1).Column + 1).Sort key1:=helpRng, order1:=xlDescending, Orientation:=xlSortColumns, Header:=xlYes
        helpRng.Clear '<--| clear the "helper" range
    End With
End Sub

由您的主要子调用如下:

Option Explicit

Sub main()
    Dim dataRng As Range, headerStrng As String

    With Worksheets("SortData") '<--| change "SortData" with your actual sheet name
        Set dataRng = .Range("A1", .Cells(.Rows.Count, "A").End(xlUp)).Resize(, 10) '<--| change "A1", "A" and '10' to reflect, respectively, your  data actual leftupmost cell, "counter" column (i.e. the one that determines its rows span) and columns number
    End With
    headerStrng = "Sort me" '<--| change "Sort me" with your actual header

    SortIt dataRng, headerStrng
End Sub

答案 1 :(得分:0)

基于我找到here的代码片段 我编辑了如下所示的代码,只需传入要排序的范围,如果要按最短长度排序,则将可选参数设置为true

Sub SortByLength(rangeToSort As Range, Optional shortest As Boolean = False)
    Dim x As Long, y As Long, lLastRow As Long
    Dim tempX As String, tempY As String
    Dim tempArray As Variant

    tempArray = rangeToSort
    'Sort array

    For x = 1 To UBound(tempArray)
        For y = x To UBound(tempArray)
            If shortest = True Then
                If Len(tempArray(y, 1)) < Len(tempArray(x, 1)) Then
                    tempX = tempArray(x, 1)
                    tempY = tempArray(y, 1)
                    tempArray(x, 1) = tempY
                    tempArray(y, 1) = tempX
                End If
            Else
                If Len(tempArray(y, 1)) > Len(tempArray(x, 1)) Then
                    tempX = tempArray(x, 1)
                    tempY = tempArray(y, 1)
                    tempArray(x, 1) = tempY
                    tempArray(y, 1) = tempX
                End If
            End If
        Next y
    Next x
    'Output sorted array
    Range(rangeToSort.Item(1), rangeToSort.Item(UBound(tempArray))) = (tempArray)

End Sub