Macro to run Macro - vba

I'm trying to write VBA to run a macro if a criteria is met. The problem is that I can get it to run the first macro but then it ends!
Each macro is dependent on a true/false result in there own individual cell.
So far I have tried this:
Sub RUN_ALL_SET_SHEETS()
If Range("C28").Value = False Then
MsgBox "No Team Members Selected?"
End
ElseIf Range("C28").Value = True Then
Dim Response As VbMsgBoxResult
Response = MsgBox("Are you sure you want to set the sheets for the Team Members selected?", vbQuestion + vbYesNo)
If Response = vbNo Then Exit Sub
Else
Return
End If
If Range("C10").Value = True Then
Call Set_Sheet_Daniel
End If
ElseIf Range("C12").Value = True Then
Call Set_Sheet_Gill
End If
ElseIf Range("C14").Value = True Then
Call Set_Sheet_Hollie
End If
ElseIf Range("C16").Value = True Then
Call Set_Sheet_Jo
ElseIf Range("C18").Value = True Then
Call Set_Sheet_Laura_H
ElseIf Range("C20").Value = True Then
Call Set_Sheet_Laura_K
ElseIf Range("C22").Value = True Then
Call Set_Sheet_Lucy
ElseIf Range("C24").Value = True Then
Call Set_Sheet_Mark
ElseIf Range("C26").Value = True Then
Call Set_Sheet_Richard
Else
End If
Sheets("Header").Select
MsgBox "Data Refreshed."
End Sub
Any help appreciated.

This should work:
Sub RUN_ALL_SET_SHEETS()
If Range("C28").Value = False Then
MsgBox "No Team Members Selected?"
End
ElseIf Range("C28").Value = True Then
Dim Response As VbMsgBoxResult
Response = MsgBox("Are you sure you want to set the sheets for the Team Members selected?", vbQuestion + vbYesNo)
' Changed single line if statement here.
' Single line if statements wont go to an else.
If Response = vbNo Then
Exit Sub
Else
Return
End If
If Range("C10").Value = True Then
Call Set_Sheet_Daniel
ElseIf Range("C12").Value = True Then
Call Set_Sheet_Gill
ElseIf Range("C14").Value = True Then
Call Set_Sheet_Hollie
ElseIf Range("C16").Value = True Then
Call Set_Sheet_Jo
ElseIf Range("C18").Value = True Then
Call Set_Sheet_Laura_H
ElseIf Range("C20").Value = True Then
Call Set_Sheet_Laura_K
ElseIf Range("C22").Value = True Then
Call Set_Sheet_Lucy
ElseIf Range("C24").Value = True Then
Call Set_Sheet_Mark
ElseIf Range("C26").Value = True Then
Call Set_Sheet_Richard
Else
End If
Sheets("Header").Select
MsgBox "Data Refreshed."
End Sub
To build off of BruceWaynes comment, this seems like something better suited for a subroutine with args. That would look something like this:
Sub Sheet_By_Name(sName as String)
' This is just a demonstration. You would have to put your code
' in this block. This also assumes the same operation is needed
' for each name.
' Checks to ensure a sheet with the supplied name exists
If Not ThisWorkbook.Sheets(sName) is Nothing Then
' Your code would replace this. It is best to avoid activate and
' select as is. Again, just for demonstration.
ThisWorkbook.Sheets(sName).Activate
Else
msgbox "A sheet with the name " & sName & " doesn't exist!"
Exit Sub
End If
End Sub

Related

Userform initialize checks then close

I have a userform. The idea is to check if there are any 'True' values in column(15) in 'Admin' sheet. If there is at least a single 'True' value, then the userform will remain open and continue its operation.
However, if there is not a single 'True' found, then the userform will display a message and close the userform automatically.
Private Sub Userform_initialize()
Dim LR As Long
LR = Sheets("Project_Name").Cells(Rows.Count, "B").End(xlUp).Row
With Worksheets("Admin")
For i = 7 To LR
If .Cells(i, 15) = "True" Then
Exit For
Else
MsgBox ("No values found")
Exit For
Unload Me
End If
Next i
End With
''' more code'''
End Sub
Everything on my userform works as expected, except for the fact I am unable to make it close itself automatically. I.e. Unload Me is not working.
Any advice?
You should check your criteria before you even display the UserForm. You can add this as a condition wherever you are calling the UserForm. No need to open the form just to immediately close it when you can check before-hand.
On the first instance of True, the UserForm will open, and exit the sub. If the loop completes (finds no True values), the sub will proceed to your MsgBox
Sub OpenForm
With Worksheets("Admin")
For i = 7 To LR
If Cells(i,15) = "True" then
Userform.Show
Exit Sub
End If
Next i
End With
MsgBox "No Values Found"
End Sub
Please look at your code; you have put Unload Me is after Exit For
'Here is something for you to ponder on .........
'Public enum type to add a set of particular vbKeys to the standard key set
Public Enum typePressKeys
vbNoKey = 0
vbExitTrigger = -1
vbAnswerKey = 100
vbLaunchKey = 102
vbPrevious = 104
vbNext = 106
vbSpecialAccessKey = 108
End Enum
Public Sub doSomethingWithMyUserform()
Dim stopLoop As Boolean, testVal As Boolean, rngX As Range, LR As Long
LR = ThisWorkbook.Sheets("Project_Name").Cells(Rows.Count, "B").End(xlUp).Row
Set rngX = ThisWorkbook.Worksheets("Admin")
testVal = False
With rngX 'Your sub can do the check here
For i = 7 To LR
If .Cells(i, 15) = "True" Then
testVal = True
Exit For
End If
Next i
End With
If testVal Then
Load UserForm1
With UserForm1
.Caption = "Something"
.Tag = vbNoKey
.button_OK.SetFocus 'Assuming you have a OK button on Userform1
End With
UserForm1.Show
stopLoop = False
Do
If UserForm1.Tag = vbCancel Then
'Do something perhaps
Unload UserForm1
stopLoop = True
ElseIf UserForm1.Tag = vbOK Then
'Do something specific
Unload UserForm1
stopLoop = True
Else
stopLoop = False
End If
Loop Until stopLoop = True
else
MsgBox "No values found"
End If
'Here you can close the way you want
Set rngX = Nothing
End Sub
enter code here

How to Set Different Privileges for Different Users of an Excel File

maybe you can help me with this issue:
I am trying to set for one excel sheet different kind of privileges.
For example, there will be an Admin with all right and a guest, how is only allowed the change an range of cells.
I started to setup 2 different kind of logins, the one for the admin is working well however the one for the guest not at all.
What am I doing wrong here?
Ps: I just started to learn VBA ☺
Private Sub CommandButton1_Click()
Dim objTargetWorksheet As Worksheet
'Gast
If (TextBox1.Value = "Gast" And TextBox2.Value = "123") _
Or (TextBox1.Value = "Amy" And TextBox2.Value = "345") _
Or (TextBox1.Value = "Paul" And TextBox2.Value = "456") Then
Me.Hide: Application.Visible = True
For Each objTargetWorksheet In ActiveWorkbook.Worksheets
If objTargetWorksheet.Name = TextBox1.Value Then
Range("K3:K50").Locked = True
ActiveSheet.Protect Password:="12345", Contents:=True
Else
Range("K3:K50").Locked = True
ActiveSheet.Protect Password:="12345", Contents:=True
End If
Next
'Admin
ElseIf TextBox1.Value = "Admin" Then
If TextBox2.Value = "" Then
MsgBox "Please Input the Password"
ElseIf TextBox2.Value = "123" Then
Me.Hide: Application.Visible = True
Else
MsgBox "Please Input the right User Name and the right Password"
End If
Else
MsgBox "Please input the right user name and the right password"
End If
End Sub
Private Sub CommandButton2_Click()
ThisWorkbook.Application.Quit
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
ThisWorkbook.Application.Quit
End Sub
You need to reference the sheet you are working on.
For Each objTargetWorksheet In ActiveWorkbook.Worksheets
If objTargetWorksheet.Name = TextBox1.Value Then
objTargetWorksheet.Range("K3:K50").Locked = True
objTargetWorksheet.Protect Password:="12345", Contents:=True
Else
objTargetWorksheet.Range("K3:K50").Locked = True
objTargetWorksheet.Protect Password:="12345", Contents:=True
End If
Next
UPDATE: Cells are locked by default so you actually have to unlock them before protecting the sheet. Try this:
For Each objTargetWorksheet In ActiveWorkbook.Worksheets
If objTargetWorksheet.Name = TextBox1.Value Then
objTargetWorksheet.Cells.Locked = False
objTargetWorksheet.Range("K3:K50").Locked = True
objTargetWorksheet.Protect Password:="12345", Contents:=True
Else
objTargetWorksheet.Cells.Locked = False
objTargetWorksheet.Range("K3:K50").Locked = True
objTargetWorksheet.Protect Password:="12345", Contents:=True
End If
Next

Excel VBA Forms Error Message loop

i currently have a problem with a simple login form in excel (VBA), when having an error, continuing and having another error it still gives me two more MsgBoxes with errors but with the "Unload Me" and "Goto Ende" it should close itself completely.
Any guesses why this isn't working? I know this is very basic and probably very redundant, but it should still work.
Public Name As Variant
Public Password As Variant
Private Sub Btn_Register_Cancel_Click()
Unload Me
End Sub
Private Sub Btn_Register_Register_Click()
Start:
Dim Error As Integer
Error = 0
Name = Tbx_Register_Name.Value
Password = Tbx_Register_Password.Value
'Check for Name, Password, Password2 if empty
If Tbx_Register_Name.Value = "" Then
Error = MsgBox("Please enter a username.", _
vbRetryCancel, "Error")
If Error = 2 Then
Unload Me
GoTo Ende
Else
Application.ScreenUpdating = False
Register.Hide
Register.Show
Application.ScreenUpdating = True
GoTo Start
End If
ElseIf Tbx_Register_Password.Value = "" Then
Error = MsgBox("Please enter a password.", _
vbRetryCancel, "Error")
If Error = 2 Then
Unload Me
GoTo Ende
Else
Application.ScreenUpdating = False
Register.Hide
Register.Show
Application.ScreenUpdating = True
GoTo Start
End If
ElseIf Tbx_Register_Password2.Value = "" Then
Error = MsgBox("This field cannot be empty.", _
vbRetryCancel, "Error")
If Error = 2 Then
Unload Me
GoTo Ende
Else
Application.ScreenUpdating = False
Register.Hide
Register.Show
Application.ScreenUpdating = True
GoTo Start
End If
End If
With Workbooks("General Makro.xlsx").Worksheets("User")
'Check for Username match in registration list
For i = 1 To 100
If .Cells(i, 1).Value = Name Then
Error = MsgBox("This username is already taken.", _
vbRetryCancel, "Error")
If Error = 2 Then
Unload Me
i = 100
GoTo Ende
Else
Application.ScreenUpdating = False
Register.Hide
Register.Show
Application.ScreenUpdating = True
GoTo Start
End If
End If
Next i
End With
'Check for the passwords to match
If Tbx_Register_Password.Value = Tbx_Register_Password2.Value Then
With Workbooks("General Makro.xlsx").Worksheets("User")
For i = 1 To 100
If .Cells(i, 1) = "" Then
.Cells(i, 1).Value = Name
.Cells(i, 2).Value = Password
Tbx_Register_Password.Value = ""
Tbx_Register_Password2.Value = ""
Application.ScreenUpdating = False
Register.Hide
Login.Show
Tbx_Login_Name.Value = .Cells(i, 1).Value
Tbx_Login_Password.Value = .Cells(i, 2).Value
Application.ScreenUpdating = True
i = 100
GoTo Ende
End If
Next i
End With
Else
Error = MsgBox("The passwords have to match!", vbRetryCancel, "Error")
If Error = 2 Then
Unload Me
GoTo Ende
Else
Application.ScreenUpdating = False
Register.Hide
Register.Show
Application.ScreenUpdating = True
GoTo Start
End If
End If
Ende:
End Sub
Edit: I Actually Tried to do the 2nd UserForm for the login, and i happen to get the same problem there. Everything works just fine, until i close the whole program, then the error-message appears again. Am i unloading the userform incorrect? Maby the login userform says open and continues when everything is getting closed.
Edit 2: I could just turn off alerts but that would be an ugly solution and definitely nothing i want to implement on every close button in the program.
You can verify blank values in textboxes with this:
If TextBox.Text = "" Then
MsgBox "Is blank!"
Unload Me
GoTo Ende
End If
'Your code
Ende: Exit Sub
To verify the username and password in a database, you can do this:
Dim sh As Worksheet
Dim LastRow As Long
Dim UserRange As Range
Dim UserMatch As Range
Set sh = ThisWorkbook.Sheets("database")
LastRow = sh.Range("A" & Rows.Count).End(xlUp).Row
Set UserRange = sh.Range("A1:A" & LastRow)
Set UserMatch = UserRange.Find(What:=UserTextBox.Text, LookIn:=xlValues)
If Not UserMatch Is Nothing Then
MsgBox "User exists!"
If PwdTextBox.Text = UserMatch.Offset(0, 1) Then
MsgBox "Pwd matched!"
'do something
Else
MsgBox "Wrong password!"
'do something
End If
Else
MsgBox "User dont exists!"
'do something
End If
This will work if in the database the usernames are in column A and the passwords in column B.

Simplify code with loop

Hi I'm pretty new at the vba so please don't shoot my code :-).
I have a set of repaeting code's. I woukld like to simplify this code by using the code name with an increasing number. I can't get it to run. Can someone help me a bit on the road to get this going.
Below what I'm trying.
The second block is a part of the code now (it's 40 blocks of the same code only increasing the number)
Sub sheet41()
Dim i As Integer
Dim chkname As Integer
chkname = "SheetCheckBox" & i
i = 1
Do
i = i + 1
If chkname.Visible = False Then Exit Sub
If chkname.value = True Then
Sheets("Item_" & i).Select
Call Finalize
End If
Loop Until i = ThisWorkbook.Worksheets.Count
End Sub
This is the old code:
Sub Sheet1()
If SheetCheckBox1.Visible = False Then Exit Sub
If SheetCheckBox1.value = True Then
Sheets("Item_1").Select
Call Finalize
End If
End Sub
Sub Sheet2()
If SheetCheckBox2.Visible = False Then Exit Sub
If SheetCheckBox2.value = True Then
Sheets("Item_2").Select
Call Finalize
End If
End Sub
Sub Sheet3()
If SheetCheckBox3.Visible = False Then Exit Sub
If SheetCheckBox3.value = True Then
Sheets("Item_3").Select
Call Finalize
End If
End Sub
As you can see this should be possible to clean I asume.
This should do it. If finalize isn't called on a worksheet then the reason why is printed to the Immediate Window.
Sub ProcessWorkSheets()
Dim check As MSForms.CHECKBOX
Dim i As Integer
For i = 1 To Worksheets.Count
On Error Resume Next
Set check = Worksheets(i).OLEObjects("SheetCheckBox" & i).Object
On Error GoTo 0
If check Is Nothing Then
Debug.Print Worksheets(i).Name; " - Checkbox not found"
Else
If check.Visible And check.Value Then
Worksheets(i).Select
Call Finalize
Else
Debug.Print Worksheets(i).Name; " - Checkbox", "Visible", check.Visible, "Value:", check.Value
End If
End If
Set check = Nothing
Next
End Sub
If the checkboxes on the Sheet are ActiveX Controls, you can use this to access the checkboxes:
Sheets("sheet1").OLEObjects("chkTest").Object
if you want to change the value of a checkbox, use it like this:
Sheets("sheet1").OLEObjects("chkTest").Object.Value = True
now replace "sheet1" with your actual sheet name and change the "chkTest" to your string chkname
So your complete code should be like this:
Dim i As Integer
Dim sheetname As String
Dim chkname As String
sheetname = "YOUR SHEETNAME HERE"
For i = 1 To ThisWorkbook.Worksheets.Count Step 1
chkname = "SheetCheckBox" & i
If Sheets(sheetname).OLEObjects(chkname).Object.Visible = False Then Exit Sub
If Sheets(sheetname).OLEObjects(chkname).Object.Value = True Then
Sheets("Item_" & i).Select
Call Finalize
End If
Next i

Loading screen userform

I've tried just about every option of modeless possible to get this to work I just cannot get it figured out. What I have is a Userform ( Main_Window ) that has a script, and on command button it executes Master_Flex_Filter_Generate()
In that code I have
' Connect and execute the SQL
rs.Open sqlString, conn, adOpenStatic
' Check if we have data.
If Not rs.EOF Then
' Dump column names in first row.
For i = 0 To rs.Fields.count - 1
ActiveSheet.Cells(1, i + 1) = rs.Fields(i).Name
Next i
Do
' Transfer results beginning at A2 from rs
ActiveSheet.Range("A2").CopyFromRecordset rs
Loop Until rs.EOF
' Close the recordset
rs.Close
' Define Record_Count as the amount of records returned. Subtract 1 for the header
Record_Count = Cells(Rows.count, "A").END(xlUp).Row - 1
' Return box on success
Answer = MsgBox((Record_Count & " Records returned") & vbCrLf & vbCrLf & "Reminder" & vbCrLf & "- This data set is already defined as a range. This allows you to create a new pivot table and use the named range: " & ActiveSheet.Name & vbCrLf & vbCrLf & "Do you want to create a Pivot Table from this data?", vbYesNo + vbQuestion, "Query generated succesfully")
' close user form
Unload mod_loading
Unload Main_Window
' Clean up
If CBool(conn.State And adStateOpen) Then conn.Close
Set conn = Nothing
Set rs = Nothing
'Now lets define this data as a range for pivot table use
Dim ActSheet As Worksheet
Dim ActSheetName As String
'This sets up an object reference to the activesheet
Set ActSheet = Sheets(ActiveSheet.Name)
'This places a string value in the variable
ActSheetName = ActiveSheet.Name
Set wb = ActiveWorkbook
Set ws = ActiveSheet
Set sheetname = ActiveWorkbook.ActiveSheet
ws.Range("A1").Select
ActiveWorkbook.Names.Add Name:="data", RefersToR1C1:= _
"=OFFSET(R1C1,0,0,COUNTA(C1),COUNTA(R1))"
wb.Names("data").Name = ActSheetName
'Filter, freeze pain, and align columns
Rows("1:1").Select
Selection.AutoFilter
Selection.Font.Bold = True
Columns("A:IV").AutoFit
With ActiveWindow
.SplitColumn = 0
.SplitRow = 1
End With
ActiveWindow.FreezePanes = True
'Take answer form msgbox and do something with it
If Answer = vbYes Then
'If yes, create pivot table
Sheets("Pivot").Select
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
"data", Version:=xlPivotTableVersion14).CreatePivotTable TableDestination _
:="Pivot!R1C1", TableName:="PivotTable1", DefaultVersion:= _
xlPivotTableVersion14
Sheets("Pivot").Select
Cells(1, 1).Select
End If
Else
mod_loading.Hide
MsgBox "Error: No records returned for your criteria.", vbCritical
End If
This form works perfectly as is here. I have another Userform called mod_loading that looks like this
Sub UserForm_Activate()
DoEvents
Do
mod_loading.loading_beag.Visible = False
mod_loading.loading_splines.Visible = True
Sleep 2000
DoEvents
mod_loading.loading_splines.Visible = False
mod_loading.loading_sheep.Visible = True
Sleep 5000
DoEvents
mod_loading.loading_sheep.Visible = False
mod_loading.loading_meteor.Visible = True
Sleep 5000
DoEvents
mod_loading.loading_meteor.Visible = False
mod_loading.loading_ozone.Visible = True
Sleep 5000
DoEvents
mod_loading.loading_ozone.Visible = False
mod_loading.loading_terrain.Visible = True
Sleep 5000
DoEvents
mod_loading.loading_terrain.Visible = False
mod_loading.loading_gravity.Visible = True
Sleep 5000
DoEvents
mod_loading.loading_gravity.Visible = False
mod_loading.loading_advisor.Visible = True
Sleep 5000
DoEvents
mod_loading.loading_advisor.Visible = False
mod_loading.loading_pool.Visible = True
Sleep 5000
DoEvents
mod_loading.loading_pool.Visible = False
mod_loading.loading_leaks.Visible = True
Sleep 5000
DoEvents
mod_loading.loading_leaks.Visible = False
mod_loading.loading_beag.Visible = True
Sleep 5000
DoEvents
Loop
End Sub
Both of these forms work as is, where I'm having the problem is placing mod_loading.Show anywhere in Master_Flex_Filter_Generate(). No matter what I set for modeless the mod_loading will run until it completely finishes. It won't let the code in Main_Window to continue running, so it halts that code. Any ideas? I was thinking it's perhaps because I'm not playing mod_loading.Show inside a loop, but since my connection string doesn't have a loop I can't figure out how to do it.
I placed the code inside If Not rs.EOF THEN but 99% of the code loads on rs.Open which is outside of the loop.
EDIT
Okay so I have changed my script all around and have placed all SQL logic inside the userform for the loading dialog. So I have Main_Window which is the form, then it calls the sub from the loading userform which pops up just fine. So I now have the loading dialog pop up and goes away just fine as intended. My only problem is now, it doesn't loop through my sleep commands. It just remains on the very first one.
Here is my code for the loading userform
Sub UserForm_Activate()
DoEvents
Call Master_Flex_Filter_Generate
DoEvents
If Cancel = True Then
Unload loading_masterflexfilter
Exit Sub
End If
loading_masterflexfilter.loading_beag.Visible = False
loading_masterflexfilter.loading_splines.Visible = True
Sleep 500
DoEvents
If Cancel = True Then
Unload loading_masterflexfilter
Exit Sub
End If
loading_masterflexfilter.loading_splines.Visible = False
loading_masterflexfilter.loading_sheep.Visible = True
Sleep 1000
DoEvents
If Cancel = True Then
Unload loading_masterflexfilter
Exit Sub
End If
loading_masterflexfilter.loading_sheep.Visible = False
loading_masterflexfilter.loading_meteor.Visible = True
Sleep 1000
DoEvents
If Cancel = True Then
Unload loading_masterflexfilter
Exit Sub
End If
loading_masterflexfilter.loading_meteor.Visible = False
loading_masterflexfilter.loading_ozone.Visible = True
Sleep 1000
DoEvents
If Cancel = True Then
Unload loading_masterflexfilter
Exit Sub
End If
loading_masterflexfilter.loading_ozone.Visible = False
loading_masterflexfilter.loading_terrain.Visible = True
Sleep 1000
DoEvents
If Cancel = True Then
Unload loading_masterflexfilter
Exit Sub
End If
loading_masterflexfilter.loading_terrain.Visible = False
loading_masterflexfilter.loading_gravity.Visible = True
Sleep 1000
DoEvents
If Cancel = True Then
Unload loading_masterflexfilter
Exit Sub
End If
loading_masterflexfilter.loading_gravity.Visible = False
loading_masterflexfilter.loading_advisor.Visible = True
Sleep 1000
DoEvents
If Cancel = True Then
Unload loading_masterflexfilter
Exit Sub
End If
loading_masterflexfilter.loading_advisor.Visible = False
loading_masterflexfilter.loading_pool.Visible = True
Sleep 1000
DoEvents
If Cancel = True Then
Unload loading_masterflexfilter
Exit Sub
End If
loading_masterflexfilter.loading_pool.Visible = False
loading_masterflexfilter.loading_leaks.Visible = True
Sleep 1000
DoEvents
If Cancel = True Then
Unload loading_masterflexfilter
Exit Sub
End If
loading_masterflexfilter.loading_leaks.Visible = False
loading_masterflexfilter.loading_beag.Visible = True
Sleep 1000
DoEvents
End Sub