I have a table to enumerate the headers in another table, and I want it to show whether a column is calculated or not. I've used ISFORMULA to look it up, which works fine as long as I stick to the same worksheet, but I can't seem to find a way to reference a cell on another sheet. I'm currently using this:
=IF(ISFORMULA(ADDRESS(2, $D2, 1, 1, "BMSB Finds")), 1, 0)
The other worksheet is called "BMSB Finds", the column number is held in column D. This just leads Excel to tell me that the formula contains an error.
I've also tried using an index match, which presents no errors but also just shows FALSE regardless of the cell content.
Using manual references works, of course, but means going cell by cell, thus ruining the point of doing it automatically.
Any idea how to make ISFORMULA accept the reference?
ADDRESS returns a text (textual representation of an address), while ISFORMULA requires an address, that's why Excel is giving you can error.
You should be able to use INDEX:
=IF(ISFORMULA(INDEX('BMSB Finds'!1:10000,2,$D2)),1,0)
Adjust the range as necessary.
Related
I have some materials in column B, a few among these are in a Table definition called Material_List. In D49 I am trying to write a conditional statement such that, if the data in B49 already exists in the table definition, then print the header name or else INDIRECT($49). C49 has the independent dropdown list and D49 will be the dependent.
In D49 I have used the following formula within the Data-->Data Validation-->Source=
=IF(MAX((ISNUMBER(MATCH(Material_List;$B49;0))*COLUMN(Material_List)))=0;
INDIRECT($C49);
INDEX(Material_List[#Headers];1;MAX((ISNUMBER(MATCH(Material_List;$B49;0))*
COLUMN(Material_List))))))
with Allow=List. But it says Error "There is a problem with this formula"
When typed the following formula in cell D50 directly, it works well but obviously without dropdown.
=IF(MAX((ISNUMBER(MATCH(Material_List;$B50;0))*COLUMN(Material_List)))=0;
INDIRECT($C50);
INDEX(Material_List[#Headers];1;MAX((ISNUMBER(MATCH(Material_List;$B50;0))*
COLUMN(Material_List))))))
I am trying to build a dropdown list based on the mentioned criteria. could anyone please tell what is wrong with my formula?
I think the main issue with your formula is that you cannot use table references in the data validation.
Don't ask me why. I think it is just an outstanding Excel bug which hasn't been fixed yet. Please see this link for further info: https://exceloffthegrid.com/using-an-excel-table-within-a-data-validation-list/
The best way I have found to work around this is to create a named range which refers to the table references you need ("Material_List" and "Material_List[#Headers]" in your case). Then you can use those named ranges in your data validation instead of the table references directly.
However, I think there are also other issues with your formula. For example, this part:
MATCH(Material_List;$B50;0)
Normally a MATCH would be in the format of:
MATCH(<single value to look for>, <range to look in>, 0)
You appear to have that reversed, meaning that it should always return a #VALUE! error.
Also, I don't think you can use match on a 2D array, so if your "Material_List" table is more than a single column, that would also cause it to return a #VALUE! error.
UPDATE:
The way I would tackle dependent dropdowns would be as follows.
I would create a "Material_List" table similar to below (could be on a hidden sheet):
Then I would create 3 named ranges.
One for the table body range, called "MaterialList_TblRange":
=Material_List
One for the table header range, called "MaterialList_TblHeaderRange":
=Material_List[#Headers]
And one to refer to the dependant dropdown options, called "DropDownOptions" (this is by far the most complicated part):
=INDEX(MaterialList_TblRange,1,MATCH(Sheet1!$B23,MaterialList_TblHeaderRange,0)):INDEX(MaterialList_TblRange,COUNTA(INDEX(MaterialList_TblRange,1,MATCH(Sheet1!$B23,MaterialList_TblHeaderRange,0)):INDEX(MaterialList_TblRange,ROWS(MaterialList_TblRange),MATCH(Sheet1!$B23,MaterialList_TblHeaderRange,0))),MATCH(Sheet1!$B23,MaterialList_TblHeaderRange,0))
I will explain what this is doing in a moment.
The last step is to set up the data validation where we want our lists.
Where we want the master lists to appear, we can simply enter:
=MaterialList_TblHeaderRange
And the defendant dropdown validation can be entered as:
=DropDownOptions
This is the result:
Now back to the long "DropDownOptions" named range formula...
Basically, we use INDEX:INDEX to select the first/last cell in the range we want to use in out dropdown.
The first INDEX:
=INDEX(MaterialList_TblRange,1,MATCH(Sheet1!$B23,MaterialList_TblHeaderRange,0))
Simply selects the first cell from the column whose header matches the selection in our first dropdown.
The second index does the same, except that instead of selecting the first cell in the column, it counts the number of cells that contain text and uses that as the last cell in the range.
This does mean that we mustn't have any gaps in this table, otherwise an option might be missed off the end.
I hope this makes sense.
I've been struggling with this longer than I care to admit, but I have a fairly simple OFFSET function call which works on one sheet, but if I copy it to a different sheet it gives a #VALUE error.
On a sheet named "Deliverable" I have this formula in a cell:
=OFFSET(Deliverable!$B$72,1,0,,3)
and it works fine.
If I go to any other sheet and use the same exact formula, or use it in the Name Manager, it gives a #VALUE error.
If I leave off the final parameter indicated the number of columns I want, it does work:
=OFFSET(Deliverable!$B$72,1,0)
but of course isn't giving me the range I need.
Any idea what's going on with this?
I'm using Excel 2016 on Windows 7.
-- Updated Info --
In a nutshell, my spreadsheet has two cells which I'm using as dropdown lists, where the 2nd cell's list feeds off the selection in the first. The data they are based on has this format:
OptionA A B C D
OptionB A B
OptionC D E F
So the first dropdown uses a simple Data Validation source pointing to the column with OptionA, OptionB, etc. Once that's chosen, the second dropdown list should contain the appropriate options for the one selected. So if OptionB is selected, then the 2nd dropdown list should show A and B.
When I initially wrote this, the data validation source was just a simple VLOOKUP entry, but the lists often had blanks since the number of options varies for each entry. Wanting to fix it up a bit, I ended up with this formula:
=OFFSET(Deliverable!B72,Deliverable!B87,0,1,COUNTA(OFFSET(Deliverable!B72,Deliverable!B87,0,1,5)))
There won't be any more than 5 options, and there are no empty cells in the middle of the data to filter out.
In one spreadsheet I have I used this as a named range definition, then specified the named range for the cells data validation source and it worked. In this other spreadsheet however, it gave me the error described earlier.
However, it looks like when I enter the statement directly into the data validation source field and not in the name manager, it works as expected.
Am I taking the totally wrong approach?
What is it that you want this formula to do? As written, it is returning a block of three horizontal cells. The #VALUE error is Excel's way of telling you "Hey, you're trying to return three cells, but I can't fit them all in the one cell that you are calling this formula from".
The reason you see a result in some places and not others is because of something called Implicit Intersection. Give it a spin on Google. But basically, it just returns whichever one of those three results corresponds to the column that the formula is entered into. If you copy that exact same formula to say row F you will see that it returns a #VALUE error there, because it doesn't know what cell it should return given the column you're calling it from doesn't match any of the cells it is returning. The fact that you don't know this indicates that the formula you're using doesn't in fact do what you think it does.
--UPDATE --
Okay, following your further clarificaiton it seems that you're talking about Cascading Dropdowns aka Dynamic Dropdowns. Lots of info on Google about how to set these up, but you may be interested in an approach I blogged about sometime back that not only provides this functionality, but also ensures that someone can't later on go and change the 'upstream' dropdown without first clearing the 'downstream' one should they want to make a change.
Note that those links talk about a slightly complicated method compared to others, but the method has it's advantages in that it also handles more levels than two, and your DV lists are easily maintained as they live in an Excel Table.
This sounds like an array equation. Try hitting Ctrl+Shift+Enter in the other sheets to validate it as an array equation.
Whenever you need to reference ranges instead of single cells, Excel needs to know that you are working with arrays.
What I am trying to achieve is matching two projects with eachother "Project No" in two tables, and return the "project name" in second table. When I do this I receive this error inside the cell error #N/A.
I have formated both tables into number value, but this does not solve the problem.
Anyone that has an idea what I can do in order to solve this problem.
Here is the first table (just a snapshot to give an idea).
Here is the second table (just a snapshot to give an idea).
The #N/A error indicates that Excel cannot find the value you've specified in the list in which you've told it look. When I run into this, there are a few things I do to troubleshoot:
1) Make sure both columns are in the same format.
You mention you've already done this (good job!) but sometimes formatting gets stuck in Excel. One thing you can do is to highlight each range and use the text to columns feature (under the data tab) to convert it all to the same format. Another option is to copy the range into Notepad or some other plain text editor and then copy it back into Excel to strip out any lingering formatting.
2) Double check your ranges.
Make sure your Vlookup is looking to the correct range, and make sure that range is locked (i.e. $A$1:$D$100 rather than A1:D100), or else your ranges are going to slide around as you move drag the formula down your table. If the range refers explicitly to a table address (e.g. Table1[#All]), then make sure every data point if validly within that table.
3) Make sure the range lookup parameter is set to FALSE
Range lookup is the last parameter of the vlookup, and determines whether the vlookup will find an exact match (set range lookup to FALSE) or a partial match (set range lookup to TRUE). Setting range lookup to TRUE can sometimes create errors like the one you've described. I always set it to FALSE by default unless I need specifically need to set it to TRUE.
4) Use the find and replace window to manually evaluate the formula
If everything looks correct, copy the value you want to look up and paste it into the find and replace window to search for it. If Excel can't find it and you can see it in your list, something is definitely wrong with the formatting or else your file may have some degree of corruption. If Excel can find the value, double check that it is within the range your vlookup is looking through.
If fist table is the one with vlookup formula and second is a source it may mean that such Project No. doesn't exist in your source table. Did you check that possibility?
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
Here is a reduced version of what I need. Essentially, we have a list of components and their status (imagine they have been tested). Component BBB has two sub-components, BBB1 and BBB2. I want their status to reflect that of the BBB component 'parent'. Easily done, apart from the list is very long, and I need to retain the option to sort it as I wish. If I user a simple cell reference to "=B3", then this is invalid once the list is sorted. Similarly with a named range as B3; the named range address is static and does not dynamically alter when the list is sorted.
I could fix this by having a 'static' BBB status somewhere that is not in the sort area, but this is inelegant, and I don't like inelegance!
Any ideas?
http://FileHost.JustFreeSpace.Com/158complist.xls
I'm not fully sure of your use and needs, but try this litte formula:
=ADDRESS(MATCH("BBB",A:A,0),1)
It will return the cell address where BBB sits.
If you remove the ADDRESS portion of the formula, it will return the Row number.
It can also be modified to pull the Value in your 'Status' Column.
If you put this formula in the 'Status' column for rows BBB1 & BBB2, then it will update when BBB changes:
=INDEX(A:C,MATCH(LEFT(A2,3),A:A,0),2)
Let me know if I'm only warm, or if I got it.
Perhaps the VLOOKUP worksheet function does what you need? See http://office.microsoft.com/en-us/excel/HP052093351033.aspx
There's a very easy solution. Just used an absolute reference, e.g. =$B3 or =B$3 or =$B$3
If I user a simple cell reference to "=B3", then this is invalid once the list is sorted.
Sorting won't invalidate these absolute references.
If you're just using =B3, on sorting Excel will update that on its own when you sort, as long as you don't sort using VBA. If you want to keep a handle on that cell, you may need to find it again manually or keep tabs on where it goes to as you move it around.
For references within the same row, use relative references. (This is not your question.)
For references to other rows, use VLOOKUP (with FALSE as the last parameter) if you can identify a unique key to each row. If there is not a natural key, construct a surrogate and make sure it is and remains unique. [I display the next value to use in the table header and use conditional formatting to highlight the non-uniques. This breaks quite easily, if you insert a copied row, for example.]
Absolute references won't work. They retain the exact cell reference - but after sorting this now points to whatever value was sorted into that position. I believe this is a bug in Excel, either in the code or in the specification. The behaviour one would expect is that the values in a tuple remain unchanged, even when that tuple is moved around by a sort. With absolute references, the value in the cell with the absolute reference changes, even if - or rather because - the reference itself remains the same.
If the cell reference is to a cell in another ROW, it will change after sorting even in spite of locking the cell reference with the $ sign.