0

We have a preregistration Excel spreadsheet database for a retirement community's continuing education program. The database has 37 data columns of which 3 are calculated, one is a date format one and all the rest receive either a zero or a one as indicators of whether a resident registers or not for a lecture/class (really a 1 or the field is left blank). It currently has 1126 rows reflecting 1123 residents.

If the residents preregister they mostly pay $1 for the class, but some events are musical performances which are $8 upfront. If they show up without having preregistered they pay $2 and $9 respectively. Also, some are classes that are more than one time events and registration for these can be up to $111, thus there is a need for calculations to figure out how much of a check the resident needs to have sent in with their registration form. What the check amount is the grand total column. We also have subtotals for the one-time events and another one for the multiple-day classes.

enter image description here

I found an an excellent recently defunct mostly free Excel add-in, which allows an unlimited number of fields, so the 32 limit on the fields for the form is not an issue. I cracked the password, so I have access to the VBA of the form and was able to add a couple of buttons, for instance, one that fills in a one for all the evening events as that is a common choice for the registers. I would be happy to pay the $15 to the programmer for the password privilege that he used to charge and will try to get in touch to do that.

What I would like to know is if it is possible for the form to instantly update the spreadsheet and the calculated fields and then the calculated fields to be updated on the form right away. I do have an update button but would like the spreadsheet to be updated as the data is entered in case the enterer forgets to press the update button. I realize that entering the data directly into the spreadsheet accomplishes that but I would like to stick with the form.

I figure this would involve somehow recognizing a change in the state of the form, but I don't know how to write the VBA to do that. I have been able to figure out how to re-enter the calculated amounts in the form, once the update button is pressed, which can then be compared against the resident's check amount from the total presented on the form.

Here is I believe where the relevant VBA would be inserted or a separate subroutine based on one or both subs would come from:

Sub UpdateForm()
    'This sub updates the fields in the form
    Dim ctl As Control
    Dim Col As Long
    Dim CurrentCell As Range
    Col = 0

    On Error Resume Next
    For Each ctl In Frame1.Controls
        If TypeName(ctl) = "TextBox" Or TypeName(ctl) = "ComboBox" Then
            Col = Col + 1
            Set CurrentCell = Cells(CurrentRecord + RowOffset, Col + ColumnOffset)
            ctl = CurrentCell
            If CurrentCell.PrefixCharacter = "'" Then ctl = "'" & ctl

            'Check for True/False cells (they would appear as 0 or -1)
            If Application.WorksheetFunction.IsLogical(CurrentCell) Then
                ctl = CurrentCell.Text
            End If

            'Is the cell displaying an error value?
            If Err <> 0 Then
                ctl = CurrentCell.Text 'Display this if the cell has an error value
                Err = 0
            End If

'           Date?
            If IsDate(Cells(CurrentRecord + RowOffset, Col + ColumnOffset)) Then
                ctl = CurrentCell.Text
            End If

            'Formula?
            If Cells(CurrentRecord + RowOffset, Col + ColumnOffset).HasFormula Then
                ctl = FormatCurrency(CurrentCell)
                ctl.Enabled = False
                ctl.BackColor = RGB(240, 240, 240)
            Else
                ctl.Enabled = True
                ctl.BackColor = RGB(255, 255, 255)
            End If
        End If
    Next ctl
    LabelRecNum = Text(9) & " " & CurrentRecord & " " & Text(10) & " " & RecordCount
    On Error GoTo 0
End Sub

Sub UpdateDatabase()
    'Updates the database with new data from the form
    Dim ctl As Control
    Dim Col As Long
    Dim TestCell As Range
    Dim NumberWritten As Long
    Col = 0
    NumberWritten = 0
    For Each ctl In Frame1.Controls
        If TypeName(ctl) = "TextBox" Or TypeName(ctl) = "ComboBox" Then
            Col = Col + 1
            Set TestCell = Cells(CurrentRecord + RowOffset, Col + ColumnOffset)
            If Not TestCell.HasFormula Then ' Don't check formula cells
                'Use Clean so cells with non-printing characters will be compared correctly
                If TestCell.PrefixCharacter & Application.WorksheetFunction.Clean(TestCell) <> Application.WorksheetFunction.Clean(ctl.Text) Then
                    'Save original data for undo
                    NumberWritten = NumberWritten + 1
                    ReDim Preserve UndoArray(1 To NumberWritten)
                    With UndoArray(NumberWritten)
                        .Address = TestCell.Address
                        .Contents = TestCell.PrefixCharacter & TestCell.Text
                        .RecNum = CurrentRecord
                    End With
                    'write the new data
                    '(date check code is new in v3) - revised Aug 6-08
                    If IsRealDate(ctl.Text) Then
                        If IsDate(DateValue(ctl.Text)) Then
                            TestCell.Value = CDate(ctl.Text)
                        End If
                    Else
                        TestCell.Value = ctl.Text
                    End If
                End If
            End If
        End If
    Next ctl

    If NumberWritten <> 0 Then
        UndoButton.Caption = Text(18) '"Undo Entry"
        UndoButton.Visible = True
    End If
End Sub

Also if anybody has any suggestions on how to gather the data and calculate more efficiently, I'd be happy to hear it. We are using manual forms now with checkboxes and rely on the seniors to calculate their check amounts. The checkmarks are transferred to the Excel spreadsheet manually. I proposed putting a computer-readable form in the course catalog, such as the ones you find for taking standardized tests, but that was shot down as being too complicated for seniors. I don't agree and would like to try it, but I'm new here and not in charge, so I can't implement the experiment.

Edit per PEH: Here is the code that doesn't work -

Sub FormMain_Change()
     UpdateDatabase 
     Call UpdateForm 
End Sub

Nor does adding ".ControlSource" to my controls ("ctl"s) in the UpdateForm codeblock fixes things.

socrtwo
  • 122
  • 1
  • 12
  • 1
    Yes it is possible to update a cell instantly: ① Either use the `_Change` event and put your update code there, or ② use the property `ControlSource` to set a cell (eg `Sheet1!A1`) that get's instanly updated automatically. Both should work for combo boxes or text boxes. – Pᴇʜ Feb 17 '20 at 07:08
  • PEH, Thanks very much for your answer. My form's name is "FormMain" but this code doesn't work: Sub FormMain_Change() UpdateDatabase Call UpdateForm End Sub Nor does adding ".ControlSource" to my controls ("ctl"s) in the UpdateForm codeblock fixes things. – socrtwo Feb 17 '20 at 16:05
  • 1
    Well you must remove `On Error Resume Next`. This line hides **all** error messages but the errors still occur. If you cannot see your errors you cannot fix them, if you don't fix them your code can obviously not work. • Also I don't get what the code has to do with the the question in your title. My first comment was refering to the question in the title only. – Pᴇʜ Feb 17 '20 at 16:08
  • OK cool, I'll remove the On Error line. – socrtwo Feb 17 '20 at 16:10
  • Ahh and you need the code in your `_change` event of your text boxes or combo boxes not the one of the form `FormMain_Change()`. • Please make sure that if you add code, to add it in the question not in comments, so it is much more readable. – Pᴇʜ Feb 17 '20 at 16:10

0 Answers0