• No results found

The above ex ample works very well when you don’t need to keep track of which answer was cho sen. But what about the ex ample from Chapter 7 in “How Did You Do: Re porting Re sults to the Teacher”? In that ex ample, each an swer needs to be stored. Short-answer questions don’t have much of an issue because you already have to use VBA to check the an swer, so you can eas ily stick the an swer in a variable at that time. But multiple-choice ques tions are more of a prob lem. In the ex ample in Chapter 7, we had a different pro cedure for each but ton. This is easy to un derstand, but the amount of code can be over whelming if you have a lot of questions.

Fortunately, there is a VBA trick that can save us. Try as signing the follow- ing pro cedure to a but ton. In fact, create a slide with several but tons, add dif fer- ent text to each but ton, and attach this procedure to each button:

Sub WhichButton(answerButton As Shape) Dim theAnswer As String

theAnswer = answerButton.TextFrame.TextRange.Text MsgBox ("You chose " & theAnswer)

End Sub

This uses a spe cial trick with pa rameters (see “Pa rameters”) . When a button is pressed, it can pass the button it self as a pa rameter to the procedure that called it. Normally, we use VBA to pass parameters (by putt ing them in pa rentheses when we call a procedure), but in this case, click ing the button passes the pa rameter. We just have to set up our pro cedure to store the pa rameter. In this ex ample, we used the variableanswerButton. Once we have a pointer to the but ton it self (i.e., answerButton), we can get the text that is in the but ton with

answerButton.TextFrame.TextRange.Text. If you have put the an swer in the text of the but ton, you can use that to get the answer that was chosen. 138 More Tricks for Your Scripting Bag

Now we can store the answers for a printable slide with out add ing any extra code for each multiple-choice ques tion and without add ing very much ex tra code for each short-answer question. Our code for the simple three-question ex - ample is a bit longer, but as you add more ques tions, the overall code will be much shorter. In fact, just like the pre vious ex ample, if you only use mul tiple- choice questions, you do not have to change the code at all when you add questions.

The new code fol lows. The GetStarted, YourName,DoingWell, and

DoingPoorly procedures are the same ones we have used many times before. We can also use the new RightAnswer and WrongAnswer pro cedures from the previous ex ample. However, these pro cedures will not be tied di rectly to but - tons. Instead, for mul tiple-choice ques tions we will add two new pro cedures,

RightAnswerButton and WrongAnswerButton, that will be tied to the but - tons with right and wrong an swers. Here are the new pro cedures, to gether with the Dim state ments and a slightly mod ified Ini tial ize pro ce dure. Use

GetStarted, YourName, DoingWell, and DoingPoorly pro ce dures from any earlier example, and use RightAnswer and WrongAnswer pro ce dures from the previous ex ample (see page 136), along with the following:

Dim numCorrect As In teger Dim numIncorrect As In teger Dim userName As String Dim qAnswered() As Boolean

Dim an swer() As String 'Ar ray to store an swers Dim numQuestions As Long

Dim printableSlideNum As Long Sub Ini tial ize()

Dim i As Long numCorrect = 0 numIncorrect = 0 printableSlideNum = ActivePresentation.Slides.Count + 1 numQuestions = ActivePresentation.Slides.Count - 2 ReDim qAnswered(numQuestions) ReDim an swer(numQuestions) For i = 1 To numQuestions qAnswered(i) = False Next i End Sub

Sub RightAnswerButton(answerButton As Shape) Dim thisQuestionNum As Long

thisQuestionNum = _

ActivePresentation.SlideShowWindow.View.Slide.SlideIndex - 1 an swer(thisQuestionNum) = answerButton.TextFrame.TextRange.Text RightAnswer

End Sub

Sub WrongAnswerButton(answerButton As Shape) Dim thisQuestionNum As Long

thisQuestionNum = _

ActivePresentation.SlideShowWindow.View.Slide.SlideIndex - 1 an swer(thisQuestionNum) = answerButton.TextFrame.TextRange.Text WrongAnswer

End Sub

You have al ready seen (in theRightAnswer and WrongAnswerpro ce dures)

thisQuestionNum used to store the number of the current question. The only new code is the Dim state ment to de clare an swer as an ar ray and the

answerButton.TextFrame.TextRange.Text to get the text from the but - ton that was pressed (as described above). In ad dition, we have done a bit of re - structuring. In the orig inal example in Chapter 7, each but ton had its own procedure, and that procedure took care of storing the answer, keeping track of which ques tion was an swered, and keep ing score. We have di vided up that work. Now theRightAnswerButton and WrongAnswerButtonpro ce dures take care of storing the answer, and theRightAnswer and WrongAnswer pro - cedures take care of keeping track of which question was answered and keeping score.

This division of labor will be important when we add a short-answer ques- tion. For short-answer questions, we are go ing to need a Ques tionpro ce dure for each question. That pro cedure will ask the ques tion, judge the answer, and store the answer. When it fig ures out if the an swer was right or wrong, it will call theRightAnswer or WrongAnswer pro cedure. So we need the fol low- ing pro ce dures:

• Each short-answer question needs its own Ques tion pro ce dure (Question1,Question2,Question3).

• All the multiple-choice ques tions need one RightAnswerButton

and one WrongAnswerButton pro cedure, which will be tied to ev - ery but ton with a right and wrong an swer, respectively.

• All the questions need one RightAnswer and WrongAnswer

procedure, which is called from RightAnswerButton,

WrongAnswerButton, and each Ques tionpro ce dure.

Next, our Ques tion pro cedures need a slight mod ification so they can store the answer in the an swer ar ray. Here is an example procedure for

Question3:

Sub Question3()

Dim theAnswer As String Dim thisQuestionNum As Long thisQuestionNum = _

ActivePresentation.SlideShowWindow.View.Slide.SlideIndex - 1

theAnswer = InputBox(Prompt:="What is the cap ital of Mary land?", _ Ti tle:="Question " & thisQuestionNum)

If qAnswered(thisQuestionNum) = False Then an swer(thisQuestionNum) = theAnswer End If

theAnswer = Trim(theAnswer) theAnswer = LCase(theAnswer) If theAnswer = "annapolis" Then RightAnswer

Else

WrongAnswer End If

End Sub

The changes to this pro cedure from the ex ample in Chapter 7 are simply to ac- count for the fact thatan swer is an ar ray now. Noth ing else has changed.

The final change to our code co mes in the PrintablePage pro ce dure. You could simply change this pro cedure to use the ar ray (usingan swer(1),

an swer(2),an swer(3), in stead of answer1,answer2,answer3), but this would require you to change the pro cedure every time you add a new ques tion. The pur pose of com plicating our code with arrays was to eliminate any un neces- sary chang ing of code. Our newPrintablePagepro ce dure fol lows:

Sub PrintablePage()

Dim printableSlide As Slide Dim homeButton As Shape Dim printButton As Shape Set printableSlide = _

ActivePresentation.Slides.Add(In dex:=printableSlideNum, _ Lay out:=ppLayoutText)

printableSlide.Shapes(1).TextFrame.TextRange.Text = _ "Re sults for " & userName

printableSlide.Shapes(2).TextFrame.TextRange.Text = _ "Your An swers" & Chr$(13)

For i = 1 To numQuestions

printableSlide.Shapes(2).TextFrame.TextRange.Text = _ printableSlide.Shapes(2).TextFrame.TextRange.Text & _ "Ques tion " & i & ": " & an swer(i) & Chr$(13)

Next i

printableSlide.Shapes(2).TextFrame.TextRange.Text = _ printableSlide.Shapes(2).TextFrame.TextRange.Text & _ "You got " & numCorrect & " out of " & _

numCorrect + numIncorrect & "." & Chr$(13) & _

"Press the Print Re sults but ton to print your an swers." printableSlide.Shapes(2).TextFrame.TextRange.Font.Size = 9 Set homeButton = _

ActivePresentation.Slides(printableSlideNum).Shapes _ .AddShape(msoShapeActionButtonCustom, 0, 0, 150, 50) homeButton.TextFrame.TextRange.Text = "Start Again"

homeButton.ActionSettings(ppMouseClick).Ac tion = ppActionRunMacro homeButton.ActionSettings(ppMouseClick).Run = "StartAgain" Set printButton = _

ActivePresentation.Slides(printableSlideNum).Shapes _ .AddShape(msoShapeActionButtonCustom, 200, 0, 150, 50) printButton.TextFrame.TextRange.Text = "Print Re sults"

printButton.ActionSettings(ppMouseClick).Ac tion = ppActionRunMacro

printButton.ActionSettings(ppMouseClick).Run = "PrintResults" ActivePresentation.SlideShowWindow.View.Next

ActivePresentation.Saved = True End Sub

Other than using the an swer ar ray, the main change to this pro cedure is that we must loop through all the an swers so we can display them. We can not put a line for each an swer, as we have done in the past, because we do not know how many questions we will have. In stead, we use aFor loop to cy cle through the an swers and add them to the slide:

For i = 1 To numQuestions

printableSlide.Shapes(2).TextFrame.TextRange.Text = _ printableSlide.Shapes(2).TextFrame.TextRange.Text & _ "Ques tion " & i & ": " & an swer(i) & Chr$(13)

Next i

In English, this code says: For each an swer in thean swer ar ray, take all the text we have already put in Shape2 of the slide (printableSlide. Shapes(2).TextFrame.TextRange.Text) and add (&) to that the question num ber ("Ques tion " & i) and the an swer with a new line (an swer(i) & Chr$(13)). Af ter the For loop, we also add to all of that the score and the in - structions for print ing the slide.

Finally, if you are us ing a version of PowerPoint that does not au tomati- cally change the size of the text to fit the text box, you will want to be sure to change the size of the text so you can fit more than three or four answers on the slide:

printableSlide.Shapes(2).TextFrame.TextRange.Font.Size = 9

Just change the 9 to a smaller number if you have more questions.

As a scripter, your burn ing question should be: How do I add ques tions to my presentation? If you have put all the above code in your presentation, you must do the following things to add questions:

1. For each multiple-choice ques tion, do not touch the VBA; just add the question slide and tie the but ton for the right answer to

RightAnswerButton and the but tons for wrong answers to

WrongAnswerButton.

2. For each short-answer question, add a slide with the ques tion and tie the question but ton to a new pro cedure that is exactly like

Question3, ex cept that it will have a dif ferent number for the name of the procedure (Question4,Question5, etc.) and it will change the text of the ques tion in theInputBox state ment and the cor rect an - swer(s) to check for in the If statement.

3. If you have a lot of questions, change the font size of the text box in thePrintablePage pro cedure to 9 or smaller.