Survey - Am I missing something obvious :(

SteveGMC

Registered User.
Local time
Today, 13:08
Joined
Dec 13, 2009
Messages
20
Hi all, I've searched the forums for surveys and questionnaires, picked up a few pointers and watched a online tutorial here but found it was based on a non normalised table.

I've created the survey as a non normalised design, works fine, just getting reporting hicups with null fields etc, so want to normalise it.

The survey is basic, 25 questions with just a 1 to 10 score.

I have created three tables with the following fields

TblResults
-----------
SurveyID (Autonumber)
fkAssessorID (Number)
fkQuestionID (Number)
QuestionResult (Number)

TblQuestions
-----------
QuestionID (Number)
QuestionDesc (Text)

Tbl_Assessors_
-----------
AssessorID (AutoNumber)
AssessorName (Text)

The question...The Form input :(
In the non normilised table its pretty easy to create a form based on a non normalised table with 25+ table fields with each table field relating to a field on form and a combo box with the 1 to 10 Result list.

What I do not understand using the Normalised structure is how to show all 25 questions on one form and then add each question result to the Results table with the questionId and Result on the appropriate row?

If I've missed the answer searching the forum, apologies!
 
If your form has a series of two controls.
One is the question, another is the combo box / list box with answer options.

And you want to have the values in these controls appending to a table to show the Question and the response plus I assume, the Name of the person.

You could use an append sql in vba code.

Give the controls similar names eg Question1, Response1 for the two controls for the first question. Not critical but just helps.

Your sql would insert Question1, Response1 and PersonsName into the relevant table and then have it loop around until EOF.

In the Code, use variables for Question1 and Response1 and have the loop change these names to Question2 and Response 2 as it goes around.
 
Thanks for the reply :) However thats a little above my current ability, so a little help would be appreciated.

Using your suggestion, I thought I start small with just getting two fields to append to a table. I'm stuck allready. I've created a query to see the SQL code which I do understand, this has given me this, I've added the do.cmd.RunSql from another web page.

Code:
DoCmd.RunSQL = "INSERT INTO tbl_Results ( QuestionID, Response ) SELECT tbl_Results.QuestionID, tbl_Results.Response"
FROM tbl_Results

WHERE "tbl_Results.QuestionID = me.txtQ1 AND tbl_Results.Response = me.txtR1;"

Now I've added this to an on click event on the form, but I'm now stuck understanding what comes before and after it. I've looked around and can see that there are examples, but I don't really understand what the code is doing.
 
see this example

Code:
Private Sub CmdLawyersLetter_Click()   'command button name is CmdLawyersLetter
On Error GoTo Err_CmdLawyersLetter_Click
            
    Dim sqlString As String
    Dim ADPK As Integer     'CustomerID
    Dim LetterID As Integer  'LetterID
    Dim strUserID As String   'Database UserID
    
    ADPK = Me.ADPK  'Sets ADPK to = Form Control Name ADPK
    LetterID = 10    'Set LetterID to - 10 - relates to an ID number in letter options table
       
       'Get current operator
    strUserID = Me.strUserID    ' also gets the userID from a form control
    
    DoCmd.SetWarnings False ' stops any warnings
    
        'Collect Data and append record to TblLetterSent
    sqlString = "INSERT INTO TblLetterSent ( LID, MID, FullName, Fax, LIDOverdue, LetterType, LetterSubject ) " & _
        "SELECT TBLLOAN.LDPK, TBLACCDET.ADPK, [ADFirstName] & "" "" & [ADSurname] AS FullName, TBLACCDET.ADFax, QryLoanCurrentBalanceResult.LoanCurrentBalance, TblLetterOptions.LetterID, TblLetterOptions.LetterType " & _
        "FROM TblLetterOptions, QryLoanCurrentBalanceResult INNER JOIN (TBLACCDET INNER JOIN TBLLOAN ON TBLACCDET.ADPK = TBLLOAN.ADPK) ON QryLoanCurrentBalanceResult.LoanID = TBLLOAN.LDPK " & _
        "WHERE (((TBLLOAN.LDPK)=" & LDPK & ") AND ((TblLetterOptions.LetterID)=" & LetterID & "));"

'Your sql should be shorter because you are just appending data from the form whereas in this example some data is found in related tables
    
      DoCmd.RunSQL sqlString    'Append Letter Details to TblLetterSent
      
         'Collect Data and append record to tblLoanComm
    sqlString = "INSERT INTO tblLoanComm ( LoanID, CommNotes, Operator, CommDate, CommTime ) " & _
        "SELECT TBLLOAN.LDPK, ""Sent "" & [TblLetterOptions].[LetterType] AS CommNotes, strUserID, Date() AS CommDate, Time() AS CommTime " & _
        "FROM TBLLOAN, TblLetterOptions " & _
        "WHERE (((TBLLOAN.LDPK)=" & LDPK & ") AND ((TblLetterOptions.LetterID)=" & LetterID & "));"
     
    DoCmd.RunSQL sqlString    'Append Loan Communication to tblLoanComm
    
        'Collect Data on Letter just printed and update the Letter Printed Flag
    sqlString = "UPDATE TblLetterSent SET TblLetterSent.LetterPrinted = 2 " & _
        "WHERE (((TblLetterSent.LID)=" & LDPK & ") AND ((TblLetterSent.LetterDate)=Date()) AND ((TblLetterSent.LetterPrinted)=1));"
        
    DoCmd.RunSQL sqlString    'Update TblLetterSent Letter Printed Flag
   
    DoCmd.SetWarnings True
            
Exit_CmdLawyersLetter_Click:
    Exit Sub

Err_CmdLawyersLetter_Click:
    MsgBox Err.Description
    Resume Exit_CmdLawyersLetter_Click
    
End Sub
My example performs more then one task so you just ignore where you see can see the second or 3rd activity
 
PNGBill Thanks very much :) I have got it appending the 1st field and understand in a limited way what it's doing, also found out what a _ does at the end on the line from this post.

Below is the code I have in place that works, may not be perfect, but does the job. I've used your code and updated with my sql, now seeing what was wrong with my first attempt. For some reason I had the table I was trying to append to as the source and criterea as the form fields. I have a few questions if you have time to answer them.


Code:
Private Sub btnAppendResult_Click()
On Error GoTo Err_btnAppendResult_Click
            
    Dim sqlString As String
  
    
' DoCmd.SetWarnings False ' stops any warnings


'Your sql should be shorter because you are just appending data from the form whereas in this example some data is found in related tables
    
        
         'Collect Data and append record to tbl_Reponses
    sqlString = "INSERT INTO tbl_Responses ( ResponseDate, GSFS, QuestionID, Score ) " & _
        "SELECT Date(), [txtGSFS] AS GSFS, [txtQ1] AS QUESTIONID, [txtS1] AS SCORE; "

    DoCmd.RunSQL sqlString    'Append Responses to tbl_Reponses

    
    DoCmd.SetWarnings True
            
Exit_btnAppendResult_Click:
    Exit Sub

Err_btnAppendResult_Click:
    MsgBox Err.Description
    Resume Exit_btnAppendResult_Click
End Sub

In the sql code, it appears that its just inserting the fields in order from left to right as they appear in the code. Just for knowledge how would you specify which field you wanted if they weren't in order?

Also where I've put '[txtGSFS] as GSFS' it seems to work fine without the AS GSFS part?

I see I could just add the SQL statement multiple times and just change the field names to update, but your Loop function sounds more efficient if adding further questions.

From your first reply, you recommend a loop and variables to change the field name. I've looked this up and after trying a few variations of the examples, I can't get it to work and I don't really understand. I've tried going through some posts here and an example here but I seem to just get errors!

Any suggestions?
 
Congratulations! you have done well to sort through this issue and your code looks clean and simple.

In the sql code, it appears that its just inserting the fields in order from left to right as they appear in the code. Just for knowledge how would you specify which field you wanted if they weren't in order?
I'm guessing here but this is an issue related to your table eg, to miss an important field may cause an error. try changing the order of your Insert sql.
The sql 1st part and 2nd part must be in the same order.

Also where I've put '[txtGSFS] as GSFS' it seems to work fine without the AS GSFS part?
the "As" can be dropped. I guess I used it to get the names the same but not needed. The Order and Format are the important issues eg, don't insert text into a date field.

I see I could just add the SQL statement multiple times and just change the field names to update, but your Loop function sounds more efficient if adding further questions.
For one, two or three questions you could repeat the code but after that it will get messy and what if you are told there will now be 100 questions?

From your first reply, you recommend a loop and variables to change the field name. I've looked this up and after trying a few variations of the examples, I can't get it to work and I don't really understand. I've tried going through some posts here and an example here but I seem to just get errors!
I should have enough info from your code to offer an example loop but how about posting your best try as well.

I need an hour or so to get back to you. 05:00hrs here.

You have to do a loop - should be examples available but you also have to change where the variable gets it's value from each time around.
What is GSFS ?
Remember, your controls on the form must all be named similar eg txtQ1, txtQ2
The Code will then use txtQ as the name and append 1, 2, 3, or 4 etc to the name as it loops around.

It will also help if you have a control on the form with the number of questions. This can be part of your Form eg here are your 25 questions where the 25 is a separate control or you can have the control Invisible so it isn't seen, except by the vba code, we hope.
This will let the code know how many times to loop.

Here is a Function that performs a Loop - after sorting out the data and when finished appends a record to a table - using rst.
Code:
Public Function LatefeesToBeCharged(LoanID As String) As Currency    'Calculate Late Fees for selected LoanID
    'Thanks To Allen Browne's Web Site for the start of this Code
   
    Dim rs As DAO.Recordset
    Dim sqlString As String
    Dim RepayFreq As String         ' Repayment Fortnightly, Monthly or Weekly
    Dim CurrentBalance As Currency  ' Balance As At each 14 days from the Start Date of the Loan plus 14 days
    Dim LateFeeRate As Currency     ' Kina Amount of Late Fee to be charged each fortnight
    Dim RepayTotal As Currency      ' Kina amount of accumulated Repayments up to Given Date
    Dim RepayPrev As Currency       ' Kina Amount Repaid Up To Last Fortnight
    Dim RepayAmount As Currency     ' Kina Amount Due to be Repaid Each Fortnight
    Dim CommenceDate As Date        ' Loan Commencement Date - Start Date plus 14 days
    Dim RepayCount As Integer       ' Count of Fortnights as Function Loops - Increases by 1 each loop
    Dim RepayNum As Integer         ' Number of Repayments agreed to for Loan
    Dim LateFeeDue As Currency      ' Accummulated Late Fee now being calculated
    Dim LateFeeNow As Currency      ' Kina Charge of Late Fee to be charged as at this date
    Dim LateFeesCharged As Currency ' Kina Amount of Late fees charged as at given date
    Dim LoanTotalOwing As Currency  ' Kina Amount of Loan to Pay
    
    RepayCount = 1          'Set Variable to start at 1
    LateFeeDue = 0          'Set variable to Zero
    LateFeeNow = 0          'Set Variable to Zero
  
    sqlString = "SELECT TBLLOAN.LDPK, TBLLOAN.LDSt AS StartDate " & _
        "FROM TBLLOAN " & _
        "WHERE (((TBLLOAN.LDPK)=" & LoanID & "));"
        
    Set rs = DBEngine(0)(0).OpenRecordset(sqlString)
    
    CommenceDate = rs!StartDate + 14
  
    sqlString = "SELECT TBLLOAN.LDPK, TBLLOAN.LDPayK AS LDRepayK " & _
        "FROM TBLLOAN " & _
        "WHERE (((TBLLOAN.LDPK)=" & LoanID & "));"
        
    Set rs = DBEngine(0)(0).OpenRecordset(sqlString)
    
    RepayAmount = rs!LDRepayK
    
    sqlString = "SELECT TBLLOAN.LDPK, TBLLOAN.LDPayNo AS RepayNo " & _
        "FROM TBLLOAN " & _
        "WHERE (((TBLLOAN.LDPK)=" & LoanID & "));"
        
    Set rs = DBEngine(0)(0).OpenRecordset(sqlString)
    
    RepayNum = rs!RepayNo
    
    sqlString = "SELECT TBLLOAN.LDPK, TBLLOAN.LDPayFre AS LDRepayFreq " & _
        "FROM TBLLOAN " & _
        "WHERE (((TBLLOAN.LDPK)=" & LoanID & "));"
        
    Set rs = DBEngine(0)(0).OpenRecordset(sqlString)
    
    RepayFreq = rs!LDRepayFreq
    
    sqlString = "SELECT TBLLOAN.LDPK, TBLLOAN.LoanLateFee AS LateFeeKina " & _
        "FROM TBLLOAN " & _
        "WHERE (((TBLLOAN.LDPK)=" & LoanID & "));"
        
    Set rs = DBEngine(0)(0).OpenRecordset(sqlString)
    
    LateFeeRate = rs!LateFeeKina
                        
    If RepayFreq = "Fortnightly" Then
    
    FuncDeleteRecord "TblLateFeeCalculated", "LDPK", LoanID
     
    Do Until Date <= CommenceDate
    
        CurrentBalance = LoanBalanceToDate(LoanID, CommenceDate)                    'Function to Get Loan Balance as at given date
        LateFeesCharged = LateFeesToDate(LoanID, CommenceDate)                      'Function to Get Late Fees Charged as at given date
        RepayTotal = LoanRepaymentToDate(LoanID, CommenceDate)                      'Function to Get Repayments To Date as at given date
        LoanTotalOwing = LoanTotalToPay(LoanID)                                     'Function to Get Total Amount Yet to Pay on Loan
       
        If RepayCount = 1 Then                                                      'If First Repayment Due
            If (CurrentBalance - LateFeesCharged) > (RepayAmount / 2) Then          'If Repament Made for less then Half of Repayment Amount
                LateFeeNow = (LateFeeRate * 2)                                      'Charge double Late Fees
            Else
                LateFeeNow = 0                                                      'No Late Fees to Charge
            End If
            RepayPrev = RepayTotal                                                  'Set Repay Value For up to First Fortnight
        ElseIf RepayCount > 1 Then                                                  'If not First Repayment
                If (CurrentBalance - LateFeesCharged) > 5 Then                      'Check If Overpaid to date or paid in full
                    If RepayCount <= RepayNum Then                                  'And is Last Repay Date or earlier
                        If (RepayTotal - RepayPrev) < (RepayAmount / 2) Then        'Compare Any Recent Repayment to at least half the Agreed Repayment
                            LateFeeNow = LateFeeRate                                'Charge Late Fee
                        Else
                            LateFeeNow = 0                                          'No Late fees Due
                        End If
                        RepayPrev = RepayTotal                                      'Reset RepayPrev to New Balance
                    Else
                        LateFeeNow = LateFeeRate                                    'Charge Late Fee
                    End If
                Else
                    If (LoanTotalOwing - LateFeesCharged) < 6 Then                  'Check If Original Loan fully repaid
                        CommenceDate = Date                                         'Loan Completed - set Commence Date to today's date to stop loop
                        LateFeeNow = 0                                              'No Late Fees Due
                    End If
                    LateFeeNow = 0                                                  'No Late fees Due
                End If
        End If
            
            If LateFeeNow > 0 Then
                Dim rst As DAO.Recordset
                Set rst = CurrentDb.OpenRecordset("TblLateFeeCalculated", dbOpenDynaset)
                rst.AddNew
                rst!LDPK = LoanID
                rst!LateFeeAmount = LateFeeNow
                rst!LateFeeDate = CommenceDate
                rst.Update
                
                rst.Close
                Set rst = Nothing
            
            End If
        CommenceDate = CommenceDate + 14                                            'Add 14 Days to get Next loop
        RepayCount = RepayCount + 1                                                 'Add 1 to RepayCount variable for next loop
        LateFeeDue = LateFeeDue + LateFeeNow                                        'Add this fortnights Late Fee Charge to Accummulated Late Fees Variable
        
    Loop
        LateFeesCharged = LateFeesToDate(LoanID, CommenceDate)                      'Refresh Late Fees Charged as at Today's date
        LateFeeDue = LateFeeDue - LateFeesCharged                                   'Deduct any Late Fees already Charged
        LatefeesToBeCharged = LateFeeDue                                            'Return Result to Function
    
    Else
        MsgBox "Loan Repayments Not Fortnightly - Calculate Late Fees Some other way" 'Calculator won't work for Weekly or Monthly repayments
    End If
    
    rs.Close
    Set rs = Nothing

End Function

Actually, my first attempt (at a serious loop) so we are both learning a bit here.:D
 
The problem I have is I'm trying to reference you code, not knowing really where to start!

You mentioned a control on the form to specify how many questions, is there something similar on the code you posted? Also which part of your code takes the txtQ1 part and adds 1 as part of the loop?

GSFS is a text reference we have to fill in. No idea what it actually stands for, it just comes on a sheet of paper that we are currently adding on an excel sheet.
 
The problem I have is I'm trying to reference you code, not knowing really where to start!

You mentioned a control on the form to specify how many questions, is there something similar on the code you posted? Also which part of your code takes the txtQ1 part and adds 1 as part of the loop?

GSFS is a text reference we have to fill in. No idea what it actually stands for, it just comes on a sheet of paper that we are currently adding on an excel sheet.
My code is not your solution, just an example of looping.

I will post the change of txtbox soon.

Your "fields" on the form are Controls - text box controls.

Add a control that has 25 in it. eg and give it a name say NumQuestions.

GSFS doesn't change for the questions? ie it is a name or like the date, the same. so there isn't a gsfs 1, 2 3?
 
Hi there. I yes the fields are text boxes and the gsfs doesn't change.

Posting from my mobile as my net connection has just died. I did find another example of the loop but can't see it on this phone. I've bookmarked it so i'll take a good look when I can get back on my PC.
 
Just finished breakfast and will start on your loop code soon.

The loop part is just a few lines.

The change of txtbox will also be a few lines.
 
Try this code.

This symbol ' means a remark only - not part of the code

You will need to add the control to your form for the number of times to loop.

Code:
Private Sub btnAppendResult_Click()
On Error GoTo Err_btnAppendResult_Click
            
    Dim sqlString As String        ' This is the sql Satatement to be run each time
    Dim NumRecords As Integer        ' This is the number of records to be appended
    Dim Count As Integer            ' this is the count of each loop action
    Dim QStart As String            ' this is the Start of the Question Control on the Form the query will look for
    Dim SStart As String            ' this is the Start of the Score Control on the form the query will look for
    Dim txtQuestion As String        ' this is the sql variable Question txt box control
    Dim txtScore As String        ' this is the sql variable Score txt box control

QStart = "txtQ"                ' Set the Fixed part of the form Question Control Name
SStart = "txtS"                ' Set the Fixed part of the form Score Control Name
Count = 1                ' Set Count to 1 to Start
NumRecords = Me.QuestionNumber    ' Set NumRecords to be the value in the Control QuestionNumber on your form
    
Do Until Count = NumRecords        ' Stop Loop when Count reaches number of records on form

    txtQuestion = QStart & Count    ' Set Control Name to be the full name for this Loop
    txtScore = SStart & Count    ' Set Control Nam eto be the Full Name for this Loop

    DoCmd.SetWarnings False ' stops any warnings
       
                 'Collect Data and append record to tbl_Reponses
        sqlString = "INSERT INTO tbl_Responses ( ResponseDate, GSFS, QuestionID, Score ) " & _
                "SELECT Date(), [txtGSFS], " & txtQuestion & ", " & txtScore & "; "
       DoCmd.RunSQL sqlString    'Append Responses to tbl_Reponses
    
        DoCmd.SetWarnings True    ' Start warnings
    
    Count = Count + 1        ' Add 1 to Count
Loop
            
Exit_btnAppendResult_Click:
    Exit Sub

Err_btnAppendResult_Click:
    MsgBox Err.Description
    Resume Exit_btnAppendResult_Click
End Sub
 
Brilliant thank you, I owe you a pint.

Now I can see what its up to knowing which bits are relating to the fields in my database it makes it a lot easier to understand. Oddly It also helped when I thought about it as like how I configure our telephone switch with Direct Dial Number to Extension translations. Well its similar as the switch replaces the first part of the DDI string with an extension which steps up. I know what I mean!

I was going to see if I could use your example it to set all the Combo's to Null values, but then I remembered I'd used a similar method with Control Types.

I have another project coming up next week which will need a loop, dont be surprised if I pop back!

Thank you again :)
 
Glad to help and as I mentioned, this is new to me too. my first time to use a variable control name like that.:)
 

Users who are viewing this thread

Back
Top Bottom