Excel TextToColumns method in VBA to ignore formulas

孤街浪徒 提交于 2019-12-23 15:00:46

问题


First, let me say that I hope that it is proper SO etiquette to be asking this in the same post as my original. It's all in the same vein, but I'm not sure this is proper. So, please, if I'm not right, correct me so I can fix it.

I created a macro to perform a TextToColumns a while back. I edited and cleaned up the macro. It was working just fine until I started propagating data into those fields using formulas instead of manually copying data into them, which was what I used to do.

Now, I've expanded on my worksheet's module code and realized that the method I wrote months ago interferes with formulas that now copy the values into the fields that I originally was performing the TextToColumns.

In short, is there a way to tell .TextToColumns to take the values of the range in which it's working and ignore the formula?

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

I checked the documentation for TextToColumns searching for xlValues but couldn't find anything like that.

---------- addendum -----------

Rachel. I appreciate your input. Perhaps you could assist a little bit more. I've plugged in your suggestion, but it simply is doing nothing. I've taken a few libterties here in hopes to combine what you've given with what I need. Disclaimer: I am by no means a VBA developer. What I know is what I've learned from google. I live in the Unix/Linux world so this is a very different bird to what I'm used to.

Here's what I have so far...

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

I cannot post an example of the spreadsheet, unfortunately. It's on a closed, secure network.

Now, when I plug this in in the worksheet via: =sbTextToColumn(C836, E836), nothing happens.

This is my first attempt at ever creating and using a UDF. Here's how I'm calling the function. I have a worksheet with the first three columns A-C grabbing data from another spreadsheet. Those columns are of course formulas. Column D is not used, but I'm placing the call to the UDF in here, hoping that that will work. Columns E-I are reserved for the T2C data and column J is used by pulling the same data as column B (yes, redundant, I know). My goal is that I'd like to get rid of column J (it's used for a vlookup in another worksheet and I may not be able to remove it but I'd like to). Ideally, I'd like to pull the source data from the other spreadsheet, sanity check it, split it out, and simply place the sorted data in the n columns necessary.

So, am I on the right track? I'm still working on this. If I make any progress, I'll post the progress. TIA!


回答1:


Functions, including UDFs, can only return a value to their caller. They cannot modify other cells.

Here is Rachel's method wrapped as a 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

You enter it as a array function. In your example, say for row 2

  • Select range E2:I1
  • Type =sbTextToColumn(C2)
  • Press Ctrl+Shift+Enter
  • Copy the 5 cell range down for as many rows as needed

Functions not being able to modify other cells means you cannot do the sanitising in the UDF.

From your sample code you want to

  • Replace I/R with IR, and N/A with NA
  • Remove spaces
  • Do this after the data is split out into columns E:I (so I/R will already be split into two cells)
  • Replace the original Column C formulas with sanitised data as values

Is this right?

If so, you would be best to not used a UDF at all, but rather use a Sub (called from a quick key, or added to a menu)

Somthing like:

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

If you actually want to sanitise before the split, simply swap the order of the Split data and Sanitise Data code blocks.




回答2:


This approach might work for you as it utilizes the Value property and is unaffected by formulas. It uses the Split function to split the data into a one-dimensional array. That array is then pasted into the cells to the right:

Sub sbTextToColumn()
    Dim vData As Variant
    vData = Split(Sheet4.Range("A1").Value, "/")
    Sheet4.Range("B1").Resize(ColumnSize:=UBound(vData) + 1) = vData
End Sub


来源:https://stackoverflow.com/questions/8597830/excel-texttocolumns-method-in-vba-to-ignore-formulas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!