Access 2007 VBA: Returning data from SQL statements that use multiple variables - sql

I am working on a form that is meant to analyze financial data ahead of an insurance policy renewal. It needs to pull various premium and claim $$ totals from the tables, and insert them into the form. From there, it will run some calculations with them, but that should be the easy part. Where I'm struggling is the SQL statements to get the data, in the first place.
After narrowing it down a bit, I've found that the problem is the code is putting the SQL statement into the field on the form, instead of the answer the SQL statement should be providing. I have tried multiple things I've seen online, and can't figure out how to resolve this.
One of the SQL statements reads like this:
L12W = "SELECT Sum(tblActPrem.APWrit) AS SumOfAPWrit FROM tblActPrem " _
& " WHERE tblActPrem.EntID = '" & Me.ctlActEntID & "' " _
& " AND tblActPrem.PolNum = '" & Me.ctltblRnwlTrack_PolNum & "'" _
& " AND tblActPrem.APDate BETWEEN #" & L12M & "# AND #" & Me.ctlRnwAnalysisDt & "#;"""
It should be totalling premium data from the table, where the policy number and account number match what's on the form, and between the selected dates, and putting that total into the field on the form. Instead, I get this on the form:
SELECT Sum(tblActPrem.APWrit) AS SumOfAPWrit FROM tblActPrem WHERE tblActPrem.EntID = '1235' AND tblActPrem.PolNum = 'Policy1' AND tblActPrem.APDate BETWEEN #1/1/2014# AND #1/1/2015#;"
That is exactly how the statement should be running, but can anyone tell me how to make the leap from the statement, to the data?
Thank you!

Consider using DLookup or DSum in the control source of the form's field.
DLookup Solution
First, change your VBA SQL query into a stored SQL Query (notice quotes and # symbols are not necessary when referencing form controls):
SELECT Sum(tblActPrem.APWrit) AS SumOfAPWrit
FROM tblActPrem
WHERE tblActPrem.EntID = Forms!<yourformname>!ctlActEntID
AND tblActPrem.PolNum = Forms!<yourformname>!ctltblRnwlTrack_PolNum
AND tblActPrem.APDate BETWEEN Forms!<yourformname>!L12M
AND Forms!<yourformname>!ctlRnwAnalysisDt
And then in the form field textbox's control source use the DLookUp function (no criteria argument is needed since this should return only one value).
= DLookUp("SumOfAPWrit", "<yournewqueryname>")
DSum Solution
Alternatively, you can change the entire SQL statement into a DSum but notice how long the criteria (WHERE statement) would have to be.
= DSum("APWrit", "tblActPrem", "EntID = Forms!<yourformname>!ctlActEntID
AND PolNum = Forms!<yourformname>!ctltblRnwlTrack_PolNum
AND APDate BETWEEN Forms!<yourformname>!L12M AND Forms!<yourformname>!ctlRnwAnalysisDt")

Related

Access Subform SourceObject Set to Query updated with SQL - Column Order and Width?

I have an Access form with different functions users can do. They are pulling lists of data, all from 1 table. Based on different filters or operations they want to do, I dynamically construct the SQL, use that to update the query defs of a query, and then set the subform object to that updated query. The problem is that the one I update the subform source object to the query, I need the columns that show to be in the order of the query.
This is the code I use, at different points of use on the form, depending on if they are interacting with a combo box, entering a filter into a textbox control on the main form, and I use similar code to set the default sql/query defs on load of the form. Why don't the columns always show in the same order as the sql that was updated to the query's definition?
Dim fsql As String
fsql = "SELECT table1.field1, table1.field2, table1.field3, table1.field4, table1.field5, table1.field6, table1.field7 " & _
"FROM tblVFileImport "
If Nz(Me.cboFilterA, "") = "" Then
fsql = fsql & "ORDER BY table1.field2, table1.field3 "
Else
fsql = fsql & "WHERE table1.field6 = '" &Me.cboFilterA & "' "
fsql = fsql & "ORDER BY table1.field4, table1.field5 "
Me.cmdExtrabutton.Visible = True
End If
CurrentDb.QueryDefs("qrySubformSpecs").SQL = fsql
Forms!frmDoStuff.Form.frmDoStuff_SubResults.SourceObject = ""
Forms!frmDoStuff.Form.frmDoStuff_SubResults.SourceObject = "Query.qrySubformSpecs"
The columns get in order some times, but not consistently.
I also want to fit the columns a small as they can, fitting the contents of their respective data, if that's possible. The column fit is not as big of a deal, because the user can select the left corner and then double-click between the columns if they really need to. The order of the columns is definitely more important here.
If anyone knows how to accomplish this, I would really love the help. Thanks!
FWIW, the backend is SQL, so this is all coming from 1 big linked table. The performance is quick and not an issue, but the column order is important and needing to work right.

Run one MS Access SQL script on a particular Table chosen by user

I have a MS Access 2016 database (*.accdb) with 20+ Tables. Fields in each of them vary slightly from Table to Table. I've no VBA experience, so I'm sticking only to the SQL query below (redacted).
SQL script
myvar below is the parameter I'd like to be prompted when the script is run so that I enter the Table I want the changes applied to.
PARAMETERS
[myvar] TableID;
UPDATE
[myvar]
INNER JOIN
Excel_Data ON [myvar].[Part Number] = Excel_Data.[Part Number]
SET
[myvar].[Value] = '?',
[myvar].Description = Excel_Data.Description,
[myvar].[Ref] = '?'
.
.
.
WHERE
[myvar].Description Is Null;
Output
Error message:
Too few parameters. Expected 0.
What I need
I prefer a solution for above in a SQL script form as above, not involving VBA, preferably. I'd like to enter the Table name when prompted so the script knows which table to UPDATE. FYI: The PARAMETERS work when it is not a Table as I've shown in my script above.
Help/advise is highly appreciated.
EDIT 1
Since it seems not possible to use parameters as Table names, could you suggest a VBA solution? A sample code, perhaps?
As said in the comments, you can't really solve this without VBA.
You can store your SQL query in a string, and use a placeholder to indicate the tablename. Then get the tablename using an inputbox and replace the placeholder with the tablename.
Dim sqlString As String
sqlString = "UPDATE [%Placeholder%] " & vbCrLf & _
"INNER JOIN Excel_Data ON [%Placeholder%].[Part Number] = Excel_Data.[Part Number] " & vbCrLf & _
"SET [%Placeholder%].[Value] = '?', " & vbCrLf & _
...
"WHERE [%Placeholder%].Description Is Null;"
sqlString = Replace(sqlString, "%PlaceHolder%", InputBox("Enter a tablename"))
CurrentDb.Execute sqlString
In a more mature solution, I'd create a form with a combobox containing all available table names, and add a function to sanitize tablenames (replace "]" with "]]")

Access 2010 VBA: SQL insert query is picking up 1 variable but not the other variable

OK usually I'm pretty good at googling around and using debug.print to isolate and solve the problem but this one is escaping me.
The purpose of this code is to create a new record in a table, using a form in which a person has selected a team member's name from a dropdown and a project phase from a dropdown and then input a number of hours into a textbox, then clicked a button that says "Add". There are a few if/thens involved but I'm leaving out the irrelevant parts (the code produces the same error in all cases.)
All of the code takes place inside one public function. All variables are Dim.
First it runs some code to find the value of "MyPersonID". (Complicated and not relevant as that works just fine).
Then it runs some code to find the value of "MyProjectPhaseID" which looks like this:
MyProjectPhaseID = [Forms]![HourValidationsFromTeam]![InputProjectPhase]
This variable populates correctly (as per Debug.Print)
Then it creates the INSERT SQL statement and runs it:
strAppendHourRecordSQL = "INSERT INTO PersonCommitmentsHours ( PersonNameLookup, ProjectPhase, WeekOfCommitment, DateValidated, HourCommitment, ValidationResult ) SELECT '" & (MyPersonID) & "' AS PersonNameLookup, '" & MyProjectPhaseID & "' AS ProjectPhase, [Forms]![HourValidationsFromTeam]![LastWeekDate] AS Week, Date$() AS TodaysDate, [Forms]![HourValidationsFromTeam]![InputSuppliedHours] AS Hours, " & Chr(34) & "More" & Chr(34) & " AS ValidationType;"
Debug.Print MyProjectPhaseID
Debug.Print strAppendHourRecordSQL
DoCmd.RunSQL strAppendHourRecordSQL
This is what Debug.Print returns:
2069
INSERT INTO PersonCommitmentsHours ( PersonNameLookup, ProjectPhase, WeekOfCommitment, DateValidated, HourCommitment, ValidationResult ) SELECT '260' AS PersonNameLookup, '' AS ProjectPhase, [Forms]![HourValidationsFromTeam]![LastWeekDate] AS Week, Date$() AS TodaysDate, [Forms]![HourValidationsFromTeam]![InputSuppliedHours] AS Hours, "More" AS ValidationType;
The query runs correctly and inserts a record with everything in the right place except it's missing the value where MyProjectPhaseID should go. It's just null. I thought maybe the variable was null, but Debug.Print returns the correct value. Even the debugger fills the value in when I hover over the SQL.
I tried different combinations of adding and removing parentheses and quotes around the variable in the SQL but they have no effect.
Please help!
I figured out the problem. The problem is that you cannot define the SQL before the variables have been populated. I thought you could define the SQL and then re-use it depending on where you get your variables from. But no. That's why it had the right value for the variable, but it couldn't put them together. I didn't make it clear from the way I wrote the question that this could be a suspect, i'm sorry about that.
So in order to not try to pre-define SQL for variables that don't exist yet, I isolated the part of the SQL that won't change and define that first as strBoilerplateSQL.
Then do the IF statement for the stuff that could change, then define the part of the SQL statement that depends on that change, then concat the 2 sql statements together. Then it runs the completed SQL statement.
strBoilerplateSQL = "INSERT INTO PersonCommitmentsHours ( PersonNameLookup, WeekOfCommitment, DateValidated, HourCommitment, ValidationResult, ProjectPhaseLookup ) SELECT " & (MyPersonID) & " AS PersonNameLookup, [Forms]![HourValidationsFromTeam]![LastWeekDate] AS Week, Date$() AS TodaysDate, [Forms]![HourValidationsFromTeam]![InputSuppliedHours] AS Hours, " & Chr(34) & "More" & Chr(34) & " AS ValidationType, "
'Check to see if this is going in to an existing project or should we create a new project first
If (IsNull([Forms]![HourValidationsFromTeam]![InputNewProject].Value)) Then
'If the Input New Project text box is null, assemble the SQL and run it
MyProjectPhaseID = [Forms]![HourValidationsFromTeam]![InputProjectPhase].Value
strMyProjectPhaseSQL = "" & (MyProjectPhaseID) & " AS ProjectPhase;"
strReadySQL = (strBoilerplateSQL) & (strMyProjectPhaseSQL)
DoCmd.RunSQL strReadySQL
Else
'Some other stuff happens here
MyProjectPhaseID = GetPhaseID![TheProjectPhase]
'Now that we have the new project phase ID we can run the SQL from above (oh hey remember that?)
strMyProjectPhaseSQL = "" & (MyProjectPhaseID) & " AS ProjectPhaseLookup;"
strReadySQL = (strBoilerplateSQL) & (strMyProjectPhaseSQL)
DoCmd.RunSQL strReadySQL
End If

MS Access multi field search with empty fields

I have a problem very similar to this one, but I just can't seem to solve it!
In MS Access (2003), I want to search a table based on entries in a number of fields, some of which may be empty.
I have:
text fields
date fields
integer fields, and
a memo field (but we can probably not bother searching this one if it is difficult).
They map onto a table exactly.
I am trying to create a query that will return matching rows when data is entered into one or more of these fields, but some fields can be left blank. How the heck do I do this?
A query like the one on the linked question works for text fields, but what do I do about the number fields, date fields (and possibly even the memo field)?
To give a clear example, the following code block works for TextField1, but not NumberField1:
PARAMETERS [Forms]![SearchForm]![FilterTextField1] Text ( 255 ), [Forms]![SearchForm]![FilterNumberField1] Text ( 255 );
SELECT Table1.[TextField1], Table1.[NumberField1], Table1.[TextField2], Table1.[TextField3], Table1.[DateField1], Table1.[DateField2], Table1.[DateField3]
FROM Table1
WHERE (Len([Forms]![SearchForm]![FilterTextField1] & '')=0 OR Table1.[TextField1] Like '*' & [Forms]![SearchForm]![FilterTextField1] & '*') AND (Len([Forms]![SearchForm]![FilterNumberField1] & '')=0 OR Table1.[NumberField1] Like '*' & [Forms]![SearchForm]![FilterNumberField1] & '*');
I do hope you can help. I'm sure I'm missing something really obvious, but for some reason my brain feels like it is leaking out of my ears at the moment.
Thank you!
If you need it, this is the basic design of the relevant entities:
Table1
SomePrimaryKeyWeDontCareAboutRightNow
TextField1
TextField2
TextField3
NumberField1
DateField1
DateField2
DateField3
MemoField1
SearchForm
FilterTextField1
FilterTextField2
FilterTextField3
FilterNumberField1
FilterDateField1
FilterDateField2
FilterDateField3
FilterMemoField1
You can check fo null values or cast to string
You could certainly spend a great deal of time crafting a huge and very hard to debug SQL query for this, or just jump into VBA and write some code to construct just the SQL you need.
VBA is there just for these kinds of scenario, where something is either impossible or becoming too complex to do otherwise.
With VBA, you can use an initial SELECT query that collect all the data, and then construct a WHERE clause based on the content of your search form to filter it.
For instance, I have a form like this, that allows the user to enter any criteria to filter a list of prices:
Some code to implement this could look like:
' Call this whenever the use click the Apply button '
Private Sub btApply_Click()
' Construct the filter '
Dim filter As String
If Not IsBlank(cbSupplierID) Then
If Not IsBlank(filter) Then filter = filter & " AND "
filter = filter & "(SupplierID=" & cbSupplierID & ")"
End If
If Not IsBlank(txtPartNumber) Then
If Not IsBlank(filter) Then filter = filter & " AND "
filter = filter & "(PartNumber LIKE '*" & txtPartNumber & "*')"
End If
If Not ckShowLocked Then
If Not IsBlank(filter) Then filter = filter & " AND "
filter = filter & "(NOT PriceLocked)"
End If
' ... code snipped, you get the jest ... '
' Now re-construct the SQL query '
Dim sql As String
sql = "SELECT * FROM Price"
If Not IsBlank(filter) Then
sql = sql & " WHERE " & filter
End If
SubForm.Form.RecordSource = sql
End Sub
It may seem like a lot of code, but each block only does one thing, and it's a lot easier to debug and maintain than cramming everything into a query.

dlookup multiple tables and set textbox to result access 2007

I'll try and break down my problem as best I can and explain what I'm trying to achieve. Firstly, I have three tables:
**RFI** (stands for Request For Information)-
Fields: rfi_id, Customer_id .....
**RFI_project** -
Fields: rfipro_id, project_id, rfi_id *"....." represents other unnecessary fields*
**Customer** -
Fields: Customer_id, company .....
I have an access form with two comboboxes. On the first combobox I select the name of a project at which point the second textbox changes to show those *rfi_id*'s where there is a match with the project name selected.
Now what I'm trying to do is this - When I select an *rfi_id* in the second combobox I want it to display in a textbox on my form the company where there the *rfi_id* value matches the value in the combobox. It's a bit tricky due to the way the tables are joined...here is what I'm essentially trying to display in the textbox field in SQL terms:
SELECT Customer.company, RFI.Customer_id
FROM Customer, RFI
WHERE (((Customer.Customer_id)=[RFI].[Customer_id]) AND ((RFI.rfi_id)=[Forms]![Request for Info Form]![Combo90]))
ORDER BY Customer.company;
In order to do this I have tried the following to no avail. In the after update event of my second combobox I have inserted the following:
companyTB = DLookup("company", "Customer", "Customer_id =" & DLookup("Customer_id", "RFI" And "rfi_id =" & [Forms]![Request for Info Form]![cmbRFI]))
When I change the combobox value I get the error Run-time error '13': Type mismatch. I've tried searching for what I've done wrong but this is a very broad error apparently and I can't find anything similar (or that I understand). I also tried this instead -
companyTB = DLookup("company", "Customer", "Customer_id =" & DLookup("Customer_id", "RFI", "rfi_id =" & cmbRFI))
which gives me the following error - Run-time error '3075': Syntax error(missing operator)in query expression. Anyway, would anybody be kind enough to give me a breakdown of what I need to do to achieve this, or what I'm doing wrong (or maybe a better way to do it?). Forgive me for being to seemingly stupid at this, I've only just begun working with access more in depth in the last 3 weeks or so. Thank you.
Your first DLookUp has incorrect syntax:
companyTB = DLookup("company", "Customer", "Customer_id ="
& DLookup("Customer_id", "RFI" And "rfi_id ="
& [Forms]![Request for Info Form]![cmbRFI]))
I have broken it into three lines to make this easier to see. The second line has And between "RFI" and "rfi_id" when it should have a comma.
companyTB = DLookup("company", "Customer", "Customer_id ="
& DLookup("Customer_id", "RFI", "rfi_id =" & cmbRFI))
The error you are getting on your second combo seems likely to be due to the result returned by cmbRFI. You can check this by filling in an actual rfi_id, rather than the reference to the combo and by setting a text box equal to cmbRFI and see what it is returning. Combo can be difficult because the displayed column and the bound column can be different.
It can be convenient to set up your combobox with several columns, as shown in your query, so the rowsource might be:
SELECT rfi.ID, Customer.company, RFI.Customer_id
FROM Customer
INNER JOIN RFI
ON Customer.Customer_id=RFI.Customer_id
ORDER BY Customer.company;
(or the three tables, joined, if necessary)
Then
Column count = 3
Column widths = 2cm;0;0
Bound column = 1
You can now refer to the second column in your textbox:
= cmbRFI.Column(1)
Columns are numbered from zero.
It is always worth reading up on sql before working with Access:
Fundamental Microsoft Jet SQL for Access 2000
Intermediate Microsoft Jet SQL for Access 2000
Advanced Microsoft Jet SQL for Access 2000
Your last Dlookup statement seems absolutely fine so I'm a little confused as to why it isn't working, you may be able to get round the problem like this though:
Combox2_AfterUpdate (Or whatever the event is called)
Dim rs As Recordset
Set rs = Currentdb.OpenRecordset("SELECT C.Company, R.Customer_ID " & _
"FROM Customer As C, RFI As R " & _
"WHERE C.Customer_ID = R.Customer_ID " & _
"AND R.RFI_ID =" & [Forms]![Request for Info Form]![Combo90] & " " & _
"ORDER BY C.Company")
CompanyTB = rs!Company
rs.Close
Set rs = Nothing
End Sub