4

I am trying to create a pop up question in powerpoint VBA, so far so good. But below code doesn’t seem to work. Idea is that you get a popup box with value to enter between 100 - 200 (inclusive). But must enter a value between or can accept failed as input. The inputbox cannot be cancelled or null/empty responses. The inner loop (loop 1) seems to work ok, but if I enter 150 it doesn't terminate the loop 2 instead keeps going unless type failed but it stops with any text rather than only "failed".

Sub OnSlideShowPageChange(ByVal SSW As SlideShowWindow)

    'Declare Variables
    Dim xType, xLimitHi, xLimitLo, xPrompt As String
    Dim InputvarTemp As String
    Dim msgResult As Integer

    xLimitHi = 200
    xLimitLo = 100
    xPrompt = "Enter Value between 100 and 200 (Inclusive)"
    Do 'loop 2 check within limit or failed
        msgResult = vbNo
        Do 'loop 1 check Empty / Null or Cancelled input
            InputvarTemp = InputBox(xPrompt, xPrompt)
            If StrPtr(InputvarTemp) = 0 Then ' Check if cancelled is pressed
                MsgBox "Invalid Input - Cannot be cancelled", 16, "Invalid Input."
            Else
                If Len(InputvarTemp) = 0 Then ' Check Null response
                    MsgBox "Invalid Input - Cannot be Empty / Null ", 16, "Invalid Input."
                Else
                    msgResult = MsgBox("You have Entered " & InputvarTemp, vbYesNo + vbDefaultButton2, "Check Value in between " & xLimitLo & " to " & xLimitHi & "(Inclusive)")
                    If CDec(InputvarTemp) < 100 Or CDec(InputvarTemp) > 200 Then ' Check within Limits
                        MsgBox "Invalid Input - Not Within Limit", 16, "Invalid Input."
                    End If
                End If
            End If
        Loop Until Len(InputvarTemp) > 0 And msgResult = vbYes And StrPtr(InputvarTemp) = 1 And IsNull(InputvarTemp) = False 'loop 1 check Empty / Null or Cancelled input
    Loop Until CDec(InputvarTemp) >= 100 And CDec(InputvarTemp) <= 200 Or InputvarTemp = "Failed" 'loop 2 check within limit

    Select Case InputvarTemp
        Case "Failed"
            MsgBox "Test Criteria Failed, Contact Production Engineer", 16, "Failed Test Criteria."
        Case Else
            MsgBox "Test Criteria Passed", 16, "Passed Test Criteria."
    End Select

End Sub

Can anyone point me to the problem? Many thanks in advance. This is a part of a bigger code project but this part is not working I have isolated this code in to a single file to run by itself to figure out the issue.

Mathieu Guindon
  • 69,817
  • 8
  • 107
  • 235
rellik
  • 304
  • 1
  • 4
  • 16
  • Blast from the past (an upvote brought me back here)! I rolled back the last revision (sorry for not noticing like, uh, *a wee bit* earlier), since it basically removed the question from the post; future viewers may be looking for a question with a specific problem similar to their own, to seek answers - and for that the site needs to retain its Q&A nature and not become some *discussion forum*. If you would like some constructive feedback on this code (or *anything that works as intended*, really), you can get exactly that and much more on SO's [codereview.se] sister site. Happy new year! – Mathieu Guindon Dec 31 '16 at 04:01

3 Answers3

10

To better understand what's going on, you need to write your code in such a way that it does as little as possible; right now you have a single procedure that does so many things it's hard to tell exactly what's going wrong and where.

Write a function to confirm user's valid numeric input:

Private Function ConfirmUserInput(ByVal input As Integer) As Boolean
    ConfirmUserInput = MsgBox("Confirm value: " & CStr(input) & "?", vbYesNo) = vbYes
End Function

Then write a function to deal with user's input:

Private Function IsValidUserInput(ByVal userInput As String,_
                                  ByVal lowerLimit As Double, _
                                  ByVal upperLimit As Double) _
As Boolean

    Dim result As Boolean
    Dim numericInput As Double

    If StrPtr(userInput) = 0 Then
        'msgbox / cannot cancel out

    ElseIf userInput = vbNullString Then
        'msgbox / invalid empty input

    ElseIf Not IsNumeric(userInput) Then
        'msgbox / must be a number

    Else
        numericInput = CDbl(userInput)
        If numericInput < lowerLimit Or numericInput > upperLimit Then
            'msgbox / must be within range

        Else
            result = ConfirmUserInput(numericInput)

        End If
    End If

    IsValidUserInput = result

End Function

This function can probably be written in a better way, but nonetheless it will return False if any of the validation rules fail, or if user doesn't confirm their valid input. Now you're equipped for looping, and since all the complex logic is extracted into its own function, the loop body gets pretty easy to follow:

Private Function GetTestCriteria(ByVal lowerLimit As Double, _
                                 ByVal upperLimit As Double) As Boolean

    Const failed As String = "Failed"

    Dim prompt As String
    prompt = "Enter Value between " & lowerLimit & _
             " and " & upperLimit & " (Inclusive)."

    Dim userInput As String
    Dim isValid As Boolean

    Do 

        userInput = InputBox(prompt, prompt)
        isValid = IsValidUserInput(userInput, lowerLimit, upperLimit) _
                  Or userInput = failed

    Loop Until IsValid

    GetTestCriteria = (userInput <> failed)

End Sub

The OnSlideShowPageChange procedure can now look like this:

Private Sub OnSlideShowPageChange(ByVal SSW As SlideShowWindow)

    If GetTestCriteria(100, 200) Then
        MsgBox "Test criteria passed."
    Else
        MsgBox "Test criteria failed, contact production engineer."
    End If

End Sub

I haven't tested any of this code, but I'm sure debugging these more specialized functions will be easier than debugging your monolithic chunk of code; by extracting these functions, you untangle the logic, and I bet the above does exactly what you're trying to do. Also note:

  • Dim xType, xLimitHi, xLimitLo, xPrompt As String declares xPrompt as a String, and everything else as a Variant. I don't think that's your intent here.
  • Select Case is best used with Enum values; use If-ElseIf constructs otherwise.

Slight modifications, per below comment:

how do i capture the user input to do something like write to a file

Now if you wanted to do something with the valid user inputs, say, write them to a file, you'd need GetTestCriteria to return the input - but that function is already returning a Boolean. One solution could be to use an "out" parameter:

Private Function GetTestCriteria(ByVal lowerLimit As Double, _
                                 ByVal upperLimit As Double, _
                                 ByRef outResult As Double) As Boolean

    Const failed As String = "Failed"

    Dim prompt As String
    prompt = "Enter Value between " & lowerLimit & _
             " and " & upperLimit & " (Inclusive)."

    Dim userInput As String
    Dim isValid As Boolean

    Do 

        userInput = InputBox(prompt, prompt)
        isValid = IsValidUserInput(userInput, lowerLimit, upperLimit, outResult) _
                  Or userInput = failed

    Loop Until IsValid

    GetTestCriteria = (userInput <> failed)

End Sub

Private Function IsValidUserInput(ByVal userInput As String,_
                                  ByVal lowerLimit As Double, _
                                  ByVal upperLimit As Double, _
                                  ByRef outResult As Double) _
As Boolean

    Dim result As Boolean
    Dim numericInput As Double

    If StrPtr(userInput) = 0 Then
        'msgbox / cannot cancel out

    ElseIf userInput = vbNullString Then
        'msgbox / invalid empty input

    ElseIf Not IsNumeric(userInput) Then
        'msgbox / must be a number

    Else
        numericInput = CDbl(userInput)
        If numericInput < lowerLimit Or numericInput > upperLimit Then
            'msgbox / must be within range

        Else
            result = ConfirmUserInput(numericInput)
            outResult = numericInput
        End If
    End If

    IsValidUserInput = result

End Function

And now you can call a method in OnSlideShowPageChange, to write the valid result to a file:

Private Sub OnSlideShowPageChange(ByVal SSW As SlideShowWindow)

    Dim result As Double

    If GetTestCriteria(100, 200, result) Then
        MsgBox "Test criteria passed."
        WriteResultToFile result
    Else
        MsgBox "Test criteria failed, contact production engineer."
    End If

End Sub

If you run into issues implementing this WriteResultToFile procedure, and existing Stack Overflow questions don't have an answer for you (slightly unlikely), feel free to ask another question!

Mathieu Guindon
  • 69,817
  • 8
  • 107
  • 235
  • Thanks @retailcoder for your valuable response, i will try a modified version of the code to fit my purpose. reason i use Cdec was i cant use integer type since they round up. and the input would need to be able to handle up 8 decimal points. maybe i will use the Limit parameters as double. – rellik Nov 06 '14 at 20:31
  • @rellik Ah, makes sense then. Wasn't clear from the original code though! But I'd use a `Double` (and `CDbl`) in that case ;) – Mathieu Guindon Nov 06 '14 at 20:33
  • how do i capture the user input to do something like write to a file my initial code i had Select Case InputvarTemp Case "Failed" MsgBox "Test Criteria Failed, Contact Production Engineer", 16, "Failed Test Criteria." Case Else MsgBox "Test Criteria Passed", 16, "Passed Test Criteria." End Select – rellik Nov 06 '14 at 21:08
  • That would be a totally different question; I'll edit this answer when I get a chance, but the idea is to make `GetTestCriteria` *return* the valid value, *and then* pass it to a method that writes it to a file. Perhaps just add a `ByRef outResult As Double` parameter to the function's signature... but I don't think it's wise to add more features to your original/broken code, without refactoring it first. – Mathieu Guindon Nov 06 '14 at 21:14
  • All done thank you been scratching me head for few hours yesterday – rellik Nov 06 '14 at 21:39
4

Retailcoder's answer as a general approach is top notch. I would like to draw attention specifically to the use of IsNumeric() which would solve most issues. Currently your code fails if any non-numeric string is entered.

Had a look at the code to try and see if I could at least answer what was happening to try and appease your curiosity. You mentioned that it looked like you couldn't leave your second loop. In practice I was unable to exit your first loop. I'm sure was due to the StrPtr(InputvarTemp) = 1. I didn't even know what that was until I looked it up. In short it is an undocumented feature that was used to check if Cancel was pushed / get the underlying memory address of variables (apparently).

Before the end of the first loop I put this in for debugging

MsgBox Len(InputvarTemp) & " " & msgResult & " " & StrPtr(InputvarTemp) & " " & IsNull(InputvarTemp)

When I type "150" in the InputBox the results of the message box are as follows. The third value represent the StrPtr(InputvarTemp)

3 6 246501864 FALSE

246501864 is greater than 1 which would cause the loop exit to fail. Again, retailcoder has an excellent answer and I will not reinvent his wheel.

Matt
  • 45,022
  • 8
  • 78
  • 119
0

with thanks to @retailcoder and @Matt below is the completed code for any to use, your help is truly appropriated

Capture user input to a file(s) from Powerpoint presentation, using a Config.ini to minimize everyday programming (or no programming code to a standard user)

> Code in Slide 1

    Option Explicit
    Option Compare Text
    Public WithEvents PPTEvent As Application
    Public TimeNow, ToDate As String
    Public WorkOrder, Serial, UserName As String
    Public ReportFile, TempReportFile, TimingFile As String
    Sub OnSlideShowPageChange(ByVal SSW As SlideShowWindow)

    'Declare Variables
    Dim ShellRun As Long
    Dim INIPath, StartTime, EndTime, TimeDifferance As String ' from Enviorment
    Dim PCPver, ModuleName, PCPFileName, Timed, ResultsFolder, TrainingFolder, TimeingFolder, TrainedFolder, xType, xPrompt, xvarUnit, y As String 'From INI file
    Dim xLimitHi, xLimitLo As Variant
    Dim result As Double
    Dim FailedResult As Double
    Dim PCPverInput, inputvar, InputvarDate, InputvarTrueFalse, InputvarGeneral, InputvarLimit, InputvarTemp As String 'From User
    Dim TrainingFile, SelfCheck, InvalidCharacter1, InvalidCharacter2 As String  'Variables for Filenames
    Dim msgResult, msgResultTemp As Integer
    Dim myVarPass As Boolean
    Dim KeyAscii As Integer 'Try and Hook Esc key
    Dim ppApp As Object
    Const fsoForAppend = 8
    'Declare and create a FileSystemObject.
    Dim fso, ResutlsFSO, TrainingFSO, TimeingFSO As Object 'Need Microsoft Script Runtime in references
    ' Declare a TextStream.
    Dim oFile, ResutlsStream, TrainingStream, TimeingStream As Object

    'Assign Variables
    INIPath = ActivePresentation.Path & "\" & "Config.ini"
    'ShellRun = Shell(ActivePresentation.Path & "\" & "Esc.exe")
    SelfCheck = ActivePresentation.Name
    ToDate = Format(Date, "dd-mmm-yyyy")
    TimeNow = Replace(Format(time, "hh:mm:ss"), ":", "-")
    StartTime = Format(time, "hh:mm:ss")
    'Retrive Folderpaths and create file names
    ModuleName = GetINIString("PCPInfo", "ModuleName", INIPath)
    Timed = GetINIString("Options", "Timed", INIPath)
    Set ResutlsFSO = CreateObject("Scripting.FileSystemObject")
    Set TrainingFSO = CreateObject("Scripting.FileSystemObject")
    Set TimeingFSO = CreateObject("Scripting.FileSystemObject")
    'Retrive PCP version from Ini file
    PCPver = GetINIString("PCPInfo", "PCPver", INIPath)
    PCPFileName = GetINIString("PCPInfo", "PCPFileName", INIPath)
    ResultsFolder = GetINIString("Folders", "ResultsFolder", INIPath)
    TrainingFolder = GetINIString("Folders", "TrainingFolder", INIPath)
    TimeingFolder = GetINIString("Folders", "TimeingFolder", INIPath)
    TrainedFolder = GetINIString("Folders", "TrainedFolder", INIPath)
        Do
            If (SelfCheck <> PCPFileName) Then
                MsgBox "Invalid Config.ini File. Replace with Correct INI file to continue. ", 16, "Invalid Config.ini File."
            End If
        Loop Until (SelfCheck = PCPFileName)
    'Collect PCP version, User Name, Work Order, Serial Number
    If (SSW.View.CurrentShowPosition = 1) Then
        'Retrive PCP Version from BOM - User Input
        Do
            Do
                PCPverInput = InputBox("Enter PCP Number including Version", "Enter PCP Number including Version")
                If (Len(PCPverInput) < 4) Then
                    MsgBox "Invalid Input - PCP version cannot be Empty / Null / cancelled", vbOKOnly, "Invalid Input"
                End If
            Loop Until (Len(PCPverInput) > 4)
            'Check PCPversion against BOM
            If (PCPver <> PCPverInput) Then
                'Display Warning Messages
                MsgBox "Incorrect PCP version. Contact Team Leader / Product Engineer. Cannot Continue the programm", 16, "Incorrect PCP version."
            End If
        Loop Until (PCPver = PCPverInput)
       'Retrive UserName - User Input
        Do
            msgResult = 7
            Do
                UserName = InputBox("Enter / Scan Operator Name", "Enter / Scan Operator Name")
                msgResult = MsgBox("You have Enterd Operator Name " & UserName, vbYesNo + vbDefaultButton2, "Operator Name")
                If (Len(UserName) < 4) Then
                    MsgBox "Invalid Input - User / Operator Name cannot be Empty / Null / cancelled", 16, "Invalid Input"
                End If
            Loop Until (Len(UserName) > 4) And (msgResult = vbYes)
        Loop Until (Len(UserName) > 4)
        'Retrive Work Order
        Do
            msgResult = 7
            Do
                WorkOrder = InputBox("Enter / Scan Work Order", "Enter / Scan Work Order")
                msgResult = MsgBox("You have Enterd Work Order " & WorkOrder, vbYesNo + vbDefaultButton2, "Work Order")
                If (Len(WorkOrder) < 4) Then
                    MsgBox "Invalid Input - Work Order cannot be Empty / Null / cancelled. Minimum 5 Numbers", 16, "Invalid Input"
                End If
            Loop Until (Len(WorkOrder) > 4) And (msgResult = vbYes)
        Loop Until (Len(WorkOrder) > 4)
        'Retrive Serial Number
        Do
            msgResult = 7
            Do
                Serial = InputBox("Enter / Scan Serial Number", "Enter / Scan Serial Number")
                msgResult = MsgBox("You have Enterd Serial Number " & Serial, vbYesNo + vbDefaultButton2, "Serial Number")
                If (Len(Serial) < 1) Then
                    MsgBox "Invalid Input - Serial Number cannot be Empty / Null / cancelled. Use -NOSERIAL- if Not Applicable", 16, "Invalid Input"
                End If
            Loop Until (Len(Serial) > 1) And (msgResult = vbYes)
        Loop Until (Len(Serial) > 1)

        If (Len(Dir(ResultsFolder, vbDirectory)) = 0) Then
        MkDir ResultsFolder
        End If

        If (Len(Dir(ResultsFolder & "\" & WorkOrder, vbDirectory)) = 0) Then
        MkDir ResultsFolder & "\" & WorkOrder
        End If

        If (Len(Dir(ResultsFolder & "\" & WorkOrder & "\" & Serial, vbDirectory)) = 0) Then
        MkDir ResultsFolder & "\" & WorkOrder & "\" & Serial
        End If

        ReportFile = ResultsFolder & "\" & WorkOrder & "\" & Serial & "\" & PCPver & "_" & ToDate & "_" & TimeNow & ".txt"
        Set ResutlsStream = ResutlsFSO.CreateTextFile(ReportFile, True)
        ResutlsStream.WriteLine PCPver & " " & ModuleName & " Build / Test Checklist"
        ResutlsStream.WriteLine "===================================================================================================="
        ResutlsStream.WriteLine ""
        ResutlsStream.WriteLine "Work Order                             :" & WorkOrder
        ResutlsStream.WriteLine "Serial Number (if Applicable)          :" & Serial
        ResutlsStream.WriteLine "Test / Assembly Operator (Full Name)   :" & UserName
        ResutlsStream.WriteLine "Date (dd-mmm-yyyy)                     :" & ToDate
        ResutlsStream.WriteLine ""
        ResutlsStream.Close

        If (Len(Dir(TrainingFolder, vbDirectory)) = 0) Then
        MkDir TrainingFolder
        End If

        If (Len(Dir(TrainingFolder & "\" & UserName, vbDirectory)) = 0) Then
        MkDir TrainingFolder & "\" & UserName
        End If

        TrainingFile = TrainingFolder & "\" & UserName & "\" & PCPver & ".csv"
        If (Len(Dir(TrainingFile)) = 0) Then
            Set TrainingStream = TrainingFSO.CreateTextFile(TrainingFile, True)
            TrainingStream.WriteLine UserName & "'s " & ModuleName & " " & PCPver & " Training File"
            TrainingStream.WriteLine "===================================================================================================="
            TrainingStream.WriteLine "Operator" & Chr(44) & "PCP Version" & Chr(44) & "W/O" & Chr(44) & "Serial" & Chr(44) & "Date" & Chr(44) & "Time"
            TrainingStream.WriteLine "===================================================================================================="
        Else
            Set TrainingStream = TrainingFSO.OpenTextFile(TrainingFile, 8)
        End If
        TrainingStream.WriteLine UserName & Chr(44) & PCPver & Chr(44) & WorkOrder & Chr(44) & Serial & Chr(44) & ToDate & Chr(44) & Format(time, "HH:MM:SS AM/PM")
        TempReportFile = ReportFile
    End If
    'Detect Slide Number and Retrive Relevant Question from INI File
    y = SSW.View.CurrentShowPosition
    If (Len(y) > 0) Then
        xType = GetINIString(SSW.View.CurrentShowPosition, "PromptType", INIPath)
        If (Len(xType) > 0) Then
            Set ResutlsStream = ResutlsFSO.OpenTextFile(TempReportFile, 8)
            Select Case xType
                Case "Message"
                    xPrompt = GetINIString(SSW.View.CurrentShowPosition, "Prompt", INIPath)
                    MsgBox xPrompt, vbYes, xPrompt
                Case "Date"
                    xPrompt = GetINIString(SSW.View.CurrentShowPosition, "Prompt", INIPath)
                    Do
                        msgResult = 7
                        Do
                            inputvar = InputBox(xPrompt, "Enter Date")
                            InputvarDate = inputvar
                            msgResult = MsgBox("You have Enterd " & Format(inputvar, "dd-Mmm-yyyy") & " to " & xPrompt, vbYesNo + vbDefaultButton2, "Check Date Input")
                            If (StrPtr(inputvar) = 0) Or (Len(inputvar) < 6) Then
                                MsgBox "Invalid Date Input - Cannot be Empty / Null / cancelled. Enter a Valid date, in dd-Mmm-yyyy format", 16, "Invalid Input."
                            End If
                            inputvar = Format(inputvar, "dd-Mmm-yyyy")
                            If (Not IsDate(inputvar)) Then
                                MsgBox "Enter a Valid date, in dd-Mmm-yyyy format", 16, "Invalid Date."
                            End If
                        Loop Until (IsDate(inputvar) = True) And (msgResult = vbYes) And (Len(InputvarDate) > 6)
                    Loop Until (IsDate(inputvar) = True) And (msgResult = vbYes)
                    ResutlsStream.WriteLine "Step " & SSW.View.CurrentShowPosition & ". " & xPrompt & Chr(9) & ":" & Chr(9) & inputvar & " " & xvarUnit
                Case "TrueFalse"
                    xPrompt = GetINIString(SSW.View.CurrentShowPosition, "Prompt", INIPath)
                    Do
                        msgResult = 7
                        Do
                            inputvar = InputBox(xPrompt, "Enter True or False")
                            msgResult = MsgBox("You have Enterd " & inputvar & " to " & xPrompt, vbYesNo + vbDefaultButton2, "Check Your Input (True/False)")
                            If (StrPtr(inputvar) = 0) Or (Len(inputvar) < 0) Then
                                MsgBox "Invalid Input - Cannot be Empty / Null / cancelled", 16, "Invalid Input."
                            End If
                            If (inputvar <> "True") And (inputvar <> "False") Then
                                MsgBox "Invalid Input - Enter Either True or False", 16, "Invalid Input."
                            End If
                        Loop Until (Len(inputvar) > 0) And (inputvar = "True") Or (inputvar = "False") And (msgResult = vbYes)
                    Loop Until (Len(inputvar) > 0) And (inputvar = "True") Or (inputvar = "False") And (msgResult = vbYes)
                    If inputvar = True Then
                        ResutlsStream.WriteLine "Step " & SSW.View.CurrentShowPosition & ". " & xPrompt & Chr(9) & ":" & Chr(9) & inputvar
                    Else
                        MsgBox "Test criteria failed, contact production engineer."
                        ResutlsStream.WriteLine "Step " & SSW.View.CurrentShowPosition & ". " & xPrompt & Chr(9) & ":" & Chr(9) & inputvar & " " & xvarUnit & " Failed" & " ***NCR Required***"
                    End If
                Case "General"
                    xPrompt = GetINIString(SSW.View.CurrentShowPosition, "Prompt", INIPath)
                    Do
                        msgResult = 7
                        Do
                            inputvar = InputBox(xPrompt, xPrompt)
                            msgResult = MsgBox("You have Enterd " & inputvar & " to " & xPrompt, vbYesNo + vbDefaultButton2, "Check Input")
                            If (StrPtr(inputvar) = 0) Or (Len(inputvar) < 0) Then
                                MsgBox "Invalid Input - Cannot be Empty / Null / cancelled", 16, "Invalid Input."
                            End If
                        Loop Until (Len(inputvar) > 0) And (msgResult = vbYes)
                    Loop Until (Len(inputvar) > 0) And (msgResult = vbYes)
                    ResutlsStream.WriteLine "Step " & SSW.View.CurrentShowPosition & ". " & xPrompt & Chr(9) & ":" & Chr(9) & inputvar & " " & xvarUnit
                Case "Limit"
                    xLimitHi = GetINIString(SSW.View.CurrentShowPosition, "LimitHi", INIPath)
                    xLimitLo = GetINIString(SSW.View.CurrentShowPosition, "LimitLo", INIPath)
                    xPrompt = GetINIString(SSW.View.CurrentShowPosition, "Prompt", INIPath)
                    xvarUnit = GetINIString(SSW.View.CurrentShowPosition, "varUnit", INIPath)
                    If GetTestCriteria(xPrompt, xLimitLo, xLimitHi, xvarUnit, result) Then
                        ResutlsStream.WriteLine "Step " & SSW.View.CurrentShowPosition & ". " & xPrompt & Chr(9) & ":" & Chr(9) & result & " " & xvarUnit
                    Else
                        MsgBox "Test criteria failed, contact production engineer."
                        Do
                            msgResult = 7
                            Do
                                FailedResult = InputBox("Enter Values Failed in " & xPrompt, "Enter Failed Value")
                                msgResult = MsgBox("You have Enterd Failed Value of " & FailedResult, vbYesNo + vbDefaultButton2, "Check Failed Input")
                                If (StrPtr(FailedResult) = 0) Or (Len(FailedResult) = 0) Then
                                    MsgBox "Invalid Input - Cannot be Empty / Null / cancelled", 16, "Invalid Input."
                                End If
                            Loop Until (Len(FailedResult) > 0) And (msgResult = vbYes)
                        Loop Until (Len(FailedResult) > 0) And (msgResult = vbYes)
                        ResutlsStream.WriteLine "Step " & SSW.View.CurrentShowPosition & ". " & xPrompt & Chr(9) & ":" & Chr(9) & FailedResult & " " & xvarUnit & " Failed" & " ***NCR Required***"
                    End If
                    ResutlsStream.Close
            End Select
        End If
    End If
    If (Timed = "ON") Then
        If (Len(Dir(TimeingFolder, vbDirectory)) = 0) Then
            MkDir TimeingFolder
        End If
        If (Len(Dir(TimeingFolder & "\" & PCPver, vbDirectory)) = 0) Then
            MkDir TimeingFolder & "\" & PCPver
        End If
        TimingFile = TimeingFolder & "\" & PCPver & "\" & "Timing-" & WorkOrder & "-" & Serial & "-" & PCPver & "-" & ToDate & ".csv"
        If (Len(Dir(TimingFile)) = 0) Then
            Set TimeingStream = TimeingFSO.CreateTextFile(TimingFile, True)
            TimeingStream.WriteLine UserName & "'s " & ModuleName & " " & PCPver & " Build Time File"
            TimeingStream.WriteLine "===================================================================================================="
            TimeingStream.WriteLine "Seq/Step" & Chr(44) & "Start Time" & Chr(44) & "End Time"
        Else
            Set TimeingStream = TimeingFSO.OpenTextFile(TimingFile, 8)
        End If
        EndTime = Format(time, "hh:mm:ss")
        TimeingStream.WriteLine "No:" & SSW.View.CurrentShowPosition & Chr(44) & StartTime & Chr(44) & EndTime
        TimeingStream.Close
    End If
End Sub
Private Function ConfirmUserInput(ByVal inputvar As Double) As Boolean
    ConfirmUserInput = MsgBox("Confirm value: " & CStr(inputvar) & "?", vbYesNo + vbDefaultButton2, "Confirm value") = vbYes
End Function
Private Function IsValidUserInput(ByVal userInput As String, ByVal xLimitLo As Double, ByVal xLimitHi As Double, ByRef outResult As Double) As Boolean

    Dim result As Boolean
    Dim numericInput As Double

    If StrPtr(userInput) = 0 Then
    MsgBox "Invalid Input - Entry cannot be cancelled", 16, "Invalid User Input"
    ElseIf userInput = vbNullString Then
        MsgBox "Invalid Input - Entry cannot be Empty / Null", 16, "Invalid User Input"
    ElseIf Not IsNumeric(userInput) Then
        MsgBox "Invalid Input - Numeric Input required", 16, "Invalid User Input"
    Else
        numericInput = CDbl(userInput)
        If numericInput < xLimitLo Or numericInput > xLimitHi Then
            MsgBox "Invalid Input - Not within Limits", 16, "Invalid User Input"
        Else
            result = ConfirmUserInput(numericInput)
            outResult = numericInput
        End If
    End If

    IsValidUserInput = result

End Function
Private Function GetTestCriteria(ByVal xPrompt As String, ByVal xLimitLo As Double, ByVal xLimitHi As Double, ByVal xvarUnit As String, ByRef outResult As Double) As Boolean

    Const failed As String = "Failed"

    Dim prompt As String
    prompt = "Enter Value between " & xLimitLo & xvarUnit & " and " & xLimitHi & xvarUnit & "(Inclusive)"

    Dim userInput As String
    Dim isValid As Boolean

    Do

        userInput = InputBox(prompt, xPrompt)
        isValid = IsValidUserInput(userInput, xLimitLo, xLimitHi, outResult) Or userInput = failed

    Loop Until isValid

    GetTestCriteria = (userInput <> failed)

End Function

Private Sub TextBox1_Change()

End Sub

Private Sub TextBox2_Change()

End Sub

Private Sub TextBox2_DblClick(ByVal Cancel As MSForms.ReturnBoolean)

End Sub

> Code in Module

Option Explicit
Option Compare Text
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
Private Declare Function GetPrivateProfileInt Lib "kernel32" Alias "GetPrivateProfileIntA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal nDefault As Long, ByVal lpFileName As String) As Long
Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpString As String, ByVal lpFileName As String) As Long
Private Const CONFIG_FILE = "Config.ini"
Public Function GetINIString(ByVal sApp As String, ByVal sKey As String, ByVal filepath As String) As String
    Dim sBuf As String * 256
    Dim lBuf As Long
    lBuf = GetPrivateProfileString(sApp, sKey, "", sBuf, Len(sBuf), filepath)
    GetINIString = Left$(sBuf, lBuf)
End Function
Public Function WriteINI(ByVal sApp As String, ByVal sKey As String, ByVal sValue As String) As String
    WritePrivateProfileString sApp, sKey, sValue, "Config.ini"
End Function

Code in Config.ini Config.ini to be remain in same folder as the .ppsm file

[PCPInfo]
;This will force the operator to check PCP version against BOM
;This is required as it is used to tie in the check list to the PCP
PCPver=12.3456.789.A01

;this is used as the heading for creating results files
ModuleName=NEW Validation Test Case

;this to check the correct PCP Power-point file is present with the ini file - if this is incorrect power point will not run
PCPFileName=12.3456.789.A01 NEW Validation Test Case.ppsm

[Options]
;Switch ON/OFF to collect timing data
Timed=ON

[Folders]
;If required creates last folder of the path 
;folder where all check-lists/result files collected
ResultsFolder=C:\Reports\Validation

;folder where all training data collected
TrainingFolder=C:\Training Records

;folder where all timing data collected
TimeingFolder=C:\Times

;Check Who has completed training here - Not implemented
TrainedFolder=C:\TrainedOP

;Do not Use Slide No 1 - Use slide number in square brackets [x]
;First Slide collects Work Order, User name , Serial Number information
;PromptTypes Message,Date,TrueFalse,General,Limit *compulsory
;Type Message Displays Pop up message only , No Data Collection
;Type Date accepts dates in DD-MMM-YYYY format
;Type TrueFalse can be used for Passed failed, checks etc.
;Type General can be used for Part Serial numbers, batch dates
;Type Limit can be used for test parameters with a range,- 
;   - if not within the range "Failed" can be used to complete the step and return to a previous step
;       LimitHi refers to Higher limit should be less than or equal to *compulsory for type Limit
;       LimitLo Refers to Lower limit should be Greater than or equal to *compulsory for type Limit
;Prompt will pop-up the user input box wit the text as question/criteria *compulsory
;VarUnit Type of Unit Ohms,Psi,kPa etc.

[2] 
PromptType=Message
LimitHi=
LimitLo=
Prompt=Revision Record
varUnit=

[4] 
PromptType=Date
LimitHi=
LimitLo=
Prompt=Enter to days Date
varUnit=

[6] 
PromptType=TrueFalse
LimitHi=
LimitLo=
Prompt=Enter True or False
varUnit=

[8]
PromptType=General
LimitHi=
LimitLo=
Prompt=Enter Any text
varUnit=

[10]
PromptType=Limit
LimitHi=200
LimitLo=100
Prompt=Enter Value within limits
varUnit=Bar

thanks again @retailcoder best regards Dumidu Roshan aka rellik - @rellik

rellik
  • 304
  • 1
  • 4
  • 16
  • 1
    If you have working code that does exactly what it's supposed to be doing, but that you would like peer reviewed, know that the folks over at [codereview.se] would love to review it! – Mathieu Guindon Nov 24 '14 at 06:05