1

I have the following Table in my macro-enabled excel file,

Table1:

enter image description here

My goal is:

Before closing this workbook, I need to clear Column D content (shown as "Column 4" in the Table1), only where column D cells value = 999. For example, looking at the screenshot above - cell content in D2 and in D4 must be cleared when "close workbook" event triggered.

Important - if user will create a new record(s) in this table, then any new cell under Column D could have 999 value too. If a new record contains cell value = 999 in the Column D - it must be cleared! Any new record where cell value = 999 in column D must be cleared!

See updated picture of what I expect -

cells D2, D4, and also D7 (after the new record created in this tbl) had 999 value and cleared:

enter image description here

Using the following vba code but it's not working:

     Private Sub Workbook_BeforeClose(Cancel As Boolean)

        Dim sht As Worksheet
        Set sht = ThisWorkbook.ActiveSheet

        If Worksheets("Sheet1").ListObjects("Table1").Columns(4).Value = 999 Then
           Worksheets("Sheet1").ListObjects("Table1").Columns(4).ClearContents
  
        End If

    End Sub
VBasic2008
  • 44,888
  • 5
  • 17
  • 28
Hell-1931
  • 489
  • 1
  • 6
  • 24

2 Answers2

3

Clear Values in an Excel Table

Option Explicit

Private Sub Workbook_BeforeClose(Cancel As Boolean)

    Dim ws As Worksheet: Set ws = Me.Worksheets("Sheet1")
    Dim tbl As ListObject: Set tbl = ws.ListObjects("Table1")
    Dim lcl As ListColumn: Set lcl = tbl.ListColumns("Column 4") ' 4
        
    lcl.DataBodyRange.Replace 999, Empty, xlWhole
    
End Sub

EDIT

  • If you want to avoid the 'save alert dialog' when the workbook was already saved you can improve with the following:
Option Explicit

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    
    Dim IsSaved As Boolean: IsSaved = Me.Saved
    
    Dim ws As Worksheet: Set ws = Me.Worksheets("Sheet1")
    Dim tbl As ListObject: Set tbl = ws.ListObjects("Table1")
    Dim lcl As ListColumn: Set lcl = tbl.ListColumns("Column 4") ' 4
        
    lcl.DataBodyRange.Replace 999, Empty, xlWhole
    
    If IsSaved Then Me.Save
    
End Sub
VBasic2008
  • 44,888
  • 5
  • 17
  • 28
  • I always forget about `Range.Replace` - this is much better than a loop. I'll blame it being quite late here :-) – BigBen Jan 06 '22 at 03:37
1

Two immediate issues:

  • A ListObject does not have a Columns property, rather a ListColumns property.
  • Loop* over the cells in the ListColumn.DataBodyRange rather than attempting to compare the entire column to 999.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Dim tbl As ListObject
    Set tbl = Me.Worksheets("Sheet1").ListObjects("Table1")
    
    Dim cell As Range
    For Each cell In tbl.ListColumns(4).DataBodyRange
        If cell.Value = 999 Then 
            cell.ClearContents
        End If
    Next
End Sub

* This can be made much faster using a Variant array but should be fine for a relatively small table.

BigBen
  • 46,229
  • 7
  • 24
  • 40
  • 1
    @Hell-1931 - VBasic2008's answer is definitely better than this btw. `Range.Replace` should be faster than a loop. Go ahead and use it (even accept it too) instead of mine :-) – BigBen Jan 06 '22 at 03:40
  • 1
    Sorry, I had to re enter my comment... In my case I think - loop and referring to cell is better. In this question I described only an example (a simplified model of the entire project) I slightly modified it, added MsgBox and added the following line in your code cell.EntireRow.Interior.ColorIndex = 8 so, now, after content clears, another part of my code is working prompting the workbook from being closed. And the entire row is highlighted - for user to delete it! – Hell-1931 Jan 06 '22 at 06:41
  • 1
    My workbook won't have too large number of records (not sure if it could create issue otherwise), but I think using loop is fine – Hell-1931 Jan 06 '22 at 06:41