Excel convert comma seperated downwards WITH other columns - excel

I'm trying to do this:
The long way to do this:
Highlight 1 cell in B. Text to columns. Copy all the cells in the output. Paste using transpose. Then drag col A to fill in the blanks downwards.
There must be an easier way :(

I claimed in the comments that you could also do this by formula with a couple of helper columns and wanted to see (a) if that was true and (b) how difficult it would be to do. The answers were (a) yes, just about and (b) very (although there are people out there who are more skilled in complex formulae than I am).
Here is the result:-
So the helper columns are just like the i's and j's in the VBA where
Column C (i) is source row
Column D (j) is string number within source row
But to achieve this you need some long formulae.
C7 and C8 are just hard-coded to 1.
In D8:-
=IF(C7="","",IF(D7<LEN(INDEX(B$2:B$4,C7))-LEN(SUBSTITUTE(INDEX(B$2:B$4,C7),",",""))+1,D7+1,IF(C7=ROWS($B$2:$B$4),"",1)))
In C8:-
=IF(D8="","",IF(D8>D7,C7,C7+1))
In B7:-
=IF(C7="","",MID(","&INDEX(B$2:B$4,C7)&",",FIND("<",SUBSTITUTE(","&INDEX(B$2:B$4,C7)&",",",","<",D7))+1,FIND(">",SUBSTITUTE(","&INDEX(B$2:B$4,C7)&",",",",">",D7+1))-FIND("<",SUBSTITUTE(","&INDEX(B$2:B$4,C7)&",",",","<",D7))-1))
In A7:-
=IF(C7="","",INDEX($A$2:$A$4,C7))
It is semi-dynamic because any changes to the source cells will be reflected in the destination cells. It is tied to a fixed source range $B$2:$B$4, but could be changed to work with a variable source range fairly easily. I haven't assumed that the numbers all have 7 digits, but if you did it would simplify the formula in B7.

I wondered how the VBA would compare with doing it with formulae.
Here is a sample VBA and it is pretty short even though there might be smarter ways of doing it:-
Option Explicit
Public Sub SplitRows()
Dim a() As String
Dim r1, r2 As Range
Dim i, j, k As Integer
Set r1 = Range("A2:B4")
Set r2 = Range("A7:B1000")
j = 1
For i = 1 To r1.Rows.Count
a = Split(r1.Cells(i, 2), ",")
For k = LBound(a) To UBound(a)
r2.Cells(j, 1) = r1.Cells(i, 1)
r2.Cells(j, 2) = a(k)
j = j + 1
Next k
Next i
End Sub

Related

Excel 3D Reference: Delineate string results from range of Worksheets

Hopefully I can explain this right.
Looking to combine cells of text strings from multiple worksheets into one master worksheet.
Basically 3-D References. But formatted into rows and columns. And referencing a range of worksheets so new worksheets can be added or removed in between the bookends.
Desired output:
Column 1
Column 2
Column 3
WS01 Cell B1
WS02 Cell B1
WS03 Cell B1
WS01 Cell B2
WS02 Cell B2
WS03 Cell B2
WS01 Cell B3
WS02 Cell B3
WS03 Cell B3
Input: Strings from B1:B3 (should become matching rows separated into columns for each linked worksheet)
Each worksheet ('Worksheet 01:Worksheet 03') follows same format:
Column B
WS## Cell B1
WS## Cell B2
WS## Cell B3
Attempts:
=CONCAT('Worksheet 01:Worksheet 03'!B1:B3)
Result:
WS01 Cell B1WS01 Cell B2WS01 Cell B3WS02 Cell B1WS02 Cell B2WS02 Cell B3WS03 Cell B1WS03 Cell B2WS03 Cell B3
Please let me know what you think. Thank you for your time.
You can use:
=HSTACK(Sheet1:Sheet3!B1:B3)
Even though the answer below works fine, please look at this answer by JvdV that is far easier to use:
https://stackoverflow.com/a/74077560/12634230
=LET(
c,CONCAT(Sheet1:Sheet4!B1:B3),
q,SEQUENCE(LEN(c)/36,3,,12),
TRANSPOSE(MID(c,q,12)))
c uses your CONCAT formula to retrieve a concatenation of all values.
q calculates a sequence by the length of c divided by the length of text for the 3 values per Sheet (3* length 12 = 36) by 3 with steps of the length of each value (12).
This sequence is used in the MID function and needs the result to be transposed to meet your requirements:
If a Sheet will be added, changing the Sheet names in c will change the result to show the values from that Sheet as well. No further adjustments of the formula are required.
And if the number of outputs per sheet, or string length may change in future you could define these as variables too:
=LET(c,CONCAT('Worksheet 01:Worksheet 03'!B1:B3),
stringlength,12,
stringcount,3,
q,SEQUENCE(LEN(c)/(stringlength*stringcount),stringcount,,stringlength),
TRANSPOSE(MID(c,q,stringlength)))
#P.b just posted a formula approach, but as an alternative here's a VBA user-defined formula which returns an array. The only tricky part is getting the 3D reference in the UDF, since there's no structure or type equivalent to that in VBA: if you try to get it directly from the argument you just get an error.
Building from: https://www.excelforum.com/excel-programming-vba-macros/476283-user-defined-function-receiving-a-range-as-parameter.html
Function MyUDF(v)
Dim c As Range, f, arr, arrWs, rngAddr
Dim arrout, indx1, indx2, i As Long, r As Long, data
On Error Resume Next
Set c = Application.Caller
On Error GoTo 0
If c Is Nothing Then
f = "=myudf(Sheet1:Sheet3!A1:A3)" 'for testing purposes (adjust as needed)...
Else
f = c.Formula 'read the formula from the calling cells
End If
f = Mid(f, 8, Len(f) - 8) 'parse out the parens and formula name
arr = Split(f, "!") 'get an array from splitting on !
arrWs = Split(arr(0), ":") 'get the start/end worksheet names
indx1 = ThisWorkbook.Worksheets(arrWs(0)).Index
indx2 = ThisWorkbook.Worksheets(arrWs(1)).Index
rngAddr = arr(1) '...and the range address
'size the output array
ReDim arrout(1 To Range(rngAddr).Rows.Count, 1 To 1 + (indx2 - indx1))
For i = indx1 To indx2 'loop over the worksheets
data = ThisWorkbook.Sheets(i).Range(rngAddr).Value
For r = 1 To UBound(data)
arrout(r, i) = data(r, 1)
Next r
Next i
MyUDF = arrout 'return the array
End Function

Excel formula: To sum the same cell values from multiple sheets with names as dates

Is there a way to sum all the values of the same cell of multiple sheets (tab) which the name of each tab is date, and show the summed value in the MasterSheet?
For example:
Currently, I use this formula =SUM(INDIRECT("'*-"&MONTH(C2)&"-2020'!$E$3")) in the cell under the "Oct-2020" cell, as shown in the figure below, and I will do the same for Nov-20 and Dec-20.
As you can see, I am getting this "#REF!" error. Currently, I have two tabs that I am trying to get the "$E$3" cell values from, "13-10-2020" and "14-10-2020". However, if I only have one sheet (let's say "14-10-2020" only), I am able to get the value.
Does anyone know what is going on with my formula? Why it works when there is only one sheet (tab) to read from, but does not work when there are multiple sheets (tabs), even I used "*" to include all dates.
Please advice. Thank you in advanced
I think this should solve your problem:
Option Explicit
Sub sub_sum_up_months()
Dim wks As Worksheet
Dim nr_month As Integer, nr_year As Integer
Dim str_month As String, str_year As String
Dim c As Integer
Dim my_Sum As Double
For c = 3 To 5 ' Iterating over the columns "C" to "E"
my_Sum = 0
nr_month = month(Worksheets("MasterSheet").Cells(2, c).Value)
If nr_month < 10 Then
str_month = "0" & nr_month
Else
str_month = CStr(nr_month)
End If
nr_year = Year(Worksheets("MasterSheet").Cells(2, c).Value)
str_year = CStr(nr_year)
For Each wks In ThisWorkbook.Worksheets
If Right(wks.Name, 4) = str_year And Left(Right(wks.Name, 7), 2) = str_month Then
my_Sum = my_Sum + wks.Cells(3, 5) 'cells(3,5) is "E3"
End If
Next wks
Worksheets("MasterSheet").Cells(3, c).Value = my_Sum
Next c
End Sub
You can use the sum function.
Follow this step by step and it will work.
In your MasterSheet C3 type =Sum(
Click on sheet 13-10-2020 and cell E3.
Now press and hold shift.
Click on the last sheet that is October and press Enter.
Now you should get the sum of all E3 in October sheets.
As far as I know there is no formula to do this dynamic but I'm quite sure it can be done in VBA if the sheet names follow a pattern.

how to insert n number of blank rows between existing rows alternatively

Can anyone suggest me procedure or a formula to insert n blank rows in between a existing data?
for example:
I have data from A1 to A50, now I have insert n number of blank rows between each row.
input:
required output:
Consider this screenshot:
In cell C3 enter the number of rows you want to insert between cells from column A. This cell has the range name "RowsToInsert". Alternatively, you can use $C$3 in the formulas below
The formula in cell E2 is
=INDEX(A:A,CEILING(ROW(A1)/(RowsToInsert+1),1))
or type the first value manually. The formula in E3 is as follows, copied down:
=IF(CEILING(ROW(A2)/(RowsToInsert+1),1)=CEILING(ROW(A1)/(RowsToInsert+1),1),"",INDEX(A:A,CEILING(ROW(A2)/(RowsToInsert+1),1)))
When you change the value in cell C3, blank rows are added accordingly. Copy the formula down as far as required. Then copy column E and use Paste Special > Values to paste only the results.
I would use VBA to achieve what you require and this is the code I would propose
Dim n As Long 'number of blanks
Dim dataLen As Long ' number of used rows
Dim currentRow As Long
Dim i, j As Long
dataLen = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
n = 3 'number of blanks
currentRow = 2 'start insert at row 2
For i = 1 To dataLen
For j = 1 To n
Sheet1.Rows(currentRow).Insert
Next j
currentRow = currentRow + n + 1 'offset the next row to start insertion
Next i
With formula It will be little complicated I guess.
Is this what you want?
=IF(ROW(B1)-(9*TRUNC(ROW(B1)/9,0))=1,"one",IF(ROW(B1)-(9*TRUNC(ROW(B1)/9,0))=4,"two",IF(ROW(B1)-(9*TRUNC(ROW(B1)/9,0))=7,"three","")))

Combine Adjacent Row Cells Depending on their Left Column Cell

I'd like to combine cells in the right column into one cell according to the adjacent cell on the left. I tried Merging but I could only get so far. And after searching online I couldn't find anything that can parse each row and combine for the length of the left cell's span. I know it's a CONCATENATE function, but how would I get it to parse the whole spreadsheet?
This is an example of the results I would want for the above:
This may be too complicated - in which case I would go back to the drawing board and do a full VBA version, but initially I was looking for a challenge to construct a solution only using formulas. Unfortunately, there appears to be no standard formula-based approach to concatenate a variable number of cells.
So, to accomplish this, I added one function:
Function CombineRange(ByRef rng As Range, ByVal delim As String)
Dim arr
Dim i As Long
arr = rng.Value
CombineRange = ""
For i = 1 To UBound(arr)
If i > 1 Then
CombineRange = CombineRange & delim
End If
CombineRange = CombineRange & arr(i, 1)
Next i
End Function
Assumptions:
your data is in a sheet called "YourData"
Your merged data is column A
Your "single row" data is column B
Row 1 is some kind of header row.
Next, set up four columns on a new sheet (I call it "Collapsed")
A - Start Row = (first row) whatever row your data starts on (2, in our case)
A - Start Row = (all others) A2+B2
B - Offset = {IFERROR(MATCH(FALSE,ISBLANK(INDIRECT(ADDRESS(A2+1,1,,,"YourData")&":A200")),0),0)}
Note this is an array function, so you need to do shift+Enter when entering it
C - Level1 = =INDEX(YourData!A:A,A2)
D - Combined Level 2 = =IF(B2<=1, INDIRECT(ADDRESS(A2,2,,,"YourData")), CombineRange(INDIRECT(ADDRESS(A2,2,,,"YourData")&":"&ADDRESS(A2+B2-1,2)),"; "))

How to get every value from one column to another column based on its corresponding value

As you can see in the image that "Col B" has same number multiple times. For ex: "1" is four times, "2" is three times, and so on. However, all these numbers correspond to a specific number from "Col A". What I am trying to do is get the the column I have highlighted in orange and yellow. You can clearly see what I have done. What I need is a excel function that does it for me. This is just a sample. I have dataset with million data points, and I can't type all that.
Thanks!!
Formula for cell E2
=IFERROR(SMALL(IF($B:$B=$D2,ROW($B:$B)-1),COLUMN(A:A)),"")
Entered as an Array Formula (Enter with Ctrl-Shift-Enter rather than just Enter)
Copy accross for as many cells as you wish
Note: this formula is quite slow. A well designed UDF will be faster.
One way to solve this with a UDF is
Function MultiLookup(Val As Variant, rItems As Range, rLookup As Range, Index As Long) As Variant
Dim vItems As Variant
Dim i As Long, n As Long
With rItems
If IsEmpty(.Cells(.Count)) Then
Set rItems = Range(.Cells(1, 1), .Cells(.Count).End(xlUp))
End If
End With
vItems = rItems
n = 0
For i = 1 To UBound(vItems, 1)
If vItems(i, 1) = Val Then
n = n + 1
If n = Index Then
MultiLookup = rLookup.Cells(i, 1)
Exit Function
End If
End If
Next
MultiLookup = vbNullString
End Function
Use like this, for cell E2
=MultiLookup($D2,$B:$B,$A:$A,COLUMN(A:A))
Again, copy accross for as many cells as use wish
Here is another non UDF solution, that works fast. Please note that it uses the AGGREGATE-Function, which is only available since Excel-2010.
Put this in E2 and drag across.
=INDEX($A$2:$A$1000,AGGREGATE(15,6,Row($1:$1000)/($B$2:$B$1000=$D2),COLUMN(A:A)))
You can also wrap this formula with a IFERROR to make sure you don't get the #VALUE! Error.
A PivotTable, with it's body copied into D2 and then blanks removed should be quick:

Resources