Use cell value to activate another sheet then clear original cell value without an error - vba

I have cell A1 on a sheet named "Data" that looks for input which when received, looks for a sheet name that matches it. If it finds a match, it opens that sheet. I'm trying to clear the value entered in A1 of "Data" after that second sheet has been opened however I'm getting a runtime error that appears to still be looking for the data used to open the second sheet. Here is the code for the "Data" sheet:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Range("A1"), Target) Is Nothing Then Exit Sub
Sheets(Target.Value).Activate
End Sub
I tried using a variable in place of Target.Value hoping that after deleting the actual data in A1, the variable would satisfy the code.
I've ran the following line on at the end of the block above as well as on the sheet which gets activated but either way I get an error.
Sheets("Data").Range("A1:A1").ClearContents
The error is "Run-time error 9 Subscript out of range.
How do I clear the contents of A1 on "Data" so it's ready to receive another request to open another sheet when I'm done with the last one?

This is the correct syntax for a single cell:
Sheets("Data").Range("A1").ClearContents
...however using a range of A1:A1 should also work, so if you're getting Subscript Out Of Range then there is likely no worksheet named Data.
If you have multiple workbooks open then by default, it's looking for the Active Workbook (whose name in contained in ActiveWorkbook.Name.) So if you're going to be working with multiple workbooks, you should explicitly state the workbook name as well:
Workbooks("Book1").Sheets("Sheet1").Range("A1").ClearContents

I didn't need to clear the value after all. I added a couple lines to ensure when returning to the "Data" sheet, cell A1 was selected. This allows for a new value to be entered replacing the previous value and serves the purpose.

Just a slight change to your code. "Is Nothing" does not work. The below code works fine for me.
If Intersect(Target, Range("A1")) = "" Then Exit Sub
Sheets(Target.Value).Activate
Target.ClearContents

Related

Subscript out of range on VBA

I am writing my first VBA. I have a sheet named Sheet1. That sheet has a column E; I would like to delete all rows which have an empty field on column E.
Therefore, I wrote this code:
Sub EmptyCells()
Sheets("Sheet1").Columns("E:E").SpecialCells(xlBlanks).EntireRow.Delete
End Sub
However, when I run it, I get this error:
Subscript out of range
Why is this error occurring? I am sure the column E exists in Sheet1. Are my references incorrect?
EDIT
If I try Columns("E") or Range("E:E"), instead of Columns("E:E") I get the same error
Your code will work if there are any REAL empty cells in column E (within UsedRange).
You may have cells that contain formulas returning Null. SpecialCells does not consider them empty. You may have cells in column E containing Null as a constant; SpecialCells also considers them filled.
EDIT#1:
Based upon your specific error message make sure the worksheet name is spelled correctly. Sheet1 is not the same as Sheet 1
Your code works if you have a sheet named/titled Sheet1.
Sub EmptyCells()
Sheets("Sheet1").Columns("E:E").SpecialCells(xlBlanks).EntireRow.Delete
End Sub
Note that there are different ways to call a sheet.
Sheets("Sheet1") 'means the visible name of the sheet is `Sheet1` (not the same as VBA name)
'the number doesn't tell anything about it's position, it's just a name.
Sheet1 'means the VBA name of the sheet.
'the number doesn't tell anything about it's position, it's just a name.
Worksheets(1) 'means the first worksheet (which ever is in the first position)
Sheets(1) 'means the first sheet (can also be a chart not only a worksheet)
'this has no relation to its name which could be "Sheet5"
'(If "Sheet5" is in first position).
I have tried this and it works:
Option Explicit
Sub TetsMe()
MsgBox (Worksheets(1).Parent.Name & VbCrLf & Worksheets(1).Name)
Worksheets(1).Columns("E:E").SpecialCells(xlBlanks).EntireRow.Delete
End Sub
The different syntax as the index may refer to a different sheet. In this case Worksheets(1) is the first worksheet in the workbook.
The MsgBox() will tell you which worksheet and which workbook you are changing. Once you know, what you are doing, you may remove it.
If the problem is in the workbook name, then it is easy to change it like this:
With Workbooks("NameYourWorkbook").Worksheets("NameYourWorksheet")
.Columns("E:E").SpecialCells(xlBlanks).EntireRow.Delete
End With

Range SpecialCells ClearContents clears whole sheet instead

I have a sheet in Excel 2010 which is setup as a pseudo form (I didn't create it, I'm just trying to fix it) so formatting suggests that the user can only enter in certain cells. Depending on certain functionality these areas need to be reset, i.e. cleared although formulae and standard/conditional formatting need to be kept. I have defined each of these cells/ranges as named ranges so I can easily loop through them using the following code: -
Public Sub ResetDetailSheet()
Dim nm As Name
With ThisWorkbook
For Each nm In .Names
If Left(nm.Name, 9) = "nmrDetail" Then
Range(nm.Name).SpecialCells(xlCellTypeConstants).ClearContents
End If
Next
End With
End Sub
For some reason instead of clearing the constants from the specific range it is clearing constants from the entire sheet so I am losing all titles/headings. Formulae and standard/conditional formatting are staying as expected.
What am I doing wrong?!?!
As a test using the immediate window I tried clearing a specific cell, e.g.
Range("G7").SpecialCells(xlCellTypeConstants).ClearContents
But this still cleared all constants from the entire sheet.
What am I missing? I don't understand. Maybe I'm being dumb.
Sorry, I can't upload an example. This place is pretty locked down.
Range({any single cell}).SpecialCells({whatever}) seems to work off the entire sheet.
Range({more than one cell}).SpecialCells({whatever}) seems to work off the specified cells.
So, make sure your range has more than a single cell before you clear it - if the range is only a single cell, then check if it .HasFormula; if that's the case then its .Value isn't a constant:
With ThisWorkbook
For Each nm In .Names
If Left(nm.Name, 9) = "nmrDetail" Then
If nm.RefersToRange.Count > 1 Then
nm.RefersToRange.SpecialCells(xlCellTypeConstants).ClearContents
ElseIf Not nm.RefersToRange.HasFormula Then
nm.RefersToRange.ClearContents
End If
End If
Next
End With
Note that I'm using Name.RefersToRange instead of fetching the range by name off the active sheet.

Using the contents of cell's as part of a file location in a macro

This is what I have:
Option Explicit
Sub EditWorksheet()
Workbooks.Open "Y:\Laurence\contents(J2)"
Sheets("contents(N2)").Select
End Sub
So what I want to do is have VBA call on the values of cells J2 and N2 in order to decide which workbook and worksheet to open. For your information J2 could contain for example "Forecast2016.xlsx" and N2 may contain "MASTER". Just to be clear, for every possible content these cells can have, I do indeed have a spreadsheet in the relevant file location (Y:\Laurence).
Thanks in advance!
The problem is you are not passing a string, but a range with that code. This causes the run time error 13. Instead of
Workbooks.Open "Y:\Laurence\contents(J2)"
Sheets("contents(N2)").Select
try
Workbooks.Open "Y:\Laurence\" & Sheets("Contents").Range("N2").Value
Sheets(Sheets("Contents").Range("N2").Value).Select
This forces the value of the cell to be passed, not a reference to the range. Also notice I qualified your worksheet that you were referencing as well. As you had it before, it would have pulled Range("N2") from whatever sheet happened to be open at that moment.

Error in passing named range as argument in VBA

I'm having a problem while passing ranges across two subprocedures. Can you suggest the possible error ?
I have defined two subprocedures in VBA. In the first subprocedure, I have a selection of cells (3X3 MATRIX), named under "ABC" which I'm copying to another selection of cells "PQR". This is working :)
I wanted to enable "all borders" when the values are copied on PQR from ABC. For this I recorded a macro.
But, whenever I run this subprocedure, it is giving an error that object doesn't exist.
I called the macro in the following manner :
All_border_test PQR
The code for subprocedure is as given below :
Sub All_borders_test(d As Range)
Range(d).Select
' Recorded Macro to enable all borders (its working)
End Sub()
1- Take a look at: What's the RIGHT way to reference named cells in Excel 2013 VBA? (I know I'm messing this up) and VBA Reference Named Range ActiveSheet
2- fix your code to be like:
Sub All_borders_test(d As Range)
d.Select ' old code was: Range(d).Select
End Sub 'no parenthesis here
3- you can call All_borders_test using one of the following calls:
Call All_borders_test([PQR])
Call All_borders_test(Range("PQR"))
Call All_borders_test(Sheet1.Range("PQR")) ' assuming that PQR range exists in Sheet1

Get the cell reference of the value found by Excel INDEX function

The Problem
Assume that the active cell contains a formula based on the INDEX function:
=INDEX(myrange, x,y)
I would like to build a macro that locates the value found value by INDEX and moves the focus there, that is a macro changing the active cell to:
Range("myrange").Cells(x,y)
Doing the job without macros (slow but it works)
Apart from trivially moving the selection to myrange and manually counting x rows y and columns, one can:
Copy and paste the formula in another cell as follows:
=CELL("address", INDEX(myrange, x,y))
(that shows the address of the cell matched by INDEX).
Copy the result of the formula above.
Hit F5, Ctrl-V, Enter (paste the copied address in the GoTo dialog).
You are now located on the very cell found by the INDEX function.
Now the challenge is to automate these steps (or similar ones) with a macro.
Tentative macros (not working)
Tentative 1
WorksheetFunction.CELL("address", ActiveCell.Formula)
It doesn't work since CELL for some reason is not part of the members of WorksheetFunction.
Tentative 2
This method involves parsing the INDEX-formula.
Sub GoToIndex()
Dim form As String, rng As String, row As String, col As String
form = ActiveCell.Formula
form = Split(form, "(")(1)
rng = Split(form, ",")(0)
row = Split(form, ",")(1)
col = Split(Split(form, ",")(2), ")")(0)
Range(rng).Cells(row, CInt(col)).Select
End Sub
This method actually works, but only for a simple case, where the main INDEX-formula has no nested subformulas.
Note
Obviously in a real case myrange, x and ycan be both simple values, such as =INDEX(A1:D10, 1,1), or values returned from complex expressions. Typically x, y are the results of a MATCH function.
EDIT
It was discovered that some solutions do not work when myrange is located on a sheet different from that hosting =INDEX(myrange ...).
They are common practice in financial reporting, where some sheets have the main statements whose entries are recalled from others via an INDEX+MATCH formula.
Unfortunately it is just when the found value is located on a "far" report out of sight that you need more the jump-to-the-cell function.
The task could be done in one line much simpler than any other method:
Sub GoToIndex()
Application.Evaluate(ActiveCell.Formula).Select
End Sub
Application.Evaluate(ActiveCell.Formula) returns a range object from which the CELL function gets properties when called from sheets.
EDIT
For navigating from another sheet you should first activate the target sheet:
Option Explicit
Sub GoToIndex()
Dim r As Range
Set r = Application.Evaluate(ActiveCell.Formula)
r.Worksheet.Activate
r.Select
End Sub
Add error handling for a general case:
Option Explicit
Sub GoToIndex()
Dim r As Range
On Error Resume Next ' errors off
Set r = Application.Evaluate(ActiveCell.Formula) ' will work only if the result is a range
On Error GoTo 0 ' errors on
If Not (r Is Nothing) Then
r.Worksheet.Activate
r.Select
End If
End Sub
There are several approaches to select the cell that a formula refers to...
Assume the active cell contains: =INDEX(myrange,x,y).
From the Worksheet, you could try any of these:
Copy the formula from the formula bar and paste into the name box (to the left of the formula bar)
Define the formula as a name, say A. Then type A into the Goto box or (name box)
Insert hyperlink > Existing File or Web page > Address: #INDEX(myrange,x,y)
Adapt the formula to make it a hyperlink: =HYPERLINK("#INDEX(myrange,x,y)")
Or from the VBA editor, either of these should do the trick:
Application.Goto Activecell.FormulaR1C1
Range(Activecell.Formula).Select
Additional Note:
If the cell contains a formula that refers to relative references such as =INDEX(A:A,ROW(),1) the last of these would need some tweaking. (Also see: Excel Evaluate formula error). To allow for this you could try:
Range(Evaluate("cell(""address""," & Mid(ActiveCell.Formula, 2) & ")")).Select
This problem doesn't seem to occur with R1C1 references used in Application.Goto or:
ThisWorkbook.FollowHyperlink "#" & mid(ActiveCell.FormulaR1C1,2)
You could use the MATCH() worksheet function or the VBA FIND() method.
EDIT#1
As you correctly pointed out, INDEX will return a value that may appear many times within the range, but INDEX will always return a value from some fixed spot, say
=INDEX(A1:K100,3,7)
will always give the value in cell G3 so the address is "builtin" to the formula
If, however, we have something like:
=INDEX(A1:K100,Z100,Z101)
Then we would require a macro to parse the formula and evaluate the arguments.
Both #lori_m and #V.B. gave brilliant solutions in their own way almost in parallel.
Very difficult for me to choose the closing answer, but V.B. even created Dropbox test file, so...
Here I just steal the best from parts from them.
'Move to cell found by Index()
Sub GoToIndex()
On Error GoTo ErrorHandler
Application.Goto ActiveCell.FormulaR1C1 ' will work only if the result is a range
Exit Sub
ErrorHandler:
MsgBox ("Active cell does not evaluate to a range")
End Sub
I associated this "jump" macro with CTRL-j and it works like a charm.
If you use balance sheet like worksheets (where INDEX-formulas, selecting entries from other sheets, are very common), I really suggest you to try it.