MS Access SQL query within VBA code - vba

I need a second set of eyes on this SQL query embedded in the VBA code. I'm making an MS Access app that returns a dataset based on the to & from date criteria set by the user in the specific date picker boxes. The sql query that you see actually has been tested statically within MS Access query design view. I tested it with actual dates where you see the Me.from_filter and Me.to_filter. It worked perfectly! If you chose something like from 1/1/2015 to 5/1/2015 it returns columns of all the months you need. Perfect. Now when I embed it in the VBA code and assign it to a control variable, I get the "Run-time error '2342': A RunSQL action requires an argument consisting of an SQL statement." Can someone please eyeball this and tell me what might be wrong?
Option Compare Database
Option Explicit
Dim strSQL As String
Private Sub Command0_Click()
If IsNull(Me.from_filter) Or IsNull(Me.to_filter) Then
MsgBox "You have not entered a start date or end date"
Else
strSQL = "TRANSFORM Sum(dbo_ASSET_HISTORY.MARKET_VALUE) AS SumOfMARKET_VALUE " _
& "SELECT [dbo_FIRM]![NAME] AS [FIRM NAME], dbo_FUND.CUSIP, dbo_FUND.FUND_NAME, dbo_FUND.PRODUCT_NAME " _
& "FROM (dbo_ASSET_HISTORY INNER JOIN dbo_FIRM ON dbo_ASSET_HISTORY.FIRM_ID = dbo_FIRM.FIRM_ID) INNER JOIN dbo_FUND ON dbo_ASSET_HISTORY.FUND = dbo_FUND.FUND " _
& "WHERE (((dbo_FIRM.Name) Like 'Voya F*') And ((dbo_ASSET_HISTORY.PROCESS_DATE) >= #" & Me.from_filter & "# And (dbo_ASSET_HISTORY.PROCESS_DATE) <= #" & Me.to_filter & "#)) " _
& "GROUP BY [dbo_FIRM]![NAME], dbo_FUND.CUSIP, dbo_FUND.FUND_NAME, dbo_FUND.PRODUCT_NAME " _
& "PIVOT [dbo_ASSET_HISTORY]![ASSET_YEAR] & '-' & [dbo_ASSET_HISTORY]![ASSET_MONTH];"
DoCmd.RunSQL (strSQL)
End If
End Sub

RunSQL is for running action queries like update, insert, select into, delete, etc as per Microsoft definition https://msdn.microsoft.com/en-us/library/office/ff194626.aspx , you should probably use OpenQuery or similar to run your query.

Related

Run-Time Error 3146 - VBA Access Execute Stored Procedure - Cursor state(#0)

I am getting an error code (3146: ODBC-call failed - Invalid cursor state (#0) on my local machine using Microsoft Access 365, but it works in our remote desktop environment using 2016 Access Professional Plus.
After reading this post, I set my ODBC timeout to 2000 in the query's property sheet, but still, get the same error and it only takes about 10 seconds to throw.
I also read that there were issues with the cursor state in an earlier version of Access 2016 and not sure if that is a problem with Office 365?
This subroutine has worked for years without any issues. It looks like it is tied to Office 365.
Any ideas?
The code errors on this line
DoCmd.OpenQuery "qryImportGMSData" 'Creates tempTable with Weekly Import from GMS
Below is my subroutine
Sub GMSImport(StartDate As Date, EndDate As Date)
Dim SqlStr As String
Dim db As DAO.Database
Set db = CurrentDb()
'Builds query string for stored procedure maintained by SWDev from GMS to show Weekly Deals for report.
SqlStr = "EXEC dbo.upRpt_WeeklyDealsReport #BeginDate = '" & Format(StartDate, "yyyy-mm-dd") & "' ," & _
" #EndDate = '" & Format(EndDate, "yyyy-mm-dd") & "' ," & _
" #RegionType_Short_List = 'CA~GC~MC~MW~SW~WE~NE' ," & _
" #IncludeBulletDeals = 0 ," & _
" #FormatType = 'spgexporttype'"
db.QueryDefs("ptqry_DataExport").sql = SqlStr 'sets the parameters for the stored procedure
DoCmd.SetWarnings False
DoCmd.OpenQuery "qryImportGMSData" 'Creates tempTable with Weekly Import from GMS
DoCmd.RunSQL "ALTER TABLE temp_GMSImport ADD COLUMN Selected BIT" 'Add Selected Column to temp table
DoCmd.RunSQL "ALTER TABLE temp_GMSImport ADD COLUMN dvsValuationDef_ID INT" 'Adds Valuation Def Column to temp table
DoCmd.RunSQL "UPDATE temp_GMSImport SET temp_GMSImport.Selected = -1;" 'Sets all Selected field to TRUE
DoCmd.SetWarnings True
End Sub
It errors out on this line:
DoCmd.OpenQuery "qryImportGMSData" 'Creates tempTable with Weekly Import from GMS
I am able to execute the stored procedure in SMSS with no issues:
"EXEC dbo.upRpt_WeeklyDealsReport #BeginDate = '" & Format(StartDate, "yyyy-mm-dd") & "' ," & _
" #EndDate = '" & Format(EndDate, "yyyy-mm-dd") & "' ," & _
" #RegionType_Short_List = 'CA~GC~MC~MW~SW~WE~NE' ," & _
" #IncludeBulletDeals = 0 ," & _
" #FormatType = 'spgexporttype'"
When I test by 64 bit ODBC connection, it test successfully.
Update -more testing inside Access:
I was able to execute the T-SQL code inside Access without using VBA.
There are 3 queries involved in the sequence and the one that is not working is qryImportGMSData. It is a problem without using VBA, so that narrows it down a bit.
qryImportGMSData
Query: Make Table Query (Replicated)
This one is causing the error
SELECT * INTO temp_GMSImport
FROM qryImportTransform;
qryImportTransform
Query: Select Query (Replicated) Works
SELECT *
FROM ptqry_DataExport;
Ptqry_DataExport
SQL Pass-Through Query (Replicated) Works
EXEC dbo.upRpt_WeeklyDealsReport #BeginDate = '2021-02-22' , #EndDate = '2021-02-28' , #RegionType_Short_List = 'CA~GC~MC~MW~SW~WE~NE' , #IncludeBulletDeals = 0 , #FormatType = 'spgexporttype'
Ok, so we narrowed down that the PT query can work from Access.
We are likely dealing with two different connections - so there is a "wee bit" of asynchronous (threading) occurring here.
If not already, use the SAME connection object to run all 3 query.
So, use this:
db.Execute "qryImportGMSData",dbFailOnError
db.Execute "ALTER TABLE temp_GMSImport ADD COLUMN Selected BIT", dbFailOnError
db.Execute "ALTER TABLE temp_GMSImport ADD COLUMN dvsValuationDef_ID INT"
db.Execute "UPDATE temp_GMSImport SET temp_GMSImport.Selected = -1;",dbFailOnError
The other BIG advantage is above is faster, does NOT mess with the Access "UI" settings, and you don't have to change setwarnings.
And the above does NOT force access to try and use "transactions".
So, the problem is we using two different connections, you using "db", and then using the docmd which is a "separate" connection - and you can't control this much.
With two connection objects, it "almost" similar to two people running the two different parts of the code.
Give the above a try - stick to "one" connection object, so they can "behave" as a similar group of commands. And as noted, dumping docmd has several downsides, and is more attached to the Access "UI" options then it is to pure code.

Using SQL statement for conditional update tables in access 2013

I am new to databases. I am creating an Access database to track the inventory dynamics of our company. I have two tables. One is the current inventory stock, another is consumption raised by production activity. The update is done immediately after each production.
Before doing update, I want to verify the same unit is used in both stock status and consumption sheet. I try to do something like these:
Private Sub Command4_Click()
CurrentDb.Execute "SELECT o.Unit, s.Material_Unit" & _
"CASE WHEN o.Unite = s.Material_Unit" & _
"THEN UPDATE tbl_Current_Stock As o INNER JOIN bl_Temp_Raw_Material_Consumption AS s ON o.Raw_Material = s.[Ingredient/Packaging material] Set o.Stock_Level = o.Stock_Level - s.Consumption" & _
" Print'Congratulations! You have successfully updated inventory balance!'" & _
"ElSE PRINT ' Units of source data and targeted data are not matched!'" & _
"Exit Sub" & _
"End" & _
"FROM tbl_Current_Stock As o, bl_Temp_Raw_Material_Consumption AS s"
END sub
But it seems some errors exist. Please help me on these codes.
Thanks.
Your code is totally wrong. You can not use CASE to datermine which statement to execute, UPDATE or PRINT(PRINT is useless here, in MS Access).
You need to use either:
IF statement in your SQL query - declare o.Unite and s.Material_Unit as variables and compare them, if they match then execute update.
IF #unite = #materialunite
BEGIN
[Your Update Statement]
END
The other way:
Declare VB variables, assign the o.Unite and s.Material_Unit values to them, and write IF - ELSE statements in VB and execute your SQL queries.

Join operation syntax error

I am trying to make a query through a button; though it says
Syntax error in JOIN operation. When I click it... I can't find the syntax error, maybe you guys can help me out? This is the code:
Set qdef = CurrentDb.CreateQueryDef("UnitMoreInfoQ", _
"SELECT UnitsT.*, WorkOrdersQ.CustomerName, WorkOrdersQ.ClientName, WorkOrdersQ.WorkOrderNumber " & _
"FROM UnitsT inner join workordersQ on WorkOrdersT.WorkOrerID=WorkOrdersQ.WorkOrderID " & _
"WHERE UnitsT.UnitID = " & txtWorkOrderID.Value)
The problem seems to be with your JOIN condition:
WorkOrdersT.WorkOrerID=WorkOrdersQ.WorkOrderID
There isn't a WorkOrdersT table or table alias defined in the FROM or other join, so your query isn't valid.
Make it easier on yourself to find and fix SQL errors.
Use a string variable to hold the SQL statement your code constructs. You can Debug.Print that statement before using it with CreateQueryDef. Then when troubleshooting, go to the Immediate window (Ctrl+g) to examine the statement your code is attempting to use. You can copy it from there and then paste it into SQL View of a new query for further testing. And if you need help, show us the completed statement text instead of the VBA code which builds the statement.
Dim strSelect As String
strSelect = "SELECT u.*, w.CustomerName, w.ClientName, w.WorkOrderNumber " & _
"FROM UnitsT As u inner join workordersQ AS w " & _
"on u.WorkOrerID=w.WorkOrderID " & _
"WHERE u.UnitID = " & txtWorkOrderID.Value
Debug.Print strSelect
Set qdef = CurrentDb.CreateQueryDef("UnitMoreInfoQ", strSelect)
Alternatively, use the query designer to create the query you need from scratch. Once you get that working, switch to SQL view, copy the statement text, and revise your VBA code to create the same statement.

Updating a field dependent on a date range in Access with VisualBasic and SQL

A friend and I have been trying for hours with little progress to a get a piece of code right for an invoicing system we're designing as a project.
We are trying to update the field InvoiceNo to a value (worked out earlier in the VisualBasic code), where the CustomerNo is the is a specific value and the FinishDate is between two dates. At first I was trying to use TO_DATE but then we realized that wasn't the same in the SQL that Access uses (after much searching).
This has been the simple statement I've been using to just test and try to get something working to then translate into VisualBasic and put in our variables. It's a little easier to read so I thought I'd provide it.
UPDATE tblJob SET tblJob.InvoiceNo = '8' WHERE tblJob.CustomerNo = '1' AND (tblJob.FinishDate BETWEEN cdate(format('08/09/2013', '##/##/####')) AND cdate(format('03/10/2013', '##/##/####')));
I have a feeling after looking at a few examples that our date is meant to be without an forward slashes. So I tried that and it wasn't working either.
Here's the VisualBasic code that has come out of all of this, it's exactly the same but using some variables rather than our set values that I've been using for testing.
DoCmd.RunSQL ("UPDATE tblJob SET tblJob.InvoiceNo = '" & newInvoiceNo & "' WHERE tblJob.CustomerNo = '" & VbCustNo & "' AND (tblJob.FinishDate BETWEEN cdate(format('" & Forms![frmMainMenu][txtFirstDate] & "', '##/##/####')) AND cdate(format('" & Forms![frmMainmenu][txtEndDate] & "', '##/##/####')));")
We had a look at: Convert a string to a date in Access and it helped us realize that it was cdate(format()) rather than TO_DATE as it is in Oracle. But we just can't seem to get it to run properly, any help would be much appreciated.
If you will be running the query from within an Access application session, you can let the db engine use the Access expression service to grab the values from the text boxes on your form.
Dim db As DAO.Database
Dim strUpdate As String
strUpdate = "UPDATE tblJob" & vbCrLf & _
"SET InvoiceNo = '" & newInvoiceNo & "'" & vbCrLf & _
"WHERE CustomerNo = '" & VbCustNo & "'" & vbCrLf & _
"AND FinishDate BETWEEN Forms!frmMainMenu!txtFirstDate AND Forms!frmMainmenu!txtEndDate;"
Debug.Print strUpdate
Set db = CurrentDb
db.Execute strUpdate, dbFailOnError
Set db = Nothing
However, if you prefer to build the literal date values from those text boxes into your UPDATE statement, you can use Format().
"AND FinishDate BETWEEN " & _
Format(Forms!frmMainmenu!txtFirstDate, "\#yyyy-m-d\#") & _
" AND " & Format(Forms!frmMainmenu!txtEndDate, "\#yyyy-m-d\#") & ";"
Either way, using a string variable to hold your UPDATE statement gives you an opportunity to examine the completed statement you're asking the db engine to execute.
You can view the output from Debug.Print in the Immediate window (go there with Ctl+g). For troubleshooting, you can copy the statement text from there and then paste it into SQL View of a new Access query.

MS Access reference issue with form fields

Hi there this is my goal, I have a for with a start date(start_Date) and end date(end_Date) field and a report which has a crosstab query as a record source. I want to be able to sort the data on my report based on the dates given on the form. I tried 3 different approaches.
Running a macro and opening the report with a where condition in which case Access would complain and say "[Reports]![AuditPTETotal]![Date] is not a valid reference"
Setting the "where condition" of my report through VBA. Another reference error but this time, it says that my forms fields are invalid.
Private Sub ViewReport_Click()
Dim strWhere As String
If Not IsNull(Me.start_Date) Then
strWhere = strWhere & " AND [Reports]![AuditPTETotal]![Date] >=#" & [Forms]! [AuditPTETotals]![start_Date] & "# "
End If
If Not IsNull(Me.end_Date) Then
strWhere = strWhere & " AND [Reports]![AuditPTETotal]![Date] <=#" & [Forms]! [AuditPTETotals]![end_Date] & "# "
End If
DoCmd.OpenReport "AuditPTETotal", acViewNormal, , strWhere
End Sub
And finally, passing in my forms values into the query. None of these approaches have worked for me and I really need to get this done. I am out of option. Any help would be appreciated.
Query
PARAMETERS [Forms]![AuditPTETotals]![start_Date] DateTime, [Forms]![AuditPTETotals]! [end_Date] DateTime;
TRANSFORM Sum(ScrapCollection.PTEtotal) AS SumOfPTEtotal
SELECT ScrapCollection.Date, ScrapCollection.regNum
FROM ScrapCollection INNER JOIN (ScrapTireType INNER JOIN ScrapCollectionTireType ON (ScrapTireType.scrapTireTypeID = ScrapCollectionTireType.scrapTireTypeID) AND (ScrapTireType.scrapTireTypeID = ScrapCollectionTireType.scrapTireTypeID)) ON ScrapCollection.scrapCollectionID = ScrapCollectionTireType.scrapCollectionID
WHERE (((ScrapCollection.Date) Between [Forms]![AuditPTETotals]![start_Date] And [Forms]![AuditPTETotals]![end_Date]))
GROUP BY ScrapCollection.Date, ScrapCollection.regNum
PIVOT ScrapTireType.description;
If you want to limit the results of a crosstab by using a form, you must have parameters:
PARAMETERS [Forms]![AForm]![text0] DateTime, [Forms]![AForm]![text2] DateTime;
TRANSFORM Count(Table1.AKey) AS CountOfAKey
SELECT Table1.AText
FROM Table1
WHERE (((Table1.ADate) Between [Forms]![AForm]![text0] And [Forms]![AForm]![text2]))
GROUP BY Table1.AText
PIVOT Table1.ADate;