I have 6 checked boxes with more than 10 values each in my Visual Basic project using Visual Studio.
I would like to insert the values of the checked box into one table, all values of checked box into one cell (if possible).
For example, I have table called Food that has user id, Fruits, Vegetables, and Snacks.
Assuming that I have 3 checked boxes as well, I want to have all Fruits checked in Fruit column as it represents one person.
I started my code like this:
sql = "INSERT INTO Food (id, Fruits, Vegetables, Snacks) VALUES ('" & txtIDR.Text & "','" & CheckedFruits.CheckedItems.ToString & "','" & CheckedVegetables.CheckedItems.ToString & "','" & CheckedSnacks.CheckedItems.ToString & "','" & ")"
I didn't got an error messages but I'm afraid that I did something wrong with the way I handled the checked list box.
Please advise.
Edit: Sorry didn't see it was CheckListBox
to access a property of the CheckListBox you should use:
CheckedListBox1.CheckedItems.Item(0)
Where 0 is your item index
However you need to remember that CheckedItems.Item will only exist if something is checked if you try to call CheckedListBox1.CheckedItems.Item(0) but nothing is checked you will get Index out of bounds
An easy way to get all checked values easily is with a For Each:
For Each check In CheckedListBox1.CheckedItems
Debug.WriteLine(check)
Next
You could have something like this:
Public Function CreateSQL() As SqlCommand
Dim Fruits As String = ""
Dim Vegetables As String = ""
Dim Snacks As String = ""
For Each check In CheckedFruits.CheckedItems
Fruits = Fruits & check & ","
Next
If Fruits.LastIndexOf(",") = Fruits.Length - 1 Then
Fruits = Fruits.Remove(Fruits.LastIndexOf(","), 1)
End If
For Each check In CheckedVegetables.CheckedItems
Vegetables = Vegetables & check & ","
Next
If Vegetables.LastIndexOf(",") = Vegetables.Length - 1 Then
Vegetables = Vegetables.Remove(Vegetables.LastIndexOf(","), 1)
End If
For Each check In CheckedSnacks.CheckedItems
Snacks = Snacks & check & ","
Next
If Snacks.LastIndexOf(",") = Snacks.Length - 1 Then
Snacks = Snacks.Remove(Snacks.LastIndexOf(","), 1)
End If
MyCommand = New SqlCommand("INSERT INTO Food (id, Fruits, Vegetables, Snacks) VALUES (#UserID, #Fruits, #Vegetables, #Snacks)", dbConn)
MyCommand.Parameters.AddWithValue("#UserID", TicBoxText.Text)
MyCommand.Parameters.AddWithValue("#Fruits", Fruits)
MyCommand.Parameters.AddWithValue("#Vegetables", Vegetables)
MyCommand.Parameters.AddWithValue("#Snacks", Snacks)
Return MyCommand
End Sub
CheckedListBox MSDN
Related
I have a splitform with some txtboxes and 1 combobox.
The combobox is related to the same form's query (qryPurchase) and it shows 3 columns of the query fields:
ID_purchase, Purchase_Type, Date_Purchase
In the query there other fields like Purchase_Item, Quantity and so on, but there are only 2 kind of Purchase_Type values, sell and borrow.
Different Purchase_Item can have the same ID_purchase and Date_Purchase like an invoice.
example of the combobox list:
ID_purchase, Purchase_Type, Date_Purchase
1, sell, 08/01/2020
1, sell, 09/01/2020
1, borrow, 09/01/2020
2, sell, 10/01/2020
2, borrow, 11/01/2020
When i choose a row from the dropdown menu of the combobox, i want that it has to filter the splitform's datasheet below by the combobox's row values in order to get a datasheet filtered list of all ID_purchase and Purchase_Type and Date_Purchase that match with the combobox row values.
like in the list above, if i choose the first row, the datasheet below shows 2 records.
I tried to achive that like this:
Private Sub fltDocCombo_AfterUpdate()
Me.Form.Filter = "[ID_purchase] =" & Me.fltDocCombo.Column(0) _
& " AND [Purchase_Type] = " & "'" & Me.fltDocCombo.Column(1) & "'" _
& " AND [Date_Purchase] = " & "#" & Me.fltDocCombo.Column(2) & "#"
Me.Form.FilterOn = True
End Sub
Private Sub Form_Close()
Me.Form.Filter = ""
Me.Form.FilterOn = False
End Sub
Private Sub Form_Open(Cancel As Integer)
Me.Form.Filter = ""
Me.Form.FilterOn = False
End Sub
This sometimes works sometimes not, it seems that the Me.Form.Filter value is locked on the first ID_purchase of the list..
like in the example above:
ID_purchase, Purchase_Type, Date_Purchase
1, sell, 08/01/2020
1, sell, 09/01/2020
1, borrow, 09/01/2020
2, sell, 10/01/2020
2, borrow, 11/01/2020
If i try to choose the 2nd row, the filter applied is the first row values..
But not everytime..
Sometimes it seems that the filter of Date_Purchase doesn't filter nothing..
I thought to apply the filters sequantially like ID_purchase first,
Purchase_Type second and Date the last one,
but when it applies the second filter it cancel the first one and so on..
In this case i don't know how to add another filter to an existing one..
help..
Solved..
the problem was the Date_Purchase Date format..
MS-ACCESS was installed for my local language and date format (dd/mm/yyyy)
but in VBA the Date default format is always mm/dd/yyyy
so i modified the Me.Form.Filter value like this:
Me.Form.Filter = "[ID_turnin_temploan] =" & Me.fltDocCombo.Column(0) _
& " AND [Posizione] = " & "'" & Me.fltDocCombo.Column(1) & "'" _
& " AND [Data_turnin_temploan] = " & "#" & Format(Me.fltDocCombo.Column(2), "mm/dd/yyyy") & "#"
and now it works!
I'm having issues avoiding a "You must enter a value in the __ field" error message in Access 2016. I have three tables, Tasks, Users, and TaskAssignments, and a split form that looks like:
User Task Assigned?
User1 Task1 True
User1 Task2 False
User1 Task3 True
User2 Task1 False
User2 Task2 False
User2 Task3 True
User3 Task1 True
User3 Task2 True
User3 Task3 True
Each task can have multiple users assigned to it, and each user is assigned to multiple tasks. I want my form to display every possible value, then use a checkbox, so that I can click and add a user to that task. The TaskAssignments table has a primary key and a unique constraint on both TaskID and UserID.
The recordsource for my form is a query:
select x.UserName, x.TaskName, ta.is_assigned
from (select * from Tasks, Users) x
left join TaskAssignments ta on (ta.TaskID = x.TaskID and ta.UserID = x.UserID)
I have an on click event that checks if a record exists in TaskAssignments and either updates or inserts into TaskAssignments. When I debug.print and manually run my queries, they both do what's expected. When I manually insert a record into my TaskAssignments table, my form behaves how I expect. When I need to insert a new record, however, I receive a message stating that I must enter a TaskID in TaskAssignments.
I've tried requerying the form, but I still receive the error message. Why can't it find the record that I just inserted?
Help please?!? Do I need to drastically rethink my approach here?
Here's the VBA:
Private Sub is_assigned_Click()
Dim CurrentUser, AssignmentQuery As String, SelectedUserID, SelectedTaskID As Integer
Dim ShouldInsert, IsAssigned As Boolean
CurrentUser = Environ$("Username")
SelectedUserID = Me.UserID
SelectedTaskID = Me.TaskID
IsAssigned = Me.is_assigned
Dim db As DAO.Database, rs As DAO.Recordset, strSQL As String
Set db = CurrentDb
strSQL = "select UserID, taskID from TaskAssignments where UserID=" & SelectedUserID & " and taskID =" & SelectedTaskID & ";"
Set rs = db.OpenRecordset(strSQL)
If rs.EOF = True Then
ShouldInsert = True
Else: ShouldInsert = False
End If
If ShouldInsert = True Then
AssignmentQuery = "insert into TaskAssignments (UserID, taskID, DateAssignmentUpdated, AssignmentUpdatedBy, is_assigned) values " _
& vbCrLf & "(" & SelectedUserID & "," & SelectedTaskID & ",#" & Now & "#,'" & CurrentUser & "'," & IsAssigned & ");"
ElseIf ShouldInsert = False Then
AssignmentQuery = "update TaskAssignments set UserID=" & SelectedUserID & ", DateAssignmentUpdated=#" & Now & "#, AssignmentUpdatedBy='" & CurrentUser & "',is_assigned=" & IsAssigned _
& vbCrLf & " where taskID = " & SelectedTaskID & " And UserID = " & SelectedUserID & ";"
End If
MsgBox AssignmentQuery
db.Execute (AssignmentQuery)
Forms("Task Assignments").Requery
Set rs = Nothing
Set db = Nothing
End Sub
Edit - here are the queries produced:
Insert
insert into TaskAssignments
(UserID, TaskID, DateAssignmentUpdated, AssignmentUpdatedBy, is_assigned)
values (301,4,Now(),'mylogin',True);
Update
update TaskAssignments
set UserID=270, DateAssignmentUpdated=Now(), AssignmentUpdatedBy='mylogin', is_assigned=False
where TaskID = 1 And UserID = 270;
And a constraint on my TaskAssignments table. Both TaskID and UserID are set as required in my table design (which was my whole goal - I was hoping to avoid adding records to TaskAssignments until the user has actually been assigned to a task).
alter table TaskAssignments add constraint TaskAssignmentsConstraint unique (TaskID, UserID);
Beware of wrong datatypes, each Dim needs its own datatype!
Dim CurrentUser As String, AssignmentQuery As String
Dim SelectedUserID As Long, SelectedTaskID As Long ' don't use 16-bit Integer for ID columns
Dim ShouldInsert As Boolean, IsAssigned As Boolean
To avoid troubles with date/time formatting: the database engine knows Now(), so you can directly use this in the Insert SQL:
AssignmentQuery = "insert into TaskAssignments (UserID, taskID, DateAssignmentUpdated, AssignmentUpdatedBy, is_assigned) values " _
& vbCrLf & "(" & SelectedUserID & "," & SelectedTaskID & ", Now(), '" & CurrentUser & "'," & IsAssigned & ");"
If it still doesn't work, use Debug.Print AssignmentQuery instead of MsgBox and add the actual SQL to your question (Ctrl+G shows the output).
Edit
Re-reading the question and comment, I think the problem is:
You are editing a bound form, and are updating/inserting in the same table the form is based on. That's where the Write conflict on Update comes from, the other error is probably because the bound form is trying to insert a record when you click is_assigned, but can't.
So yes, you need to rethink your approach, at least partially.
One solution is to insert the recordsource into a temp table, and base your form on that. Then the rest of the code will probably work.
It may be over-complicating things, though.
I got this problem trying to update a field that use to be a primary field in my table. When I altered what was considered the primary field I assume access would automatically stop enforcing is not null, but for some reason it didn't.
I fixed it by deleting the field, saving the table recreating the field and saving the table and the problem went away. Of course this wouldn't be an ideal solution if you have data in that table you don't want to lose so you might want to try backing it up first, before you give the solution a try, then reinserting the values.
I have an expenditures subform in Access 2010 that lists the predicted costs associated with the project for each year. Most projects only have one year, but some have more than one. Each cost has a Final checkbox next to it that should be checked when the amount is confirmed, ie. at the end of each year.
It basically looks something like this:
Year | Cost | Final
--------+-----------+--------------------
2017 | $100 | [checked box]
2018 | $200 | [unchecked box]
| | [unchecked box]
I have another field outside the table, FinalCost, that adds up everything in the Cost field. Right now, it fills in the amount from any year which has a checked Final box. That should only be filled when all the Final boxes are checked.
Ex. Right now, it should show nothing even though Final for 2017 is checked. When 2018 is checked, it should show $300. Instead, it shows $100 even though there's still an empty checkbox.
This is the code for this form.
Private Sub Form_AfterUpdate()
Dim rs1, rs2 As Recordset
Dim sql, sql2 As String
sql = "SELECT Sum(Amount) as Final From Expenditures " & _
"Where ProjNo = '" + Me.ProjNo + "' And Final = True Group by ProjNo"
sql2 = "SELECT FinalExpenditure From ActivityCash " & _
"Where ProjNo = '" + Me.ProjNo + "'"
Set rs1 = CurrentDb.OpenRecordset(sql, dbOpenDynaset, dpinconsistent)
Set rs2 = CurrentDb.OpenRecordset(sql2, dbOpenDynaset, dpinconsistent)
If rs1.RecordCount > 0 Then
If rs2.RecordCount > 0 Then
Do While Not rs2.EOF
rs2.Edit
rs2!FinalExpenditure = rs1!Final
rs2.Update
rs2.MoveNext
Loop
End If
End If
rs2.Close
rs1.Close
Set rs1 = Nothing
Set rs2 = Nothing
End Sub
What would be the best way to go about doing this?
EDIT: When the last box is checked, a new row is automatically added with an untoggled checkbox but no information.
Replace the statement beginning with sql = ... with this:
sql = "SELECT SUM(e1.Amount) AS Final " & _
" FROM Expenditures AS e1 " & _
" WHERE NOT EXISTS (SELECT 'x' FROM Expenditures e2 WHERE e2.Final=0 AND e1.ProjNo = e2.ProjNo) " & _
" AND e1.ProjNo = '" & Me.ProjNo & "'"
This query will return data only if there are all expeditures for the project marked as final. As you check for rs1.RecordCount > 0 there will be no update if this query returns no records.
So, before sql, I would verify that all records have True in your Final field.
To do that, let's just return a COUNT() of (any) records that have Final = False, and we can then decide to do what we want.
So, something like,
Dim Test as Integer
test = DCount("*", "YourTableName", "Final = False AND ProjNo = " & Me.ProjNo &"")
If test > 0 Then
'Don't fill the box
Else
'Fill the box, everything is True
'Read through your recordsets or whatever else you need to do
End If
To use a query, we essentially need to replicate the Dcount() functionality.
To do this, we need another Recordset variable, and we need to check the value of the Count() field from our query.
Create a query that mimicks this:
SELECT COUNT(*) As CountTest
FROM YourTable
HAVING Final = False
AND ProjNo = whateverprojectnumberyou'reusing
Save it, and remember that query's name.
Much like the DCount(), we need to make this "check" determine the route of your code.
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("YourQuery'sNameHere")
If rst!CountTest > 0 Then
'They are not all Checked (aka True)
Else
'Supply the value to the FinalCost
End If
Set rst = Nothing
Change this:
sql = "SELECT Sum(Amount) as Final From Expenditures " & _
"Where ProjNo = '" + Me.ProjNo + "' And Final = True Group by ProjNo"
For this:
"SELECT SUM(Amount) - SUM(IIF(Final,1,0)*Amount) as YetToConfirm, SUM(Amount) as Confirmed From Expenditures " & _
"Where ProjNo = '" + Me.ProjNo + "' Group by ProjNo"
rs1 will return two values, the total value if all costs were confirmed in the rs1!Confirmed, and the value yet to confirm in rs1!YetToConfirm
Then here:
Do While Not rs2.EOF
rs2.Edit
rs2!FinalExpenditure = rs1!Final
rs2.Update
rs2.MoveNext
Loop
change it to:
Do While Not rs2.EOF
rs2.Edit
rs2!FinalExpenditure = Iif(rs1!YetToConfirm = 0, rs1!Confirmed, 0)
rs2.Update
rs2.MoveNext
Loop
One way to process this would be check using a subquery whether last year(verified using a dmax function) in each project has been checked in the final column, if this is true, get your sum of checked amounts, else dont calculate the sum.
I have modified your sql string to include this and I tested it against your given example to confirm its showing a sum of $300 or nothing.
SQL = ""
SQL = SQL & " SELECT Sum(Amount) as Final From Expenditures "
SQL = SQL & " Where ProjNo = '" & Me.ProjNo & "' And Final = True "
SQL = SQL & " And (SELECT Expenditures.Final FROM Expenditures where year = ( "
SQL = SQL & " DMax('Year','Expenditures','ProjNo= " & Chr(34) & Me.ProjNo & Chr(34) & "'))) = true "
SQL = SQL & " Group by ProjNo "
In Microsoft Access, I would like to merge a specific column from tables having an identical key (=being duplicates) into a new table.
The source table would look like this
Key Content
Apple X
Banana B
Banana D
Banana E
Banana G
Lemon A
Lemon X
Orange A
I would like to create a new table where there is only one entry per key, each key having a field consisting of all corresponding “content” fields accumulated into one field. Each “content” value should be delimited with something, example:
Apple X
Banana B<x>D<x>E<x>G
Lemon A<x>X
Orange A
I would prefer to have it like above, but it could also work if they are in different fields/columns like below:
Apple X
Banana B D E G
Lemon A X
Orange A
I would really appreciate help with this. When googling on this I have found a quit a few of third party add-ons (like this one http://www.tucows.com/preview/1586663/MS-Access-Join-Two-Tables-Software) that seems to be solving this, but surely this can be done with MS Access itself….or…?
Another approach would be to create the table with the two columns (Key, Content) then run the function below to copy the data into the new table. You'll have to replace "ExistingTableName" and "NewTableName" with your table names.
Sub CreateNewTable()
Dim rs As Recordset
Dim rsContent As Recordset
Dim strContent As String
'Select and loop through all keys
Set rs = CurrentDb.OpenRecordset("SELECT DISTINCT Key FROM [ExistingTableName]")
Do Until rs.EOF
'Select all content records for this key and combine into a string
Set rsContent = CurrentDb.OpenRecordset("SELECT Content FROM [ExistingTableName] WHERE Key = " & Chr(34) & Nz(rs!Key) & Chr(34))
strContent = ""
Do Until rsContent.EOF
strContent = strContent & rsContent!Content & ","
rsContent.MoveNext
Loop
If Len(strContent) > 0 Then
strContent = Mid(strContent, 1, Len(strContent) - 1)
End If
CurrentDb.Execute "INSERT INTO [NewTableName] (Key, Content) VALUES (" & Chr(34) & Nz(rs!Key) & Chr(34) & ", " & Chr(34) & Nz(strContent) & Chr(34) & ")"
rs.MoveNext
Loop
Set rs = Nothing
Set rsContent = Nothing
End Sub
I don't think there is a way to do this without VBA.
Seeing as you are using a relational database you should consider using one table to store keys and another table to store content (one content per row/record), then link them up either by using a third table or by adding the 'key' as a foreign key in the content table. I would also always use an autonumber as the primary key in all MS Access tables, if not for every other reason this is a good idea, simply to avoid corruption and enable you to change a spelling mistake like 'aple' to 'apple' without breaking your relationships.
One version would be to use a UDF and this query:
SELECT Distinct Fruit.Key,
ConcatADO("SELECT Content FROM Fruit WHERE Key='" & [Key] & "'","<x>","<x>")
AS AllRows
INTO NewFruit
FROM Fruit
User Defined Function (UDF)
Function ConcatADO(strSQL As String, strColDelim, strRowDelim)
Dim rs As New ADODB.Recordset
Dim strList As String
On Error GoTo Proc_Err
If strSQL <> "" Then
rs.Open strSQL, CurrentProject.Connection
strList = rs.GetString(, , strColDelim, strRowDelim)
strList = Mid(strList, 1, Len(strList) - Len(strRowDelim))
End If
ConcatADO = strList
Exit Function
Proc_Err:
ConcatADO = "***" & UCase(Err.Description)
End Function
Working within the query design window, you can create a crosstab
TRANSFORM Min(Fruit.Content) AS MinOfContent
SELECT Fruit.Key
FROM Fruit
GROUP BY Fruit.Key
PIVOT Fruit.Content;
Which would return
Key A B D E G X
Apple X
Banana B D E G
Lemon A X
Orange A
You could then save the crosstab and create a new query based on the cross tab. This query could be a Make Table query to get the new table, but as you can see, you have several columns.
If you have a predetermined number of possible rows for each key, there are other approaches.
Finally, you must ask yourself, is de-normalizing really the way to go?
The table name is water and it has two field fname and serial.
In the field fname suppose a value 'bill' has 3 serial 1, 2, and 3. now I need when I type bill in textbox1 and click search button, the combobox1 should show the serials of 'bill' are 1,2 and 3.
I'm using ms access as db and I'm using this code but it not working.
Is there any other way to solve this?
Set rs4 = cn.Execute("select fname, serial from water where fname = '" & Text1.Text & "'")
rs4.MoveFirst
Do While Not rs4.EOF
Combo1.AddItem rs4("serial")
rs4.MoveNext
Loop
You could have a problem when someone enters a single-quote in to the text box. You should do something like this:
Set rs4 = cn.Execute("select fname, serial from water where fname = '" & Replace(Text1.Text, "'", "''") & "'")
Another problem you may have is if there is no match found. You're not checking to see if there is any data in the recordset object.
Combo1.Clear
Set rs4 = cn.Execute("select fname, serial from water where fname = '" & Replace(Text1.Text, "'", "''") & "'")
If not rs4.Eof Then
rs4.MoveFirst
Do While Not rs4.EOF
Combo1.AddItem rs4("serial")
rs4.MoveNext
Loop
End If
I'm not really sure what the problem is, but your loop should look something more like this:
rs4.MoveFirst
Do While Not rs4.EOF
Combo1.AddItem rs4("holding")
rs4.MoveNext
Loop
Have you considered telling the compiler more explicitly what you want, something more like:
Set rs4 = cn.Execute("select fname, serial from water where fname = '" & Text1.Text & "'")
With rs4
Do Until .EOF
Combo1.AddItem CStr(!serial.Value)
.MoveNext
Loop
End With