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
Related
Consider the following table:
I have a series of blank cells with missing data. From this missing data I only have the year in the next column. I need to fill any blank cells with a standard day/month of 30/06. The year of each cell however needs to be the year in the next column. The attached file shows how my data is arranged. So at cell B 2091, the date shall be 30/06/2011 while for cell B 2098 the date shall be 30/06/2018 and at cell B 2100 the date shall be 30/06/2008.
Filter on the blank cells in column B. Then, in the topmost cell (which I'll assume to be B1 but will likely be different), enter a formula similar to the following and fill down
=DATE(C1,6,30)
where the row number in C1 is the same as your first row of data.
You can achieve this with a helper column (any blank column in the same worksheet where you need the dates). In that column enter this formula in the first cell (here in row 2) and copy down.
=IF(ISBLANK(B2),DATE(C2,6,30),B2)
Then copy the Values from the helper column to the date column and delete the helper.
Below is a small macro that is doing the same job. It needs no helper column and over-writes your existing blanks. Before you run it make sure to check the values of the 2 constants at the top and the name of the worksheet (especially the latter!) against your requirements.
Sub WriteStandardDate()
'293
Const FirstDataRow As Long = 2 'change to suit
Const DateClm As Long = 2 'change to suit
' year column must be adjacent to DateClm
Dim R As Long
Dim Arr As Variant
Dim Rng As Range
With Worksheets("Sheet1") ' change name as required
Set Rng = .Range(.Cells(FirstDataRow, DateClm), _
.Cells(.Rows.Count, DateClm).End(xlUp)) _
.Resize(, 2)
Arr = Rng.Value
For R = 1 To UBound(Arr)
If IsEmpty(Arr(R, 1)) Then
Arr(R, 1) = DateSerial(Arr(R, 2), 6, 30)
End If
Next R
Rng.Value = Arr
End With
End Sub
Update: I used the formula suggested by Variatus: =IF(ISBLANK(B2),DATE(C2,6,30),B2) and worked fine through a helper column. There was no need to copy / paste the new dates into the Dates column. I just used the helper column as the new Dates column since full dates from the original column were not changed and got inserted in the helper column thanks to the IFBLANK portion of the formula. Thanks.
I need to go through a table (X by Y) where every column (X) should have the same value (string) and would like the cell to get highlighted if is not the same value. I'm stuck in building the comparison method, because I would like it to be dynamic. I would like to first determine what is the value that is present the most in the column and determine that is what everything else needs to be compared against and highlight the cell that is not equal to this value.
Example (6x5 table) -
A 3 4 C M R
A 3 4 O M R
8 3 T O M F
8 3 4 O M G
A 3 T O Y K
In the first column, A is the most prevalent value therefore the (8s) are highlighted, second column nothing is highlighted, third both (T) are highlighted, fourth column (C), fifth column (Y) and sixth column (F),(G) and (K) are highlighted.
Thank you in advance.
I can suggest a workaround. Not sure if this is the best way though.
Step 1. Create a count if table which basically gives you the count of a value in the column. Ex: for cell F4 use formula =COUNTIF($B$4:$B$8,B4)
Step 2. Create a row with max values of each column. Ex: Cell F11 =MAX(F4:F8)
Step 3. For each cell, give a conditional formatting condition that if the value in the count table does not match the max value, color it. Ex: for cell B4, go to conditional formatting -> new rule -> use a formula and write this formula =F4<>F$11. Then copy paste the format to all other cells.
Note: this will not work when multiple values in a column have the same max count.
Here is a VBA solution, I've commented the code so you can understand
Sub HighlightNonFrequentInColumn()
Dim rng As Range
Dim col As Range
Dim cell As Range
Dim myVal As String
Dim colRng As String
Set rng = Selection '<<change range as required
For Each col In rng.Columns
'determine the most frequent value
colRng = col.Address
On Error Resume Next
myVal = Application.Evaluate("INDEX(" & colRng & ",MODE(IF(" & colRng & "<>"""",MATCH(" & colRng & "," & colRng & ",0))))")
If Application.countblanks(col) > Application.CountIf(col, myVal) Then myVal = "" '<<if blanks are most frequent
'highlight all cells not equals to most frequent value
For Each cell In col.Cells
If Not cell = myVal Then cell.Interior.Color = vbYellow '<<change colour as desired
Next
Next
End Sub
i m new to VBA, need help on this issue from experts.
I splitted a BBG function into cell B1 and D1
B1="BDS($C"D1=","PG_REVENUE","PRODUCT_GEO_OVERRIDE=G","number_of_periods=6")"
C2 To C6 are names of stocks
It looks like this when pasted to cells
=BDS($C2,"PG_REVENUE","PRODUCT_GEO_OVERRIDE=G","number_of_periods=6")
As the code below, I would like to copy the formula to cell firstly H11, and then move 10 cells to the right to cell R11 and paste the formula again and repeat the process.
For cell H11, i would like the formula to use $C2 as the first argument, for R11, i want 2 to be increased to 3, so the first argument becomes $C3
My codes allow me to loop and paste the formula horizontally but failed to increase the count each time it moves. (All cells gives $C6 as the input)
How can i change my codes so that the counter will increase by 1 as when it moves to the right?
Sub paste_formula()
Dim cp As Worksheet
Dim x As Integer
Dim y As Integer
Dim t As Integer
Dim m As Range
Set cp = Sheets("Control Panel")
cp.Activate
For t = 8 To 100 Step 10
For x = 2 To cp.Range("C2").End(xlDown).Row
cp.Cells(11, t).Formula = "=" & cp.Range("B1") & x & cp.Range("D1")
Next x
Next t
End Sub
I want
At cell H11, =BDS($C2,"PG_REVENUE","PRODUCT_GEO_OVERRIDE=G","number_of_periods=6")
At cell R11, =BDS($C3,"PG_REVENUE","PRODUCT_GEO_OVERRIDE=G","number_of_periods=6")
At cell AB11, =BDS($C4,"PG_REVENUE","PRODUCT_GEO_OVERRIDE=G","number_of_periods=6")
etc
I have data in excel file for which filter has to be applied for each column independently but the filter condition is same. The reason for asking this is each column has that cell that meets the condition in a different row number.In table 1 I have 3 columns a,b and c.
I want to filter each columns independently with value=20 so that the result looks like table below
Try out this VBA code,
Sub matchvalues()
Dim i As Long, j As Long
Sheets.Add.Name = "newSheet"
j = InputBox("Enter the value to filter")
Rows("1:1").Copy Sheets("newSheet").Cells(1, 1)
For i = 1 To Cells(1, Columns.Count).End(xlToLeft).Column
If IsError(Application.Match(j, Columns(i), 0)) Then
Sheets("newSheet").Cells(2, i) = ""
Else
Sheets("newSheet").Cells(2, i) = j
End If
Next i
End Sub
This code will prompt the value that has to be filtered. Need to give that as input which will create a new sheet and output the values if present.
If you want to do this with just formulas, try the below. If the value that you are searching is in cell E1, enter the below formula in cell G2 and drag across.
=IF(ISNUMBER(MATCH($E$1,A:A,0)),$E$1,"")
You can change the values in E1 directly to see the updated result. Hope this helps.
I am trying to find a way to get multiple values from an array to display in one cell
Say for example I have the two columns as below
a 1
b 2
c 1
d 3
e 2
I want all the values form the first column where the second column is 1
vlookup and index with match both only provide the first matching instance, is there a way to do this with a function or does it have to be created in a macro with VBA?
Thanks
If you want all the results to be shown in ONE cell you could use that VBA formula:
'r is the range of cells that you have a value to look for
'v is the value you are looking for
Function getValues(r As Range, v As Variant)
Dim c As Range
getValues = ""
For Each c In r
If c.Value = v Then
If getValues = "" Then
'Offset(0,-1) will give you value from previous coulmn
getValues = c.Offset(0, -1).Value
Else
getValues = getValues & "," & c.Offset(0, -1).Value
End If
End If
Next c
End Function
Use example: in cell C1 enter this =getValues(B1:B5,1)
Considering your data is in range A1:B5 and Cell C1 contains the number you are looking for.
Enter the following array formula in Cell D1 and drag/copy down till the row as required.
=IFERROR(INDEX($A$1:$A$5, SMALL(IF($C$1=$B$1:$B$5, ROW($B$1:$B$5)-MIN(ROW($B$1:$B$5))+1, ""), ROW(A1))), "")
Being an array formula you'll have to commit above formula by pressing Ctrl+Shift+Enter.
Using helper columns this is possible with formulas alone.
Formulas:
In D1:
=""
In D2 downwards:
=IF(B2=$B$1,D1&A2&", ",D1)
In C1:
=LEFT(LOOKUP(2,1/(D:D<>0),D:D),LEN(LOOKUP(2,1/(D:D<>0),D:D))-2)