Invalid use of property in VBA - excel

I've been following a tutorial on Youtube for an employee manager, It uses a lot of features that i don't need so I've been trying to pick out parts that it need.
I have no experience with VBA or coding so I'm struggling to work out why certain things wont work.
The Screenshots have annotations of the intended results.
Than you in advance
Example and annotations of intended result
Error message
Debug view
Here are my Macros for the buttons and the refresh
Option Explicit
Public EventRow As Long
Public EventCol As Long
Public MapRng As String
Sub Event_SaveNew()
With Sheet6
'check req fields
If Sheet3.Range("g3").Value = Empty Or Sheet3.Range("g5").Value = Empty Then
MsgBox ("Event Name and Event Type are required fields for ANY Event")
Exit Sub
End If
EventRow = .Range("E2000").End(xlUp).Row + 1 'first av row
.Cells(EventRow, 5).Value = Sheet3.Range("b7").Value 'new event id
For EventCol = 6 To 12
.Cells(EventRow, EventCol).Value = Sheet3.Range(.Cells(1, EventCol).Value).Value 'event feild
Next EventCol
End With
With Sheet3
.Range("B2").Value = False 'set new event to false
.Range("B4").Value = Sheet6.Cells(EventRow, 1).Value 'New event ID
Event_Refresh
'reload events
End With
End Sub
Sub Event_Refresh()
Dim LastEventRow As Long
Dim LastFiltRow As Long
With Sheet3
'load Events list into events sheet using adv filter and sort
.Range("f22:m2000").ClearContents 'clear existing events list
LastEventRow = Sheet6.Range("e2000").End(xlUp).Row + 6
Sheet6.Range ("e4:L" & LastEventRow)
End With
End Sub
Sub Event_AddNew()
With Sheet3
.Range("B1").Value = True 'set event load to true
.Range("b2").Value = True 'set new event to true
.Range("J7,j5,g5,g3,f11:j17,g7,g8,j3").ClearContents
.Range("b1").Value = False 'set event load to false
.Range("G3").Select
End With
End Sub
Sub Event_Load()
Dim SelRow As Long
With Sheet3
SelRow = .Range("b9").Value
If .Range("B3").Value = Empty Then
MsgBox "Please select on an Event to display Event details"
Exit Sub
End If
.Range("b1").Value = True 'set empload to true
EventRow = .Range("b3").Value
End With
With Sheet6
For EventCol = 6 To 12
MapRng = Sheet6.Cells(1, EventCol).Value
.Range(MapRng).Value = Sheet6.Cells(EventRow, EventCol).Value 'add maped values
Next EventCol
End With
With Sheet3
.Range("B2").Value = False 'set new event to false
.Range("B1").Value = False 'set event load to false
End With
End Sub
Sub Event_Delete()
If MsgBox("Are you sure you want to DELETE this event?", vbYesNo, "Delete Event") = vbNo Then Exit Sub
With Sheet3
If .Range("B3").Value = Empty Then Exit Sub
EventRow = .Range("B3").Value 'event row
Sheet6.Range(EventRow & ":" & EventRow).EntireRow.Delete
Event_Refresh 'refresh events
End With
End Sub
Sub Event_CancelNew()
With Sheet3
.Range("b2").Value = False
Sheet3.Range("F22").Select
End With
End Sub
And here is the code for the Event log page
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim MapRng As Range
Dim FoundMapRng As Range
Dim CellAdd As String
Dim SellRow As Long
'exsisting event change update event tab
If Not Intersect(Target, Range("F3:L17")) Is Nothing And Range("B2").Value = False And Range("B1").Value = False And IsNumeric(Cells(Target.Row, Target.Column + 25).Value) = True And Cells(Target.Row, Target.Column + 25).Value <> Empty Then
Sheet6.Cells(Range("b3").Value, Cells(Target.Row, Target.Column + 25).Value).Value = Target.Value
End If
'update below
CellAdd = Target.Address
SellRow = Range("b9").Value
Set MapRng = Sheet3.Range("EventDataMap")
Set FoundMapRng = MapRng.Find(CellAdd, , xlValues, xlWhole)
If Not FoundMapRng Is Nothing Then Cells(SellRow, FoundMapRng.Column).Value = Sheet6.Cells(Range("b3").Value, Cells(Target.Row, Target.Column + 25).Value).Value
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
'on table selection
If Not Intersect(Target, Range("F22:M2000")) Is Nothing And Range("f" & Target.Row).Value <> Empty Then
Range("b9").Value = Target.Row 'add in selection row
Range("b4").Value = Range("f" & Target.Row).Value 'add event ID
Event_Load
End If
End Sub

Related

Delete checkbox from a Specific Cell with VBA

I'm putting together a spreadsheet that should populate checkboxes in a specific column when the spreadsheet opens if the appropriate A Column/Row is not empty. It should also remove checkboxes when it finds that same A column to be empty. My VB is correctly creating the checkboxes, but I cannot figure out how to tell the code to delete the checkbox from a specific cell.
Most articles I find mention removed ALL checkboxes, but I'm looking to do it conditionally. Any guidance would be greatly appreciated.
Private Sub Workbook_Open()
'declare a variable
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
'calculate if a cell is not blank across a range of cells with a For Loop
For x = 2 To 1000
If ws.Cells(x, 1) <> "" Then
Call Add_CheckBox(CInt(x))
Else
Call Delete_CheckBox(CInt(x))
End If
Next x
End Sub
Private Sub Add_CheckBox(Row As Integer)
ActiveSheet.CheckBoxes.Add(Cells(Row, "T").Left, Cells(Row, "T").Top, 72, 12.75).Select
With Selection
.Caption = ""
.Value = xlOff '
.LinkedCell = "AA" & Row
.Display3DShading = False
End With
End Sub
Private Sub Delete_CheckBox(Row As Integer)
Dim cb As CheckBox
If cb.TopLeftCell.Address = (Row, "T") Then cb.Delete
End Sub
Naming the CheckBoxes will make it easier to maintain your code.
Private Sub Workbook_Open()
Const CheckBoxPrefix As String = "Sheet1TColumnCheckBox"
'declare a variable
Dim CheckBoxName As String
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
'calculate if a cell is not blank across a range of cells with a For Loop
Dim r As Long
For r = 2 To 1000
CheckBoxName = CheckBoxPrefix & r
If Len(ws.Cells(r, 1)) > 0 Then
If Not WorksheetContainsCheckBox(CheckBoxName, ws) Then Add_CheckBox CheckBoxName, ws.Cells(r, 1), ws.Cells(r, "AA")
Else
If WorksheetContainsCheckBox(CheckBoxName, ws) Then ws.CheckBoxes(CheckBoxName).Delete
End If
Next
End Sub
Private Sub Add_CheckBox(CheckBoxName As String, Cell As Range, LinkedCell As Range)
With Cell.Worksheet.CheckBoxes.Add(Cell.Left, Cell.Top, 72, 12.75)
.Caption = ""
.Value = xlOff '
.LinkedCell = LinkedCell
.Display3DShading = False
.Name = CheckBoxName
End With
End Sub
Function WorksheetContainsCheckBox(CheckBoxName As String, ws As Worksheet)
Dim CheckBox As Object
On Error Resume Next
Set CheckBox = ws.CheckBoxes(CheckBoxName)
WorksheetContainsCheckBox = Err.Number = 0
On Error GoTo 0
End Function
Try something like this (put a checkbox "in" A1 but not C1)
Sub tester()
Debug.Print Delete_CheckBox([A1])
Debug.Print Delete_CheckBox([C1])
End Sub
'Return True if able to delete a checkbox from range `rng`
Private Function Delete_CheckBox(rng As Range) As Boolean
Dim cb As CheckBox
For Each cb In rng.Worksheet.CheckBoxes
If Not Application.Intersect(cb.TopLeftCell, rng) Is Nothing Then
Debug.Print "Deleting checkbox in " & cb.TopLeftCell.Address
cb.Delete
Delete_CheckBox = True
Exit For 'if only expecting one matched checkbox
End If
Next cb
End Function

Edit filtered listbox

Can anyone help me with a solution or a different method for this? I would like to edit the filtered listbox
I'm trying to get a listbox that is able to display my sheet1 and be able to filter all the blanks/not found in column A. I also want to be able to edit the listbox aswell
I would like my userform2 listbox to display the sheet1 information.
There will also be a checkbox which will filter the listbox to show “not found” or blank lines.
If i double click the selected item on the listbox i would like to edit the information
for userform2
Private Sub ListBox2_Click()
TextBox1.Enabled = True
TextBox1.Value = ListBox2.Value
End Sub
Private Sub TextBox1_Change()
Dim rCell As Range
With ListBox2
Set rCell = Range(.RowSource).Resize(1).Offset(.ListIndex)
rCell.Value = TextBox1.Value
End With
End Sub
Private Sub CheckBox1_Click()
OptimizedMode True
If userform2.CheckBox1.Value = True Then
Worksheets("Table").Range("A1").AutoFilter Field:=1, Criteria1:="Not Found", Operator:=xlOr, Criteria2:="="
userform2.ListBox2.RowSource = vbNullString
userform2.ListBox2.ColumnHeads = False
Dim rng As Range
Dim Cel1 As Range
Dim LR As Long
Dim ws As Worksheet
Set ws = Sheets("Table")
With ws
LR = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rng = .Range("A2:A" & LR).SpecialCells(xlCellTypeVisible)
With userform2.ListBox2
.ColumnCount = 1
For Each Cel1 In rng
.AddItem CStr(Cel1.Value)
.List(.ListCount - 1, 1) = Cel1.Offset(0, 1).Value
Next Cel1
End With
End With
End If
If CheckBox1.Value = False Then
With userform2.ListBox2
.RowSource = "Table!A2:A1048576"
End With
End If
OptimizedMode False
End Sub
I've re-designed my code and I believe this will achieve what you are after.
NOTE: This code uses all default object names. You will need to modify it to target the names for your workbook, sheet, useform, controls etc, if you wish to implement into your project.
In designing this answer I used the following:
A new blank Workbook with 1 new Worksheet
A new UserForm (captioned "ListBox Editor") with 1 ListBox that has 2 columns (ColumnCount = 2) and 1 CheckBox (captioned "Show Blanks").
The sample data I used was in Range("A1:A10") filling only odd numbers from row 1. This allows testing for including/excluding blank/empty rows. Screenshots of the Worksheet and UserForm below.
Worksheet data:
UserForms both with and without blanks in the listbox:
All code is written in the code behind module for the UserForm
Most can be written into any other module with calls made to the subs/functions from the UserForm/ListBox events if you'd prefer not to have the working code in the UserForm module.
Code blocks with explanations below (full code block at the end for copy/paste):
Option Explicit
Option Explicit should be included at the top of each and every code module you use. It forces explicit declaration of all variables which helps significantly in avoiding typo's in your code etc.
Private Sub PopulateListBox(ByVal IncludeBlanks As Boolean)
Dim TargetCell As Range
Dim TargetWorksheet As Worksheet
Set TargetWorksheet = ThisWorkbook.Sheets("Sheet1")
With UserForm1.ListBox1
.Clear
For Each TargetCell In TargetWorksheet.Range("A1:A10")
If Not IncludeBlanks Then
If Not TargetCell.Value = "" Then
.AddItem TargetCell.Value
.List(.ListCount - 1, 1) = TargetCell.Row
End If
ElseIf IncludeBlanks Then
.AddItem TargetCell.Value
.List(.ListCount - 1, 1) = TargetCell.Row
End If
Next TargetCell
.ColumnWidths = ";0" 'Hides listbox column that holds row number
End With
End Sub
PopulateListBox is a subroutine I wrote to handle population of the items in the ListBox. It first clears the list, allowing each population of the listbox to be 'refreshed' data. Then it iterates through each TargetCell of the defined Range. If IncludeBlanks is True it has no conditions to meet and adds each cell value into the list, if IncludeBlanks is False it will only add the cell value to the list if the value is not "".
Private Sub CheckBox1_Click()
If Me.CheckBox1.Value = False Then
PopulateListBox False
ElseIf Me.CheckBox1.Value = True Then
PopulateListBox True
End If
End Sub
This _Click event simply updates the ListBox list based on if the CheckBox is checked or not. The CheckBox represents if you are including blanks/empty cells or not so it passes True or False respective to it's Value, to the IncludeBlanks argument in PopulateListBox.
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim NewValue As Variant
Dim TargetWorksheet As Worksheet
Set TargetWorksheet = ThisWorkbook.Sheets("Sheet1")
NewValue = InputBox("What is the new value to replace " & UserForm1.ListBox1 & "?")
If Not StrPtr(NewValue) = 0 Then 'Check user did NOT click cancel or [X]
With ListBox1
If NewValue = "" Then NewValue = vbNullString
TargetWorksheet.Cells(.List(.ListIndex, 1), 1).Value = NewValue
.AddItem NewValue, .ListIndex
.RemoveItem .ListIndex
End With
End If
End Sub
The _DblClick Event triggers the code when a list item is double clicked. This code first opens an InputBox to allow the user to enter a new value for the selected listbox item. When the user clicks OK or hit's Enter, the new value is first written to the Cell that the original value came from, then the new value is added as a new list item and finally the previous value is removed. If the user clicks [X] or 'Cancel' the code does nothing.
Private Sub UserForm_Initialize()
PopulateListBox False
End Sub
Much the same as the Checkbox_Change code, this simply populates the ListBox when the UserForm is first initialized. It's written to exclude blanks, specified by False for the IncludeBlanks argument.
Put it all together and you have:
Option Explicit
Private Sub CheckBox1_Click()
If Me.CheckBox1.Value = False Then
PopulateListBox False
ElseIf Me.CheckBox1.Value = True Then
PopulateListBox True
End If
End Sub
Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim NewValue As Variant
Dim TargetWorksheet As Worksheet
Set TargetWorksheet = ThisWorkbook.Sheets("Sheet1")
NewValue = InputBox("What is the new value to replace " & UserForm1.ListBox1 & "?")
If Not StrPtr(NewValue) = 0 Then 'Check user did NOT click cancel or [X]
With ListBox1
If NewValue = "" Then NewValue = vbNullString
TargetWorksheet.Cells(.List(.ListIndex, 1), 1).Value = NewValue
.AddItem NewValue, .ListIndex
.RemoveItem .ListIndex
End With
End If
End Sub
Private Sub UserForm_Initialize()
PopulateListBox False
End Sub
Private Sub PopulateListBox(ByVal IncludeBlanks As Boolean)
Dim TargetCell As Range
Dim TargetWorksheet As Worksheet
Set TargetWorksheet = ThisWorkbook.Sheets("Sheet1")
With UserForm1.ListBox1
.Clear
For Each TargetCell In Range("A1:A10")
If Not IncludeBlanks Then
If Not TargetCell.Value = "" Then
.AddItem TargetCell.Value
.List(.ListCount - 1, 1) = TargetCell.Row
End If
ElseIf IncludeBlanks Then
.AddItem TargetCell.Value
.List(.ListCount - 1, 1) = TargetCell.Row
End If
Next TargetCell
.ColumnWidths = ";0"
End With
End Sub

Execute Procedure when Value in a Cell/Range Changes

I'm new to VBA and wrote the following codes according to my data set. The goal here is to execute my procedure if a cell/range gets changed by pasting new data into the worksheet, most probably the sheet will be empty as it will follow by a clear content procedure.
However, the code is not triggering the change event, I've tried several codes from Google, but none of them worked. Please note that my procedure gets me exactly the data I want in the format I want, however, if changes are needed, kindly let me know.
PLEASE HELP
1. Change event trigger - stored under Sheet1
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("A1")) Is Nothing Then
Application.EnableEvents = False
Call LoopandIfStatement
Application.EnableEvents = True
End If
End Sub
2. My procedure - stored under Sheet1 below the event above
Sub LoopandIfStatement()
Dim SHT As Worksheet
Set SHT = ThisWorkbook.Worksheets("CB")
MyLr = SHT.Cells(Rows.Count, 1).End(xlUp).Row
Dim I As Long
For I = 1 To MyLr
Dim O As Long
Dim U As Range
Set U = SHT.Range("A" & I)
If IsEmpty(SHT.Range("a" & I).Value) = False Then
SHT.Range("k" & I).Value = SHT.Range("A" & I).Value
Else
On Error GoTo ABC
SHT.Range("k" & I).Value = U.Offset(-1, 0)
End If
Next I
For O = 2 To MyLr
If SHT.Range("g" & O).Value = "Closing Balance" Then
SHT.Range("l" & O).Value = SHT.Range("j" & O).Value
End If
Next O
ABC:
End Sub
Results
This will trigger whenever new data is pasted in any cell of columns A to J
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("A:J")) Is Nothing Then
Application.EnableEvents = False
Call LoopandIfStatement
Application.EnableEvents = True
End If
End Sub
Regarding your sub LoopandIfStatement here are some suggestions:
Use Option explicit at the top of your modules (see this)
Declare all your variables (you're missing: Dim MyLr as long)
Try to name your variables to something understandable (e.g. instead of MyLr you could have lastRow)
If you need to exit a Sub you can use Exit Sub instead of a Goto ABC
EDIT:
Added code for the loop and the change worksheet event.
Paste it behind the CB Sheet module
Some highlights:
When you triggered the loop on each worksheet change, it would re-apply all the steps to all the cells. You can work with changed ranges using the Target argument/variable in the Worksheet_Change event
To loop through an existing range see the AddAccountBalanceToRange procedure
Try to think and plan your code in steps or actions that can be grouped
Use comments to describe the purpose of what you're doing
Remember to delete obsolete code (saw you had a copy of the procedure in a module)
Option Explicit
Private Sub CommandButton1_Click()
ThisWorkbook.Worksheets("Data").Columns("A:J").Copy
ThisWorkbook.Worksheets("CB").Range("A:J").PasteSpecial Paste:=xlPasteValues
End Sub
Private Sub CommandButton2_Click()
ThisWorkbook.Worksheets("CB").Range("A:L").ClearContents
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim targetUsedRange As Range
' Do something on non empty cells
Set targetUsedRange = Intersect(Target, Target.Parent.UsedRange)
If Not Intersect(Target, Me.Range("A:J")) Is Nothing Then
Application.EnableEvents = False
Call AddAccountBalance(targetUsedRange)
Application.EnableEvents = True
End If
End Sub
Private Sub AddAccountBalance(ByVal Target As Range)
Dim targetSheet As Worksheet
Dim evalRow As Range
Dim lastColumn As Long
Dim accountNumber As String
Dim balanceString As String
Dim narrative As String
Dim balanceValue As Long
balanceString = "Closing Balance"
' If deleting or clearing columns
If Target Is Nothing Then Exit Sub
' Do something if there are any values in range
If Application.WorksheetFunction.CountA(Target) = 0 Then Exit Sub
' Get the parent sheet of the cells that were modifid
Set targetSheet = Target.Parent
' Get the last empty cell column in row 1 -Cells(3 -> this is row 3)- In the sample book: column K
lastColumn = targetSheet.Cells(3, targetSheet.Columns.Count).End(xlToLeft).Column
' Loop through each of the rows that were modified in range
For Each evalRow In Target.Cells.Rows
' Do something if account number or narrative are not null
If targetSheet.Cells(evalRow.Row, 1).Value <> vbNullString Or targetSheet.Cells(evalRow.Row, 7).Value <> vbNullString Then
' Store columns values in evaluated row
accountNumber = targetSheet.Cells(evalRow.Row, 1).Value
narrative = targetSheet.Cells(evalRow.Row, 7).Value
If IsNumeric(targetSheet.Cells(evalRow.Row, 10).Value) Then balanceValue = targetSheet.Cells(evalRow.Row, 10).Value
' Add account number
If accountNumber <> vbNullString Then
targetSheet.Cells(evalRow.Row, lastColumn).Value = accountNumber
End If
' Add closing balance
If narrative = balanceString Then
targetSheet.Cells(evalRow.Row, lastColumn).Value = targetSheet.Cells(evalRow.Row, 1).Offset(-1, 0).Value
targetSheet.Cells(evalRow.Row, lastColumn).Offset(0, 1).Value = balanceValue
End If
' Format last two columns (see how the resize property takes a single cell and expands the range)
With targetSheet.Cells(evalRow.Row, lastColumn).Resize(, 2).Interior
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.799981688894314
.PatternTintAndShade = 0
End With
' Auto fit last column (K) (you could use the resize property as in the previous statement)
targetSheet.Columns(lastColumn).EntireColumn.AutoFit
End If
Next evalRow
End Sub
Public Sub AddAccountBalanceToRange()
Dim targetSheet As Worksheet
Dim evalRange As Range
Set targetSheet = ThisWorkbook.Worksheets("CB")
Set evalRange = targetSheet.Range("A1:A42")
AddAccountBalance evalRange
End Sub

Update excel cell with date if a cell in a range is update

I need to update a cell with the date and time stamp (NOW()) if any cell is updated within any cell before it within that same row.
So update cell "CU" with date and time when any cell from "A-CR" is updated.
I have done some searching but I can only seem to find bits that work if only updating a single cell, I'm looking for if anything changes within that range.
I currently have some Vba which does something similar which will update the adjacent cell with time and date which is required but I also need an overall one for the whole process.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("F:F, I:I, L:L, O:O, R:R, U:U, X:X, AA:AA, AB:AB, AE:AE, AH:AH, AK:AK, AN:AN, AQ:AQ, AT:AT, AW:AW, AZ:AZ, BC:BC, BF:BF, BI:BI, BL:BL, BO:BO, BR:BR, BU:BU, BX:BX, CA:CA, CD:CD, CG:CG, CJ:CJ, CM:CM, CP:CP")) Is Nothing Then
On Error GoTo safe_exit
With Application
.EnableEvents = False
.ScreenUpdating = False
Dim trgt As Range, ws1 As Worksheet
'Set ws1 = ThisWorkbook.Worksheets("Info")
For Each trgt In Intersect(Target, Range("F:F, I:I, L:L, O:O, R:R, U:U, X:X, AA:AA, AB:AB, AE:AE, AH:AH, AK:AK, AN:AN, AQ:AQ, AT:AT, AW:AW, AZ:AZ, BC:BC, BF:BF, BI:BI, BL:BL, BO:BO, BR:BR, BU:BU, BX:BX, CA:CA, CD:CD, CG:CG, CJ:CJ, CM:CM, CP:CP"))
If trgt <> vbNullString Then
If UCase(trgt.Value) = "Y" Or UCase(trgt.Value) = "N" Then
Cells(trgt.Row, trgt.Column + 1) = Now()
Cells(trgt.Row, trgt.Column + 2) = Environ("username")
'Select Case trgt.Column
' Case 2 'column B
' Cells(trgt.Row, trgt.Column + 1) = Environ("username")
' Case 4 'column D
' 'do something else
' End Select
Else
trgt = ""
Cells(trgt.Row, trgt.Column + 1) = ""
Cells(trgt.Row, trgt.Column + 2) = ""
End If
End If
Next trgt
'Set ws1 = Nothing
End With
End If
safe_exit:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
This works for me:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Intersect(Target, Me.Range("A" & Target.Row & ":CR" & Target.Row)) Is Nothing Then GoTo SafeExit
Me.Cells(Target.Row, "CU") = Now()
SafeExit:
Application.EnableEvents = True
End Sub
The below code takes care of:
Clearing the time if the row is blank.
Updating the time only if the values really change from the previous value.
Dim oldValue As String
'Change the range below where your data will be
Const RangeString = "A:CR"
'Below variable decides the column in which date will be displayed
'Change the below value to 1 for column A, 2 for B, ... 99 for CU
Const ColumnIndex = 99
Private Sub Worksheet_Change(ByVal Target As Range)
Dim WorkRng As Range
Dim HorizontalRng As Range
Dim Rng As Range
Dim HorRng As Range
Dim RowHasVal As Boolean
Set WorkRng = Intersect(ActiveSheet.Range(RangeString), Target)
If Not WorkRng Is Nothing Then
If WorkRng.Cells.Count = 1 And WorkRng.Cells(1, 1).Value = oldValue Then
Exit Sub
End If
Application.EnableEvents = False
For Each Rng In WorkRng
Set HorizontalRng = Intersect(ActiveSheet.Range(RangeString), Rows(Rng.Row))
RowHasVal = False
For Each HorRng In HorizontalRng
If Not VBA.IsEmpty(HorRng.Value) Then
RowHasVal = True
Exit For
End If
Next
If Not RowHasVal Then
ActiveSheet.Cells(Rng.Row, ColumnIndex).ClearContents
ElseIf Not VBA.IsEmpty(Rng.Value) Then
ActiveSheet.Cells(Rng.Row, ColumnIndex).Value = Now
ActiveSheet.Cells(Rng.Row, ColumnIndex).NumberFormat = "dd-mm-yyyy, hh:mm:ss"
End If
Next
Application.EnableEvents = True
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, ActiveSheet.Range(RangeString)) Is Nothing Then
If Target.Cells.Count = 1 Then
oldValue = Target.Value
Else
oldValue = ""
End If
End If
End Sub

Is there away to have cell value add or delete copies of either cell ranges or worksheets without use of a button

I'm trying to make a cell value dictate how many copies should be made. I'm trying to make it if the cell value goes down that it will delete the sheets that are higher than the value. I currently have the adding working no problem just can't figure out how to make it delete copies when the value gets smaller. I figure I could make a button do a check just trying to make it more automated.
Sub CreateDistro()
Dim i As Long
Dim Num As Integer
Dim Name As String
Dim xActiveSheet As Worksheet
On Error Resume Next
Application.ScreenUpdating = False
Set ActiveSheet = ActiveSheet
Num = Range("C1")
If Num > 1 Then
For i = 1 To Num
Name = ActiveSheet.Name
xActiveSheet.Copy After:=ActiveWorkbook.Sheets(Name)
ActiveSheet.Name = "Distro-" & i
Next
End If
xActiveSheet.Activate
Application.ScreenUpdating = True
End Sub
Problem of the code below: it reacts on the Range("C1") of all sheets!
You might want to use a named range or limit the number of possible sheets(e.g. minimum number of sheets = 2, template to be copied is sheet 2,only sheet1 has the Worksheet_Change code.
Sheet1:
Option Explicit
Private Sub Worksheet_Change(ByVal target As Range)
Call ChangeSheets(target)
End Sub
Module1:
Option Explicit
Sub ChangeSheets(ByVal target As Range)
Dim iCt As Integer
Dim Num As Integer
Dim maxSh As Integer
'If Not Intersect(Target, Range("C1")) Is Nothing Then
' MsgBox ("C1: " & Target.Value)
'End If
If target.Value <= 0 Then
MsgBox "Minimum worksheet count = 1!" & vbCrLf & "Nothing to do!"
Application.EnableEvents = False
target.Value = 1
Application.EnableEvents = True
Application.DisplayAlerts = False
maxSh = Sheets.Count
For iCt = maxSh To 2 Step -1
Sheets(iCt).Delete
Next iCt
Application.DisplayAlerts = True
Exit Sub
End If
If Worksheets.Count = target.Value Then
MsgBox "Worksheet count = " & target.Value & vbCrLf & "Nothing to do!"
Exit Sub
End If
'add some sheets
If Worksheets.Count < target.Value Then
Num = target.Value - Worksheets.Count
For iCt = 1 To Num
ActiveSheet.Copy After:=Sheets(Sheets.Count)
Next iCt
Exit Sub
End If
'delete some sheets
If Worksheets.Count > target.Value Then
Num = Worksheets.Count - target.Value
Application.DisplayAlerts = False
maxSh = Sheets.Count
For iCt = 0 To Num - 1
Debug.Print maxSh - iCt; ": "; Sheets(maxSh - iCt).Name
Sheets(maxSh - iCt).Delete
Next iCt
Application.DisplayAlerts = True
Exit Sub
End If
End Sub

Resources