Determine if ActiveCell is in a specific table - vba

I am trying to determine by VBA in Excel 2013 if the ActiveCell is not just in any table, but in a specific table.
Below is the code as is, but only detects ActiveCell being in any table. The commented out line is what I'm looking for, but obviously it doesn't work.
...
Set rng = Intersect(.EntireRow, ActiveCell.ListObject.DataBodyRange)
'Set rng = Intersect(.EntireRow, ActiveCell.ListObjects("myTable").DataBodyRange)
On Error GoTo 0
If rng Is Nothing Then
MsgBox "Please select the cell of a row within the consensus input table.", vbCritical, "Delete Evaluator"
Else
...
Any suggestions on the right syntax for this?
Thanks!

To test if ActiveCell is in the body of Table1:
Sub qwerty()
If Intersect(ActiveCell, ActiveSheet.ListObjects("Table1").DataBodyRange) Is Nothing Then
MsgBox "activecell not in Table1"
Else
MsgBox "activecell in Table1"
End If
End Sub

Generally, we're interested in work being performed within the DataBodyRange of a table and Excel provides us a shortcut for that area of a Table. For a table named "myTable", you directly access the DataBodyRange in code using [myTable].
Thus, for inclusive table location testing of the ActiveCell one could test as follows:
If Not Intersect(ActiveCell, [myTable]) Is Nothing Then

A more general solution, adaptable to other tables
Sub Demo()
Dim r As Range
Dim lo As ListObject
Set r = ActiveCell
Set lo = r.ListObject
If Not lo Is Nothing Then
Select Case lo.Name
Case "Table1"
If r.Row = lo.Range.Row Then
MsgBox "In Table1 Header"
Else
MsgBox "In Table1 Body"
End If
Case "SomeOtherTable"
'...
End Select
Else
MsgBox "Not in any table"
End If
End Sub

A Range object has a ListObject property that will return the table of the Range. All you have to do is to test if the cell is in any table:
If ActiveCell.ListObject Is Nothing Then
...
and see if it is in your specific table:
If ActiveCell.ListObject.Name = "MyTable" Then
...
and you're done!
Much cleaner than using Application.Intersect(...). chris neilsen's answer alludes to this as well.

I use the following line of code:
ActiveCell.ListObject.Name
or sub:
Sub IsActiveCellInTable()
'If active cell in table then get name'
Dim strTblName As String
'Disable error checking'
On Error Resume Next
strTblName = ActiveCell.ListObject.Name
'Reset error checking'
On Error GoTo 0
If strTblName <> "" Then
MsgBox "Cell (" & ActiveCell.Address & ") is included in: " & strTblName
Else
MsgBox "Cell (" & ActiveCell.Address & ") is not included in table."
End If
End Sub

Related

How to record problem records when deleting Table rows by『On Error』statement

Sub FilterRows(Field As String, Values As Collection)
Dim FinalRow As Long
Dim KeepValue As Variant
Dim Table As ListObject
Dim TableRange As Range
Dim i As Integer
With Worksheets("原始資料")
FinalRow = .Cells(Rows.Count, 1).End(xlUp).row
On Error GoTo ErrorHandler
Set Table = .ListObjects("Table1")
Set TableRange = Table.Range
For i = TableRange.Rows.Count To 1 Step -1
For Each KeepValue In Values
If Intersect(TableRange.Rows.Item(i), Table.ListColumns(Field).Range).Value <>
CStr(KeepValue) Then
TableRange.Rows.Item(i).Delete
End If
Next KeepValue
Next
End With
Exit Sub
ErrorHandler:
Debug.Print Err.Number; ":" & Err.Description
If Table Is Nothing Then
Worksheets("原始資料").ListObjects.Add(xlSrcRange, Worksheets("原始資料").Range("A1:AK" &
FinalRow), , xlYes).Name = "Table1"
Set Table = Worksheets("原始資料").ListObjects("Table1")
Else
Debug.Print "Error Record ID:" & Intersect(TableRange.Rows.Item(i),
Table.ListColumns("Record ID").Range).Value<===I'm not able to do This Line...
End If
Resume Next
End Sub
Hi Folks,
the purpose of this code is to delete table row based on a condition.
Somehow I got Error in certain table rows in the process of deletion, and I would like to know which row is fail.so I wrote this line :
『Debug.Print "Error Record ID:" & Intersect(TableRange.Rows.Item(i), Table.ListColumns("Record ID").Range).Value』.
There may be variable scope issue but I don't know how to pass varaible to Errorhandler. Or there is another good way to achieve what I want to do?
Thanks!
While testing your code, it's usually a good idea not to let the error handler handle you problem but let the runtime engine stop immediately at the line throwing the error. You can achieve this by either comment out the line On Error Goto, or go to the VBA Options and select "Break on all errors" (in the General Tab).
Scope of variables is the whole subroutine, so that shoudn't be a problem.
You should use the error handler to catch only unexpected errors. The logic of defining the table if it doesn't exist should be done at the point where you assign the variable:
On Error Resume Next
Set Table = .ListObjects("Table1")
On Error GoTo ErrorHandler
If table Is Nothing Then
With Worksheets("原始資料")
Set table = .ListObjects.Add(xlSrcRange, .Range("A1:AK" & FinalRow), , xlYes)
End With
table.Name = "Table1"
End If
Set TableRange = Table.Range
I am almost sure your problematic row is 1: You cannot delete the header row of a table.

How to vlookup another excel sheet in VBA

Sub lookuphcpcs()
On Error GoTo errorbox:
Dim hcpcs_code As Long
Dim desc As Variant
hcpcs_code = ActiveCell.Value
If Len(hcpcs_code) > 0 Then
desc = Application.WorksheetFunction.VLookup(Active_cell, 'C:\Users\Username\Desktop\[Fruit Code.xlsx]Sheet1'!$A$2:$B$7, 2, False)
MsgBox "Description for HCPCS Code " & hcpcs_code & " is """ & desc & """"
Else
MsgBox "You did not enter any input!"
End If
Exit Sub
errorbox:
If Err.Number = 1004 Then
MsgBox "No Description found under HCPCS list!"
End If
End Sub
I am not able to put table array value under Vlookup in VBA to point to another excel sheet.
How do I do that?
First, when working with Vlookup you need to handle errors, such as when Vlookup was unable to find a match, you can use If Not IsError(Application.VLookup(.... to achieve this.
Second, in your case you don't need to use On Error GoTo errorbox:, just use the Vlookup error handling I wrote in the first point.
Third, you can use If Trim(ActiveCell.Value2) <> "" Then to verify there is a valid text or number inside ActiveCell rather than empty spaces.
Fourth, you should avoid using ActiveCell, and use fully qualified object instead.
Last, you want to make sure "Fruit Code.xlsx" workbook is open before using the Vlookup, as suggested by #Tim Williams in the comments above.
Modified Code
Option Explicit
Sub lookuphcpcs()
Dim desc As Variant
Dim SourceWb As Workbook
' error trapping in case Fruit Code workbook is closed
On Error Resume Next
Set SourceWb = Workbooks("Fruit Code.xlsx")
On Error GoTo 0
If SourceWb Is Nothing Then
Set SourceWb = Workbooks.Open("C:\Users\Username\Desktop\Fruit Code.xlsx") ' open workbook if it's closed
End If
If Trim(ActiveCell.Value2) <> "" Then ' make sure cell has a string other than space
If Not IsError(Application.VLookup(ActiveCell.Value2, SourceWb.Sheets("Sheet1").Range("A2:B7"), 2, 0)) Then
desc = Application.VLookup(ActiveCell.Value2, SourceWb.Sheets("Sheet1").Range("A2:B7"), 2, 0)
MsgBox "Description for HCPCS Code " & ActiveCell.Value2 & " is """ & desc & """"
Else
MsgBox "No Description found under HCPCS list!"
Exit Sub
End If
Else
MsgBox "You did not enter any input!"
End If
End Sub

Check if a value is present in a range or not with VBA

I'm looking to check if a value is present in a range or not. If it's not there then I want it to jump to WriteProcess else I want it to give a message box saying it's present and exit the sub.
This is code,
'Write the Selected Value in the Range - Next Available row in the Column of Source
For i = TableStartingRow + 1 To AddNewEntrow
If Range(EntryColLett & i).Value = wb21Tool.Sheets("Home").ComboBox1.Value Then
MsgBox "The data exists in the Table"
GoTo StopSub
Else
GoTo WriteProcess
End If
Next
WriteProcess:
wbTool.Sheets("Home").Range(EntryColLett & AddNewEntrow).Value = wb21Tool.Sheets("Home").ComboBox1.Value
StopSub:
'Turn on the ScreenUpdate
Application.ScreenUpdating = True
Please share your thoughts. Thanks.
Your problem is that if the loop expires (exhausts all of the iterations) there is no control to prevent it from entering the WriteProcess.
This is one problem with using GoTo statements. Preferably keep these to a minimum. For example, although this doesn't check every row, just an example of how you might avoid the extra GoTo.
'Write the Selected Value in the Range - Next Available row in the Column of Source
For i = TableStartingRow + 1 To AddNewEntrow
If Range(EntryColLett & i).Value = wb21Tool.Sheets("Home").ComboBox1.Value Then
MsgBox "The data exists in the Table"
GoTo StopSub
Else
wbTool.Sheets("Home").Range(EntryColLett & AddNewEntrow).Value = wb21Tool.Sheets("Home").ComboBox1.Value
End If
Next
StopSub:
'Turn on the ScreenUpdate
Application.ScreenUpdating = True
However, a brute-force iteration over the table data seems unnecessary and if you need to check all rows int he table it's probably better to just use the Find method.
Assuming EntryColLet is a string representing the column letter:
Dim tblRange as Range
Dim foundRow as Range
Set tblRange = Range(EntryColLet & (TableStartingRow+1) & ":" & EntryColLet & AddNewEntRow)
Set foundRow = tblRange.Find(wb21Tool.Sheets("Home").ComboBox1.Value)
If foundRow Is Nothing Then
'The value doesn't exist in the table, so do something
'
Else
'The value exists already
MsgBox "The data exists in the Table"
GoTo StopSub
End If
'More code, if you have any...
StopSub:
Application.ScreenUpdating = True
And regarding the remaining GoTo -- if there's no more code that executes after the condition If foundRow Is Nothing then you can remove the entire Else clause and the GoTo label:
Dim tblRange as Range
Dim foundRow as Range
Set tblRange = Range(EntryColLet & (TableStartingRow+1) & ":" & EntryColLet & AddNewEntRow)
Set foundRow = tblRange.Find(wb21Tool.Sheets("Home").ComboBox1.Value)
If foundRow Is Nothing Then
'The value doesn't exist in the table, so do something
End If
Application.ScreenUpdating = True
End Sub
Alternate solution if you need to check every row before performing the "WriteProcess":
Dim bExists As Boolean
bExists = False
'Write the Selected Value in the Range - Next Available row in the Column of Source
For i = TableStartingRow + 1 To AddNewEntrow
If Range(EntryColLett & i).Value = wb21Tool.Sheets("Home").ComboBox1.Value Then
bExists = True
MsgBox "The data exists in the Table"
Exit For
End If
Next
If Not bExists Then wbTool.Sheets("Home").Range(EntryColLett & AddNewEntrow).Value = wb21Tool.Sheets("Home").ComboBox1.Value
'Turn on the ScreenUpdate
Application.ScreenUpdating = True

Find value in column and change cell to left with an if statment

This VBA script should take the value in the cell A37 and check if its in the C column of another worksheet. When the number is found the column to the left should be changed to 0. If it is already 0 then a message box will inform the user and if the number does not exist another message box will inform them of this.
This is the VBA I am using to accomplish this. However, every time I try to run it there is a "compile error: Next without For"
Update This issue now is that I need to activate the cell that the fcell is in before doing an Active.cell offset
Sub Cancelled()
Dim x As Long
Dim regRange As Range
Dim fcell As Range
x = ThisWorkbook.Sheets("Welcome").Range("A37").Value
Set regRange = ThisWorkbook.Sheets("Registration").Range("C:C")
For Each fcell In regRange.Cells
If fcell.Value = x Then
ActiveCell.Offset(0, -1).Select
If ActiveCell.Value = 1 Then
ActiveCell.Value = 0
MsgBox "Changed to zero"
Exit Sub
Else
MsgBox "That registration number is already cancelled"
Exit Sub
End If
End If
Next fcell
MsgBox "That number does not exist"
End Sub
Edit for new question: No need to use Select and ActiveCell
If fcell.Value = x Then
If fcell.Offset(0,-1).Value = 1 Then
fcell.Offset(0,-1).Value = 0
...
Edit 2: A further suggestion: You could also use the Range.Find method. This will throw an error if nothing is found so you have to catch that:
On Error Resume Next 'If an error occurs, continue with the next line
Set fcell = regRange.Find(x)
On Error GoTo 0 'disable the error handler
If fcell Is Nothing Then 'If Find failed
MsgBox "That number does not exist"
Else
'do your stuff with fcell here
End If
Hope this is not too late to answer your question:
Sub Cancelled()
Dim x As Long
Dim regRange As Range
Dim fcell As Range
x = ThisWorkbook.Sheets("Welcome").Range("A7").Value
Set regRange = ThisWorkbook.Sheets("Registration").Range("C:C")
For Each fcell In regRange.Cells
If fcell.Value = x Then
If fcell.Offset(0, -1).Value = 1 Then
fcell.Offset(0, -1).Value = 0
MsgBox "Changed to zero"
Else
MsgBox "That registration number is already cancelled"
End If
Exit Sub
End If
Next fcell
MsgBox "That number does not exist"
End Sub
Instead of
Set regRange = ThisWorkbook.Sheets("Registration").Range("C:C")
its better to get the last row in Column C and then set your range as:
Dim lastRow As Long
lastRow = ThisWorkbook.Sheets("Registration").Cells(Rows.Count, "C").End(xlUp).Row
Set regRange = ThisWorkbook.Sheets("Registration").Range("C1:C" & lastRow)

Range & If Statement using multiple sheets

I have several Sheets involved but I'll have Sheet 2 Active. When I'm on "Sheet 2" I need to know when cell ("C14") becomes active with an IF statement I'm guessing. Once it becomes active, I then need to know if the string in cell ("B2") on Sheet 1 = "Fighter" then I want to insert "some wording regarding the fighter here" in cell ("C14") on Sheet 2. IF it's not "Fighter"then is it "Mage"? If so then insert "some wording regarding the mage here".
This is short hand for example.
if cell C14 on Sheet 2 is active then
check cell B2 on Sheet1. If the text = "Fighter"? Then
insert "You are brave and use a sword" into cell C14 Sheet2
if it's not equal to Fighter then is it = "Mage"? Then
insert "You cast spells" in cell C14 sheet2
etc..
I need to know how to code this in VBA. I've spent hours searching and trying various code but can't seem to get it right. Thanks ahead of time for your help.
Try something like this:
'The way you check which cell is active is by using an
'Event like this one. This goes into the Sheet2 code module
'which you can get to by right clicking on the sheet's tab and
'selecting View Code.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim rng_Source As Excel.Range
Dim rng_Target As Excel.Range
On Error GoTo ErrorHandler
'Setting the cells that you're interested in as
'ranges will help minimise typo errors.
Set rng_Target = ThisWorkbook.Sheets("Sheet2").Range("C14")
Set rng_Source = ThisWorkbook.Sheets("Sheet1").Range("B2")
'Target is a range that specifies the new
'selection. Check its address against rng_Target
'which we defined above.
If Target.Address <> rng_Target.Address Then
Exit Sub
End If
'If you don't want case sensitivity, convert to upper case.
If UCase(rng_Source.Value) = "FIGHTER" Then
rng_Target.Value = "some wording regarding the fighter here"
ElseIf UCase(rng_Source.Value) = "MAGE" Then
rng_Target.Value = "You cast spells"
'You get the idea.
End If
ExitPoint:
On Error Resume Next
'Clean up
Set rng_Source = Nothing
Set rng_Target = Nothing
On Error GoTo 0
Exit Sub
ErrorHandler:
MsgBox "Error " & Err.Number & vbCrLf _
& Err.Description
Resume ExitPoint
End Sub
I do agree with the comments that you should always post the code that you've already tried (which you subsequently did), but this is a relatively trivial one and this just clears it out of the way and may be of use to somebody else as well in the future.
Try this ;)
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error GoTo errH
Dim rng1 As Range
Set rng1 = ThisWorkbook.Worksheets(1).Range("B2")
If Not Intersect(Target, Me.Range("C14")) Is Nothing Then
Application.EnableEvents = False
If rng1.Value2 = "Mage" Then
Target.Value = "OMG This is MAGE!!! Run run run away!!!"
ElseIf rng1.Value2 = "Fighter" Then
Target.Value = "Fighter? :/ Was hoping for something better"
MsgBox "Fighter? :/ Was hoping for something better"
rng1.Value2 = "Mage"
Target.Value = "Mage. Now This is better ;)"
Else
Target.Value = "No, we haven't discussed it."
End If
Application.EnableEvents = True
End If
Exit Sub
errH:
MsgBox ("Error number: " & Err.Number & "Description: " & Err.Description)
Application.EnableEvents = True
End Sub