I want to concatenate a range of cells into one cell, without macros/vbscript.
The formula CONCATENATE() gets individual cells.
Its not that easy, but I end up with a solution that works wonders!
A1: the text to search
B1:BN: The range within the results would go
B5: The delimiter text
=MID($A$1,LEN(CONCAT($B$1:B1))+COUNTA($B$1:B1)*LEN($B$5)+1,
SEARCH(
$B$5,
$A$1,
LEN(
CONCAT($B$1:B1)) + COUNTA($B$1:B1)*LEN($B$5)+1)
-(LEN(CONCAT($B$1:B1))+COUNTA($B$1:B1)*LEN($B$5)+1))
As for now it works perfect. Note that you can use whatever text as delimiter. In my case it was "comma + space".
Where Concat is a simple function that concatenates a range of cells:
Function Concat(myRange As Range) As String
Dim r As Range
Application.Volatile
For Each r In myRange
If Len(r.Text) Then
Concat = Concat & IIf(Concat <> "", "", "") & r.Text
End If
Next
End Function
You can either use CONCATENATE() or & to join cells. There is no range you can grab all at once unless you use a UDF such as MCONCAT.
Related
I am VERY new to VBA.
I am trying to build a UDF function to parse comma delimited text in a cell into rows. I have a Sub that works fine, but requires a manual "run"; I want it to be a function.
Say I have in cell A1 the following string comma delimited string
M89-76,M64-62,M76-80
and I want to list each M... in a separate row cell. The sub code accomplishes this but requires a manual run; I need a UDF of the sub code so I can type =myUDF(A1) into B1 and the list of M...'s is returned in cells B1 through B3
Sub TransposeRange()
Dim rng As Range
Dim InputRng As Range, OutRng As Range
Set InputRng = Application.Selection.Range("A1")
Set InputRng = Application.InputBox("Range(single cell) :", xTitleId, InputRng.Address, Type:=8)
Set OutRng = Application.InputBox("Out put to (single cell):", xTitleId, Type:=8)
Arr = VBA.Split(InputRng.Range("A1").Value, ",")
OutRng.Resize(UBound(Arr) - LBound(Arr) + 1).Value =
Application.Transpose(Arr)
End Sub
If you are using a verion that supports Dynamic Arrays (Office365) then your UDF can spill the result into as many cells as required.
Function MyUDF(r As Range) As Variant
Dim s() As String
s = Split(r.Value2, ",")
MyUDF = Application.Transpose(s)
End Function
For data in A put =MyUDF(A1) in Cell B1, the result will spill down
Note that Application.Transpose has a string length limit of 32765 characters. If the data in A1 is longer that that, the result will be truncated. In that case you would need to code the transpose (loop s, into a 2D array)
If you don't have Dynamic Arrays, the formula will still work when entered as an Array Formula into a range large enought to hold the result (eg B1:B3)
If you have FILTERXML (introduced in 2013, thanks T.M.), then you can do this with a formula:
=FILTERXML("<t><x>" & SUBSTITUTE(A1, ",", "</x><x>") & "</x></t>", "//x")
Where you convert the string into an xml formatted tree and then pass in an xpath selector. This will spill into as many rows as are needed.
You can also use this. It's made much simpler by LET, but I'm going to give the non-parameterized version, because if you have LET you should have FILTERXML anyway:
=TRIM(
MID(
SUBSTITUTE(A1, ",", REPT(" ", 100)),
IF(
ROW(OFFSET(A1, 0, 0, LEN(A1)-LEN(SUBSTITUTE(A1,",",""))+1)) = 1,
1,
(ROW(OFFSET(A1, 0, 0, LEN(A1)-LEN(SUBSTITUTE(A1,",",""))+1))-1)*100
),
100
)
)
where you replace the commas with an arbitrarily long amount of whitespace, then use MID to select out substrings, and ROW to generate an array of indexes the size of the elements in the string. Wrap it in TRIM to get rid of the whitespace.
If you need to do this with a UDF, then you can do this:
Function splitIt(raw)
splitIt = Application.Transpose(Split(raw, ","))
End Function
and use it like any other function. This is functionally identical to Chris Nielsen's solution.
Will update shortly with two other options for other Excel versions.
How to create a formula in result column based on the values of the previous column
if values in any previous columns (from c1 to c5) is greater than zero, I want to add it to the result.
If you happen to have access to TEXTJOIN function you can use the following:
Formula in F2:
=TEXTJOIN(",",TRUE,IF(A2:E2>0,$A$1:$E$1,""))
Note 1: It's an array formula and needs to be confirmed through CtrlShiftEnter
Note 2: Without access to TEXTJOIN this will become a much more painfull process, but for just the 5 columns you can try =IF(A2>0,A$1&",","")&IF(B2>0,B$1&",","")&IF(C2>0,C$1&",","")&IF(D2>0,D$1&",","")&IF(E2>0,E$1&",",""), however you'll have to expand to get rid of the trailing comma
If both the above options are not feasible, your best bet will be to write a UDF. For this exercise, you can write a rather simple one:
Public Function TextJoin2(rng1 As Range, rng2 As Range) As String
With Application
Dim arr As Variant: arr = .Evaluate("IF(" & rng1.Address & ">0," & rng2.Address & ","" "")")
TextJoin2 = Replace(.Trim(Join(arr, " ")), " ", ",")
End With
End Function
Call in F2 like: =TEXTJOIN2(A2:E2,A$1:E$1) and drag down.
You can use =CONCAT(IF(A2:E2>0;$A$1:$E$1&",";"")) as array formula, confirm with ShiftCtrlEnter.
Put this formula in F2 cell in your example. Expand that formula to whole range
What remains here is to remove comma on the end of result string.
That full formula would be like this
=LEFT(CONCAT(IF(A2:E2>0;$A$1:$E$1&",";""));LEN(CONCAT(IF(A2:E2>0;$A$1:$E$1&",";"")))-1)
For example i have two cells
A1: =1/2
A2: /abc
I want to replace / char in second cell with something else without changing first cell which contains formula. Final result should be like this
A1: = 1/2
A2: #abc
Select your cells and run:
Sub dural()
Dim r As Range
For Each r In Selection
If Not r.HasFormula Then
r = Replace(r.Text, "/", "#")
End If
Next r
End Sub
Replace /a with #a as shown below:
You can use a formula creating a new column: Let's say that the value is in cell A1, you could put this in the cell b1:
=IF(ISFORMULA(A1),A1,SUBSTITUTE(A1,"/",""))
I have 3 columns A,B,C and I need to merge the 3 columns and I have applied the forumala =A1&","&B1&","&C1 the output came as E column I need the output as D column.
The following formula will achieve your desired result:
=TEXTJOIN(",",TRUE,A1:C1)
Textjoin works like concatenate but can have a delimiter as an argument, also it gives you the ability to ignore blank cells, the first argument is the delimiter, the second is the flag to ignore blanks and the third is for the range.
As comments do mention that TEXTJOIN is only available for Office 365 subscribers, a possible alternative would be to build your UDF as below, this will allow you to use the formula above without an Office 365 subscription:
Function TEXTJOIN(delimiter As String, ignore_empty As Boolean, rng As Range) As String
Dim compiled As String
For Each cell In rng
If ignore_empty And IsEmpty(cell.Value) Then
'nothing
Else
compiled = compiled + IIf(compiled = "", "", delimiter) + CStr(cell.Value)
End If
Next
TEXTJOIN = compiled
End Function
Enter this formula into E1:
=CONCATENATE(A1, IF(AND(B1<>"", A1<>""), ",", ""), B1,
IF(AND(OR(A1<>"", B1<>""), C1<>""), ",", ""), C1)
Using TEXTJOIN might be a cleaner option, but is only available on more recent versions of Excel.
'Put this code in module and use formula concmulti and select the range
Function concmulti(slt As Range) As String
Dim str As String
Dim cell As Range
For Each cell In slt
str = str & cell.Value & ", "
Next cell
concmulti = str
End Function
If there are no spaces within the cells, then in D1 enter:
=SUBSTITUTE(TRIM(A1 & " " & B1 & " " & C1)," ",",")
and copy downwards:
I have a column that contains data for eg: 6B31-21045M22-AA
I'm trying to split the data before and after '-'. Like
A B C D
6B31-21045M22-AA 6B31 21045M22 AA
I tried
=LEFT(A2, SEARCH(“-”,A2)-1) and =Right(A2, SEARCH(“-”,A2)-1)
but if "-" occurs more than once then how do i split the 6B31-21045M22-AA or
6B31-21045M22-AA-SWQ
You don't need a formula or a VBA script. You can use Text to Columns function. Simply select the column with your data and use Text to Columns button on the Data panel. Then in a Wizard select Delimiter and set a "-" symbol as a delimiter.
With data in A1, in B1 enter:
=TRIM(MID(SUBSTITUTE($A1,"-",REPT(" ",999)),COLUMNS($A:A)*999-998,999))
and copy across:
(this can also be done with VBA)
EDIT#1:
Using VBA, select the cell you wish to process and run this:
Sub Splitter()
Dim ary, i As Long, a
With ActiveCell
ary = Split(.Value, "-")
i = 1
For Each a In ary
.Offset(0, i).Value = a
i = i + 1
Next a
End With
End Sub