Update multiple Named Ranges created by Dynamic Source using Spill

278 Views Asked by At

In Excel 365, currently I manually update multiple named ranges based on a dynamic header row, with dynamic values under each header. I hoping someone can help me with using VBA code to update the names and ranges all together based on the current data/table.

The goal is to have a drop down list with the relevant Units values, without blanks or duplicates, for each Item.

The source data comes from an external workbook that is updated weekly. The data is in columns of Item and Units, but there is often multiple instances of each Item and Units and each week there may be new Items or some removed, same with the associated Units values. The source is as per below example:

ITEM UNITS
AA 120 100
AA 120 100
AA 120 150
AA 60 350
BB 200 36
BB 200 30
BB 200 30
SH 1001 55
SH 1001 55

The unique headers are pulled using the formula

=IFERROR(INDEX($B$4:$B$600, MATCH(0, COUNTIF($K$2:K2, $B$4:$B$600), 0)),"")

The following formula is in the row below the headers, to pull the unique values for each header

=UNIQUE(FILTER($C$4:$C$600,$B$4:$B$600=L2))

The resulting table is as per below example:

AA 120 AA 60 BB 200 SH 1001
100 350 36 55
150 30

Currently I have highlight all the headers and the row below and select Create from Selection under Defined Names and select Top row. This creates named ranges that refer to the cell below each header. I then edit each range that the name refers to, by adding # at the end, so it refers to the spilled data, as it is a dynamic range.

e.g. Update the named range reference for AA_120 from =SHEET1!$L$3 to =SHEET1!$L$3#

I do this one by one for 100+ named ranges. Any tips or help to make this more efficient?

oh and the formula I'm using for the source of the Data Validation is =INDIRECT(C7) where C7 is the Item/named range. This all works well...

TIA

EDIT: I worked out some VBA code to add the # at the end of the referred range. The range for all Named Ranges starts on row 3, so this worked to update all relevant ranges at once...

Sub RangeRename()

Dim n As Name
    For Each n In Names
        If Right(n.RefersTo, 1) = "3" Then n.RefersTo = n.RefersTo & "#"
    Next n
End Sub

Would still really appreciate it if someone could improve on my VBA, to update all the ranges from when the source data is updated. Currently I delete all named ranges in the Name Manager, then select the 2 rows with all the updated Item and Units data. Then Create from Selection under Defined Names and select Top row. Then I run my macro. But if the Macro could do all above, that would be great. The difficulty I see if that the amount of Items and corresponding Units vary as it is dynamic. Plus there are 3 data sources on 3 different sheets, all rows 2&3 but columns start at L, N & T for the 3 sheets.

What I have worked out will work for me, but if anyone can improve on my code, I'd be extremely grateful!

2

There are 2 best solutions below

0
On BEST ANSWER

Just in case anyone is wanting to achieve the same thing.

I used a filter to create the column of items, then TRANSPOSE(UNIQUE(FILTER(G:G,B:B=T7 for the rows of unit options next to each item.

For the VBA I added the following to a module

Function xDAV(c As Range) As Range
Dim r As Range
 
With Sheets("LookUpList").Columns("T:T") 'Items
    
    Set r = .Find(What:=c.Value, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
    SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
    
    'Units are in col U
    'col U is 1 column to the right from col T
    n = 1 'change to suit
    
    If Not r Is Nothing Then
        Set f = r.Offset(, n)
            If f.Offset(, 1) = "" Then
                Set xDAV = f 'single cell or blank cell
            Else
                rc = f.End(xlToRight).Column 'get last column with data
                Set xDAV = f.Resize(, rc + 1 - f.Column)
            End If
    End If

End With

End Function

Then in the data validation I entered =toXDAV in the source field.

1
On

Maybe I don't understand exactly what you're trying to do...but can't you get the info you want with a simple pivot table? I imagine there are advanced tricks you can apply to that to get to the formatting you want...

But using current Excel formulas, I think I got what you want by doing this:

  1. I pasted your source data into a worksheet (A1:B10) and made it into a table (Control+T), selecting 'My table has headers' option. (I think it's better to use a table but it's certainly possible to tweak the formulas below if you don't want to.)

    source data

  2. I picked another cell on the same or another sheet--let's say E2--and entered =TRANSPOSE(UNIQUE(Table1[ITEM])). This gives a horizontal spill of unique items.

  3. In the cell immediately below that (ie, E3) I entered =IFERROR(SORT(UNIQUE(FILTER(Table1[[UNITS]:[UNITS]],Table1[[ITEM]:[ITEM]]=D15))),""). (You need to repeat the bracketed column names like this if you want to drag things horizontally, which we do.) If you don't need/want to sort the Units in the columns we're going to create, you can leave that part of the formula out.

  4. I dragged that cell horizontally to the left, going way beyond you need it right now (in case any new Items appear in your list). The IFERROR in the formula will keep the table looking clean on the right-most columns where no data currently appear. If/when you add more rows to your source data table, the spilled formulas will adjust accordingly, so I think your worry about dynamic sources is taken care of.

Results shown below. Maybe there's a way to devise a single formula that when put into E3 will spill into a 2-D array, so you don't even need to drag things...but I'll leave that to someone else.

resulting table