Filtering Information in A Report Using VBA-Access - Finding the next avaliable null field - ms-access

I'm trying to organize information in a report in a certain way
I have 9 fields that will be used to store the label for the information
and another 9 fields that store the actual value of the information.
Whenever a field is full, I want it to place the information in the next available field. So that there will be no blank fields in between information.
The issue is that when trying to run this code which triggers two functions, it is not updating the report I referenced to in the two functions, nor is it pulling information from SpecSheetQuery, and I can't figure out why. My guess is that I'm not referencing the information correctly. I also have to figure out how to run this code individually on each record.
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
Servings = DLookup("[servings]", "SpecSheetQuery")
Calories = DLookup("[calories]", "SpecSheetQuery")
If Not IsEmpty(Servings) Then
OpenSlot ("Servings")
OpenFact (Servings)
End If
If Not IsEmpty(Calories) Then
OpenSlot ("Calories")
OpenFact (Calories)
End If
End Sub
OpenSlot function, puts title/label of information into field1 ( which is a field on the report) on the first null/empty field. so that no space is left blank.
Option Compare Database
Option Explicit
Public Function OpenSlot(Slot As String)
Debug.Print Reports!SpecSheet!field1.Value
If Reports!SpecSheet!field1.Value = Null Then
Debug.Print "Slot1"
Slot = Reports!SpecSheet!field1.Value
Debug.Print Reports!SpecSheet!field1.Value
ElseIf Reports!SpecSheet!field2.Value = Null Then
Reports!SpecSheet!field2.Value = Slot
End If
End Function
OpenFact function, puts fact into nut1 ( which is a field on the report) on the first null/empty field. so that no space is left blank.
Public Function OpenFact(fact As String)
If Reports!SpecSheet!nut1.Value = Null Then
Reports!SpecSheet!nut1.Value = fact
Debug.Print Reports!SpecSheet!nut1.Value
ElseIf Reports!SpecSheet!nut2.Value = Null Then
Reports!SpecSheet!nut2.Value = fact
End If
End Function
I'm trying to store this information into this report.
Any help would be greatly appreciated.

Related

Junction between categories

I am making a database for a freelance sign language interpreter. I have a subject table tblClient which holds information regarding the freelancer's clients. There is a lookup table tlkClientClientType showing the various types of clients (categorized on condition -- deaf, deaf/blind, etc). There is also a table called tlkClientModality. In this table are the different types of sign language offered by the interpreter. You can pick the client's preferred modality from the Client table.
Now the tricky part. There are certain modalities (basically just flavors of sign language) that should not be available to pick if the client is a certain type. For example, you cannot use "regular" (visual) sign language with someone who is deaf/blind. This is because regular sign language depends on the person being able to see. Instead, one would use "Tactile ASL" which is a hand-over-hand version of sign language. Basically, I want to limit the modality list based on the client type picked.
To start off my associations, I am making a junction table between the tlkClientClientType and tlkClientModality tables. Here, I will create the correct allowable pairs of client types and modalities. In addition, there is not really a necessary "junction field" to justify this relationship. I am considering making a "dummy field" as a way to still justify such a relationship.
Later, in a form for the client, I will edit the row source query on the modality combo box to be dependent on the choice selected in the client type box. This would be accomplished by checking what records in the junction table match the choice in the client type combo box.
Am I on the right track here? Making a junction table between two lookup tables seems weird. Is there anything wrong with it?
Note -- I would like to stay away from VBA, but I am up to writing macros to accomplish these goals. Any thoughts would be appreciated.
A photo of the relationships is given below.
Relationshipsphoto
Keep your tables in whatever normal form works for your business case. Your choice just changes how the information is stored which means you have to change how you write your queries as the information may be located in a different place. I chose a many to many relationship between client and clienttype.
You want to set the modality combobox contents from the client combobox. This is a problem of the view not the model hence we change the view and not the organization of the data. the key is to set the recordsource of the modality combobox from the afterupdate event of the client combobox.
Showing the results first: if the client is deaf we get:
if the client is blind or blind and deaf we get:
Private Sub cmbClient_AfterUpdate()
Dim RegularASL As Integer: RegularASL = 1
Dim TactileASL As Integer: TactileASL = 2
Dim ClientID As Integer: ClientID = Me.cmbClient
If ClientisBlindandDeaf(ClientID) Then
cmbModality.RowSource = "SELECT * FROM tlkClientModality WHERE ClientModalityID = " & TactileASL
ElseIf isClientBlind(ClientID) Then
cmbModality.RowSource = "SELECT * FROM tlkClientModality WHERE ClientModalityID = " & TactileASL
Else
cmbModality.RowSource = "SELECT * FROM tlkClientModality WHERE ClientModalityID = " & RegularASL
End If
cmbModality.Requery 'reload cmbmodality data
Me.Refresh 'repaint cmbmodality
End Sub
Public Function isClientBlind(ClientID As Integer) As Boolean
'Get rid of * in names vba can't parse the *
Dim isblind: isblind = 2
Dim ClientClientTypeID As Variant 'allows null return type
ClientClientTypeID = DLookup("ClientClientTypeID", "tlkClientClientType", "ClientID = " & ClientID & " AND ClientTypeID = " & isblind)
If IsNull(ClientClientTypeID) Then
isClientBlind = False
Else
isClientBlind = True
End If
End Function
Public Function isClientDeaf(ClientID As Integer) As Boolean
Dim isdeaf: isdeaf = 1
Dim ClientClientTypeID As Variant 'allows null return type
ClientClientTypeID = DLookup("ClientClientTypeID", "tlkClientClientType", "ClientID = " & ClientID & " AND ClientTypeID = " & isdeaf)
If IsNull(ClientClientTypeID) Then
isClientDeaf = False
Else
isClientDeaf = True
End If
End Function
Public Function ClientisBlindandDeaf(ClientID As Integer) As Boolean
If isClientBlind(ClientID) And isClientDeaf(ClientID) Then
ClientisBlindandDeaf = True
Else
ClientisBlindandDeaf = False
End If
End Function
note: cmbModality is set up just like it is bound to the entire tlkModality table then the record source changes are used to filter it in effect.

How to display number values with commas in form

In my Access query, I have the query using a VBA function to figure the value that goes in the query field.
In the form, if the stringval textbox has a value, then I want to compute it, but if not, it should remain empty (null).
Function GetValue(stringval, numval)
Dim result
stringval= stringval & ""
result= IIf(stringval<> "", numval* 1.5, Null)
GetValue = Int(result)
End Function
Now, I have a form that uses this query, and on the form is a textbox that displays the query value. I want the value to be formatted with commas in the numbers for easy reading. Everything I've tried so far does not show any commas.
I've tried:
used Standard for the Format > Formatfor the textbox (in properties)
putting #,###.### in the textbox Format value
putting #,##0.0## in the textbox Format value
changing Data > Text Format but it only gives me Plain Text and Rich Text - no option for numbers.
returning a double from the function
Note: if I don't use a custom VBA function, and write the formula directly into the query, then it does display commas. But when I move the formula into the function then the commas are lost.
What do I do?
[update]
I tried Gustav's solutions and since they didn't work for me, I added those as items to my "what I've tried" list above.
Also, if I look at the query in datasheet view, the number values sort alphabetically instead of by the size of the value. When I used the forumulae directly in the query instead of using functions, it sorted by the value of the number. I hope this is a clue.
Numbers carries no format. A format is applied when displayed only.
But be sure to return a Double if not Null:
Function GetValue(stringval, numval)
Dim result
If stringval & "" <> "" Then
result = Int(CDbl(numval) * 1.5)
Else
result = Null
End If
GetValue = result
End Function
Then apply your Format to the textbox
#,##0.0##
Or force a formatted string to be returned:
If stringval & "" <> "" Then
result = Format(Int(CDbl(numval) * 1.5), "#,##0.0##")
Else
result = Null
End If
and skip formatting of the textbox.
The solution is this: the function has to be declared as a double.
That allows the query's datasheet view to know it is displaying numbers - and so you can set the field's format to Standard for the comma to display. This also allows the form to know it has a number and it will display the comma there, too. I knew it had to do with double, but didn't realize before that the function needed to be declared as such.
Function GetValue(stringval, numval) as double '<----THIS!!!!
Dim result
If stringval & "" <> "" Then
result = numval * 1.5
Else
result = 0 `<--can't return null here; use nz function in control source for textbox
End If
GetValue = int(result) 'to remove decimals
End Function
The problem I was having was in some of my functions I need to return double or null, because I wanted textboxes to remain blank if they contained no data. Now, at least I know how to make the numbers generated by functions to display commas.
And here is how to deal with the fact that you can't return null as the value of a double. The function is originally from here.
Put this function in a module so it is public, and then in the control source for the textbox, instead of just putting the field value, put Zn(fieldvalue). This works like a charm (although using functions in the control source seems to have a delay on the form display). This way you can keep the underlying value as a double and still get commas to display in both the form and the query whilst keeping the field blank if necessary.
Public Function Zn(pvar)
' Return null if input is zero or ""
If IsNull(pvar) Then
Zn = Null
ElseIf IsNumeric(pvar) Then
If pvar = 0 Then
Zn = Null
Else
Zn = pvar
End If
Else
If Len(pvar) = 0 Then
Zn = Null
Else
Zn = pvar
End If
End If
End Function

Access Combobox Not In List Event Not finding Added Record

I'm trying to add a record to a ComboxBox source when the entered item isn't in the list.
The code correctly creates the record and then returns Response = acDataErrAdded but still displays the error Item not in list. And if I then manually scroll down the list the new user record is there!
tblUsers
ID(Auto Number), UserCode(Text), UserName(Text)
1, ID00001, "Tom Jones"
2, ID00007, "Fred Smith"
cmbUsers
RowSource = SELECT UserCode, UserName, ID FROM tblUsers
Bound Column = 3
Column Count = 3
Column Widths = "2cm;4cm;2cm"
Input Mask "ID00000;;_"
Private Sub cmbUsers_NotInList(NewData as string, Response as integer)
dim sUserCode as string
sUserCode = "ID" & NewData ' Doesn't have the "ID" ?!?!?
if ActiveDirectoryUserIDExists(sUserCode) then
AddNewUserFromActiveDirectory sUserCode
Response = acDataErrAdded
exit sub
end if
Response = acDataErrDisplay
End Sub
When NotInList is entered the NewData value is 00001 and is not prepended with the input mask "ID".
So I suspect that when the NotInList sub returns Access is using NewData value that is not prepended with "ID" so never finds the value is the re-queried list!
I have tried setting the NewData value to "ID" & NewData before exiting but this did not work.
So I'm really not sure!
Any ideas on how I can get this to work?
InputMask details
The docs for InputMask property say this regarding the second section for InputMask property:
If you use 0 for this section, all literal display characters (for example, the parentheses in a phone number input mask) are stored with the value; if you enter 1 or leave this section blank, only characters typed into the control are stored.
Example:
Input Mask: "ID"00000;0;_
This should cause the entire text value, e.g. "ID00001", to be passed to NotInList event handler in the NewData parameter.
Buggy InputMask behavior for bound ComboBox control
After extensive testing, it seems that this only works flawlessly for an unbound control. If the datatype of the column in the Control Source property does not support saving the fully formatted text value, then the text input value will be formatted to be compatible with (i.e. match) the bound field datatype even though the displayed text is not what is actually saved in the field. This is the best description I could come up with and I could not find any direct resolution to this bug.
So if the bound column is of text type (e.g. Short Text) then there is no problem. But as in the original question where the bound field is a foreign key column of Long Integer type (Control Source: [Assigned User]; Bound Column: 3; Row Source has [ID] as third column), then the input value is converted to a numerical string value before being passed to NotInList.
Workaround
This preserves the desired behavior of the ComboBox and InputMask with minimal code and one extra hidden TextBox control.
Add a simple bound TextBox control for the numeric foreign key field with the following properties:
Control Name: [Foreign_Key_Column_Name]
Control Source: [Foreign_Key_Column_Name]
Visible: False
Add unbound ComboBox control setup with InputMask property and NotInList event handler:
Control Name: [X_Foreign_Key_Column_Name]
Control Source: < Blank / null >
InputMask: "ID"00000;0;_
Row Source: SELECT UserCode, UserName, ID FROM tblUsers
Bound Column: 3 (this is not the same as the Control Source property binding to the form record source and apparently not what causes the buggy behavior)
Add NotInList event handler to unbound control with same code as before.
Private Sub X_Foreign_Key_Column_Name_NotInList(NewData as string, Response as integer)
dim sUserCode as string
sUserCode = NewData
if ActiveDirectoryUserIDExists(sUserCode) then
AddNewUserFromActiveDirectory sUserCode
Response = acDataErrAdded
Else
Response = acDataErrDisplay
end if
End Sub
Add the following code to manually bind the ComboBox value to the numeric foreign-key column.
Private Sub Form_Current()
Me.X_Foreign_Key_Column_Name.Value = Me.Foreign_Key_Column_Name.Value
End Sub
Private Sub X_Foreign_Key_Column_Name_AfterUpdate()
Me.Foreign_Key_Column_Name.Value = Me.X_Foreign_Key_Column_Name.Value
End Sub

Convert values from Access Combo Box to string

I need to convert the values from combo box to a string so I can add that string to a variable, to a function to eventually add to a database.
Here is my sub that grabs text from my form and from the combo box:
Private Sub cbRowStudentGrade_Change()
Course_ID.SetFocus
rowCourseID = Course_ID.Text
StuRed_ID.SetFocus
rowStudentRedID = StuRed_ID.Text
cbRowStudentGrade.SetFocus
cbRowStudentGrade = cbRowStudentGrade.Column(0)
CurrentDb.Execute "qryInputGrades"
MsgBox (rowCourseID)
MsgBox (rowStudentRedID)
MsgBox (cbRowStudentGrade)
Requery
Repaint
End Sub
And here are the functions that I am using as criteria in my Access query builder.
Public Function funcRowCourseID() As String
funcRowCourseID = rowCourseID
End Function
Public Function funcRowStudentRedID() As String
funcRowStudentRedID = rowStudentRedID
End Function
Public Function funcCbRowStudentGrade() As String
funcCbRowStudentGrade = cbRowStudentGrade
End Function
My query:
INSERT INTO tblRegistrationGrade ( Red_ID, Course_ID, Grade )
VALUES (funcRowStudentRedID(), funcRowCourseID(), funcCbRowStudentGrade());
I think there is a datatype mismatch between the database and what the combobox value actually is. But, if there were a datatype mismatch wouldn't there be an error stating as such? My database requires short text, which these are.
You're doing this way too complicated.
You can directly refer from your INSERT query to the form controls:
INSERT INTO tblRegistrationGrade ( Red_ID, Course_ID, Grade )
VALUES (Forms!myForm!StuRed_ID, Forms!myForm!Course_ID, Forms!myForm!cbRowStudentGrade);
and get rid of almost all of the code, except calling the query.
As John wrote, it would be better placed in cbRowStudentGrade_AfterUpdate().
Or, instead of the INSERT query, use a DAO.Recordset with AddNew, see:
How to: Add a Record to a DAO Recordset
There you can also directly use the values from your from controls without worrying about data types.

Access VBA Combo Box Reference

I am running into a snag on the code below. When the code runs, values are being placed on "tblPrepayments", with the exception of the AccountID value. The me.cboAccountID.column(2) is on "frmInvoices", which pulls in the AccountID, but displays a clients name for usability reasons.
I don't get any errors, but the value is not pulling into "tblPrepayments". What am I missing? Please let me know if you need additional clarification.
If [Rec'd_Prepayments] <> "0.00" And [Prepayment_Month] <> "" Or [Prepayment_Year] <> "" Then
Dim RecSet As Recordset
Set RecSet = CurrentDb.OpenRecordset("tblPrePayments")
RecSet.AddNew
RecSet![AccountID] = me.cboAccountID.column(2)
RecSet![Prepayment_Month] = "Billing_Month"
RecSet![Prepayment_Year] = "Billing_Year"
RecSet![Rec'd_Prepayment] = "Prepayment1"
RecSet.Update
End If
End Sub
If I run MsgBox me.cboAccountID.column(2), I get a run time error '94': Invalid use of Null. If I change the code to Msgbox me.cboAccountID.column(1), I get the client's name, not the ID, and subsequently an error for mismatched data types.
Here is the row source for cboAccountID.
SELECT tblClientLists.[AccountID], [tblClientLists].Invoice_To
FROM tblClientLists
ORDER BY [Invoice_To];
combobox values are 0 based, so you're looking for Me.cboAccountID.column(0) or Me.cboAccountID.Value should also work here.