Following on from a previous question I asked today - I have modified code written by Roy Cox (Thank you for saving me SO much time!) to create a userform to add, modify and delete users' details in an analysis tool I am creating.
It works perfectly when working with user data on a single worksheet.
Selecting a user and clicking 'delete' deletes their user data on the worksheet. I have modified the code so that when a user is added or deleted, it should check each worksheet and adds or deletes rows accordingly.
This is the code to delete the pupil data on a single sheet:
Private Sub cmbDelete_Click()
Dim msgResponse As String 'confirm delete
Application.ScreenUpdating = False
'get user confirmation
msgResponse = MsgBox("This will delete the selected record. Continue?", _
vbCritical + vbYesNo, "Delete Entry")
Select Case msgResponse 'action dependent on response
Case vbYes
'c has been selected by Find button on UserForm
Set c = ActiveCell
c.EntireRow.Delete 'remove entry by deleting row
'restore form settings
With Me
.cmbAmend.Enabled = False 'prevent accidental use
.cmbDelete.Enabled = False 'prevent accidental use
.cmbAdd.Enabled = True 'restore use
'clear form
Call ClearControls
End With
Case vbNo
Exit Sub 'cancelled
End Select
Application.ScreenUpdating = True
End Sub
I have tried modifying it to delete the user data on each worksheet, as follows:
Private Sub cmbDelete_Click()
Dim Sh As Worksheet
Dim msgResponse As String 'confirm delete
Application.ScreenUpdating = False
'get user confirmation
msgResponse = MsgBox("This will delete the selected record. Continue?", _
vbCritical + vbYesNo, "Delete Entry")
Select Case msgResponse 'action dependent on response
Case vbYes
For Each Sh In ThisWorkbook.Sheets
With Sh.UsedRange
'c has been selected by Find button
Set c = ActiveCell
c.EntireRow.Delete 'remove entry by deleting row
End With
Next
'restore form settings
With Me
.cmbAmend.Enabled = False 'prevent accidental use
.cmbDelete.Enabled = False 'prevent accidental use
.cmbAdd.Enabled = True 'restore use
'clear form
Call ClearControls
End With
Case vbNo
Exit Sub 'cancelled
End Select
Application.ScreenUpdating = True
End Sub
but this version deletes the user's data and the data on the 4 rows beneath them. It does not delete data from the next worksheet at all.
Can anyone offer any advice please?
change:
Case vbYes
For Each Sh In ThisWorkbook.Sheets
With Sh.UsedRange
'c has been selected by Find button
Set c = ActiveCell
c.EntireRow.Delete 'remove entry by deleting row
End With
Next
to:
Case vbYes
Dim l As Long
l = ActiveCell.Row 'store currently active cell row
For Each Sh In ThisWorkbook.Worksheets
Sh.Rows(l).Delete
Next
should you ever be interested in knowing why your previous code didn't work:
1)
Set c = ActiveCell
would set c to the currently active cell, i.e. the cell your "Find" button selected in the currently active sheet
2) while
c.EntireRow.Delete
would always, quite unsurprisingly, delete c entire row, i.e. the same row in the sheet where c has been found in, since nobody is setting c again and point to another sheet range.
and simply looping through Sheets collection doesn't change the Active sheet
Related
I am currently trying to write a piece of code where someone is able to use a checkbox to choose which worksheets they would like to keep and what they would like removed. Here is what that looks like:
(currently debating if I should turn this into a userform but i would still be stuck at this point).
What I would like to do is if the checkbox is unchecked (false) on the worksheet called "Setup", delete the worksheet and move onto the next if statement. From the code below, I am prompt with the run-time error '1004': Unable to get the OLEObjects property of the worksheet class. I have checked and the Checkbox name is the same as what I have in my code.
Sub DeleteSheetCB()
If ThisWorkbook.Worksheets("Setup").OLEObjects("CheckBox1") = False Then
ThisWorkbook.Worksheets("Program Information").Delete
End If
If ThisWorkbook.Worksheets("Setup").OLEObjects("CheckBox2") = False Then
ThisWorkbook.Worksheets("Spend and Trx Data").Delete
End If
If ThisWorkbook.Worksheets("Setup").OLEObjects("CheckBox3") = False Then
ThisWorkbook.Worksheets("Requirements").Delete
End If
If ThisWorkbook.Worksheets("Setup").OLEObjects("CheckBox4") = False Then
ThisWorkbook.Worksheets("TMC Overview").Delete
End If
End Sub
Thank you in advance
EDIT:
I was able to get this piece of code to delete sheets but if possible, would someone be able to sense check this for me please?
Sub DeleteSheetCB()
If ThisWorkbook.Worksheets("Setup").Shapes("Check Box 1").ControlFormat.Value <> 1 Then
ThisWorkbook.Worksheets("Program Information").Delete
Else: End If
If ThisWorkbook.Worksheets("Setup").Shapes("Check Box 2").ControlFormat.Value <> 1 Then
ThisWorkbook.Worksheets("Spend and Trx Data").Delete
Else: End If
If ThisWorkbook.Worksheets("Setup").Shapes("Check Box 3").ControlFormat.Value <> 1 Then
ThisWorkbook.Worksheets("Requirements").Delete
Else: End If
If ThisWorkbook.Worksheets("Setup").Shapes("Check Box 4").ControlFormat.Value <> 1 Then
ThisWorkbook.Worksheets("TMC Overview").Delete
Else: End If
End Sub
The main thing I'd take from your second code is:
It will give you a warning before it deletes each sheet
You'll get a subscript out of range error if the sheet has already been deleted.
You have to update your code if you add a new tick box.
The code below assumes the caption of the checkbox is exactly the same as the name of the sheet to be deleted.
Sub DeleteSheetCB()
Dim chkBox As CheckBox
Dim sMissing As String
With ThisWorkbook.Worksheets("Setup")
For Each chkBox In .CheckBoxes 'Look at all checkboxes in Setup sheet.
If chkBox.Value = 1 Then 'If it's ticked.
If WorksheetExists(chkBox.Caption) Then 'Check worksheet exists.
Application.DisplayAlerts = False 'Turn off warnings about deleting a sheet.
ThisWorkbook.Worksheets(chkBox.Caption).Delete
Application.DisplayAlerts = True 'Turn on warnings about deleting a sheet.
Else
sMissing = sMissing & "- " & chkBox.Caption & vbCr
End If
End If
Next chkBox
End With
If sMissing <> "" Then
MsgBox "These sheet(s) could not be deleted as they were already missing: " & vbCr & vbCr & sMissing
End If
End Sub
Public Function WorksheetExists(SheetName As String) As Boolean
Dim wrkSht As Worksheet
On Error Resume Next
Set wrkSht = ThisWorkbook.Worksheets(SheetName) 'Try and set a reference to the sheet.
WorksheetExists = (Err.Number = 0) 'Was an error thrown?
On Error GoTo 0
End Function
Might also be worth mentioning that you can rename your checkboxes:
Select a check box so the Shape Format ribbon becomes visible.
Click Selection Pane under the Arrange section.
A sidebar will appear showing the shapes on the sheet. You can rename or change their visibility here.
chkRemoveProgramInfo makes more sense than Check Box 1.
Save ONLY when adding new record
I have only tried to add
objExcel.ActiveWorkbook.Close False
It did not work. I still get the Save message even if I am only querying the database
There are two parts of the script. The first one just allows me to view the word associated with the code. The second part allows me to create a new word and assigns the next code number (sequential). There is not much code so I am showing both modules here.
Private Sub Worksheet_Change(ByVal Target As Range)
' ActiveSheet.Unprotect Password:="wood3481"
' Range("c3:g10000").Locked = True
Dim PW As Range
If Target.Address <> "$C$3" Then Exit Sub
Application.EnableEvents = False
Set PW = Sheet1.Columns(6).Find(Target)
If Not PW Is Nothing Then
[D3] = PW.Offset(, 1)
Else
MsgBox "Not Found"
End If
' ActiveSheet.Protect Password:="wood3481"
Range("C3").Select
Application.EnableEvents = True
' All cells are Locked except for C3, D3 and D4 which is required to change them with script
' Additionaly, the data storage range (g2:f10000) is Locked to allow the sript to run
End Sub
Private Sub CommandButton21_Click()
' This script records the new password
Worksheets("sheet1").Activate
Dim id
Dim idnew
Dim pswd
' Unprotect the spreadsheet to allow modification
' ActiveSheet.Unprotect Password:="vfgtrfd"
pswd = Application.InputBox("Enter New Password")
' Find the end of the password codes column
Range("f1").End(xlDown).Select
' Remember last code assigned
id = ActiveCell.Value
' Move down 1 cell which is where new code will be stored
ActiveCell.Offset(1, 0).Select
' Write new code to database
ActiveCell.Value = id + 1
idnew = ActiveCell.Value
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = pswd
MsgBox ("Here is your new password ID: " & idnew)
Range("c4").Value = idnew
' Range("c4").Locked = True
' Protect the spreadsheet before returning teh unlocked cell
' ActiveSheet.Protect Password:="vfgrfdr"
' Move cursor back to Input cell
Range("c3").Select
End Sub
I found an answer. I went for SIMPLE. I added a ActiveWorkbook.Save command so now I SAVE no matter what I am doing. It is easy, quick and simple. Problem solved.
I am having an issue regarding setting a range of cells to be editable by a user after my code runs when the file opens. The file gets a runtime error "Unable to set the locked property of the range class".
I have done some digging online and it appears other people have the same issue when their cells are merged. My cells aren't merged.
What I am trying to do:
Lock all cells on all sheets apart from specific ones
Still allow user to group and ungroup data
The code runs fine without selecting specific cells
Sub Workbook_Open()
Application.StatusBar = "Loading Please Wait..." 'change status bar text
Application.ScreenUpdating = False 'freeze screen
Application.Cursor = xlWait 'change cursor
UserForm1.Show vbModeless 'show loading form
UserForm1.Repaint 'update form
For Each ws In Sheets 'loop for every sheet
With ws
.Unprotect Password:="11Oceans" 'unprotect sheet
.Range("D6:J6").Locked = False 'format certain cells to unprotect -ERROR HERE
.Protect Password:="11Oceans", UserInterfaceOnly:=True 'protect sheet but leave data grouping
.EnableOutlining = True
End With
Next ws 'next worksheet
Application.ScreenUpdating = True 'return control to user
Application.StatusBar = "" 'return status bar to default
Application.Cursor = xlDefault 'return cursor to default
Unload UserForm1 'close loading form
End Sub
Google hasn't given me quite what I want, I thought maybe SO might have the answer.
Instead of using a input box or user prompt that asks the user for info that will be stored in cell, I'm looking for some code to simulate clicking in the formula bar. I am currently using sendkeys method with "F2" to allow the user to enter info into the selected cell. It would be much easier to look into the formula bar, instead of a single cell in a sea of data.
Sub CopyTemplate()
'ActiveWorkbook.Save
Worksheets("HR-Cal").Activate
Dim rng As Range
Dim trng As Range
Dim tco As String
'Use the InputBox select row to insert copied cells
Set rng = Application.InputBox("select row to paste into", "Insert template location", Default:=ActiveCell.Address, Type:=8)
If rep = vbCancel Then
End If
startrow = rng.Row
' MsgBox "row =" & startrow
Range("AG2") = startrow
Application.ScreenUpdating = False
'copy template block
Range("C6").End(xlDown).Select
Range("AG1") = ActiveCell.Row
tco = "A5:AN" & Range("AG1")
Range(tco).Select
Selection.Copy
Range("A" & Range("AG2")).Activate
Selection.Insert Shift:=xlDown
Range("c100000").End(xlUp).Select
Selection.End(xlUp).Select
'select first value
Range("AG1:AG2").ClearContents
Application.ScreenUpdating = True
SendKeys "{F2}"
SendKeys "{BS}"
End Sub
when the codes runs this is what the user sees (col 2 col 2621)
I don't believe there is a single keypress to "activate" the formula bar. There is probably a way to do with multiple keypress events like <alt><tab><tab>...~nine years later and a couple of other keys~...<tab><tab>
The quicker and more direct way would be to turn off the "EditDirectlyInCell" setting:
Application.EditDirectlyInCell = False
This will bring the cursor to the formula bar when you sendkey F2
You could just turn this thing off on Workbook_Open() in the workbook's code:
Private Sub Workbook_Open()
Application.EditDirectlyInCell = False
End Sub
Perhaps on Workbook_BeforeClose() you could toggle that setting back on so you don't change their defaults:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.EditDirectlyInCell = True
End Sub
maybe this will help, i set the Application.EditDirectlyInCell to false, before entering cell editing, then call DoEvents before returning EditDirectlyInCell to true
Sub EditRange(ByVal Target As Range) 'so any change in target would not affect
'the caller's variable
Set Target = Target.Areas(1).Resize(1, 1) 'to make sure the target is single cell
Target.Worksheet.Activate 'to make sure the worksheet is active
Target.Activate 'activate the designated cell
Application.EditDirectlyInCell = False 'turn cell editing to false, any attempt _
to edit cell will be done in formula bar
SendKeys "{F2}" 'send F2 to start editing the cell
DoEvents 'make sure every command is fully executed
Application.EditDirectlyInCell = True 'return in cell editing to default value
End Sub
see codes below.
I have the 'beforesave' code in the Workbook module and it works fine when I'm in the active sheet. However from the table I use on sheet 2 I also have a pivot table on sheet 1. To refresh my pivot I use an inserted button with an attached macro (this is in the module section)
Sub Refresh_Pivot()
'
' Refresh_Pivot Macro
ActiveSheet.PivotTables("PivotTable1").PivotCache.Refresh
ActiveWorkbook.Save
End Sub
On Activate.Workbook.Save its starts to act on my other code (which is in the workbook module), I want this to happen as a pivot table with missing data is not a good tool. However on using this it defaults with an error and highlights the cell.Offset(0, 1).Select - How can I prevent this?
Ideally I want the user to select OK on the msgbox and then the screen page changes to Sheet 2 and highlights the offending cell.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim esave As Range
Dim psave As Range
Dim jsave As Range
Dim RAll As Range
Dim cell As Range
Set esave = Sheet2.Range("Table1[Estimated Claim (USD)]")
Set psave = Sheet2.Range("Table1[Provisional Claim (USD)]")
Set jsave = Sheet2.Range("Table1[Agreed Claim (USD)]")
Set RAll = Union(esave, psave, jsave)
For Each cell In RAll
If cell.Value <> "" And cell.Offset(0, 1).Value = "" Then
Dim missdata
missdata = MsgBox("Missing Data - Enter the Date for WorkBook to Save", vbOKOnly, "Missing Data")
Cancel = True
cell.Offset(0, 1).Select
Exit For
End If
Next cell
End Sub
.Select should be avoided.
INTERESTING READ
I also want to know why are you trying to select that cell? What is the purpose. If you want to interact with it, then you can do that without selecting it. For example
If cell.Value <> "" And cell.Offset(0, 1).Value = "" Then
Dim missdata
missdata = MsgBox("Missing Data - Enter the Date for WorkBook to Save", vbOKOnly, "Missing Data")
Cancel = True
With cell.Offset(0, 1)
'
''~~> Do something
'
End With
Exit For
End If
Having said that if you still want to select that cell then you need to be on that sheet. There are two ways now. One is like I mentioned in the comment above.
Add Sheet2.Activate just before For Each cell In RAll in the Workbook_BeforeSave event or do that in the button's click event.
Sub Refresh_Pivot()
ActiveSheet.PivotTables("PivotTable1").PivotCache.Refresh
Sheet2.Activate
ActiveWorkbook.Save
End Sub
Another point. You might want to pass Cancel = True before the Exit For to disable the save?