Метод Excel TextToColumns в VBA, чтобы игнорировать формулы - PullRequest
4 голосов
/ 22 декабря 2011

Во-первых, позвольте мне сказать, что я надеюсь, что это правильный ТАК, что спрашивать об этом в том же посте, что и мой оригинал. Это все в том же духе, но я не уверен, что это правильно. Так что, пожалуйста, если я не прав, поправьте меня, чтобы я мог это исправить.

Я создал макрос для выполнения TextToColumns некоторое время назад. Я отредактировал и убрал макрос. Это работало очень хорошо, пока я не начал распространять данные в эти поля, используя формулы вместо того, чтобы вручную копировать в них данные, что я и делал.

Теперь я расширил код модуля моего рабочего листа и понял, что метод, который я написал несколько месяцев назад, взаимодействует с формулами, которые теперь копируют значения в поля, которые я первоначально выполнял в TextToColumns.

Короче говоря, есть ли способ сказать .TextToColumns принять значения диапазона, в котором он работает, и игнорировать формулу?

 Sheet4.Range(categorySrcColumn & srcCategoryColLastRow)
       .TextToColumns _
            Destination:=Range(categoryDestColumn), _
            Other:=True, _
            OtherChar:="/", _
            FieldInfo:=Array(1,1), _
            TrailingMinusNumbers:=true

Я проверил документацию по TextToColumns для поиска xlValues, но не смог найти ничего подобного.

---------- приложение -----------

Рейчел. Я ценю ваш вклад. Возможно, вы могли бы помочь немного больше. Я включил ваше предложение, но оно просто ничего не делает. Я взял несколько закусок здесь в надежде объединить то, что вы дали, с тем, что мне нужно. Отказ от ответственности: я ни в коем случае не разработчик VBA. То, что я знаю, это то, что я узнал от Google. Я живу в мире Unix / Linux, так что это совсем не то, к чему я привык.

Вот что у меня есть ...

Public Function sbTextToColumn(srcRange As String, dstRange As String)
    Dim vData As Variant

    vData = Split(ActiveSheet.Range(srcRange).Value, "/")

    ' I need to massage the data in the srcRange a bit before I can separate it out. 
    ' This is a partial sanity check on the data as well.
    Range(srcRange).Replace What:="I/R", Replacement:="IR", Lookat:=xlPart, _
                    SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False _
                    ReplaceFormat:=False

    Range(srcRange).Replace What:="N/A", Replacement:="NA", Lookat:=xlPart, _
                    SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False _
                    ReplaceFormat:=False

    Range(srcRange).Replace What:=" ", Replacement:="", Lookat:=xlPart, _
                    SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False _
                    ReplaceFormat:=False

    ActiveSheet.Range(dstRange).Resize(ColumnSize:=UBound(vData) + 1) = vData
    sbTextToColumn = ""
End Function

К сожалению, я не могу опубликовать пример таблицы. Он находится в закрытой защищенной сети.

Теперь, когда я подключаю это к рабочему листу через: =sbTextToColumn(C836, E836), ничего не происходит.

Это моя первая попытка создания и использования UDF. Вот как я вызываю функцию. У меня есть лист с первыми тремя столбцами A-C, извлекающий данные из другой таблицы. Эти столбцы, конечно, формулы. Столбец D не используется, но я размещаю здесь вызов UDF, надеясь, что это сработает. Столбцы E-I зарезервированы для данных T2C, а столбец J используется для извлечения тех же данных, что и столбец B (да, избыточно, я знаю). Моя цель состоит в том, чтобы я хотел избавиться от столбца J (он используется для vlookup на другом листе, и я не могу удалить его, но я бы хотел). В идеале я хотел бы извлечь исходные данные из другой электронной таблицы, проверить их, разделить и просто поместить отсортированные данные в n необходимых столбцов.

Итак, я на правильном пути? Я все еще работаю над этим. Если я сделаю какой-либо прогресс, я опубликую прогресс. ТИА!

Ответы [ 2 ]

3 голосов
/ 22 декабря 2011

Этот подход может работать для вас, поскольку он использует свойство Value и не зависит от формул. Он использует функцию Split для разделения данных в одномерный массив. Затем этот массив вставляется в ячейки справа:

Sub sbTextToColumn()
    Dim vData As Variant
    vData = Split(Sheet4.Range("A1").Value, "/")
    Sheet4.Range("B1").Resize(ColumnSize:=UBound(vData) + 1) = vData
End Sub
1 голос
/ 23 декабря 2011

Функции, включая UDF, могут только возвращать значение своему вызывающему.Они не могут изменять другие ячейки.

Вот метод Рэйчел, заключенный в UDF:

Function sbTextToColumn(rng As Range) As Variant
    Dim vData As Variant

    vData = Split(rng.Value2, "/")
    ReDim Preserve vData(0 To Application.Caller.Columns.Count - 1)
    sbTextToColumn = vData
End Function

Вы вводите его как функцию массива.В вашем примере, скажем, для row 2

  • Выберите диапазон E2:I1
  • Тип =sbTextToColumn(C2)
  • Нажмите Ctrl + Shift + Ввести
  • Скопировать диапазон из 5 ячеек на столько строк, сколько необходимо

Функции, не позволяющие изменять другие ячейки, означают, что выневозможно выполнить очистку в UDF.

Из вашего примера кода вы хотите

  • Заменить I / R на IR, а N / A на NA
  • Удалитьпробелы
  • Сделайте это после того, как данные разбиты на столбцы E:I (поэтому I / R уже будет разбит на две ячейки)
  • Замените исходный столбец C формулами с обработанными данными в виде значений

Это правильно?

Если это так, вам лучше вообще не использовать UDF, а использоватьSub (вызывается с помощью быстрой клавиши или добавляется в меню)

Что-то вроде:

Sub sbTextToColumn()
    Dim ws As Worksheet
    Dim srcRng As Range
    Dim rw As Range
    Dim vData As Variant
    Dim srcData As Variant
    Dim dstData As Variant
    Dim i As Long, j As Long
    Dim maxCol As Long

    Set ws = ActiveSheet
    Set srcRng = Range(ws.Columns(3).Cells(1, 1), _
        ws.Columns(3).Cells(ws.Columns(3).Rows.Count).End(xlUp))

    srcData = srcRng
    ReDim dstData(LBound(srcData, 1) To UBound(srcData, 1), 1 To 5)

    For i = LBound(srcData, 1) To UBound(srcData, 1)
        If srcData(i, 1) <> "" Then
            ' Split data
            vData = Split(srcData(i, 1), "/")
            maxCol = UBound(vData, 1)
            If maxCol > 5 Then maxCol = 5
            For j = 1 To maxCol + 1
                dstData(i, j) = vData(j - 1)
            Next

            ' Sanitise data
            srcData(i, 1) = Replace(srcData(i, 1), "I/R", "IR", Compare:=vbTextCompare)
            srcData(i, 1) = Replace(srcData(i, 1), "N/A", "NA", Compare:=vbTextCompare)
            srcData(i, 1) = Replace(srcData(i, 1), " ", "", Compare:=vbTextCompare)
        End If
    Next

    ' Put results back in sheet
    srcRng = srcData
    srcRng.Offset(0, 2).Resize(, 5) = dstData
End Sub

Если вы действительно хотите очистить перед разделением, просто поменяйте местами порядокРазделить данныеи дезинфицировать блоки кода данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...