Split Text based on delimiter

Pete2020

Board Regular
Joined
Apr 25, 2020
Messages
68
Office Version
  1. 2016
Platform
  1. Windows
I am looking to create a multiple combination of a sentence based on Curly brackets and "|" Separators in the text. We usually call this as nested spintax .
  • Every Curly bracket contains a word separator with "|" delimiter
  • The Output is shown in the Column F for every combination of words using curly brackets and "|" delimiter

Column A is the Primary Key ID and based on it The column B should generate multiple combinations and Out put should be generated in column E and F

These are the common patterns of my data.

Book1
ABCDEF
1IDTextIDText Output
2SP-001{Nice|Cool|Beautiful} photo.SP-001Nice photo.
3SP-002{Hello|Hi} {World|People}!SP-001Cool photo.
4SP-003{hello there my {friend|dude|buddy|pal}SP-001Beautiful photo.
5SP-004Very {interesting|beautiful} woman {image|photo|picture}SP-002Hello World!
6SP-005This is nested {{very|quite} deeply|deep}.SP-002Hi People!
7SP-002Hello People!
8SP-002Hi World!
9SP-003hello there my friend
10SP-003hello there my dude
11SP-003hello there my buddy
12SP-003hello there my pal
13SP-004Very interesting woman image
14SP-004Very interesting woman photo
15SP-004Very interesting woman picture
16SP-004Very beautiful woman image
17SP-004Very beautiful woman photo
18SP-004Very beautiful woman picture
19SP-005This is nested very deeply.
20SP-005This is nested quite deeply.
21SP-005This is nested deep.
22SP-005This is nested deeply.
Sheet1
 
Thank You @mikerickson for your generous effort in building a Good Excel Function.I tried interpret function it is only producing one result. When i drag to another cell down it is not giving multiple sentence variations based on delimiter.

Is there any way to create a macro. I dont know VBA as it needs some expertise.

Your help is much needed in this regard.

I just found few references relating to this spin text i did not tried them.

multiple variation VBA

text Spinner
 
Upvote 0

Excel Facts

Using Function Arguments with nested formulas
If writing INDEX in Func. Arguments, type MATCH(. Use the mouse to click inside MATCH in the formula bar. Dialog switches to MATCH.
To use this in a worksheet formula you have to enter it in an array of cells as an array formula
If you have "{Nice|Cool|Beautiful} photo." in cell B1, you can select cells E1:K1, type =Interpret(B1) into the formula bar and press Ctrl+Shift+Enter at the same time.
Notice that cells on the right have #N/A since there aren't any results for those cells.
Dragging down, will show the results for the other strings.

To get the lay-out shown in the OP you could use this macro
VBA Code:
Sub test()
    Dim rngInput As Range, rngOutput As Range
    Dim returnCount As Long, i As Long
    Dim arrResults As Variant
    Dim oneCell As Range
    
    With Sheet2.Range("A:A")
        Set rngInput = Range(.Cells(2, 1), .Cells(Rows.Count, 1).End(xlUp))
    End With
    Set rngOutput = Sheet2.Range("E1")
    
    With rngOutput.Resize(1, 2)
        .EntireColumn.ClearContents
        .Value = Array("ID", "Text Output")
    End With
    For Each oneCell In rngInput
        arrResults = Interpret(oneCell.Offset(0, 1).Text)
        returnCount = UBound(arrResults) + 1
        With rngOutput.EntireColumn.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
            With .Resize(returnCount, 1)
                .Value = oneCell.Value
                .Offset(0, 1).Value = Application.Transpose(arrResults)
            End With
        End With
    Next oneCell
End Sub
 
Upvote 0
O.K. I think I've got it.
The function Interpret will take a string and return a (0-based, 1 dimensional) array of the combinations that that string produces.

Interpret("You are {beautiful|pretty}.") = Array("You are beautiful.", "You are pretty.")

It also takes sub brackets


While it doesn't completely answer the OP, it does the heavy lifting.
Let me know if this does what you want and if you need help building the multi-input macro requested in the OP
VBA Code:
Const strLeft As String = "{"
Const strRight As String = "}"
Const strPipe As String = "|"

Function Interpret(ByVal aString As String, Optional PipeMode As Boolean) As Variant
    Dim i As Long
    Dim Result() As String, Pointer As Long
    Dim Elements As Variant, oneElement As Variant, oneString As Variant
    Dim ElementResults As Variant, oneResult As Variant, elementCount As Long
    Dim ElementIndexes() As Long
    Dim thisResult As Variant, thisSubString As String
    Dim IndexPointer As Long, IndexFlag As Boolean
    Dim temp
    ReDim Result(0 To 0): Pointer = -1
  
    If PipeMode Then
        Elements = ParseString(aString, "|")
        For Each oneElement In Elements
            For Each oneResult In Interpret(oneElement)
                Pointer = Pointer + 1
                If UBound(Result) < Pointer Then ReDim Preserve Result(0 To 2 * Pointer)
                Result(Pointer) = oneResult
            Next oneResult
        Next oneElement
    Else
        Elements = ParseString(aString)
        If (UBound(Elements) = 0) And aString Like ("{*}") Then
            temp = Mid(aString, 2, Len(aString) - 2)
            Result = Interpret(temp, True)
            Pointer = UBound(Result)
        ElseIf aString Like "*{*}*" Then
            elementCount = UBound(Elements)
            ReDim ElementResults(0 To elementCount)
            For i = 0 To elementCount
                ElementResults(i) = Interpret(CStr(Elements(i)))
            Next i
          
            ReDim ElementIndexes(0 To elementCount)
          
            Do
                Pointer = Pointer + 1
                If UBound(Result) < Pointer Then ReDim Preserve Result(0 To 2 * Pointer)
                For i = 0 To elementCount
                    thisResult = ElementResults(i)
                    thisSubString = thisResult(ElementIndexes(i))
                    Result(Pointer) = Result(Pointer) & thisSubString
                Next i
              
                Rem incriment indexees
                IndexPointer = elementCount
                Do
                    IndexFlag = False
                    ElementIndexes(IndexPointer) = ElementIndexes(IndexPointer) + 1
                    If ElementIndexes(IndexPointer) > UBound(ElementResults(IndexPointer)) Then
                       ElementIndexes(IndexPointer) = 0
                        IndexPointer = IndexPointer - 1
                        IndexFlag = True
                        If IndexPointer < 0 Then Exit Do
                    End If
                Loop While IndexFlag
                IndexFlag = (IndexPointer < 0)
          
            Loop Until IndexFlag
        Else
            Rem aString is single string
            Pointer = 0
            Result(Pointer) = aString
        End If
    End If
    ReDim Preserve Result(0 To Pointer)
  
    Interpret = Result
End Function

Function ParseString(aString As String, Optional onDelimiter As String = "{") As Variant
    Dim BracketCount As Long
    Dim thisChr As String
    Dim i As Long
    Dim Result() As String, Pointer As Long
  
    ReDim Result(0 To Len(aString))
    Pointer = 0
  
    If onDelimiter = strLeft Then
        For i = 1 To Len(aString)
            thisChr = Mid(aString, i, 1)
            If thisChr = strLeft Then
                If 0 = BracketCount Then
                    Rem end previous
                    Pointer = Pointer + Sgn(Len(Result(Pointer)))
                End If
                Result(Pointer) = Result(Pointer) & thisChr
                BracketCount = BracketCount + 1
            ElseIf thisChr = strRight Then
                BracketCount = BracketCount - 1
                Result(Pointer) = Result(Pointer) & thisChr
                 If 0 = BracketCount Then
                    Rem end previous
                    Pointer = Pointer + Sgn(Len(Result(Pointer)))
                End If
            Else
                Result(Pointer) = Result(Pointer) & thisChr
            End If
          
        Next i
        If Result(Pointer) = vbNullString Then Pointer = Pointer - 1
      
        If Pointer < 0 Then Pointer = 0
        ReDim Preserve Result(0 To Pointer)
    Else
        For i = 1 To Len(aString)
            thisChr = Mid(aString, i, 1)
            If thisChr = strPipe And BracketCount = 0 Then
                Pointer = Pointer + 1
            ElseIf thisChr = strLeft Then
                BracketCount = BracketCount + 1
                Result(Pointer) = Result(Pointer) & thisChr
            ElseIf thisChr = strRight Then
                BracketCount = BracketCount - 1
                Result(Pointer) = Result(Pointer) & thisChr
            Else
                Result(Pointer) = Result(Pointer) & thisChr
            End If
        Next i
        ReDim Preserve Result(0 To Pointer)
    End If
    ParseString = Result
End Function

This is great! Very close to what I was looking for....

Is there anyway to make the output spintax random? Seems like currently it is doing them in order...
Lets say I have a list of 50 phrases all containing spintax on Column one... then I want o select B1:C1 to and run the function, as a results it would output 2 random versions of the spintax phrase on B1 and C1... Then I drag it down to have the same for the other phrases.
Basically adding randomness to what it already does..
 
Upvote 0
This is a three year old thread. Thank you for reminding me of this UDF that I wrote.
Yes a function that incorporated randomness in the result would be possible. But it would have the same lack of stability that RAND has.
It would be easier to get the result using the current formula and then apply some randomizer to the result.
 
Upvote 0

Forum statistics

Threads
1,214,810
Messages
6,121,690
Members
449,048
Latest member
81jamesacct

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top