I've been trying to figure out what is wrong with my code. Can anyone please help?
Here is my code.
Dim addTrans_SQL2 As String = "INSERT INTO Table1(Field1,Field2,Field3,Field4) SELECT (Field01,Field02,Field03,Field04) FROM InventoryItems WHERE Field1 = " & c_Field1 & ""
Dim addTrans_dbcmd2 As OleDbCommand = New OleDbCommand(addTrans_SQL2, strCon)
addTrans_dbcmd2.ExecuteNonQuery()
c_Field1 has a value of 1.
I already checked the data type of each field in both tables and they are the same.
My strCon connection has no problem.
The only error it says is my INSERT INTO statement.
Can anyone please help? Thanks!
As we do not have the table structure, so we assume your InventoryItems have Field01 but not Field1
Let's focus on your select statement:
SELECT (Field01,Field02,Field03,Field04)
FROM InventoryItems
WHERE Field1 = " & c_Field1 & ""
The problem is the Field1 in Where clause, you may change it to Field01, which match the selection criteria
SELECT (Field01,Field02,Field03,Field04)
FROM InventoryItems
WHERE Field01 = " & c_Field1 & ""
Related
I have an Access Form that lists addresses and details related to those addresses. It is filtered manually by staff using the standard menus to come down to a list of relevant addresses.
I'd like to output those filtered results to a table (temp table) so that I can use it to create mailings.
Is this possible and if so what sort of code should I be using for a button.
TIA
MK
When users filtering records, they are changing .Filter property of form. Text of this property is equivalent of WHERE clause of SQL. So, all you need is to create INSERT ... SELECT... SQL query with the same source as record source of form and use filter text for WHERE clause. Something like this:
Dim str_filter As String
Dim str_recSource As String
str_recSource = Me.RecordSource
str_filter = Me.Filter
CurrentDb.Execute "DELETE * FROM MyExportTable"
If str_filter = "" Or Me.FilterOn = False Then
CurrentDb.Execute "INSERT INTO MyExportTable SELECT * FROM (" & Replace(str_recSource, ";", "") & ") as t"
Else
CurrentDb.Execute "INSERT INTO MyExportTable SELECT * FROM (" & Replace(str_recSource, ";", "") & ") as t" & " WHERE " & str_filter
End If
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 followed the tips by others to produce an access query.
I have two tables. See figure1. And the result is figure2.
Figure1
http://img.libk.info/f1.png http://img.libk.info/f1.png
Figure2
http://img.libk.info/f2.png http://img.libk.info/f2.png
The method to generate the result query is solved in another question.
The query script :
TRANSFORM Nz(Count([number]),0) AS CountValue
SELECT Table1.ID
FROM Table1, Table2
WHERE (((Table2.number) Between [table1].[start] And [table1].[end]))
GROUP BY Table1.ID
PIVOT DatePart("yyyy",[ndate]);
My question is:
Is there anyway to write back the query result to table 1?
I want to add two new columns in table 1. And be able to add or update the query value to the field base on its "ID".
I'm not sure my description is clear or not. Hope you may understand and thanks for your help!
You won't be able to do it directly. However, here are two ways it could be done indirectly.
Method 1: Temp Table
This method is best for a quick-and-dirty one-time solution.
Create a Make-Table query based on your query and use it to make a temporary table.
Use the temporary table joined to [Table 1] to update your two new fields.
Delete the temporary table
Method 2: VBA Routine
This method is best when you want a repeatable method. It's overkill if you're only going to do it once. However, if you want calculated values for every year, you'll need to run it again.
Read the query into a recordset
Loop through the Recordset and for each ID, either
Run a sql statement to update table 1, or
open a second recordset querying by the ID and Edit/Update
Here's a simple version that updates the value for a single year.
Public Sub UpdateAnnualTotal(ByVal nYear As Long)
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim sSQL As String
Dim sId As String
Dim nTotal As Long
Set db = CurrentDb
sSQL = "SELECT [ID],[" & nYear & "_count"] FROM AnnualTotalsQuery"
Set rs = db.OpenRecordset(sSQL)
With rs
Do Until .EOF
sId = .Fields("ID").Value
nTotal = .Fields(nYear & "_count").Value
sSQL = "UPDATE [Table 1] SET [" & nYear & "_count"] = " & nTotal _
& " WHERE [ID] = '" & sId & "'"
db.Execute sSQL
.MoveNext
Loop
.Close
End With
End Sub
Thank you beforehand for your assistance. I know enough about Access, SQL, and VBA to get myself into trouble. Here is what I want to do.
I want to create a query that starts with a certain year and then lists each year up until the current year. The problem is that I want the query to automatically update as time progresses. In other words, say the start year is 2009, I want my query to list 2009, 2010, 2011, 2012, and 2013 since we are currently in the year 2013. Next year, the list will expand to include 2014. I suspect this is possible using a query in SQL but not sure how to go about coding it properly.
I bet that there is no simple solution for this simple process. We must use VBA to perform following steps:
Create a temporary table:
CREATE Table tblTmpYears (
ID COUNTER CONSTRAINT PrimaryKey PRIMARY KEY,
Year Long
);
In VBA:
Dim strSQL
strSQL = "CREATE Table tblTmpYears (" _
& " ID COUNTER CONSTRAINT PrimaryKey PRIMARY KEY," _
& " Year Long" _
& ");"
CurrentDb.Execute strSQL, dbFailOnError
Fill the temporary table:
INSERT INTO tblTmpYears (year) VALUES (2009);
INSERT INTO tblTmpYears (year) VALUES (2010);
INSERT INTO tblTmpYears (year) VALUES (2011);
INSERT INTO tblTmpYears (year) VALUES (2012);
INSERT INTO tblTmpYears (year) VALUES (2013);
In VBA, for 5 years, valid even after 100 years after our life existence:
Dim y as long, ymin, ymax, strSQL
ymax = Year(Date)
ymin = ymax - 4
For y = ymin to ymax
strSQL = "INSERT INTO tblTmpYears (Year) VALUES (" & y & ");"
CurrentDb.Execute strSQL, dbFailOnError
Next
Create a query for listing with the temporary table:
SELECT * FROM tblStudents INNER JOIN tblTmpYears
ON tblStudents.Year=tblTmpYears.Year
ORDER BY Year;
In VBA like this:
Dim qdf, strSQL
strSQL = "SELECT * FROM tblStudents INNER JOIN tblTmpYears" _
& " ON tblStudents.Year=tblTmpYears.Year" _
& " ORDER BY Year;"
Set qdf = CurrentDB.CreateQueryDef("qrySelTemporary", strSQL)
DoCmd.OpenQuery qdf.Name
Here you will have the Query Datasheet Windows with your students's list, it's printable. Even better, you can use it as
MyReport.RecordSource = "qrySelTemporary"
in an Access Report with a beautiful presentation.
Delete the temporary table after printing, for example:
DROP TABLE tblTmpYears;
In VBA:
Dim strSQL
strSQL = "DROP TABLE tblTmpYears;"
CurrentDb.Execute strSQL, dbFailOnError
Only VBA can accomplish this... rather than a single SQL query.
How about this - a small VBA function that outputs the SQL for an appropriate UNION query, which you can then assign as the RowSource for a combo box, use as a sub-query inside another dynamically generated query, or whatever:
Function CreateYearsToCurrentSQL(From As Integer) As String
Dim I As Integer, S As String
For I = From To Year(Date)
If I <> From Then S = S + "UNION "
S = S + "SELECT " & I & " AS Year FROM MSysObjects" + vbNewLine
Next I
CreateYearsToCurrentSQL = S
End Function
The FROM MSysObjects is because Access will whinge about no FROM clause if one isn't there, and MSysObjects is bound to be an existing table in an Access context (if you prefer though, replace it with the name of any other table).
So I managed to create a Query Criteria that does what I need.
Like (Right(Year(Now()),2)-3) & "-" Or Like (Right(Year(Now()),2)-2) & "-" Or Like (Right(Year(Now()),2)-1) & "-" Or Like Right(Year(Now()),2) & "-"
Thank you everyone for your efforts.
I have a button which uses two separate queries that pull data from two tables and insert into another table:
Dim lngID As Long
Dim lngIDCallout As Long
Dim strSQL1 As String
lngID = CalloutAttendance_MultiSelect.Value
lngIDCallout = Forms![Callouts].[CalloutID].Value
strSQL1 = "INSERT INTO Members_Callouts(MemberID) SELECT MemberID FROM Members WHERE MemberID=" & lngID
strSQL2 = "INSERT INTO Members_Callouts(CalloutID) SELECT CalloutID FROM Callouts WHERE CalloutID=" & lngIDCallout
CurrentDb.Execute strSQL1
CurrentDb.Execute strSQL2
CalloutAttendance_MultiSelect.Requery
And whilst it almost does what I want it to do, it inserts the the two values as two separate new records, whereas I'd like it to insert it into ONE new record. I've had a go, but I either get syntax errors, or in the case below, I got a 3067 runtime error "Query input must contain at least one table or query"
strSQL1 = "INSERT INTO Members_Callouts(MemberID, CalloutID) SELECT
(SELECT MemberID FROM Members WHERE MemberID=" & lngID & "),
(SELECT CalloutID FROM Callouts WHERE CalloutID=" & lngIDCallout & ")"
Anyone know where I might be going wrong?
Thanks :-)
In this case you're just inserting the key values so all you need to do is
strSQL1 = _
"INSERT INTO Members_Callouts (MemberID, CalloutID) " & _
"VALUES (" & lngID & ", " & lngIDCallout & ")"
In other words, you don't need to bother with something like...
"(SELECT MemberID FROM Members WHERE MemberID=" & lngID & ")"
...since the value it returns is just lngId (assuming that the value exists in the [Members] table).
INSERT INTO
MyTable (Col1,Col2,Col3,Col4,Col5,Col6,Col7)
SELECT
f1.col1, f2.col2, f3.col3, f3.col4, f3.col5, f4.col6, f5.col7
FROM
(SELECT Col1 FROM Func1()) AS f1
CROSS JOIN
(SELECT Col2 FROM Func2()) AS f2
CROSS JOIN
(SELECT Col3,Col4,Col5 FROM Func3()) AS f3
CROSS JOIN
(SELECT Col6 FROM Func4()) AS f4
CROSS JOIN
(SELECT Col7 FROM Func5()) AS f5