i have a named range that refers to range D3:I23 and this range is well-defined for some automation purposes.
Recently i had an update that required me to redefine this range as F3:I23 and exclude, initially, columns D & E. But further in the various logic coding, i need to include E for evaluation (turning dynamic data to static data).
Was thinking of using Resize but didnt seem right. Also thought Offset but that moves the whole range forward or backwards. I basically need to resize the range back 1 column while retaining the original defined range
In essence i need the named range to be defined as F3:I23 but during this one code segment i need the range to be evaluated to E3:I23.
Any thoughts, or combination of Range properties to use in VBA? At the point that i am passing the reference, it is being stored in a Range object, so any chained set of properties is fair game.
Please try to apply the KISS policy when answering. Doesnt need to be an overly complex formula, as i am not guaranteed to be the one supporting the end result.
As Rachel indicated... this should do the trick assumes your named range is defined as namedRange:
Set neededRange = namedRange.Resize(namedRange.Rows.Count, _
namedRange.Columns.Count + 1).Offset(0, -1)
Resize to increase the columns included by 1, then offset the entire range by -1 column to get your neededRange.
Related
I'm trying to make a graph for excel that takes data from a extending plot range, and I'm trying to use define a name with the range and use it as a legend entry, which doesn't work.
Formula for name I used.
=OFFSET(Sheet2!A2, 0, 0, COUNTA (Sheet2!A:A) - 1)
the name + range formula I used
the error
You should always be able to find a way around Offset. It's a volatile function and using Index is almost always better. It looks like you're trying to create a range that's dynamic... so this should work:
(Updated with absolute references)
=Sheet2!$A$2:INDEX(Sheet2!$A:$A,COUNTA(Sheet2!$A:$A),1)
See sample spreadsheet using it in a sum function. You'd have to use that for the named range, but just a copy paste.
How do I get the current region surrounding the ActiveCell using the Excel JS API?
In VBA this is
Set rng=ActiveCell.CurrentRegion
The current region property in the JavaScript API has now been implemented. The property is called getSurroundingRegion()
There is no direct equivalent, but we do have a range.getUsedRange() that will take an existing range and give you a smaller range that represents the non-empty portions. Note that this method will throw a not-found error if there is nothing in the entire range (since effectively it's an empty range, which Excel can't express).
If you really need the CurrentRegion scenario (and I'd be curious to learn more), you could first get the used range (to ensure you're not loading too much data), then load the values property, and then do range.getExpandedRange(indexOfLastRow, indexOfLastColumn).
BTW, unlike VBA's usedRange, the JS "getUsedRange()" always creates an accurate snapshot of the current used range (the VBA one could get stale), and we're exposing it not just on the worksheet but also on a given range.
Update
What I mean is that there are a couple of scenario, one simpler, the other harder.
The simpler one: you know roughly what range you need, but you just need to trim it. For example, you know you have a table-like entity in columns A:C, but you don't know the row count. That's where
worksheet.getRange("A:C").getUsedRange()
would get you what you need.
The harder one: you use getUsedRange() to trim down what you can, but you then load range.values and manually do a search for rows and columns where each cell is empty (""). Once you have that (suppose you found that the relative row index you care about is 5, and column index 2), you could do
originalRange.getCell(0, 0).getExpandedRange(rowIndex, columnIndex)
Concrete example for the above: You have data in A2:C7, though the getUsedRange() of the worksheet is much larger (and hence my suggestion could try to trim it down further by doing a range.getUsedRange()). But for this case, let's imagine that getUsedRange on a worksheet returned a range corresponding to A1:Z100. worksheet.getRange(0, 0) would get you the first cell, which you can then expand by 5 rows and 2 columns (which you find through simple albeit tedious array iteration) to get the range you care about. Makes sense?
I'm seeing quite some of methods to select a range, but not for my problem. I want to select a variable range, and i think the best way is to tell it to go upto a certain value. (then copy paste etc)
Within the range (one column) the number of rows will vary regularly. Also, there will be several empty rows within that range, and below it will be more full rows.
So, i'm thinking i put in an Anchor value, and always select the range upto that value, so adding and removing rows will not interfere. But how do i do that...
edit: So it's important i only copy upto that anchor value, what is below it must not be copied...
Anyone?
Solved As;
Set EndCell = ActiveSheet.Range("L7:L45").Find("AnchorSec", LookIn:=xlValues)
ActiveSheet.Range("L7", EndCell).Copy
AAR.Worksheets("Portfolio_2016").Range("K7").PasteSpecial
I still have to be careful with the range in which it looks for AnchorSec, but that could in theory be upto L1000 or where ever.
As an example if you were looking to have the range C1:C100 to be variable, you can just type C:C there. There is no need to specify the row numbers. (Am not sure if I have gotten your problem correctly. Sorry can't type this in the comments, don't have the reputation)
Many "advanced" (aka: VBA) excel tutorials on the web or even excel's vba help encurage us to use the
Range("B2:B10")
method (to be precise: object) for selecting cells or getting values. In the same place they often add it's totally ok to use predefined names as well:
Range("valuesabove")
On the other hand I fell in love with the incredible power of relatively defined cell names. They make it so much easier to write and handle big composite formulas, and basically to refer to nearly anything.
However, relative names don't work in the Range("valuesabove") method the way we are used to it.
Usually (when used on the worksheet) relative names are relative to the currently selected cell or to the cell in which they are used.
In VBA's Range() object this is not true. Range is relative to a WorkSheet object, by default to the ActiveSheet. But ActiveSheet is represenetd by its leftupper cell, A1. And this is what Range turns out to be relative to. And this is why absolute names ($C$23) do work with it, and relative ones ("one column to the left, two rows up") don't.
So my question is:
How can I harness the power of relative names in VBA then?
EDIT:
Realising that my question was rather unclear (thx's go to you guys commenting tirelessly) let me try to put it in a specific form and clarify terms:
IMHO on an excel worksheet it is very comfortable to use names in order to refer to cells or define calculated values by functions based on cell values.
In excel a reference to a cell can be either relative, absolute, or mixed. This is true also when creating names. Thus we can speak about absolute, relative or mixed names (in terms of referring of course).
Here an absolute name is used a couple times (created using excel's Trace Dependents function):
Name "name" = $D$2
A relative name is used a couple times here:
Name "upright24" while, e.g. cell A7 is selected = C3 (without $ signs!). But this changes constantly according to the selected cell or region. You can check it in the name manager! (Ctrl+F3)
And this is what we can consider as a mixed name:
Name "rel_serialnumber" while, e.g. cell C6 is selected = $B6. The row of which (6) changes constantly according to the selected cell or region.
The creation of a relative or a mixed name is explicitly based on the active cell at the moment of creating the name. The creation of an absolute name naturally doesn't rely on the cursor position.
Note, that
absolute names mean a dinamic offset from the referenced cell, which is one and only
relative names mean a static offset from the referenced cell, which thus changes always corresponding to the place where the name is used
mixed names mean a mixed (or half-dynamic) offset from the referenced cell, the row or column of which thus changes always corresponding to the place where the name is used while the other remains always the same (the offset in one or the other direction remains zero).
Okay, now here is the thing. I have a database-like excel sheet where I handle the rows like records and the columns as fields for properties. The user uses this thing as follows: he "selects a record" by placing the cursor in any cell of the row of the desired record. Then he presses a big command button which starts my VBA macro. This intends to open a prepared skeleton file and fill some specific cells in it (which are btw defined by absolute names) with some values (which are defined by mixed names) from the selected record.
Since Range("name") is considered ok to use in VBA (see above) I thought Range("relativename") or Range("mixedname") will work just as fine while automatically relying on the active cell.
I couldn't be worse.
Only Range("absolutename") works in the way one would expect! Explanation see above.
So I'm after a function / method / object that is possibly as comfortable to use with a "relativename" or a "mixedname" as Range("absolutename") is.
It appears you are looking for Range.Offset() http://msdn.microsoft.com/en-us/library/office/ff840060%28v=office.15%29.aspx
However you could do it as:
'Your example Range(Col_B_in_current_row) as
Range("B" & ActiveCell.Row).Select
'Your example Range("B2:B10") -> Range("valuesabove") as
Range("B2:B10").Offset(-1, 0).Select
Just seems like a relatively simple syntax already exists for this.
I think I've found a proper and compact solution. It's
Names("mixedname").RefersToRange
Not as short as Range("mixedname") would be but it is really providing the expected values.
UPDATE:
This solution is mostly unuseful if you want to copy relative-named cell values in a source workbook to relative-named cells in a dest workbook with a single codeline. This is because Names() relies on the actual position of the cursor which is depending on which workbook is currently the active one and in most cases this won't be ok for the other.
In this case the non-fixed part of the name has to be stored:
sourcerow = ActiveCell.Row
[...]
'opening a wbk, this also makes it the active one
[...]
Names("dest").RefersToRange = mysheet.Cells(sourcerow, mybook.Names("src").RefersToRange.Column)
To reference a Range relative to another Range you can use this syntax:
myRange.Range("namedRange")
Note: This only works if both the Row offset AND the Column offsets are positive. For example if the "Refers to" formula for the named range is "=Offset(A1,r,c)", then the above syntax will throw an error if Either r Or c is negative. But, it will work if both are positive.
The asymmetry is unfortunate but business as usual for VBA...
To Reference the third column in the row of the current ActiveCell:
ActiveCell.EntireRow.Range("C1")
To reference a cell offset by (for example) 1 row and 3 columns relative to the ActiveCell:
ActiveCell.Range("C2")
Obviously, you can use the same syntax with the Selection Object or any other Range value in VBA.
Private Sub Worksheet_Change(ByVal Target as Range)
If Not Intersect(Target.Address,ThisWorkbook.Sheets('sheetname).Range('RangeName)) Is Nothing Then _
'Do whatever you want down here.
ThisWorbook.Sheets('sheetname).Range('RangeName).Offset(0,Target.Row)
End If
End Sub
This should send you on the right path to what you want (which is super unclear). Use the worksheet change event to bring in user worksheet selections and changes into VBA modules. Put it into the relevant sheet.
I had the same problem, but I did get it to work - sort of. I don't know what is different about the simple example below, but it works. At first I thought selection mattered, but no - it works without changing the active cell.
(I still can't get it to work in my main spreadsheet.)
Named range: "TestName" = Sheet1!$H1
Values in H1:H10 = 1,2,3,4,5,6,7,8,9,10
Sub Test()
Dim x As Integer
For x = 0 To 10
Range("A1").Offset(x, 0).Value = Range("A1").Offset(x, 0).Range("Testname").Value
Next x
End Sub
Result: A1:A10 = 1,2,3,4,5,6,7,8,9,10
I'd like to reference a cell in a named range depending on a value outside of this named range
What I would like to see is ideally:
INDEX(named_range;;COLUMN()-RC1)
However, INDEX does not allow for the RC1 whilst it recognizes Column().
One way would be to make RC1 part of the named range (by copying the data into first column of range etc), but as the named range is somewhere completely different to the cell containing the formula, "I don't want to...".
Any other options to achieve it?
Thanks
*Addition:
Maybe the purpose helps. The aim is to find the number of installed units (named_range) that need to be replaced in the future depending on the lifetime which is in RC1.*
As per comments, you need to take into account the start column of the named range to get the correct column, possibly use
=INDEX(named_range;;COLUMN()-RC1-MIN(COLUMN(named_range))+1)
INDEX has two version, you're thinking solely of the INDEX/MATCH (2D) version, but it also has an INDEX/MATCH/MATCH version, too.
INDEX(My3DRange, MATCH("Y", MyYValues, 1), MATCH("X", MyXValues, 1))