Blending Code Explanation – Chapter 15 Event Code for InputsForm Userform_Initialize Sub We make sure all three check boxes are checked when the user sees the form. Private Sub Userform_Initialize() MonBox = True OctBox = True DemBox = True End Sub OKButton_Click Sub We set the public Boolean variables MonOpt, OctOpt, and DemOpt equal to the same values (True or False) as the corresponding check boxes, and then we unload the form. Note that since the default property of a check box is the Value property, a statement such as MonOpt = MonBox is equivalent to MonOpt = MonBox.Value, and this value is either True or False. Private Sub OKButton_Click() MonOpt = MonBox OctOpt = OctBox DemOpt = DemBox Unload Me End Sub CancelButton_Click Sub We unload the form and terminate the program. Private Sub CancelButton_Click() Unload Me End End Sub Event Code for MonForm Userform_Initialize Sub We populate the variables text boxes with the values from corresponding values (probably from a previous run) in the corresponding cells of the Model sheet. For example, the text in the CCost1 text box becomes the value in the first cell of the PurchCosts range. Private Sub Userform_Initialize() With Range("PurchCosts") CCost1 = .Cells(1) CCost2 = .Cells(2) CCost3 = .Cells(3) End With With Range("SellPrices") GPrice1 = .Cells(1) GPrice2 = .Cells(2) GPrice3 = .Cells(3) End With PCost = Range("ProdCost") End Sub OKButton_Click Sub The majority of this sub is a loop through all controls for error checking. Note that Me refers to the current user form. Therefore, Me.Controls refers to the collection of all controls on this form. Private Sub OKButton_Click() Dim ctl As Control For Each ctl In Me.Controls The function TypeName can be used to check what type of control any particular control is. If the control type is a text box, we check that it is not blank and that it contains a positive numeric value. If not, we exit the sub without unloading the form, so that the user has to try again. If TypeName(ctl) = "TextBox" Then If ctl.Value = "" Or Not IsNumeric(ctl) Or ctl.Value <= 0 Then MsgBox "Enter positive numeric values in all boxes.", vbInformation, "Invalid entry" ctl.SetFocus Exit Sub End If End If Next By this time, all inputs are valid, so we capture them in the PurchCosts, SellPrices, and ProdCost worksheet ranges, and we unload the form. ' Capture the user inputs in the various ranges in the (hidden) Model sheet. With Range("PurchCosts") .Cells(1) = Val(CCost1) .Cells(2) = Val(CCost2) .Cells(3) = Val(CCost3) End With With Range("SellPrices") .Cells(1) = Val(GPrice1) .Cells(2) = Val(GPrice2) .Cells(3) = Val(GPrice3) End With Range("ProdCost") = Val(PCost) Unload Me End Sub CancelButton_Click Sub We unload the form and terminate the program. Private Sub CancelButton_Click() Unload Me End End Sub Code in the Module Main Sub We first shows the InputsForm to see which groups of inputs the user wants to view/change. Then we show the corresponding forms to allow the user to view/change the inputs. Sub Main() InputsForm.Show If MonOpt Then MonForm.Show If OctOpt Then OctForm.Show If DemOpt Then DemForm.Show

We turn off screen updating (to prevent a lot of screen flickering) and then unhide and activate the Model sheet. Application.ScreenUpdating = False With Worksheets("Model") .Visible = True .Activate End With

Next, we run the Solver, using the Userfinish argument with value True to prevent the final Solver message from being displayed. We check whether the “result” of the SolverSolve function is 5, which indicates no feasible solutions. If there is no feasible solution, we display a message and return the user to the Explanation sheet by running the ViewExplanation sub. If SolverSolve(UserFinish:=True) = 5 Then MsgBox "There is no feasible solution to the problem with these " _ & "inputs. Try again with different inputs.", vbInformation, "Not feasible" Worksheets("Model").Visible = False ViewExplanation

There must be a feasible solution, so we hide the model sheet, unhide and activate the Report sheet, place the cursor in cell A1, and turn screen updating back on. Note that the Report sheet is already filled in (since it was set up at design time), so all we have to do is activate it. Else Worksheets("Model").Visible = False With Worksheets("Report") .Visible = True .Activate End With Range("A1").Select End If Application.ScreenUpdating = True End Sub RepositionButtons Sub This sub is run once only at design time to position the eight buttons on the Report sheet precisely—more precisely than you can do manually. Actually the first button is positioned and sized manually at design time. Then this sub positions the rest below it. We first capture the Top, Left, Height, and Width properties of the first button. Note that this button is referred to as .Shapes(1), which means the first Shape object in the Shapes collection. Sub RepositionButtons() Dim i As Integer, t, l, h, w With Worksheets("Report") With .Shapes(1) t = .Top l = .Left h = .Height w = .Width End With

Now we make sure each succeeding button is the same size as the top button and is positioned slightly (2 points, or 2/72 inch) below the previous button. That is, we use the same Left, Height, and Width properties for all buttons, but the Top property is incremented by h+2 For i = 2 To 8 With .Shapes(i) .Top = Worksheets("Report").Shapes(i - 1).Top + h + 2 .Left = l .Height = h .Width = w End With Next End With End Sub