Создайте строку с запятой - PullRequest
7 голосов
/ 20 января 2012

Я хочу построить строку с разделителями-запятыми из диапазона A1:A400.

Каков наилучший способ сделать это?Должен ли я использовать For цикл?

Ответы [ 3 ]

17 голосов
/ 20 января 2012

Самый ленивый путь это

s = join(Application.WorksheetFunction.Transpose([a1:a400]), ",")

Это работает, потому что свойство .Value многоклеточного диапазона возвращает двумерный массив, а Join ожидает одномерный массив, а Transpose пытается быть слишком полезным, поэтому, когда он обнаруживает двумерный массив только с одним столбцом, он преобразует его в одномерный массив.

В производстве рекомендуется использовать как минимум чуть менее ленивый вариант,

s = join(Application.WorksheetFunction.Transpose(Worksheets(someIndex).Range("A1:A400").Value), ",")

в противном случае активный лист всегда будет использоваться.

4 голосов
/ 21 августа 2012

Я бы расценил ответ @ GSerg как окончательный ответ на ваш вопрос.

Для полноты - и для устранения некоторых ограничений в других ответах - я бы предложил использовать функцию «Объединение», которая поддерживает двухмерные массивы:

s = Join2d(Worksheets(someIndex).Range("A1:A400").Value)

Дело в том, что свойство Value диапазона (при условии, что это не одна ячейка) всегда является двумерным массивом.

Обратите внимание, что разделитель строк в функции Join2d ниже присутствует только в том случае, если есть разделители строк (множественное число): вы не увидите его в объединенной строке из однострочного диапазона.

Join2d: двумерная функция соединения в VBA с оптимизированной обработкой строк

Кодовые примечания:

  1. Эта функция Join не страдает от ограничения в 255 символов, которое влияет на большинство (если не на все) встроенных функций Concatenate в Excel, и приведенный выше пример кода Range.Value передаст данные полностью из ячеек, содержащих более длинные строки.
  2. Это сильно оптимизировано: мы используем конкатенацию строк как можно меньше, так как собственные конкатенации строк VBA медленны и становятся все медленнее, когда конкатенируется более длинная строка.
    Public Function Join2d(ByRef InputArray As Variant, _ 
                           Optional RowDelimiter As String = vbCr, _ 
                           Optional FieldDelimiter = vbTab,_ 
                           Optional SkipBlankRows As Boolean = False) As String

' Join up a 2-dimensional array into a string. Works like VBA.Strings.Join, for a 2-dimensional array.
' Note that the default delimiters are those inserted into the string returned by ADODB.Recordset.GetString
On Error Resume Next

' Coding note: we're not doing any string-handling in VBA.Strings - allocating, deallocating and (especially!) concatenating are SLOW.
' We're using the VBA Join & Split functions ONLY. The VBA Join, Split, & Replace functions are linked directly to fast (by VBA standards)
' functions in the native Windows code. Feel free to optimise further by declaring and using the Kernel string functions if you want to.

' **** THIS CODE IS IN THE PUBLIC DOMAIN ****   Nigel Heffernan   Excellerando.Blogspot.com

Dim i As Long
Dim j As Long
Dim i_lBound As Long
Dim i_uBound As Long
Dim j_lBound As Long
Dim j_uBound As Long
Dim arrTemp1() As String
Dim arrTemp2() As String
Dim strBlankRow As String

i_lBound = LBound(InputArray, 1)
i_uBound = UBound(InputArray, 1)
j_lBound = LBound(InputArray, 2)
j_uBound = UBound(InputArray, 2)

ReDim arrTemp1(i_lBound To i_uBound)
ReDim arrTemp2(j_lBound To j_uBound)

For i = i_lBound To i_uBound

    For j = j_lBound To j_uBound
        arrTemp2(j) = InputArray(i, j)
    Next j
    arrTemp1(i) = Join(arrTemp2, FieldDelimiter)
Next i

If SkipBlankRows Then
    If Len(FieldDelimiter) = 1 Then
        strBlankRow = String(j_uBound - j_lBound, FieldDelimiter)
    Else
        For j = j_lBound To j_uBound
            strBlankRow = strBlankRow & FieldDelimiter
        Next j
    End If

    Join2d = Replace(Join(arrTemp1, RowDelimiter), strBlankRow & RowDelimiter, "")
    i = Len(strBlankRow & RowDelimiter)

    If Left(Join2d, i) = strBlankRow & RowDelimiter Then
        Mid$(Join2d, 1, i) = ""
    End If 
Else
    Join2d = Join(arrTemp1, RowDelimiter)
End If
Erase arrTemp1
End Function

Для полноты вот соответствующая функция 2-D Split:

Split2d: 2-мерная функция разделения в VBA с оптимизированной обработкой строк


Public Function Split2d(ByRef strInput As String, _ 
                        Optional RowDelimiter As String = vbCr, _ 
                        Optional FieldDelimiter = vbTab, _ 
                        Optional CoerceLowerBound As Long = 0) As Variant

' Split up a string into a 2-dimensional array. Works like VBA.Strings.Split, for a 2-dimensional array.
' Check your lower bounds on return: never assume that any array in VBA is zero-based, even if you've set Option Base 0
' If in doubt, coerce the lower bounds to 0 or 1 by setting CoerceLowerBound
' Note that the default delimiters are those inserted into the string returned by ADODB.Recordset.GetString
On Error Resume Next

' Coding note: we're not doing any string-handling in VBA.Strings - allocating, deallocating and (especially!) concatenating are SLOW.
' We're using the VBA Join & Split functions ONLY. The VBA Join, Split, & Replace functions are linked directly to fast (by VBA standards)
' functions in the native Windows code. Feel free to optimise further by declaring and using the Kernel string functions if you want to.


' **** THIS CODE IS IN THE PUBLIC DOMAIN ****   Nigel Heffernan  Excellerando.Blogspot.com

Dim i   As Long
Dim j   As Long
Dim i_n As Long
Dim j_n As Long
Dim i_lBound As Long
Dim i_uBound As Long
Dim j_lBound As Long
Dim j_uBound As Long
Dim arrTemp1 As Variant
Dim arrTemp2 As Variant

arrTemp1 = Split(strInput, RowDelimiter)

i_lBound = LBound(arrTemp1)
i_uBound = UBound(arrTemp1)

If VBA.LenB(arrTemp1(i_uBound)) 

Делитесь и наслаждайтесь ... И следите за нежелательными переносами строк в коде, вставленном вашим браузером (или полезными функциями форматирования StackOverflow)

1 голос
/ 20 января 2012

Вы можете использовать функцию StringConcat, созданную Чипом Пирсоном. Пожалуйста, смотрите ссылку ниже:)

Тема: Конкатенация строк

Ссылка : http://www.cpearson.com/Excel/StringConcatenation.aspx

Цитировать По ссылке на случай, если ссылка когда-либо умрет

На этой странице описана функция VBA, которую можно использовать для объединения строковых значений в формулу массива.

Функция StringConcat

Чтобы преодолеть эти недостатки функции CONCATENATE, необходимо создать нашу собственную функцию, написанную на VBA, которая будет решать проблемы CONCATENATE. Остальная часть этой страницы описывает такую ​​функцию с именем StringConcat. Эта функция преодолевает все недостатки CONCATENATE. Его можно использовать для объединения отдельных строковых значений, значений одного или нескольких диапазонов рабочей таблицы, литеральных массивов и результатов операции формулы массива.

Объявление функции StringConcat выглядит следующим образом:

Функция StringConcat (Sep как строка, ParamArray Args ()) как строка

Параметр Sep - это символ или символы, которые разделяют соединяемые строки. Это может быть 0 или более символов. Параметр Sep является обязательным. Если вы не хотите использовать разделители в результирующей строке, используйте пустую строку для значения Sep. Значение Sep отображается между каждой объединяемой строкой, но не появляется ни в начале, ни в конце строки результата. Параметр ParamArray Args является последовательностью значений, которые необходимо объединить. Каждый элемент в ParamArray может быть любым из следующих:

Буквенная строка, такая как "A" Диапазон ячеек, указанный либо по адресу, либо по имени диапазона. Когда элементы двумерного диапазона объединяются, порядок объединения проходит через одну строку, а затем до следующей строки. Литеральный массив. Например, {"A", "B", "C"} или {"A"; "B"; "C"}

Функция

Function StringConcat(Sep As String, ParamArray Args()) As Variant
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' StringConcat
' By Chip Pearson, chip@cpearson.com, www.cpearson.com
'                  www.cpearson.com/Excel/stringconcatenation.aspx
' This function concatenates all the elements in the Args array,
' delimited by the Sep character, into a single string. This function
' can be used in an array formula. There is a VBA imposed limit that
' a string in a passed in array (e.g.,  calling this function from
' an array formula in a worksheet cell) must be less than 256 characters.
' See the comments at STRING TOO LONG HANDLING for details.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim S As String
Dim N As Long
Dim M As Long
Dim R As Range
Dim NumDims As Long
Dim LB As Long
Dim IsArrayAlloc As Boolean

'''''''''''''''''''''''''''''''''''''''''''
' If no parameters were passed in, return
' vbNullString.
'''''''''''''''''''''''''''''''''''''''''''
If UBound(Args) - LBound(Args) + 1 = 0 Then
    StringConcat = vbNullString
    Exit Function
End If

For N = LBound(Args) To UBound(Args)
    ''''''''''''''''''''''''''''''''''''''''''''''''
    ' Loop through the Args
    ''''''''''''''''''''''''''''''''''''''''''''''''
    If IsObject(Args(N)) = True Then
        '''''''''''''''''''''''''''''''''''''
        ' OBJECT
        ' If we have an object, ensure it
        ' it a Range. The Range object
        ' is the only type of object we'll
        ' work with. Anything else causes
        ' a #VALUE error.
        ''''''''''''''''''''''''''''''''''''
        If TypeOf Args(N) Is Excel.Range Then
            '''''''''''''''''''''''''''''''''''''''''
            ' If it is a Range, loop through the
            ' cells and create append the elements
            ' to the string S.
            '''''''''''''''''''''''''''''''''''''''''
            For Each R In Args(N).Cells
                If Len(R.Text) > 0 Then
                    S = S & R.Text & Sep
                End If
            Next R
        Else
            '''''''''''''''''''''''''''''''''
            ' Unsupported object type. Return
            ' a #VALUE error.
            '''''''''''''''''''''''''''''''''
            StringConcat = CVErr(xlErrValue)
            Exit Function
        End If

    ElseIf IsArray(Args(N)) = True Then
        '''''''''''''''''''''''''''''''''''''
        ' ARRAY
        ' If Args(N) is an array, ensure it
        ' is an allocated array.
        '''''''''''''''''''''''''''''''''''''
        IsArrayAlloc = (Not IsError(LBound(Args(N))) And _
            (LBound(Args(N)) <= UBound(Args(N))))
        If IsArrayAlloc = True Then
            ''''''''''''''''''''''''''''''''''''
            ' The array is allocated. Determine
            ' the number of dimensions of the
            ' array.
            '''''''''''''''''''''''''''''''''''''
            NumDims = 1
            On Error Resume Next
            Err.Clear
            NumDims = 1
            Do Until Err.Number <> 0
                LB = LBound(Args(N), NumDims)
                If Err.Number = 0 Then
                    NumDims = NumDims + 1
                Else
                    NumDims = NumDims - 1
                End If
            Loop
            On Error GoTo 0
            Err.Clear
            ''''''''''''''''''''''''''''''''''
            ' The array must have either
            ' one or two dimensions. Greater
            ' that two caues a #VALUE error.
            ''''''''''''''''''''''''''''''''''
            If NumDims > 2 Then
                StringConcat = CVErr(xlErrValue)
                Exit Function
            End If
            If NumDims = 1 Then
                For M = LBound(Args(N)) To UBound(Args(N))
                    If Args(N)(M) <> vbNullString Then
                        S = S & Args(N)(M) & Sep
                    End If
                Next M

            Else
                ''''''''''''''''''''''''''''''''''''''''''''''''
                ' STRING TOO LONG HANDLING
                ' Here, the error handler must be set to either
                '   On Error GoTo ContinueLoop
                '   or
                '   On Error GoTo ErrH
                ' If you use ErrH, then any error, including
                ' a string too long error, will cause the function
                ' to return #VALUE and quit. If you use ContinueLoop,
                ' the problematic value is ignored and not included
                ' in the result, and the result is the concatenation
                ' of all non-error values in the input. This code is
                ' used in the case that an input string is longer than
                ' 255 characters.
                ''''''''''''''''''''''''''''''''''''''''''''''''
                On Error GoTo ContinueLoop
                'On Error GoTo ErrH
                Err.Clear
                For M = LBound(Args(N), 1) To UBound(Args(N), 1)
                    If Args(N)(M, 1) <> vbNullString Then
                        S = S & Args(N)(M, 1) & Sep
                    End If
                Next M
                Err.Clear
                M = LBound(Args(N), 2)
                If Err.Number = 0 Then
                    For M = LBound(Args(N), 2) To UBound(Args(N), 2)
                        If Args(N)(M, 2) <> vbNullString Then
                            S = S & Args(N)(M, 2) & Sep
                        End If
                    Next M
                End If
                On Error GoTo ErrH:
            End If
        Else
            If Args(N) <> vbNullString Then
                S = S & Args(N) & Sep
            End If
        End If
        Else
        On Error Resume Next
        If Args(N) <> vbNullString Then
            S = S & Args(N) & Sep
        End If
        On Error GoTo 0
    End If
ContinueLoop:
Next N

'''''''''''''''''''''''''''''
' Remove the trailing Sep
'''''''''''''''''''''''''''''
If Len(Sep) > 0 Then
    If Len(S) > 0 Then
        S = Left(S, Len(S) - Len(Sep))
    End If
End If

StringConcat = S
'''''''''''''''''''''''''''''
' Success. Get out.
'''''''''''''''''''''''''''''
Exit Function
ErrH:
'''''''''''''''''''''''''''''
' Error. Return #VALUE
'''''''''''''''''''''''''''''
StringConcat = CVErr(xlErrValue)
End Function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...