In Acces I have a continuous form with independant textbox.
I try to fill it using vba for each record find in the query result, but this fill all the textbox with the same value.
This is my Form
Private Sub Form_Open(Cancel As Integer)
Dim WO As String
WO = Forms![Maintenance input formulaire]![Maintenance input sous formulaire].Form![WONumber]
query = "select comment from SystemAircraftStatus where SystemID = " + CStr(Me.SystemID) + " and WO = '" + WO + "';"
Debug.Print (query)
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset(query)
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst
Me.Texte54.Value = rs.Fields("comment") 'PROBLEME : est appliqué a tous les enregistrements
End If
End Sub
and this is the VBA code, only the first result (with "autre") have a comment.
Is there a solution to fill each textbox separately ?
The reason why it fills all the textboxes with one value: It is a continous
form and the textbox is unbound.
The textbox has to be bound to a value in the recorset of the form in order to show different values.
I suggest you use the recordset object to bind the textbox to a value in the recordset of the form. Like this:
Sub Form_Open(Cancel As Integer)
dim qry as string
qry = _
"select WO, comment from SystemAircraftStatus where SystemID = " + CStr(Me.SystemID) + " and WO = '" + WO + "';"
me.recordset = qry
End Sub
You need to select the two values directly in your SQL query for the recordset object.
Then you use the properties of the textbox to bind it to the value in the query.
Best regards
Related
I am working on a database for our company. One of the big things they want this database to do is to create reminders and emails based on changed fields and newly created records. For example, when the user puts a date in the First_Meeting field, an event should be triggered that will create 3 reminders on an Outlook Calendar. As a second example, when a new record is created in the Contract table, an event should be triggered to create 2 reminders in an Outlook Calendar and 2 Outlook emails.
I have the logic to do all of this, but I am trying to figure out the best way to handle the events. It is important that the trigger happens on whatever form the First_Meeting field is updated. If I do a form field event, I have to make sure I add the code to all forms that include that field. I am wondering if there is a way to do this with Class modules so that I could fire an event on a table field or record. I have not done any OO, but looked into it a little bit years ago, so I have a very vague understanding of how it works. I apologize that my question is somewhat non-specific, but I don’t want to spend a lot of time on the learning curve of OO & Class Modules only to find out that what I am trying to do cannot be done. On the other hand, if I could do all of this in one place and not have to worry about it going forward that would be well worth any time spent!
My question is: Can I create a class on a table field that would fire an event anytime that field is edited? And can I create a class on a table (or table record) that would fire any time there is a record inserted into the table? What is the logic to accomplish this?
I am using a table to hold all of the items that will be created based on the field that is updated, or record that is created.
I am using Access 2016. Thanks in advance for any help you can give me!!!
Kim
This is the event code I am currently using for the First_Meeting Event:
'This code calls a form to select the reminders to create
Private Sub First_Meeting_AfterUpdate()
Dim strSql As String
Dim strWhere As String
Dim strOrderBy As String
Dim intRecordCount As Integer
'Save any changes to data before selecting appointments to set
If Me.Dirty Then
Me.Dirty = False
End If
'The "Where" keyword is not included here so it can be used for the DCount function
strWhere = " [Appt Defaults].[Field Name]='First Meeting Date'"
strOrderBy = " ORDER BY [Appt Defaults].[Order for List], [Appt Defaults Child].[Date Offset]"
strSql = "SELECT Count([Appt Defaults Child].ID) AS CountOfID " & _
"FROM [Appt Defaults] INNER JOIN [Appt Defaults Child] ON [Appt Defaults].ID = [Appt Defaults Child].ReminderID"
intRecordCount = DCount("ReminderID", "qDefaultAppts", strWhere)
If intRecordCount > 0 Then
DoCmd.SetWarnings False
'Delete records from the Temp table
DoCmd.RunSQL "Delete * From TempApptToSelect"
'Add the "Where" keyword to be used in the query
strWhere = "Where " & strWhere
strSql = CurrentDb.QueryDefs("[qAddApptsToTemp-MinusCriteria]").SQL
'The ";" symbol is added to the end of the query so it needs to be stripped off
strSql = Replace(strSql, ";", "")
strSql = strSql & strWhere & strOrderBy
DoCmd.RunSQL strSql
'Flag all of the events in the Temp Table as Selected
DoCmd.RunSQL "UPDATE TempApptToSelect SET TempApptToSelect.IsSelected = -1"
DoCmd.SetWarnings True
DoCmd.OpenForm "Reminders - Select Main", , , , , , OpenArgs:=Me.Name
End If
End Sub
'This code is from the form where the reminders are selected
Private Sub cmdCreateReminders_Click()
' This Routine copies all of the selected default records from the Appt Defaults tables and copies them to the Reminder Tables
'
Dim rstReminderDefaults As Recordset
Dim rstReminders As Recordset
Dim nID As Integer
Dim dtStartDate As Date
Dim dtStartTime As Date
Dim dtEndTime As Date
Dim strProjectName As String
Dim strProjectAddress As String
Dim strApptArea As String
Dim iCount As Integer
' The calling form has the info needed to set the values for the reminders
' The form "frmCalendarReminders" is generic and will be on all forms that need to set reminders
txtCallingForm = Me.OpenArgs()
'The form recordset is a temp query created from the calling routine which determines the record filter
Set rstReminders = Forms(txtCallingForm)!frmCalendarReminders.Form.RecordsetClone
Set rstReminderDefaults = CurrentDb.OpenRecordset("qApptsToSet")
nID = Forms(txtCallingForm)!ID
strApptArea = Left(rstReminderDefaults![Appt Area], 8)
Select Case strApptArea
Case "Projects"
strProjectName = Forms(txtCallingForm)!txtProjectName
strProjectAddress = Forms(txtCallingForm)!txtProjectAddressLine & vbCrLf & Forms(txtCallingForm)!txtProjectCityLine
With rstReminderDefaults
Do While Not .EOF
'If this reminder has not already been created
If DCount("ID", "PR_Child-Reminders", "[Project ID] =" & Forms(txtCallingForm)![ID] & " And [ReminderChildID]= " & ![ReminderChildID]) = 0 Then
rstReminders.AddNew
'Initialize fields with values from defaults
rstReminders![ReminderChildID] = ![ReminderChildID]
rstReminders![Project ID] = nID
rstReminders![Reminder Type] = ![Outlook Item Type]
rstReminders![Reminder Subject] = ![Subject]
rstReminders![Reminder Text] = ![Body]
rstReminders![Invited] = ![Invite]
rstReminders![Email CC] = ![Email CC]
rstReminders!Calendar = !CalendarID
rstReminders!Color = !ColorID
Select Case ![Appt Type]
.
.
Case "First Meeting"
If Not IsNull(Forms(txtCallingForm)!dtFirstMeeting) Then
'dtStartDate will be used later to fill in Placeholder field in Subject and Body of Calendar and Email Items
dtStartDate = Forms(txtCallingForm)!dtFirstMeeting
rstReminders![Reminder Date] = dtStartDate + ![Date Offset]
Else
'Quit working on this reminder since it has invalid conditions
MsgBox "No date has been set for the " & ![Appt Type] & " so reminders cannot be created"
rstReminders.CancelUpdate
GoTo NextLoop
End If
End Select
.
rstReminders.Update
CreateOrSend (txtCallingForm)
.
NextLoop:
.MoveNext
Loop
End With
End Select
DoCmd.Close
End Sub
‘This code is used to create the reminder or email
Sub CreateOrSend(CallingForm)
Dim bError As Boolean
Dim strName As String
Dim strSubject As String
Dim strBody As String
Dim strType As String
Dim strAttendees As String
Dim strCC As String
Dim strColorCategory As String
Dim dtStartDate As Date
Dim dtEndDate As Date
Dim strReminderText As String
Dim strLocation As String
Dim decDuration As Single
With Forms(CallingForm)!frmCalendarReminders.Form
'bError will be used to determine if the calendar item is created without error
bError = False
If !cmbReminderType = "Calendar" Then
strName = !cmbCalendar.Column(2)
strSubject = !txtReminderSubject
If Not IsNull(!txtReminderNote) Then
strBody = !txtReminderNote
Else
strBody = ""
End If
If Not IsNull(!txtInvite) Then
strAttendees = !txtInvite
Else
strAttendees = ""
End If
strColorCategory = !cmbColor.Column(1)
dtStartDate = !dtStartDate & " " & !dtStartTime
dtEndDate = !dtEndDate & " " & !dtEndTime
If Not IsNull(!txtReminderNote) Then
strReminderText = !txtReminderNote
Else
strReminderText = ""
End If
strLocation = IIf(IsNull(.Parent!txtProjectAddressLine), ".", .Parent!txtProjectAddressLine & ", " & .Parent![Project City])
' Parameter Order: strName, strSubject, strBody, strAttendees, strColorCategory, dtStartDate, dtEndDate, strReminderText Optional: strLocation, decDuration
Call CreateCalendarAppt(bError, strName, strSubject, strBody, strAttendees, strColorCategory, dtStartDate, dtEndDate, strReminderText, strLocation)
If bError = False Then
!dtCreatedItem = Date
Else
MsgBox "***** YOUR APPOINTMENT FAILED ******"
End If
Else
If Not IsNull(!txtReminderNote) Then
strBody = !txtReminderNote
Else
strBody = ""
End If
strSubject = !txtReminderSubject
If Not IsNull(!txtInvite) Then
strAttendees = !txtInvite
strCC = !txtEmailCC
SendCustomHTMLMessages strAttendees, strCC, strSubject, strBody
!dtCreatedItem = Date
Else
MsgBox "There were no email addresses to send this message to"
End If
End If
End With
End Sub
Unfortunately, there is no way to accomplish what you want. Although Access has something like "Data Macros", there is no way to to run a VBA procedure from there.
But don't be afraid of using event procedures in your forms. You don't have to copy all your existing code to each and every event procedure. You can place the existing code in a standard module, and in the forms, use very short event procedures that call these procedures in the standard modules. This still makes the main routines easy to maintain.
I don't agree with Wolfgang.
Of course I would suggest using MSSQL Server as backend, but with Access and the Data-Macros you can update a timestamp field in the underlying tables that updates on every change.
In addition run a script on a server (I don't knpw what intervall would be sufficent for you) every x minutes and check if row was updated since last run of script (compare timestamp)..
If true run your tasks.
If this is not an option we can talk about intercepting form-events with a class and WithEvents but this will need more effort to implement.
I have a form (frm_main)
and i have a subform on this form (frm_weblogs_subform)
I am trying to search the subform using a text box.
the code i've found and have been playing with to no avail is:
Private Sub find_weblog_button_Click()
Dim D As Database
Dim wlog As DAO.Recordset
Dim Criteria As String
Set D = CurrentDb
Set wlog = D.OpenRecordset("form_frm_weblogs_subform", dbOpenDynaset)
Criteria = "[weblog_number]='" & [weblogSearch] & "'"
wlog.FindFirst Criteria
wlog.Close
End Sub
It doesn't seem to register the form at all it keeps saying it can't be found.
can anyone help point me in the right direction?
It should read:
Dim wlog As DAO.Recordset
Dim Criteria As String
Set wlog = Me!<NameOfTheSubformCONTROL>.RecordsetClone
If wlog.RecordCount > 0 Then
Criteria = "[weblog_number]='" & [weblogSearch] & "'"
wlog.FindFirst Criteria
If wlog.NoMatch = False
' Found.
Else
' Not found.
End If
End If
wlog.Close
Replace <NameOfTheSubformCONTROL> with that, not the name of the subform.
I have an unbound textbox in form f_FeuilleBleue. In my code, I give it a certain value;
Debug.Print strAHNS '00 0AA 00-100 F TX-01
Form_f_FeuilleBleue.txt_AHNS = strAHNS
If I put a stopping point on the next line, the immediate window shows that
?Form_f_FeuilleBleue.txt_AHNS
answer: 00 0AA 00-100 F TX-01
However, I still see it as blank in my form. There is no data to be read!
How do I fix this? Is it an issue with screen updating? (I have nothing setting it to off) Maybe form updating? (I have a msgBox in the BeforeUpdate event but it doesn't go in that event)
EDIT - additional info:
When I open the form, there is no problem. I can change the value in the form or by code. However the issue only happens when the form is opened from a menu-style form. Code below. Even after the opening sub finishes, the textbox won't update (visually - it does in value). After testing I see that the Change and the Update event are NOT launched when changing the value of the textbox from another sub (Private subs may be the cause?) But why is it continuing to not show the values even after the subs end?
Could be very, very relevant to read but I'm not sure what to make of it: Obtaining textbox value in change event handler
Here is the code that opens the form:
Private Sub Command7_Click()
Dim strAHNS As String
Dim strquery As String
strAHNS = Replace(Mid(Me.Combo_Dessin2, InStr(Me.Combo_Dessin2, "=") + 1), "=", " ")
strquery = "[ID] = (SELECT Max([ID]) FROM [Feuilles])"
Debug.Print strquery
If (PremierAffichage) Then
DoCmd.OpenForm FormName:="f_feuillebleue", WhereCondition:=strquery
Else
MsgBox "Le projet ou dessin n'a pas été trouvé."
End If
End Sub
Function PremierAffichage() As Boolean
Dim rsFeuilles As DAO.Recordset
Dim rsProjets As DAO.Recordset
Dim strContrat As String
Dim strProjet As String
Dim strDessin As String
Dim sqlquery As String
Dim strAHNS As String
Dim strGroupe As String
Dim strMachine As String
If IsNull(Me.Combo_Dessin2) Or IsNull(Me.Combo_Projet) Or Me.Combo_Dessin2.Value = "" Then
PremierAffichage = False
Exit Function
End If
strProjet = Me.Combo_Projet
strAHNS = Me.Combo_Dessin2
strMachine = Mid(strAHNS, 4, 3)
strGroupe = Mid(strAHNS, 8, 2)
Debug.Print strProjet & " ** " & strAHNS & " ** " & strMachine & " ** " & strGroupe
sqlquery = "SELECT [AHNS], [Contrat], [No Projet], [EP (groupe)], [Type machine], [Mois] FROM [Feuilles]" 'WHERE [AHNS] = '" & strAHNS & "'"
Set rsFeuilles = CurrentDb.OpenRecordset(sqlquery)
sqlquery = "SELECT [Projet HNA] FROM [Projets] WHERE [Projet AHNS] = '" & strProjet & "'"
Set rsProjets = CurrentDb.OpenRecordset(sqlquery)
Debug.Print strAHNS '========================================--------
Form_f_FeuilleBleue.txt_AHNS = strAHNS ' this works in .value but not showing the result
DoEvents ' any changes from there on don't update the value visually
' ==========================================------
If rsProjets.RecordCount > 0 Then
rsFeuilles.AddNew
rsFeuilles![Contrat] = rsProjets![Projet HNA]
rsFeuilles![No Projet] = strProjet
rsFeuilles![AHNS] = strAHNS
rsFeuilles![Mois] = MonthName(Mid(Date, 6, 2))
If strMachine Like "[A-Z][A-Z][A-Z]" Then
rsFeuilles![Type machine] = strMachine
rsFeuilles![EP (groupe)] = strGroupe
End If
rsFeuilles.Update
PremierAffichage = True
End If
rsProjets.Close
Set rsProjets = Nothing
rsFeuilles.Close
Set rsFeuilles = Nothing
End Function
Assign your value to the active form instance (the open form) instead of to the form's class.
So assuming the open form's name is f_FeuilleBleue and you want to assign that value to the form's txt_AHNS control ...
'Form_f_FeuilleBleue.txt_AHNS = strAHNS
Forms!f_FeuilleBleue!txt_AHNS = strAHNS
Reference the form by its name as a member of the Forms collection.
I'm having a problem in which I can't requery a subform inside of a form in Access.
The form's name is frmSearch
The subform's name is SearchResults
I've tried
Private Sub Command38_Click()
Me!SearchResults.Form.Requery (or)
Me.SearchResults.Form.Requery
End Sub
My form & subform look like this:
To be clear, I'm using the "Search" button to create a string which contains the textbox and combobox values. This string creates a SQL query called qryTrialQuery. Then my subform makes a query of the qryTrialQuery and produces the results in the table bellow.
I would like to be able to press the search button and then the results appear below it immediately after. The problem is, is that the results don't appear unless I close and reopen the form.
Thanks for all your help in advance.
Update
The following is the code I used to create a query from the textbox and combobox values.
LineOne = "SELECT tblPoolPersonnel.LName, tblPoolPersonnel.FName, tblPoolPersonnel.[Tel Natel], tblPoolPersonnel.[Tel Home], tblPoolPersonnel.Email" & vbCrLf
LineTwo = "FROM (tblPoolPersonnel INNER JOIN tblDayAvailable ON tblPoolPersonnel.Code_Personal = tblDayAvailable.Code_Personal) INNER JOIN tblServiceYES ON tblPoolPersonnel.Code_Personal = tblServiceYES.Code_Personal" & vbCrLf
LineThree = "WHERE (((tblServiceYES.Service)=" & comboService & ") AND ((tblDayAvailable.Availability)=True) AND ((tblDayAvailable.Date)=" & txtDate & ") AND ((tblDayAvailable.CodeHoraire1)=" & comboCodeHoraire & "));"
Set qdf = CurrentDb.QueryDefs("myQuery")
Application.RefreshDatabaseWindow
strSQL = LineOne & LineTwo & LineThree
qdf.SQL = strSQL
qdf.Close
Set qdf = Nothing
Set dbs = Nothing
Assuming you are reconstructing the SQL of your query based on the criteria the user selected, you should just be able to do something like this:
Private Sub Command38_Click()
Dim qryTrialQuery as String
...
' code to construct the SQL SELECT statement for the query, '
' based on the criteria the user entered '
...
SubForm.Form.RecordSource = qryTrialQuery
End Sub
Setting the Subform's RecordSource will refresh the data.
You can try this:
Dim frm as Form
Set frm = frmSearch
frmSearch!SearchResults.Form.Requery
I trust you're all well. I would like to know what I'm doing wrong and how to fix it. My intent with the code below is the query my MySQL database and display one column of the table inside a ComboBox. Then, when that value in the ComboBox is selected, I want all the records associated to be populated into other controls on my form (I'll create a separate question for this part).
Right now, the query is working but the ComboBox isn't being populated. What am I doing wrong? Please help, thanks.
HERE'S MY CODE:
Private Sub RetrieveMySQLdata()
Try
Dim dbConn As New MySqlConnection
Dim dbQuery As String = ""
Dim dbCmd As New MySqlCommand
Dim dbAdapter As New MySqlDataAdapter
Dim dbTable As New DataTable
If dbConn.State = ConnectionState.Closed Then
dbConn.ConnectionString = String.Format("Server={0};Port={1};Uid={2};Password={3};Database=accounting", FormLogin.ComboBoxServerIP.SelectedItem, My.Settings.DB_Port, My.Settings.DB_UserID, My.Settings.DB_Password)
dbConn.Open()
End If
dbQuery = "SELECT *" & _
"FROM cc_master INNER JOIN customer ON customer.accountNumber = cc_master.customer_accountNumber " & _
"WHERE customer.accountNumber = '" & TextBoxAccount.Text & "'"
With dbCmd
.CommandText = dbQuery
.Connection = dbConn
End With
With dbAdapter
.SelectCommand = dbCmd
.Fill(dbtable)
End With
Dim i As Integer
For i = 0 To dbTable.Rows.Count - 1
ComboBoxCard.ValueMember = "ccNumber"
Next
Catch ex As Exception
MessageBox.Show("A DATABASE ERROR HAS OCCURED" & vbCrLf & vbCrLf & ex.Message & vbCrLf & _
vbCrLf + "Please report this to the IT/Systems Helpdesk at Ext 131.")
End Try
End Sub
Where are you trying to populate the ComboBox? The only interaction I see is here:
For i = 0 To dbTable.Rows.Count - 1
ComboBoxCard.ValueMember = "ccNumber"
Next
Which I'm guessing isn't doing what you think it's doing. For one thing, you're setting ValueMember to the same value multiple times in a loop. Nothing in the statement changes with each iteration of the loop, so why loop it?
More specifically, ValueMember isn't actually any kind of displayed value. It's used to indicate which field in the bound data should contain the value. This is used when you provide a DataSource for the control, which you're missing.
I'll assume the DataSource should be dbTable, so you're probably looking to do something like this:
ComboBoxCard.DataSource = dbTable
ComboBoxCard.ValueMember = "ccNumber"
ComboBoxCard.DisplayMember = "Some Other Field in the database"
I don't remember if you need to explicitly call .DataBind() on the control after these statements, but the example I linked to doesn't do it so I'll leave it out.
Essentially what you're trying to do in your code is loop through the results and add them to the ComboBox. You don't need to do this. The ComboBox is capable of doing this internally if you just point its DataSource to the set of data being used and tell it which fields it needs to use on that set. This is called data binding.
It looks like you aren't setting the DataSource for the ComboBox object. Instead of this code:
Dim i As Integer
For i = 0 To dbTable.Rows.Count - 1
ComboBoxCard.ValueMember = "ccNumber"
Next
Use something like this code:
ComboBoxCard.DataSource = dbTable
ComboBoxCard.ValueMember = "ccNumber"
ComboBoxCard.DisplayMember = "(some other column if you want)"