I have recently started using Access with VBA.
Problem Statement : There are 4 optional subjects say Maths,Economics,Computer Science,Home Science. A column called 'Subject' for each student stores the optional subjects(the number of subjects varies with each student).
What I did : I made a multi-valued field in the table called 'Subject' using the lookup wizard in design view. In the form view, I have these 4 checkboxes listed to select and submit . When I try writing an update statement for field 'Subject' using the checkbox values it gives me an error.
Is there some other way to solve this problem or can I correct the method I have used?
Thanks !
Create a new table with 2 fields; Student ID and Subject. Write all subjects into that table. When you need to return them, either use a subform (linked on StudentID) or create a pivot table if necessary.
Multi-Value columns are not optimal, they create a lot of problems. If you absolutely must use one, then you need to parse the data when you extract it. When you first write it, you need to write a statement like;
MyStr = ""
If Me.Checkbox1 = True then
MyStr = MyStr & "SomeValue, "
EndIf
If Me.Checkbox2 = True then
MyStr = MyStr & "SomeValue2, "
EndIf
If Me.Checkbox3 = True then
MyStr = MyStr & "SomeValue3, "
EndIf
If Me.Checkbox4 = True then
MyStr = "SomeValue4, "
EndIf
If Len(MyStr) > 2 Then
MyStr = Left(MyStr, Len(MyStr) - 2)
EndIF
What this does is continually append the values you assign to the checkboxes, and then removes the last 2 characters (which should be ", ") so you have a complete string. Then you write MyStr to your Subject field.
When you go to read this info, you'll need to parse it out into an array and work backwards, determining which checkbox should be marked based on the values in your array.
Related
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.
I have two tables.
1.Test_Cap_Model1
2.Router
I have one report: ReportYield
In this report I made one control text box that contains code sql statement as below
This code will generate route value from router table if model value in report (its from query that generate from test_cap_model1 table) contain in router.[testmodel].
I tried to do in query but my problem is value of model in test_cap_model1 table are not the same in test model in router table. As example
Model value in test_cap table = 1471D3BTL-Non HW
but
Test Model Value in Router table = 1471D3BTL
Use DLookup for such tasks, and the Value property:
Private Sub Text10_Click()
Me!Text10.Value = DLookup("[Route]", "[Router]", "[Model] Like '" & Me!Model.Value & "*'")
' or:
' Me!Text10.Value = DLookup("[Route]", "[Router]", "[Model] Like '" & Me!Model.Value & "%'")
End Sub
There is nothing to requery. And do change your control names to something meaningful.
I am using MS-Access to get information from 2 tables. I have used inner join, left, right, and outer with all variations, and it will either pull 1 row when 316 are expected, all data for the fields in test with no values for the fields from test 1, or all data for fields from test 1, and no values for test. How do I resolve this? The actual fields had to be changed for privacy, but the below is the exact layout.
SELECT [TEST].a,
[TEST].b,
[TEST].c,
[TEST 1].[D],
[TEST].E,
[TEST].F,
[TEST].G,
[TEST].H,
[TEST 1].[I],
[TEST].J,
[TEST].K,
[TEST 1].L,
[TEST 1].[M]
FROM [TEST 1]
INNER JOIN [TEST] ON [TEST 1].[ID] = [TEST].[CLAIMSNO];
This is a data-validation and debugging exercise, so if you can't share concrete example data then there is really no definite answer to this question. Technically it may not be answerable according to common StackOverflow standards, but I feel generous right now.
Since the joined fields are text, there are various possibilities keeping them from matching: extra spaces, null-terminated strings, case sensitivity (although Access by default should be case insensitive), wide (Unicode) vs narrow (ASCII, UTF-8) encoding, etc. You did not reveal where the data came from, nor how it was loaded into the database, so I make no assumptions. In order to understand the data and determine the reason for the failed matches, you need to investigate the details of the strings. You could likely narrow the problem by investigating the source of the data values and understanding the range of possible characters, encoding, string termination, etc.
Since you are already having troubles matching data AND since you already indicated that the original tables had no primary key or indexes, I highly recommend adding a new AutoNumber field with a unique index to each table, perhaps named [AID] (for AutoNumber ID). Do this even if you have added indices to existing columns. This will at least provide a reliable "handle" to select and refer to a particular row while debugging the other columns.
The big idea is to use VBA or other built-in functions to inspect and report on various attributes of the string values. There are just too many ways you could do this, but my preference is to create a public VBA function in a normal VBA module and then call this function from an SQL query. Although you could do this for every row, instead I suggest manually choosing rows from each table which you think should match... record the [AID] value for each row. If the manually-selected rows don't result in anything enlightening, then run it against an entire table and see what interesting results you get.
Consider these functions:
Public Function CheckSpaces(val As Variant) As String
Dim result As String
If IsNull(val) Then
result = "Null"
ElseIf VarType(val) = VbVarType.vbString Then
If Len(val) = 0 Then
result = "Empty String"
Else
Dim temp As String
Dim n As Integer, m As Integer
n = Len(val)
result = "Length " & n
temp = LTrim(val)
m = Len(temp)
If n <> m Then
result = result & " AND " & (n - m) & " left spaces"
End If
temp = RTrim(val)
m = Len(temp)
If n <> m Then
result = result & " AND " & (n - m) & " right spaces"
End If
End If
Else
result = "Not a string!"
End If
CheckSpaces = result
End Function
Public Function NullChar(val As Variant) As Boolean
Dim result As Boolean
result = False
If Not IsNull(val) Then
If VarType(val) = VbVarType.vbString Then
If InStr(val, vbNullChar) > 0 Then 'vbNullChar = Chr(0)
result = True
End If
End If
End If
NullChar = result
End Function
And execute queries similar to the following. Let's say that [Test 1] row AID = 10 has [ID] == 'name'. Likewise, imagine row AID == 20 of [Test] has [CLAIMSNO] = ' name ':
SELECT [ID], CheckSpaces([ID]), NullChar([ID])
FROM [TEST 1]
WHERE [AID] = 10
and
SELECT [CLAIMSNO], CheckSpaces([CLAIMSNO]), NullChar([CLAIMSNO])
FROM [TEST]
WHERE [AID] = 20
Compare the returned values. Is there anything that indicates a failed match?
I'm trying to figure out a solution on how to concatenate strings from about 15 different options. Each result comes from a checkbox that is selected based on the state a person has lived in within a certain area.
I know how to turn the checkbox option into a text result. What I'm looking for is how to take these text results, combine them, then ignore null results so there isn't any weird spacing or formatting.
In short, if someone select 3 of the 15 results it would combine the 3 results cleanly and ignore the rest. Example would be: FL, CA, NY
There are, of course, multiple ways that this can be achieved, and since you didn't provide any code or examples of how you are attempting to do this, I will provide two options.
1 - You can concatenate the values using a combination of the & and + operators.
For example, let's say you have 15 checkboxes, all named similarly like chkState01, chkState02 ... through chkState15. And for the simplicity of my sample code, let's assume that when referencing the checkbox control directly in code as chkState01 that it will return either the 2 letter string abbreviation of the State it represents (i.e. NY) if the checkbox was checked, or it will return Null if the checkbox was not checked. With that, you could get your results in 2 ways:
Option A
StateList = (chkState01 + ",") & (chkState02 + ",") & (chkState03 + ",") ....
If those 3 check boxes returned the following values
chkState01 = "NY"
chkState02 = Null
chkState03 = "FL"
Then the result of that concatenation code would be:
NY,FL,
Notice that the string ends with an extra comma (,) and always would since you can't know ahead of time how many of the checkboxes will be checked. You would then need to trim that comma from your list before using it most likely.
Option B
'Create the list with a trailing comma that will need removed
Dim x as Integer
For x = 1 to 15
StateList = StateList & (Me("chkState" & Format(x, "00")) + ",")
Next x
or, you could do:
'Create the list without a trailing comma
Dim x as Integer
For x = 1 to 15
If Not IsNull(Me("chkState" & Format(x, "00"))) Then
If Len(StateList) > 0 Then
StateList = StateList & "," & Me("chkState" & Format(x, "00"))
Else
StateList = Me("chkState" & Format(x, "00"))
End If
End If
Next x
Notice that you can reference a control on a form by "generating" the name of that control as a string and referencing it in the Me("yourcontrolname") format. This is one advantage to naming controls that are similar in a fashion that lends itself to a looping structure like this. The Format command formats the number returned by x as a 2 digit with leading zeros i.e. 1 becomes 01
Further, using & to concatenate two items, where at least one of them is a string, will always result in a string output (Null & "S" = "S"). However, using the + to concatenate two items, where at least one of them is a Null, will always result in Null output (Null + "S" = Null). Hence the checkboxes where the value returns Null does not cause additional commas to be included in the result.
2 - You can write more complicated code to dynamically loop through the checkboxes and build the output list.
More likely, you are going to need to use additional code to determine which checkbox is which state abbreviation and to return the correct string value. Maybe you made the state abbreviation part of the checkbox name i.e. chkState_NY, chkState_FL or maybe you have put the abbreviation in the Tag property of each checkbox.
Let's say you used special control naming chkState_NY, chkState_FL. You could do the following:
Dim ctl as Access.Control
For Each ctl in Me.Controls
If ctl.Name Like "chkState_??" Then
If ctl.Value = True Then
If Len(StateList) > 0 Then
StateList = StateList & "," & Right(ctl.Name,2)
Else
StateList = Right(ctl.Name,2)
End If
End If
End If
Next ctl
My situation is
I have a parameter, this is a list, allowing multi values. That mean the first record in the list is 'Select All'
When user select All I need to include in my report all records that match with the list plus those that are blank. (My dataset is returning these)
When user select only 1 or a few I want to include only these records. No those that are blank
My problem:
I have a filter in my dataset that evaluate a parameter in a list, but I need to add a conditional filter to include a blank records when the selection will be "Select All"
I tried to use expression but this doesn't work
Filter expression
Fields!NAME.Value in = Parameters!List.Value !!!!!!!!!!!! Work Fine
But I need to change it like as
If Parameters!List.Value = 'Select All' Then
Fields!NAME.Value in = Parameters!List.Value or Fields!NAME.Value = " "
Else
Fields!NAME.Value in = Parameters!List.Value
End
Can you give an advice who can I resolve it please !!!
I'm working in SSRS R2
Thanks!!
This worked for me
Expression: =IIF(Parameters!pLocation.Value <> " All Locations", Fields!LOCATION.Value, FALSE)
Operator: =
Value: =IIF(Parameters!pLocation.Value <> " All Locations", Parameters!pLocation.Value, FALSE)
If you use Filter on your Dataset, try this:
Expression: [NAME]
Operator: IN
Value (fx): =Split(Replace(Join(Parameters!List.Value, ","), "Select All", " "), ",")
Try to work along this path. Basically you can reconstruct the multi value items into a string with Join(), and deconstruct it again into array by using Split(); where in between, you can manipulate them, for modifying (e.g. converting "Select All" into " "), adding (imitating "OR"), or removing extra items.
There is an alternative for this.
Add one more item to the paramater dataset values say "Not Available" as Label and value with the null. then there will be no change in the stored procedure and you can retrieve the data.
If the user select the specific item then he will get those values only. If he selects all then he will get the data for the null also with the all the others.
Hope this will help
You can put the logic in just one location if you do it this way.
You filter on the parameter, unless it's all values then the filter always matches.
Just a little cleaner.
Expression: =IIF(Parameters!pLocation.Value <> " All Locations", Fields!LOCATION.Value, " All Locations")
Operator: =
Value: =Parameters!pLocation.Value