I have the following VBA script:
Private Sub CmbTermLookup_AfterUpdate()
Dim BusinessTerm As Integer
Dim SqlString As String
If IsNull(Me!CmbTermLookup) Then
Me!CmbTermLookup = ""
Else
BusinessTerm = Me!CmbTermLookup
End If
SqlString = "SELECT TblBusinessTerm.BusinessTermID, TblBusinessTerm.BusinessTerm, TblField.FieldID, TblField.FieldName," _
& " TblField.FieldDescr, TblField.TableID" _
& " FROM TblBusinessTerm INNER JOIN TblField ON TblBusinessTerm.BusinessTermID = " & BusinessTerm
Me.RecordSource = SqlString
End Sub
I get the error - JOIN EXPRESSION NOT SUPPORTED.
When I run the sqlstring in a query though it works.
Any ideas why?
Thank you
You need to specify a field in each of the two tables to join the tables on, and then you need to specify a WHERE clause if you only want certain records:
SqlString = "SELECT TblBusinessTerm.BusinessTermID, TblBusinessTerm.BusinessTerm, TblField.FieldID, TblField.FieldName," _
& " TblField.FieldDescr, TblField.TableID" _
& " FROM TblBusinessTerm INNER JOIN TblField ON TblBusinessTerm.BusinessTermID = TblField.BusinessTermID " _
& " WHERE TblBusinessTerm.BusinessTermID = " & BusinessTerm
Related
I have an Access VBA list box with a rowsource that will not populate. It was working last week and after reopening the DB this week, for some reason it will not show the results of my string.
Private Sub PullData(strType As String)
Dim rst As DAO.Recordset
Dim sSQL As String
On Error GoTo Err_PullData
Set rst = CurrentDb.OpenRecordset("SELECT * FROM TBLactionstaken_ARCHIVE", dbOpenDynaset, dbReadOnly)
Select Case strType
Case "Actions"
If Me.Frame388.Value = 1 Then
Me.lstActionsTaken.RowSource = "SELECT TBLactionstaken_ARCHIVE.RecordNumber, TBLactionstaken_ARCHIVE.ActionTakenID, TBLparticipants.[PartSS#], TBLactionstaken_ARCHIVE.ActionDate, TBLactionstaken_ARCHIVE.ActionStatus, TBLactionstaken_ARCHIVE.ReasonID, " & _
"TBLreasons.Description, TBLactionstaken_ARCHIVE.MANHType, TBLactionstaken_ARCHIVE.ProcessedDate, TBLactionstaken_ARCHIVE.PayOutStatus, " & _
"TBLactionstaken_ARCHIVE.PayOutDate FROM (TBLactionstaken_ARCHIVE INNER JOIN TBLparticipants ON TBLactionstaken_ARCHIVE.RecordNumber = " & _
"TBLparticipants.RecordNumber) INNER JOIN TBLreasons ON TBLactionstaken_ARCHIVE.ReasonID = TBLreasons.ReasonID WHERE " & _
"(((TBLactionstaken_ARCHIVE.ActionDate)<= [Form]![txtEndDate] And (TBLactionstaken_ARCHIVE.ActionDate)>= [Form]![txtEndDate]));"
Me.lstActionsTaken.Requery
ElseIf Me.Frame388.Value = 2 Then
Me.lstActionsTaken.RowSource = ""
Else
MsgBox "No Data Available", vbExclamation, "Archive Search"
Exit Sub
End If
Case "Transactions"
lstActionsTaken.Visible = False
lstTransactions.Visible = True
End Select
Exit_PullData:
Exit Sub
Err_PullData:
MsgBox Err.Description
Resume Exit_PullData
End Sub
The list box is set up with 11 columns. It's not throwing an error and I can use the immediate window to determine that my fields have values.
Try with specificly formatted date expressions:
If Me.Frame388.Value = 1 Then
Me.lstActionsTaken.RowSource = _
"SELECT TBLactionstaken_ARCHIVE.RecordNumber, TBLactionstaken_ARCHIVE.ActionTakenID, TBLparticipants.[PartSS#], TBLactionstaken_ARCHIVE.ActionDate, TBLactionstaken_ARCHIVE.ActionStatus, TBLactionstaken_ARCHIVE.ReasonID, " & _
"TBLreasons.Description, TBLactionstaken_ARCHIVE.MANHType, TBLactionstaken_ARCHIVE.ProcessedDate, TBLactionstaken_ARCHIVE.PayOutStatus, " & _
"TBLactionstaken_ARCHIVE.PayOutDate FROM (TBLactionstaken_ARCHIVE INNER JOIN TBLparticipants ON TBLactionstaken_ARCHIVE.RecordNumber = " & _
"TBLparticipants.RecordNumber) INNER JOIN TBLreasons ON TBLactionstaken_ARCHIVE.ReasonID = TBLreasons.ReasonID WHERE " & _
"(TBLactionstaken_ARCHIVE.ActionDate <= #" & Format(Me!txtEndDate.Value, "yyyy\/mm\/dd") & "# And TBLactionstaken_ARCHIVE.ActionDate >= #" & Format(Me!txtEndDate.Value, "yyyy\/mm\/dd") & "#);"
' Not needed: Me.lstActionsTaken.Requery
I have one table and one query. Both have the same data field but table COLUMN names are equal to query's ROW name. I update table from query's row data using the following code successfully but it takes too much time to update as there are more than 50 columns name in the table for each employee-
Set rst1 = CurrentDb.OpenRecordset("SELECT * FROM tblPayRollDataTEMP")
Set rst2 = CurrentDb.OpenRecordset("SELECT * FROM qryEmpVerifySalary ")
Do Until rst1.EOF
rst2.MoveFirst
Do Until rst2.EOF
For l = 0 To rst1.Fields.count - 1
If rst1!EmpID = rst2!EmpID And rst1.Fields(l).Name = rst2!Head And rst1!PayBillID = TempVars!BillID Then
With rst1
rst1.Edit
rst1.Fields(l).Value = rst2!Amount
rst1!totDeductions = DSum("Amount", "qryEmpVerifySalary", "[PayHeadType] = 'Deductions' AND [EmpID] = " & rst2!EmpID & "") + DLookup("NPS", "qryEmpPayEarning", "[EmpID] = " & rst2!EmpID & "")
rst1!totRecoveries = DSum("Amount", "qryEmpVerifySalary", "[PayHeadType] = 'Recoveries' AND [EmpID] = " & rst2!EmpID & "")
rst1!NetPayable = rst1!totEarnings - (Nz(rst1!totDeductions, 0) + Nz(rst1!totRecoveries, 0))
rst1.Update
End With
End If
Next
rst2.MoveNext
Loop
rst1.MoveNext
Loop
Set rst1 = Nothing
Set rst2 = Nothing
How to improve the performance of the code?
You should use a query to update your records. This would be the fastest solution. Normally one would match the EmpID and drag and drop the fields into the update query or use an expression. If you have to group before or other complex stuff split it in more querys (two or three). It doesnt matter thou, because in the end you just execute one update query.
For your code, you can replace the domainaggregate functions. DLookup(), DSum(), etc... these are worst for performance. A simple select statement runs way faster than DLookup(). Here are a few replacements:
Function DCount(Expression As String, Domain As String, Optional Criteria) As Variant
Dim strSQL As String
strSQL = "SELECT COUNT(" & Expression & ") FROM " & Domain
'Other Replacements:
'DLookup: strSQL = "SELECT " & Expression & " FROM " & Domain
'DMax: strSQL = "SELECT MAX(" & Expression & ") FROM " & Domain
'DMin: strSQL = "SELECT SUM(" & Expression & ") FROM " & Domain
'DFirst: strSQL = "SELECT FIRST(" & Expression & ") FROM " & Domain
'DLast: strSQL = "SELECT LAST(" & Expression & ") FROM " & Domain
'DSum: strSQL = "SELECT SUM(" & Expression & ") FROM " & Domain
'DAvg: strSQL = "SELECT AVG(" & Expression & ") FROM " & Domain
If Not IsMissing(Criteria) Then strSQL = strSQL & " WHERE " & Criteria
DCount = DBEngine(0)(0).OpenRecordset(strSQL, dbOpenForwardOnly)(0)
End Function
I can't figure out the error. I already tried adding more parentheses but this didn't help. This code checks to see if there is already a query called "InsertFilmZip" and if there isn't one, it creates it with the given statement. For some reason, it's saying that there is a Run-time error 3139: Syntax error in PARAMETER clause but I can't find the error.
Private Sub Command8_Click()
Dim dbsCurrent As Database
Set dbsCurrent = CurrentDb
Dim query As QueryDef
Dim sql As String
Dim item_val As String
item_val = Me.Text314
For Each query In CurrentDb.QueryDefs
If query.Name = "InsertFilmZip" Then
Exit For
End If
Next query
If query Is Nothing Then
sql = "parameters " & "P1 Number" & _
"INSERT INTO [tbl_FilmZipInfo] " & _
"(qty_per_unit) " & _
" VALUES ([P1])" & _
"WHERE (((tbl_FilmZipInfo.qty_per_unit)='" & Me.Text314 & "'))"
Set query = CurrentDb.CreateQueryDef("InsertFilmZip", sql)
End If
query.Parameters("P1").Value = Me.Text317
query.Execute
End Sub
Your SQL doesn't make sense, so try this adjustment:
sql = "parameters P1 Long;" & _
"UPDATE [tbl_FilmZipInfo] " & _
"SET qty_per_unit = [P1] " & _
"WHERE qty_per_unit = " & Me.Text314 & ""
In the following code, I would like to join ADODB record set 'rs3' to table 'tblValueChain10' and update 3 different columns based on the values extracted in the ADODB record set 'rs3'. Currently, the update query is not returning anything.
Dim st_Sql3 As String
Dim rs3 As ADODB.Recordset
Set rs3 = New ADODB.Recordset
Dim Max3 As Integer
rs3.Open "SELECT tblRisk05Holding.IDMacroProcesso01, tblRisk05Holding.Level01Risk, Max(tblRisk05Holding.ManualityStatus) AS MaxDiManualityStatus, Max(tblRisk05Holding.RiskProbabilityStatus) AS MaxDiRiskProbabilityStatus, Max(tblRisk05Holding.RiskExposureStatus) AS MaxDiRiskExposureStatus FROM tblRisk05Holding GROUP BY tblRisk05Holding.IDMacroProcesso01, tblRisk05Holding.Level01Risk", CurrentProject.Connection
st_Sql3 = "UPDATE tblValueChain10 INNER JOIN rs3 ON (tblValueChain10.IDMacroProcesso01 = tblRisk05Holding.IDMacroProcesso01) SET L1RiskManuality = " & rs3.Fields(2) & ", L1RiskProbability = " & rs3.Fields(3) & ", L1RiskGravity = " & rs3.Fields(4) & ""
Application.DoCmd.RunSQL (st_Sql2)
rs3.Close
Set rs3 = Nothing
Access never allows you to use a recordset object as a data source in another query. It doesn't matter whether you have an ADO or DAO recordset; you can't do it. And the query type (SELECT, UPDATE, INSERT, etc.) also doesn't matter; you can't use a recordset object as a data source in any query type.
You might get a workable UPDATE by first saving your SELECT statement as a named query, qryRS3. Then revise the UPDATE to INNER JOIN tblValueChain10 to qryRS3. But I'm uncertain whether Access would consider that query to be updatable; the GROUP BY might cause Access to treat it as not updatable. You'll have to test to see.
Although the goal you try to achieve using ADO Recordset in the way presented can't be done (as user #HansUp wrote), you could try the approach with updating your table tblValueChain10 using subquery taken from the rs3 recordset open call.
I hope that the following query :
UPDATE
tblValueChain10
INNER JOIN
(
SELECT
tblRisk05Holding.IDMacroProcesso01,
tblRisk05Holding.Level01Risk,
Max(tblRisk05Holding.ManualityStatus) AS MaxDiManualityStatus,
Max(tblRisk05Holding.RiskProbabilityStatus) AS MaxDiRiskProbabilityStatus,
Max(tblRisk05Holding.RiskExposureStatus) AS MaxDiRiskExposureStatus
FROM
tblRisk05Holding
GROUP BY
tblRisk05Holding.IDMacroProcesso01,
tblRisk05Holding.Level01Risk
) AS qry_Risk05Holding
ON (tblValueChain10.IDMacroProcesso01 = qry_Risk05Holding.IDMacroProcesso01)
SET
tblValueChain10.L1RiskManuality = qry_Risk05Holding.MaxDiManualityStatus,
tblValueChain10.L1RiskProbability = qry_Risk05Holding.MaxDiRiskProbabilityStatus,
tblValueChain10.L1RiskGravity = qry_Risk05Holding.MaxDiRiskExposureStatus
could help you solve your problem.
You should be able to run the above SQL with the following code:
Dim st_Sql3 As String
st_Sql3 = " UPDATE tblValueChain10 INNER JOIN ( "
st_Sql3 = st_Sql3 & " SELECT " _
& " tblRisk05Holding.IDMacroProcesso01, " _
& " tblRisk05Holding.Level01Risk, " _
& " Max(tblRisk05Holding.ManualityStatus) AS MaxDiManualityStatus, " _
& " Max(tblRisk05Holding.RiskProbabilityStatus) AS MaxDiRiskProbabilityStatus, " _
& " Max(tblRisk05Holding.RiskExposureStatus) AS MaxDiRiskExposureStatus "
st_Sql3 = st_Sql3 & " FROM " _
& " tblRisk05Holding " _
& " GROUP BY " _
& " tblRisk05Holding.IDMacroProcesso01, " _
& " tblRisk05Holding.Level01Risk "
st_Sql3 = st_Sql3 & " ) AS qry_Risk05Holding " _
& " ON (tblValueChain10.IDMacroProcesso01 = qry_Risk05Holding.IDMacroProcesso01) " _
& " SET " _
& " tblValueChain10.L1RiskManuality = qry_Risk05Holding.MaxDiManualityStatus, " _
& " tblValueChain10.L1RiskProbability = qry_Risk05Holding.MaxDiRiskProbabilityStatus, " _
& " tblValueChain10.L1RiskGravity = qry_Risk05Holding.MaxDiRiskExposureStatus "
Application.DoCmd.RunSQL (st_Sql3)
The query is being built-up in four stages because as far as I remember there is a restriction in VBA that there can't be too many line breaks _.
Please notice also that the JOIN used in the update query assumes that connecting two tables by IDMacroProcesso01 would ensure that the records are updated in the right way.
I can't check the solution in Acces right now but maybe it could somehow help you, at least a concept. If there were any errors, please write.
You need to loop through the recordset to iteratively update by each record:
Do While NOT rs3.EOF
st_Sql3 = "UPDATE tblValueChain10"_
& " INNER JOIN rs3 ON (tblValueChain10.IDMacroProcesso01 = tblRisk05Holding.IDMacroProcesso01)" _
& " SET L1RiskManuality = " & rs3.Fields(2) & ", L1RiskProbability = " & rs3.Fields(3) & "," _
& " L1RiskGravity = " & rs3.Fields(4) & ""
DoCmd.RunSQL (st_Sql3)
rs3.MoveNext
Loop
Also please note, your RunSQL () command is calling the incorrect SQL string.
If no err appears, then try to place this code:
Set rs3 = New ADODB.Recordset
in form_load, as in,
private sub Form_load()
Set rs3 = New ADODB.Recordset
End Sub
note: this sample is in vb6.0. that's what I can do. Besides, check the version in references
I have an array which can have a different amount of values, depending on the situation. I want to put these values as a parameter in a query in ms access.
The problem is, if I use the following code to generate a parameter, it sends the whole string as one value to the query, which obviously does not return any rows.
Do Until i = size + 1
If Not IsEmpty(gvaruocat(i)) Then
If Not IsEmpty(DLookup("uo_cat_id", "tbl_uo_cat", "[uo_cat_id] = " & CInt(gvaruocat(i)))) Then
If IsEmpty(get_uocat_param) Then
get_uocat_param = CInt(gvaruocat(i))
Else
get_uocat_param = get_uocat_param & " OR tbl_uo_step.uo_step_cat = " & CInt(gvaruocat(i))
End If
End If
End If
i = i + 1
Loop
At the moment I have 'Fixed' it by generating an SQL string and leaving the query out all together.
get_uocat = "SELECT tbl_product.prod_descr, tbl_uo_cat.uo_cat_descr, tbl_uo_step.uo_step_descr" & vbCrLf _
& "FROM (tbl_product INNER JOIN tbl_uo_cat ON tbl_product.prod_id = tbl_uo_cat.uo_cat_prod) INNER JOIN tbl_uo_step ON tbl_uo_cat.uo_cat_id = tbl_uo_step.uo_step_cat" & vbCrLf _
& "WHERE (((tbl_uo_step.uo_step_cat) = " & get_uocat_param & ")) " & vbCrLf _
& "ORDER BY tbl_product.prod_descr, tbl_uo_cat.uo_cat_descr, tbl_uo_step.uo_step_descr;"
This is however not very friendly to many changes. So my question is, how do I get the array to send each value as a separate parameter to the query?
Note: IsEmpty() is a custom function which checks for empty variables in case you were wondering.
You can still use a parameterized query in this case, despite your comment to the question. You just need to build the SQL string to include as many parameters as required, something like this:
Dim cdb As DAO.Database, qdf As DAO.QueryDef, rst As DAO.Recordset
Dim sql As String, i As Long
' test data
Dim idArray(1) As Long
idArray(0) = 1
idArray(1) = 3
Set cdb = CurrentDb
sql = "SELECT [LastName] FROM [People] WHERE [ID] IN ("
' add parameters to IN clause
For i = 0 To UBound(idArray)
sql = sql & "[param" & i & "],"
Next
sql = Left(sql, Len(sql) - 1) ' trim trailing comma
sql = sql & ")"
Debug.Print sql ' verify SQL statement
Set qdf = cdb.CreateQueryDef("", sql)
For i = 0 To UBound(idArray)
qdf.Parameters("param" & i).Value = idArray(i)
Next
Set rst = qdf.OpenRecordset(dbOpenSnapshot)
' check results
Do Until rst.EOF
Debug.Print rst!LastName
rst.MoveNext
Loop
rst.Close
Set rst = Nothing
Set qdf = Nothing
Set cdb = Nothing
When I run this on my test database I get
SELECT [LastName] FROM [People] WHERE [ID] IN ([param0],[param1])
Thompson
Simpson
you could make use of the IN Clause, instead. Which would work out better.
Do Until i = size + 1
If Not IsEmpty(gvaruocat(i)) Then
If Not IsEmpty(DLookup("uo_cat_id", "tbl_uo_cat", "[uo_cat_id] = " & CInt(gvaruocat(i)))) Then
If IsEmpty(get_uocat_param) Then
get_uocat_param = CInt(gvaruocat(i))
Else
get_uocat_param = get_uocat_param & ", " & CInt(gvaruocat(i))
End If
End If
End If
i = i + 1
Loop
Then your Query build could use,
get_uocat = "SELECT tbl_product.prod_descr, tbl_uo_cat.uo_cat_descr, tbl_uo_step.uo_step_descr" & vbCrLf _
& "FROM (tbl_product INNER JOIN tbl_uo_cat ON tbl_product.prod_id = tbl_uo_cat.uo_cat_prod) INNER JOIN tbl_uo_step ON tbl_uo_cat.uo_cat_id = tbl_uo_step.uo_step_cat" & vbCrLf _
& "WHERE ((tbl_uo_step.uo_step_cat IN (" & get_uocat_param & "))) " & vbCrLf _
& "ORDER BY tbl_product.prod_descr, tbl_uo_cat.uo_cat_descr, tbl_uo_step.uo_step_descr;"