Automatically select option (Radio) buttons based on condition - excel

I have two groups of radio buttons. see below image.
where one group for transaction type and another for transaction number.
total 6 transactions are allowed in a day. where 3 for withdrawals and other three for deposits.
I am using below vba code to auto select next radio button if one is
used. but no luck.
Sub OBWithdrawal_Click()
Dim OBWithdrawal, OBDeposit, OB1st, OB2nd, OB3rd As OptionButton
'transaction type
Set OBWithdrawal = Sheet1.Shapes("OBWithdrawal").OLEFormat.Object
Set OBDeposit = Sheet1.Shapes("OBDeposit").OLEFormat.Object
'transaction number
Set OB1st = Sheet1.Shapes("OB1st").OLEFormat.Object
Set OB2nd = Sheet1.Shapes("OB2nd").OLEFormat.Object
Set OB3rd = Sheet1.Shapes("OB3rd").OLEFormat.Object
If Sheet1.Range("G24").Value = "#NUM" Then
OB1st.Value = True
If Sheet1.Range("G24").Value = 1 Then
OB2nd.Value = True
If Sheet1.Range("G24").Value = 2 Then
OB3rd.Value = True
If Sheet1.Range("G24").Value = 3 Then
OB1st.Value = False
OB2nd.Value = False
OB3rd.Value = False
MsgBox "You have only 3 withdrawal are allowed in a single day." & vbNewLine & ""
End If
End If
End If
End If
End Sub
I did not received any error messages. so I cant figure out where I m doing wrong.
please help

1. Always declare variables separately. If you declare them as Dim OBWithdrawal, OBDeposit, OB1st, OB2nd, OB3rd As OptionButton, then only the last one which is OB3rd will be declared as OptionButton. Rest will be declared as Variant
2. You can use a single IF-ELSEIF-ENDIF statement to handle all those criteria.
3. This procedure is for Withdrawal. Similarly, create for Deposit. Alternatively, you can create a common procedure for both and then use Application.Caller to identify which is the "calling" option button and then execute the relevant code.
Is this what you are trying?
Option Explicit
Sub OBWithdrawal_Click()
Dim OBWithdrawal As OptionButton
Dim OB1st As OptionButton
Dim OB2nd As OptionButton
Dim OB3rd As OptionButton
Set OBWithdrawal = Sheet1.Shapes("OBWithdrawal").OLEFormat.Object
With Sheet1
Set OB1st = .Shapes("OB1st").OLEFormat.Object
Set OB2nd = .Shapes("OB2nd").OLEFormat.Object
Set OB3rd = .Shapes("OB3rd").OLEFormat.Object
If .Range("G24").Value = "#NUM" Then
OB1st.Value = True
ElseIf .Range("G24").Value = 1 Then
OB2nd.Value = True
ElseIf .Range("G24").Value = 2 Then
OB3rd.Value = True
ElseIf .Range("G24").Value = 3 Then
OB1st.Value = False
OB2nd.Value = False
OB3rd.Value = False
MsgBox "You have only 3 withdrawal are allowed in a single day." & vbNewLine & ""
End If
End With
End Sub
EDIT
This is the 3rd way that I was talking about. Assign this code to both the Withdrawal and Deposit button. This will work for both.
Option Explicit
Sub OBWithdrawalDeposit_Click()
Dim OptBtn As OptionButton
Dim OB1st As OptionButton
Dim OB2nd As OptionButton
Dim OB3rd As OptionButton
Dim OptBtnName As String
Dim TrnType As String
OptBtnName = Application.Caller
'~~> If Withdrawal was selected
If OptBtnName = "OBWithdrawal" Then
Set OptBtn = Sheet1.Shapes("OBWithdrawal").OLEFormat.Object
TrnType = "Withdrawals"
ElseIf OptBtnName = "OBDeposit" Then '<~~ If Deposit was selected
Set OptBtn = Sheet1.Shapes("OBDeposit").OLEFormat.Object
TrnType = "Deposits"
Else
MsgBox "This procedure was not called the right way"
Exit Sub
End If
With Sheet1
Set OB1st = .Shapes("OB1st").OLEFormat.Object
Set OB2nd = .Shapes("OB2nd").OLEFormat.Object
Set OB3rd = .Shapes("OB3rd").OLEFormat.Object
If .Range("G24").Value = "#NUM" Then
OB1st.Value = True
ElseIf .Range("G24").Value = 1 Then
OB2nd.Value = True
ElseIf .Range("G24").Value = 2 Then
OB3rd.Value = True
ElseIf .Range("G24").Value = 3 Then
OB1st.Value = False
OB2nd.Value = False
OB3rd.Value = False
MsgBox "You are allowed only 3 " & TrnType & " in a single day."
End If
End With
End Sub

Related

VBA User Form Initialization Object Required

Something strange is happening where I call a userform to show via a module, but it says object is required and does not initialize the form. The strange part is the method of calling does not change from a workbook that functions the exact same.
I have a module with the following code assigned to a button:
Sub SHOW_INSERT_TASK_FORM()
INSERT_TASK_FORM.Show ' Error Occurs here
End Sub
This should initialize the "INSERT_TASK_FORM" user form and run its code but I receive an object required error upon the "Show" method.
Here is the code imbedded within the user form:
Private Sub SUBMIT_BUTTON_Click()
Unload Me
End Sub
Private Sub UserForm_Initialize()
'DECLARE OBJECT VARIABLES
Dim planner_ws As Worksheet, data_ws As Worksheet
Dim departments As ListObject
Dim types As ListObject
Dim tasks As ListObject
Dim dep_arr() As Variant
Dim type_arr() As Variant
Dim task_arr() As Variant
Dim i As Double, j As Double, x As Double
Dim lrow As Double, srow As Double
'SET WS VARIABLES
Set planner_ws = ThisWorkbook.Worksheets("TASK_PLANNER")
Set data_ws = ThisWorkbook.Worksheets("DATA")
'ASSIGN OBJECT VARIABLES
Set departments = data_ws.ListObjects("DEPARTMENT_TABLE")
Set types = data_ws.ListObjects("TASK_TYPE_TABLE")
Set tasks = data_ws.ListObjects("TASKS_TABLE")
'ASSIGN VARIABLE VALUES
dep_arr = departments.DataBodyRange
type_arr = types.DataBodyRange
task_arr = tasks.DataBodyRange
lrow = planner_ws.Cells(planner_ws.Rows.Count, 2).End(xlUp).Row
'INITIAL USER FORM VALUES
TASK_NAME_TBOX.Value = ""
DESC_TBOX.Value = ""
SDATE_TBOX.Value = ""
EDATE_TBOX.Value = ""
Task_Option = False
Sub_Option = False
'POPULATE COMBO BOXES
With TYPE_CBOX
For i = LBound(type_arr) To UBound(type_arr)
.AddItem type_arr(i, types.ListColumns("Task_Type").Index)
Next i
End With
With DEP_CBOX
For i = LBound(dep_arr) To UBound(dep_arr)
.AddItem dep_arr(i, types.ListColumns("Department").Index)
Next i
End With
With TASK_CBOX
For i = LBound(task_arr) To UBound(task_arr)
.AddItem task_arr(i, types.ListColumns("Task Name").Index)
Next i
End With
End Sub
Private Sub SUB_OPTION_Click()
If Sub_Option.Value = True Then
Task_Label.Visible = True
TASK_CBOX.Visible = True
Else
Task_Label.Visible = False
TASK_CBOX.Visible = False
End If
End Sub
For reference, the following code in another workbook of mine works just fine:
Sub GameSale_Form()
xInput_GameSale.Show
End Sub
Private Sub UserForm_Initialize()
LCS_Option = False
NOTLCS_Option = False
Qty_TextBox.Value = ""
Discount_TextBox.Value = ""
InputCost_Textbox.Value = ""
InRegion_Option.Value = False
NotInRegion_Option = False
New_Option.Value = False
Used_Option.Value = False
InputCost_Option = False
AvCost_Option = False
FDAPricing_Option = False
NoFDAPricing_Option = False
With Cabinet_Combobox
For i = 2 To ThisWorkbook.Worksheets("List_Data").Cells(Rows.Count, 36).End(xlUp).Row
.AddItem ThisWorkbook.Worksheets("List_Data").Cells(i, 36).Value
Next i
End With
Opening_Textbox.Value = ""
Ambition_Textbox.Value = ""
Goal_Textbox.Value = ""
WalkAway_Textbox.Value = ""
Qty_SpinButton.Min = 0
Qty_SpinButton.Max = 1000
End Sub

Using the output from a User Form in the macro with IF structure

I am trying to merge 4 models into one. All models have a common part of the code as well as a model specific parts. I have created a user form, which identifies what model to run based on the criteria selected by user. So the user form has 4 criteria and produces 12 different outcomes. So I want to create a sub which will run the commons parts of the code for all outcomes and then outcome specific parts.
Currently the user form code displays message boxes depending on the selection. I want to connect this code (see it below) to the code in the VBA model and use in the IF structure. For example, if a user select Template 1, Private data type and Tier 2, No Wipe Out then the model will run the common part, then the parts for Template 1 with Private data type, Tier 2 and No Wipe Out and then again a common part.
For example, the Wipe Out/No Wipe Out part is similar for all models. Other parts have a lot of similarities.
Here is the User Form code:
Private Sub modelrun_btn_Click()
If radiotempl1.Value = True Then
If datatype.Value = "Public" Then
If wipe_format.Value = True Then
MsgBox "Template 1 Public Model Wipe Out"
Else
MsgBox "Template 1 Public Model No Wipe Out"
End If
ElseIf datatype.Value = "Private" Then
If radiotier1.Value = True Then
If wipe_format.Value = True Then
MsgBox "Template 1 Private Model Tier 1 Wipe Out"
Else
MsgBox "Template 1 Private Model Tier 1 No Wipe Out"
End If
Else
If wipe_format.Value = True Then
MsgBox "Template 1 Private Model Tier 2 Wipe Out"
Else
MsgBox "Template 1 Private Model Tier 2 No Wipe Out"
End If
End If
Else
MsgBox "Please select a data type"
End If
ElseIf radiotempl2.Value = True Then
If datatype.Value = "Public" Then
If wipe_format.Value = True Then
MsgBox "Template 2 Public Model Wipe Out"
Else
MsgBox "Template 2 Public Model No Wipe Out"
End If
ElseIf datatype.Value = "Private" Then
If radiotier1.Value = True Then
If wipe_format.Value = True Then
MsgBox "Template 2 Private Model Tier 1 Wipe Out"
Else
MsgBox "Template 2 Private Model Tier 1 No Wipe Out"
End If
ElseIf radiotier2.Value = True Then
If wipe_format.Value = True Then
MsgBox "Template 2 Private Model Tier 2 Wipe Out"
Else
MsgBox "Template 2 Private Model Tier 2 No Wipe Out"
End If
Else
MsgBox "Please select a tier"
End If
Else
MsgBox "Please select a data type"
End If
Else
MsgBox "Please select a template"
End If
End Sub
And this is an example of one of the models. Basically it opens an Excel file generated by a different programme, copies one or two worksheets into the model (depending on template), there are worksheets in teh model with commented out formulas, so the macro uncomments them, hides those which are not needed and does some formatting.
Sub UploadData()
Dim FileOpenDial As Variant
Dim FileSaveAs As Variant
Dim wb As Workbook
Dim activeWB As Workbook
Dim bFileSaveAs As Boolean
Dim finstart As Range
Dim endcell As Range, startcell As Range
Dim yearsno As Range
Dim numrowsadj As Integer
Dim cfyearsno As Range
Dim numrows As Integer
Dim numrowscf As Integer
Dim c As Range
Dim decimaltab As Range
Dim d As Range
Dim MySheets As Variant
Dim r As Range
'Import the data
'Optimize Code
Application.ScreenUpdating = False
EventState = Application.EnableEvents
Application.EnableEvents = False
CalcState = Application.Calculation
Application.Calculation = xlCalculationManual
PageBreakState = ActiveSheet.DisplayPageBreaks
ActiveSheet.DisplayPageBreaks = False
Application.DisplayAlerts = False
Set activeWB = Application.ActiveWorkbook
FileOpenDial = Application.GetOpenFilename(FileFilter:="Excel Files (*.XML), *.XML", Title:="Select File To Be Opened")
If FileOpenDial = False Then Exit Sub
Set wb = Workbooks.Open(FileOpenDial)
Sheets(Array("Accounts", "Types")).Select
Sheets(Array("Accounts", "Types")).Copy Before:=activeWB.Sheets(1)
wb.Close savechanges:=False 'or True
'Save a file
FileSaveAs = Application.GetSaveAsFilename(FileFilter:="Exel Files (*.xlsx), *.xlsx", Title:="Select Name To Save The File")
If FileSaveAs <> False Then
ActiveWorkbook.SaveAs Filename:=FileSaveAs, _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End If
'Unhide sheets
For Each MySheets In Array("FS", "CF", "tables", "Calcs", "tables_for_output", "Tier_I", "Tier_II")
Worksheets(MySheets).Visible = True
Next
'Build tables from the data
Sheets("FS").Select
'Remove apostrophe from the formulas
For Each c In Range("D1:D250").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'FillRight Formulas
Set yearsno = ThisWorkbook.Sheets("Accounts").Range("F2:Z2")
numrows = Application.WorksheetFunction.CountA(yearsno)
If 5 - numrows >= 0 Then
numrowsadj = 0
Else: numrowsadj = 5 - numrows
End If
With ThisWorkbook.Sheets("FS")
Set startcell = .Range("D1")
Set endcell = Cells(Range("D" & Rows.Count).End(xlUp).Row, 3 + numrows + numrowsadj)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
End With
ThisWorkbook.Sheets("FS").Range("C1").Select
'Build CF
Sheets("CF").Select
'Remove apostrophe from the formulas
For Each c In Range("F1:F160").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'FillRight Formulas
Set cfyearsno = ThisWorkbook.Sheets("FS").Range("C1:XFD1")
numrowscf = Application.WorksheetFunction.CountA(cfyearsno)
With ThisWorkbook.Sheets("CF")
Set startcell = .Range("F1")
If numrowscf = 3 Then
Set endcell = Range("F" & Rows.Count).End(xlUp).Offset(, 1)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
ElseIf numrowscf > 3 Then
Set endcell = Range("F" & Rows.Count).End(xlUp).Offset(, 2)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
Else
End If
End With
ThisWorkbook.Sheets("CF").Range("E1").Select
'Activite the Summary tables
Sheets("tables").Select
For Each c In Range("C1:G88").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
Sheets("tables").Range("B1").Select
'Activate Calcs
Sheets("Calcs").Select
'Remove apostrophe from the formulas
For Each c In Range("B1:H22").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'Activate tables_for_output
Sheets("tables_for_output").Select
For Each c In Range("B2:O43").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'Activate Tier_I
Sheets("Tier_I").Select
For Each c In Range("D6:I15").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'Activate Tier_II
Sheets("Tier_II").Select
For Each c In Range("D6:I15").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
'Hide the working worksheets
Sheets(Array("Model", "Calcs")).Visible = False
'Stop Optimize Code
'Call OptimizeCode_End
'ActiveSheet.DisplayPageBreaks = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
'Replace Conditional formating with normal based on a checkbox
If Sheets("Model").Shapes("Check Box 7").ControlFormat.Value = 1 Then
Sheets("tables_for_output").Select
Range("F4:O4").Select
For Each r In Selection
r.Interior.Color = r.DisplayFormat.Interior.Color
Next r
Selection.FormatConditions.Delete
'Tier_I
Sheets("Tier_I").Select
Range("F6:H15").Select
For Each r In Selection
r.Interior.Color = r.DisplayFormat.Interior.Color
Next r
Selection.FormatConditions.Delete
Sheets("Tier_I").Range("C2").Select
'Tier_II
Sheets("Tier_II").Select
Range("F6:H15").Select
For Each r In Selection
r.Interior.Color = r.DisplayFormat.Interior.Color
Next r
Selection.FormatConditions.Delete
End If
ThisWorkbook.Sheets("tables_for_output").Select
Sheets("tables_for_output").Range("A1").Select
ThisWorkbook.Sheets("Tier_II").Select
Sheets("Tier_II").Range("C2").Select
'Hide a Tier sheet based on the selection
If Sheets("Calcs").Range("B24").Value = 1 Then
Sheets("Tier_II").Visible = False
ElseIf Sheets("Calcs").Range("B24").Value = 2 Then
Sheets("Tier_I").Visible = False
End If
'Formatting
'Columns Width
ThisWorkbook.Sheets("FS").Cells.SpecialCells(xlCellTypeVisible).EntireColumn.AutoFit
ThisWorkbook.Sheets("CF").Cells.SpecialCells(xlCellTypeVisible).EntireColumn.AutoFit
'Decimal Formatting
'tables
Sheets("tables").Select
Set decimaltab = [C2:E16,C25:E49,C62:E69,C71:E75,C77:E83]
For Each d In decimaltab.SpecialCells(xlCellTypeFormulas, xlNumbers)
If Abs(d.Value) < 20 And Round(d.Value, 0) <> 0 Then
d.NumberFormat = "0.0;(0.0)"
Else
d.NumberFormat = "#,##0;(#,##0)"
End If
Next d
'tables_for_output
Sheets("tables_for_output").Select
Set decimaltab = [B2:B3,B11:D15,B17:D18,B20:D23,B33:D34,B37:D39,B43:D43]
For Each d In decimaltab.SpecialCells(xlCellTypeFormulas, xlNumbers)
If Abs(d.Value) < 101 And Round(d.Value, 0) <> 0 Then
d.NumberFormat = "0.0;(0.0)"
Else
d.NumberFormat = "#,##0;(#,##0)"
End If
Next d
Application.ScreenUpdating = True
ActiveWorkbook.Save
End Sub
I just cannot figure out a good way to integrate the user form into the existing code. I guess I need to get the output of the user form in a form of variable and them to build an algorithm. But I do not know how to start.
Basically I need to achieve the following algorithm:
Fill User Form
If any of the options are not selected ask user to do it
Run Upload Data sub
Optimise
Open external Excel file
If Template 1 Selected Then
Import Accounts and Types sheets
Else
Import Accounts sheet
End If
Save file under a different name
Unhide hiden templates
If Template 1 Then
If datatype Private Then
Unhide FS_1, CF_1, tables, calcs, tables_for_output, Tier 1, Tier 2
Rename FS_1 and CF_1 to FS and CF
Else
Unhide FS_1, CF_1, tables
Rename FS_1 and CF_1 to FS and CF
Else
If datatype Private Then
Unhide FS_2, CF_2, tables, calcs, tables_for_output, Tier 1, Tier 2
Rename FS_2 and CF_2 to FS and CF
Else
Unhide FS_2, CF_2
Rename FS_2 and CF_2 to FS and CF
End If
End If
Activite Templates
Activate FS
Activate CF
Activate tables
If datatype Private
Activate calcs
Acivate tables_for_output
Activate Tier 1
Activate Tier 2
Otimisation ends
Tidying up
Hide unneeded sheets
If datatype Private Then
If Tier 1 Then
Hide Model, cacls, Tier 2
Else
Hide Model, calcs, Tier 1
Else
Hide Model
End If
If datatype Private replace conditional formatting with normal
If Tier 1
In tables_for_otput, Tier 1
Else
in tables_for_output, Tier 2
End If
Additional Formattng
If datatype Public
Format FS, CF, tables
Else
Format FS, CF, table, tables for output
End If
Workbook Save
Sub End
I've worked on it last weekend but got interrupted rather early on. Apologies for the delay.
The ByVal wasn't really needed here, I may have worded myself incorrectly. Here's the documentation in case you'd like to read up on it: Byval & ByRef
As for the code, I tried to get it done the way you mentioned but wipe_out was not included in your Sub? So couldn't implement it either.
Hope the code works and was the way you specified:
Option Explicit
Sub UploadData()
Dim FileOpenDial As Variant
Dim FileSaveAs As Variant
Dim wb As Workbook, activeWB As Workbook
Dim bFileSaveAs As Boolean
Dim finstart As Range, endcell As Range, startcell As Range
Dim yearsno As Range, cfyearsno As Range
Dim numrows As Long, numrowscf As Long, numrowsadj As Long 'I prefer to not have number rows in Integer due to limitations of size
Dim c As Range, d As Range, r As Range, decimaltab As Range
Dim MySheets As String, tier As String
Dim templ As Integer, dType As Integer, wipe As Integer
'Checking user form
If radiotempl1.Value Then templ = 1
ElseIf radiotempl2.Value Then templ = 2
Else
MsgBox "Please select a template"
End If
If dataType.Value = "Public" Then
dType = 1
ElseIf dataType.Value = "Private" Then
dType = 2
Else
MsgBox "Please select a data type"
End If
If wipe_format.Value Then wipe = 1
If radiotier1.Value Then tier = "Tier_1"
If radiotier2.Value Then tier = "Tier_2"
Else
If dType = 2 Then
MsgBox "Please select a tier"
Exit Sub
End If
End If
If templ + dType < 2 Then Exit Sub
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
ActiveSheet.DisplayPageBreaks = False
Application.DisplayAlerts = False
Set activeWB = Application.ActiveWorkbook
FileOpenDial = Application.GetOpenFilename(FileFilter:="Excel Files (*.XML), *.XML", Title:="Select File To Be Opened")
If FileOpenDial = False Then Exit Sub
Set wb = Workbooks.Open(FileOpenDial)
'you mentioned "copies one or two worksheets into the model (depending on the template) but I'm not sure which way you wanted this
Sheets(Array("Accounts", "Types")).Copy Before:=activeWB.Sheets(1) 'avoid select as much as possible
wb.Close savechanges:=False 'or True
'Save a file
FileSaveAs = Application.GetSaveAsFilename(FileFilter:="Exel Files (*.xlsx), *.xlsx", Title:="Select Name To Save The File")
If FileSaveAs <> False Then
ActiveWorkbook.SaveAs Filename:=FileSaveAs, _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End If
copySheet "FS", templ 'this is to copy the right sheet and delete the FS if it alreasdy existed from a previous time you ran the code
copySheet "CF", templ
Set yearsno = ThisWorkbook.Sheets("Accounts").Range("F2:Z2")
With Sheets("FS")
'Remove apostrophe from the formulas
For Each c In .Range("D1:D250").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
numrows = Application.WorksheetFunction.CountA(yearsno)
If 5 - numrows >= 0 Then
numrowsadj = 0
Else: numrowsadj = 5 - numrows
End If
Set startcell = .Range("D1")
Set endcell = Cells(Range("D" & Rows.Count).End(xlUp).Row, 3 + numrows + numrowsadj)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
Set cfyearsno = .Range("C1:XFD1")
numrowscf = Application.WorksheetFunction.CountA(cfyearsno)
End With
With Sheets("CF")
'Remove apostrophe from the formulas
For Each c In Range("F1:F160").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
Set startcell = .Range("F1")
If numrowscf = 3 Then
Set endcell = Range("F" & Rows.Count).End(xlUp).Offset(, 1)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
ElseIf numrowscf > 3 Then
Set endcell = Range("F" & Rows.Count).End(xlUp).Offset(, 2)
Set finstart = .Range(startcell.Address & ":" & endcell.Address)
finstart.FillRight
Else
End If
End With
With Sheets("tables")
For Each c In .Range("C1:G88").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
End With
With Sheets("Calcs")
For Each c In Range("B1:H22").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
End With
With Sheets("tables_for_output")
For Each c In Range("B2:O43").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
End With
'no need to hide sheets if you keep them hidden :)
Calculate
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
With Sheets("tables_for_output")
For Each r In Range("F4:O4")
r.Interior.Color = r.DisplayFormat.Interior.Color
Next r
Range("F4:O4").FormatConditions.Delete
End With
If dType = 2 Then
With Sheets(tier) 'same here as last time with tier
For Each c In .Range("D6:I15").SpecialCells(xlCellTypeConstants)
c.Formula = Replace(c.Formula, "'", "")
Next c
For Each r In Range("F6:H15")
r.Interior.Color = r.DisplayFormat.Interior.Color
Next r
Range("F6:H15").FormatConditions.Delete
.Visible = True
End With
End With
'Formatting
'Columns Width
ThisWorkbook.Sheets("FS").Cells.SpecialCells(xlCellTypeVisible).EntireColumn.AutoFit
ThisWorkbook.Sheets("CF").Cells.SpecialCells(xlCellTypeVisible).EntireColumn.AutoFit
'Decimal Formatting
'tables
With Sheets("tables")
Set decimaltab = Union(.Range("C2:E16"), .Range("C25:E49"), .Range("C62:E69"), .Range("C71:E75"), .Range("C77:E83"))
For Each d In decimaltab.SpecialCells(xlCellTypeFormulas, xlNumbers)
If Abs(d.Value) < 20 And Round(d.Value, 0) <> 0 Then
d.NumberFormat = "0.0;(0.0)"
Else
d.NumberFormat = "#,##0;(#,##0)"
End If
Next d
'tables_for_output
With Sheets("tables_for_output")
Set decimaltab = Union(.Range("B2:B3"), .Range("B11:D15"), .Range("B17:D18"), .Range("B20:D23"), .Range("B33:D34"), .Range("B37:D39"), .Range("B43:D43"))
For Each d In decimaltab.SpecialCells(xlCellTypeFormulas, xlNumbers)
If Abs(d.Value) < 101 And Round(d.Value, 0) <> 0 Then
d.NumberFormat = "0.0;(0.0)"
Else
d.NumberFormat = "#,##0;(#,##0)"
End If
Next d
.Activate
'You will have to decide which sheet you actually want to be presented first but I got rid of the copious use of .Select
'For now it's this one
End With
Application.ScreenUpdating = True
ActiveWorkbook.Save
End Sub
Sub copySheet(shtName As String, templNo As Integer)
If WorksheetExists(shtName) Then ActiveWorkbook.Sheets(shtName).Delete
shtName = shtName & "_" & templNo
Sheets(shtName).Copy After:=Worksheets(Worksheets.Count)
With ActiveSheet
.Name = Left(shtName, 2)
.Visible = True
End With
End Sub
Function WorksheetExists(shtName As String, Optional wb As Workbook) As Boolean
Dim sht As Worksheet
If wb Is Nothing Then Set wb = ActiveWorkbook
On Error Resume Next
Set sht = wb.Sheets(shtName)
On Error GoTo 0
WorksheetExists = Not sht Is Nothing
End Function
If you have any more questions, feel free to ask

Using check boxes to filter list box of worksheets

I have a workbook with multiple worksheets. I create a list box on a user form with these worksheets in alphabetical order, click on the line and hit print.
I would like to check a box and hit search and have only the filtered worksheets appear.
User Form
Worksheet tabs
Dim i As Long
Private Sub CommandButton1_Click()
ListBox1.Clear
SE = False
TE = False
SS = False
TS = False
AK = False
EK = False
End Sub
Private Sub FilterButton1_Click()
If SE = True Then
For i = 1 To ActiveWorkbook.Sheets.Count
ListBox1.AddItem ActiveWorkbook.Sheets(i).Name
Next i
End If
If TE = True Then
For i = 1 To ActiveWorkbook.Sheets.Count
ListBox1.AddItem ActiveWorkbook.Sheets(i).Name = "*TE*"
Next i
End If
If SS = True Then
For i = 1 To ActiveWorkbook.Sheets.Count
ListBox1.AddItem ActiveWorkbook.Sheets(i).Name = "*SS*"
Next i
End If
If TS = True Then
For i = 1 To ActiveWorkbook.Sheets.Count
ListBox1.AddItem ActiveWorkbook.Sheets(i).Name = "*TS*"
Next i
End If
If AK = True Then
For i = 1 To ActiveWorkbook.Sheets.Count
ListBox1.AddItem ActiveWorkbook.Sheets(i).Name = "*AK*"
Next i
End If
If EK = True Then
For i = 1 To ActiveWorkbook.Sheets.Count
ListBox1.AddItem ActiveWorkbook.Sheets(i).Name = "*EK*"
Next i
End If
End Sub
Your initial form load calls LoadSheetList with no argument, so all sheets will be loaded.
Your "Filter" button calls LoadSheetList True which will only add sheets based on the checkbox statuses.
Sub LoadSheetList(Optional filtered As Boolean = False)
Dim ws As Worksheet, nm
ListBox1.Clear 'first remove all items
'loop all sheets
For Each ws In ActiveWorkbook.Worksheets
nm = ws.Name
If Not filtered Or (filtered And SheetOK(nm)) Then
ListBox1.AddItem nm 'add if included or not filtering
End If
Next ws
End Sub
'review checkbox status to see is a sheet with the provided name should be added
'EDIT: updated to "and" checkboxes, not "or"
Function SheetOK(sheetName) As Boolean
Dim cb, rv as Boolean
rv = False 'default result
For Each cb In Array(SE, TE, SS, TS, AK, EK)
If cb.Value = True then
if not sheetName Like "* " & cb.Name & "*" then
rv = False
Exit For
Else
rv = True
End If
End If
SheetOK = rv
Next cb
End Function

Use VBA code for enabling checkboxes on multiple rows

enter image description hereI have a spreadsheet that has 3 checkbox options for each row, I have created a VBA to disable the other 2 checkboxes once a checkbox is created (so that only 1 checkbox can be checked), however my solution only works for one row and I need some help in rewriting this so that it will apply to all rows please. (I'm new to VBA).
The code I have used is this:
Private Sub CheckBox1_Click()
If CheckBox1.Value = True Then
CheckBox2.Value = False
CheckBox2.Enabled = False
CheckBox3.Value = False
CheckBox3.Enabled = False
Else
CheckBox2.Value = False
CheckBox2.Enabled = True
CheckBox3.Value = False
CheckBox3.Enabled = True
End If
End Sub
Private Sub CheckBox2_Click()
If CheckBox2.Value = True Then
CheckBox1.Value = False
CheckBox1.Enabled = False
CheckBox3.Value = False
CheckBox3.Enabled = False
Else
CheckBox1.Value = False
CheckBox1.Enabled = True
CheckBox3.Value = False
CheckBox3.Enabled = True
End If
End Sub
Private Sub CheckBox3_Click()
If CheckBox3.Value = True Then
CheckBox1.Value = False
CheckBox1.Enabled = False
CheckBox2.Value = False
CheckBox2.Enabled = False
Else
CheckBox1.Value = False
CheckBox1.Enabled = True
CheckBox2.Value = False
CheckBox2.Enabled = True
End If
End Sub
You should probably just use Radios it would be a lot simpler.
If you are intent on doing this you will need to delete all your boxes and then put this code in. It will create and name your boxes and assign them code on click.
Alright, This needs to go in your Sheet module:
Sub Worksheet_Activate()
'Change Module2 to whatever the module name you are using is.
Module2.ActivateCheckBoxes ActiveSheet
End Sub
This next stuff will go into the module you're referencing from the Worksheet Module.
Sub ActivateCheckBoxes(sht As Worksheet)
If sht.CheckBoxes.Count = 0 Then
CreateCheckBoxes sht
End If
Dim cb As CheckBox
For Each cb In sht.CheckBoxes
'You may be able to pass sht as an object, It was giving me grief though
cb.OnAction = "'Module2.CheckBoxClick """ & cb.name & """, """ & sht.name & """'"
Next cb
End Sub
Sub CreateCheckBoxes(sht As Worksheet)
Dim cell As Range
Dim chkbox As CheckBox
With sht
Dim i As Long
Dim prevrow As Long
prevrow = 0
For Each cell In .Range("B2:D5") 'Change this to whatever range you want.
If prevrow < cell.row Then
prevrow = cell.row
i = 0
End If
Set chkbox = .CheckBoxes.Add(cell.Left, cell.Top, 30, 6)
With chkbox
.name = "CheckBox" & i & "_" & cell.row
.Caption = ""
End With
i = i + 1
Next cell
End With
End Sub
Sub CheckBoxClick(chkname As String, sht As String)
Dim cb As CheckBox
With Worksheets(sht)
For Each cb In .CheckBoxes
If Split(cb.name, "_")(1) Like Split(chkname, "_")(1) And Not cb.name Like chkname Then
cb.Value = -4146
End If
Next cb
End With
End Sub
You do not say anything about your sheet check boxes type... Please, test the next solution. It will be able to deal with both sheet check boxes type:
Copy this two Subs in a standard module:
Public Sub CheckUnCheckRow(Optional strName As String)
Dim sh As Worksheet, s As CheckBox, chK As OLEObject ' MSForms.CheckBox
Set sh = ActiveSheet
If strName <> "" Then
Set chK = sh.OLEObjects(strName) '.OLEFormat.Object
solveCheckRow chK.Object.Value, sh, Nothing, chK
Else
Set s = sh.CheckBoxes(Application.Caller)
solveCheckRow s.Value, sh, s
End If
End Sub
Sub solveCheckRow(boolVal As Long, sh As Worksheet, chF As CheckBox, Optional chK As OLEObject)
Dim s As CheckBox, oObj As OLEObject, iCount As Long
If Not chF Is Nothing Then
For Each s In sh.CheckBoxes
If chF.TopLeftCell.Address <> s.TopLeftCell.Address Then
If s.TopLeftCell.Row = chF.TopLeftCell.Row Then
s.Value = IIf(boolVal = -4146, 1, -4146): iCount = iCount + 1
If iCount = 2 Then Exit Sub
End If
End If
Next
ElseIf Not chK Is Nothing Then
For Each oObj In sh.OLEObjects
If oObj.TopLeftCell.Address <> chK.TopLeftCell.Address Then
If oObj.TopLeftCell.Row = chK.TopLeftCell.Row Then
boolStopEvents = True
oObj.Object.Value = IIf(boolVal = 0, True, False): iCount = iCount + 1
boolStopEvents = False
If iCount = 2 Then Exit Sub
End If
End If
Next
End If
End Sub
For case of Form check boxes type:
a). Manually assign the first sub to all your Form Type check boxes (right click - Assign Macro, choose CheckUnCheckRow and press OK).
b). Automatically assign the macro:
Dim sh As Worksheet, s As CheckBox
Set sh = ActiveSheet ' use here your sheet keeping the check boxes
For Each s In sh.CheckBoxes
s.OnAction = "'" & ThisWorkbook.Name & "'!CheckUnCheckRow"
Next
End Sub
If your check boxes have already assigned a macro, adapt CheckUnCheckRow, in Form check boxes section, to also call that macro...
For case of ActiveX check boxes:
a). Create a Public variable on top of a standard module (in the declarations area):
Public boolStopEvents
b). Manually adapt all your ActiveX check boxes Click or Change event, like in the next example:
Private Sub CheckBox1_Click()
If Not boolStopEvents Then CheckUnCheckRow "CheckBox1"
End Sub
Private Sub CheckBox2_Click()
If Not boolStopEvents Then CheckUnCheckRow "CheckBox2"
End Sub
Private Sub CheckBox3_Click()
If Not boolStopEvents Then CheckUnCheckRow "CheckBox3"
End Sub
and so on...
c). Or do all that with a click, using the next piece of code:
Sub createEventsAllActiveXCB()
Dim sh As Worksheet, oObj As OLEObject, strCode As String, ButName As String
Set sh = ActiveSheet 'use here your sheet keeping ActveX check boxes
For Each oObj In sh.OLEObjects
If TypeName(oObj.Object) = "CheckBox" Then
ButName = oObj.Name
strCode = "Private Sub " & ButName & "_Click()" & vbCrLf & _
" If Not boolStopEvents Then CheckUnCheckRow """ & ButName & """" & vbCrLf & _
"End Sub"
addClickEventsActiveXChkB sh, strCode
End If
Next
End Sub
Anyhow, the code cam be simplified in order to deal with only a type of such check boxes. If you intend to use it and looks too bushy, I can adapt it only for the type you like. Like it is, the code deals with both check box types, if both exist on the sheet...
Save the workbook and start playing with the check boxes. But, when you talk about check boxes on a row, all tree of them must have the same TopLeftCell.Row...

Select a list of items in a slicer

I am trying to help a bookstore with its Xmas sales! I use a PivotTable connected to an OLAP Cube, with a lot of product references, with valuable information as sales of last week, inventory level etc.
I want to display only the data (sales and inventory levels) for the books on a current commercial actions (about 400 books) to check if inventory level is enough.
I have a slicer with ISBN numbers, with more than a million captions, and I want to manipulate that slice with VBA to display only the books I want.
List of the ISBN that I want to be displayed are in sheet "Catalogue EOY", column 3. I try to build an array with the right slicer names, to be used with the VisibleSlicerItemsList statement, but I get a message "Object required" on that line (last line). In my example, I have limited the list of books to the first 50 items.
Any idea how I can solve this?
Sub ShowProductList()
Dim ProductList(0 To 50) As Variant
Dim i
Dim Sc As SlicerCache
Dim sL As SlicerCacheLevel
Set Sc = ActiveWorkbook.SlicerCaches("Slicer_ISBN")
Set sL = Sc.SlicerCacheLevels(1)
For i = 2 To 52
ProductList(i - 2) = Chr(34) & "[DIM Artikel].[ISBN].&[" & _
Worksheets("Catalogue EOY").Cells(i, 3).Value & "]" & Chr(34)
Next i
sL.VisibleSlicerItemsList = ProductList
End Sub
Sub f()
Dim piv As PivotItem, pivf As PivotField, pivt As PivotTable, ProductList() As Variant, filterrng As Range, rng As Range
'the range where your background data is
Set filterrng = Worksheets("filter_criteria").Range("C2:C52") 'the range where your product list is
ReDim ProductList(filterrng.Cells.Count - 1)
For Each rng In filterrng
ProductList(i) = rng.Value2
i = i + 1
Next rng
Set pivt = Sheets("piv").PivotTables("PivotTable1") 'your pivottable, define it properly
Set pivf = pivt.PivotFields("ISBN") 'the pivot field
On Error Resume Next
For Each pvi In pivf.PivotItems
pvi.Visible = False
pvi.Visible = Application.Match(pvi.Name, ProductList, False) > -1 'if it's in the range, then make it visible, otherwise hide it
Next pvi
End Sub
Not the answer you want but the one you need.
You need to loop through each SlicerItem and test it against your list to choose to select it or not, here is how :
Sub ShowProductList()
With Application
.EnableEvents = False 'stop executing this code until we are done
.DisplayAlerts = False
.ScreenUpdating = False
'.Calculation = xlCalculationManual
End With
Dim ProductList(0 To 50) As Variant
Dim i As Long
Dim Sc As SlicerCache
Dim sI As SlicerItem
Dim sL As SlicerCacheLevel
Dim inLisT As Boolean
Set Sc = ActiveWorkbook.SlicerCaches("Slicer_ISBN")
Set sL = Sc.SlicerCacheLevels(1)
For i = 2 To 52
ProductList(i - 2) = Chr(34) & "[DIM Artikel].[ISBN].&[" & _
Worksheets("Catalogue EOY").Cells(i, 3).Value & "]" & Chr(34)
Next i
Sc.ClearManualFilter
For Each sI In Sc.SlicerItems
inLisT = False
For i = LBound(ProductList) To UBound(ProductList)
If sI.Name <> ProductList(i) Then
Else
inLisT = False
Exit For
End If
Next i
If inLisT Then
sI.Selected = True
Else
sI.Selected = False
End If
Next sI
With Application
.EnableEvents = True 'stop executing this code until we are done
.DisplayAlerts = True
.ScreenUpdating = True
'.Calculation = xlCalculationAutomatic
End With
End Sub

Resources