This question already has answers here:
How do I use parameters in VBA in the different contexts in Microsoft Access?
(2 answers)
Closed 2 years ago.
Sorry for my dumb question.
I programming in Access (VBA) and I’m trying to send a variable called machine into a sql code and then insert it into a table. But i have no idea how to do it. this is my code for so far:
Private Sub MachineToevoegen_Click()
Dim SQL As String
Dim Machine As String
Machine = Machine_keuze
SQL = "INSERT INTO Machines ([Machine]) VALUES(Machine)"
DoCmd.RunSQL SQL
End Sub
If someone could help me with this it would be great.
Create a query where you pass the Machine as parameter.
For example:
PARAMETERS [prmMachine] Text (255);
INSERT INTO Machines ([Machine])
SELECT [prmMachine] AS _Machine;
Then, call the query in VBA:
With CurrentDb().QueryDefs("YourQueryName")
.Parameters("[prmMachine]").Value = Machine_keuze
.Execute dbFailOnError
End With
Try below.
Private Sub MachineToevoegen_Click()
Dim SQL As String
Dim Machine As String
Machine = "Machine_keuze"
SQL = "INSERT INTO Machines ([Machine]) VALUES('" & Machine & "')"
DoCmd.RunSQL SQL
End Sub
Related
Is there a way to know which SQL Server the linked tables in MS Access database are pointing to using the ODBC connection?
I used the code below but I got the database name only and not the SQL server name.
Private Function checkconn()
Dim strConnect As String
Dim lngLocation As String
strConnect = CurrentDb.TableDefs("dbo_buh_summary").Connect
lngLocation = InStr(strConnect, ";DATABASE=")
If lngLocation <> 0 Then
GetDataPath = Mid(strConnect, lngLocation + 10)
End If
End Function
Assuming you used a FILE dsn to original link the tables?
(or a DSN less). I strong, but rather strong recommend you link always using a FILE dsn (not system or user). The reason is Access converts these links to DSN-less for you automatic. (and thus you don't need to setup a DSN on each computer).
Having noted the above? You can grab the server and the database name with this:
Sub m34343()
Dim strCon As String
strCon = CurrentDb.TableDefs("dbo_tblHotels3").Connect
Debug.Print strCon
Debug.Print Split(Split(strCon, "SERVER=")(1), ";")(0)
Debug.Print Split(Split(strCon, "DATABASE=")(1), ";")(0)
End Sub
Output:
ODBC;DRIVER=SQL Server;SERVER=ALBERTKALLAL-PC\SQLEXPRESS;
Trusted_Connection=Yes;APP=Microsoft Office 2010;DATABASE=test3
ALBERTKALLAL-PC\SQLEXPRESS
test3
So, I in above printed out the connection string, but then the next two lines grabs the server and the database name.
I'm using Access 2010. Right now I have a function called SetQuerySource:
Private Sub SetQuerySource()
Dim sql As String
sql = DLookup("QueryText", "tblQuery", "QueryName ='qselDailyMilkYield'")
CurrentDb.QueryDefs("qselDailyMilkYield").sql = sql
sql = sql & vbCrLf & "where pt.DLVDate between '" & Me.txtDate
& "' AND '" & Me.txtEndDate & "' and pb.ITEMID like '%pm%' and pjb.ITEMID
like '%pm%' group by pt.ITEMID, pb.ITEMID, pt.NAME, pt.DLVDATE"
CurrentDb.QueryDefs("qselDailyMilkYield").sql = sql
End Sub
I use this to run a query located in a table named tblQuery in my Access database. I then append the Where clause to the query using VBA in case (as shown above) I need to point to a named control which holds a value based on user input.
I came into this setup. By that I mean I didn't create this function I just began using it. My question is how do I point to a different database on a different server? The query I need to run has tables (connected via ODBC) already linked to this Access database but my search of OpenDatabase proved futile as I didn't understand how to use it in my environment.
I receive this error:
[Microsoft][ODBC SQL Server Driver][SQL Server]Invalid object name 'dbo.MilkReceived'. (#208)
Private Sub cmdTruckDeliveries_Click()
SetQuerySource
DoCmd.OpenReport "rptTruckDeliveries", acViewPreview
End Sub
This is my code for the button click event jic.
Thank you,
I currently have a SQL 2008 R2 database backend with an Access 2013 accdb front end with ODBC DSN-less connection and linked tables. In SQL I have many parameterized tSQL UDFs created to feed data into reports (currently working well in my Access 2010 adp frontend). The reports are complicated: multiple tSQL UDFs run calculations and then feed into a final UDF that feeds the respective report. I would like to keep the UDFs on the server – rewriting into Access queries would be a poor solution.
My problem is that I have not been able to figure out how to write the VBA correctly to send a pass-through query to call the tSQL UDF and give it a parameter, which would change for each report. I know pass-through queries are read-only, that’s ok. I’ve read that I can call a stored procedure (SP) from VBA, but can I call the UDF rather than having to convert each to a SP or create a SP just to call the UDF so that I could call the SP from VBA. Based on my research, I think I might have to either create a SP to call the UDF or convert the UDF to a SP to get the VBA to work (i.e., return results without error). Is this correct?
I found this discussion: https://social.msdn.microsoft.com/Forums/office/en-US/898933f5-73f9-44e3-adb9-6aa79ebc948f/calling-a-sql-udf-from-access?forum=accessdev , but it has conflicting statements “You can't call a tSql udf from Access.”, and “You can use a passthrough query to call UDF's or stored procedures or anything else written in tsql.” Also, their code is written in ADO instead of DOA so it’s a bit cryptic to me since I’ve only written DAO so far, but the general gist that I got was they converted their UDF to a SP.
I found this article a great read, but again did not get a clear “yes” to my question:
http://technet.microsoft.com/en-us/library/bb188204(v=sql.90).aspx
It may be possible to remove the parameter from the Server side and add it to the Access side similar to this Access 2007 forms with parameterized RecordSource , but wouldn't that cause Access to load the entire dataset before filtering, instead of processing on the Server side – possibly causing performance issues?
I can successfully create a pass-through query in the Access interface if I supply it with a constant parameter, for example “Select * from udf_FinalReport(2023)”, but what I really need is to be able to pass a dynamic parameter. For example, the parameter would be from Forms!Control![txtboxValue]. Can I do this? The following code is what I’m using– it works if I use a table name in the SQL (ex, “SELECT * FROM Table WHERE tblYear = “&intYear ) in line 9 so I feel like I have everything coded right, but when I put my UDF in the SQL like below I get the error #3131 “Syntax error in FROM clause.” (I did verify that I should not use the prefix schema (dbo.) – this gives error 3024 “could not find file”.) Is this user error or just plain telling me I can’t call a UDF this way?
1 Sub AnnualSummary()
2 Dim dbs As DAO.Database
3 Dim qdfPoint As DAO.QueryDef
4 Dim rstPoint As DAO.Recordset
5 Dim intYear As Integer
6 intYear = Reports!Annual_Delineation_Summary!txtYear
7 Set dbs = OpenDatabase("", False, False, "ODBC;DRIVER=sql server;SERVER=******;APP=Microsoft
8 Office 2010;DATABASE=*******;Network=DBMSSOCN")
9 Set qdfPoint = dbs.CreateQueryDef("", "Select * from udf_AnnualReport(" & intYear& ")")
10 GetPointTemp qdfPoint
11 ExitProcedure:
12 On Error Resume Next
13 Set qdfPoint = Nothing
14 Set dbs = Nothing
15 Set rstPoint = Nothing
16 Exit Sub
17 End Sub
18
19 Function GetPointTemp(qdfPoint As QueryDef)
20 Dim rstPoint As Recordset
21 With qdfPoint
22 Debug.Print .Name
23 Debug.Print " " & .SQL
24 Set rstPoint = .OpenRecordset(dbOpenSnapshot)
25 With rstPoint
26 .MoveLast
27 Debug.Print " Number of records = " & _
28 .RecordCount
29 Debug.Print
30 .Close
31 End With
32 End With
33 End Function
I also tried writing the code a little differently, using the following instead of lines 5, 6, and 9. This also works when I use a table name in the select statement, but I get error #3131 when I use a UDF name:
Set qdfPoint = dbs.CreateQueryDef("", "Parameters year int; Select * from Point_Info where
year(Sample_Date) = year")
qdfPoint.Parameters("year").Value = intYear
Both code variations also work if I try use the name of a SQL View in the tSQL SELECT statement.
My consensus is using ADO language instead of DAO to write the pass-through query works well. But, I have found that it is still probably better to execute a stored procedure than to try to call the UDF. Here is the code that ended up working most smoothly for me: (my ADO Connection uses Public variables strUID and strPWD)
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim strPoint As String
strPoint = Forms!FRM_Vegetation_Strata!Point_ID
Set cn = New ADODB.Connection
cn.Open "Provider = sqloledb;Data Source=imperialis.inhs.illinois.edu;" & _
"Initial Catalog=WetlandsDB_SQL;User Id=" & strUID & ";Password=" & strPWD
Set rs = New ADODB.Recordset
With rs
Set .ActiveConnection = cn
.Source = "sp_Report_VegWorksheet '" & strPoint & "'"
.LockType = adLockOptimistic
.CursorType = adOpenKeyset
.CursorLocation = adUseClient
.Open
End With
Set Me.Recordset = rs
On a side note I found that to get set the .Recordset to fill a subform put this code in the "Open" event of the subform.
Then to clean up your connection:
Private Sub Form_Unload(Cancel As Integer) 'use "unload", not "close"
'Close the ADO connection we opened
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = Me.Recordset.ActiveConnection
cn.Close
Set cn = Nothing
Set rs = Nothing
Set Me.Recordset = Nothing
End Sub
This approach does not work for populating a report. "Set Me.Recordset" only works for forms. I believe I will have to call a stored procedure then populate a temp table to use as the report recordset.
EDIT: I have found that I can call a SQL UDF or SP from VBA in Access using DOA. This is particularly helpful when one wants to pull the data from a complicated SQL function/procedure and put it into an Access-side temp table. See Juan Soto's blog https://accessexperts.com/blog/2012/01/10/create-temp-tables-in-access-from-sql-server-tables/#comment-218563 This code puts the info into a temp table, which is what I wanted to populate my reports. I used his code example and the following to call the sub:
To execute as SP: CreateLocalSQLTable "testTBL","exec dbo.sp_Report_WetDet_point '1617-1-1A'",False
To call a UDF: CreateLocalSQLTable "testTBL","Select * from dbo.QryReport_Main('1617-2-2A')",False
I don't know if it's the most efficient method of passing a variable parameter through a pass-through query into a function and returning the results to Access, as I am still relatively new to Access, but I came across this earlier when I was attempting a similar problem.
I managed it by creating a couple of pass-through queries that executed functions in SQL server and returned a result. I then made a small VBA script that re-wrote the pass-through queries with the new variable every time I wanted to change it, and executed them.
I got the result back out using OpenRecordset, and stored it as a string to use in the rest of my code.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
I have a table with multiple fields in MS access. These fields have field names representing periods of time, such as 2011_2, 2011_3,..., 2013_9, 2013_10, ... , 2015_1, 2015_2...
How do I run a query that selects the next 12 months as the needed fields based on today's date? i.e, if today is 22 Dec 2013, it selects the fields : 2013_12, 2014_1, 2014_2, ..., 2014_12?
Thanks a bunch.
The short answer to your question is that you can't have dynamic field names in the Access query builder. Ideally, you should modify your data so that you have one date field. That way you can specify a date range for that field in the query criteria that doesn't require the gymnastics below.
If that's not possible, though, the long answer is that you'll need to use VBA code to construct your query. The code below should create a new query in your database (cleverly called "YourQuery") that will contain the fields you need.
Since I don't know what your table is called, it'll be "table" in this example. You should change it to whatever your table is if you use this code.
You'll need to install this code in a VBA module in your database, and then devise some means of calling the function to produce the new query. For example, you could create a macro using the "RunCode" action that uses "DynamicQuery()" as the procedure to run. Note that the function call will fail if the query for this month already exists so delete that manually if you need to run it again for some reason (you could also add additional code to function to accomplish this).
Again, just because you can do something doesn't mean you should. You really should redesign your table so you don't have to resort to workarounds like this.
Public Function DynamicQuery()
Dim strSQL As String
dim datFieldDate As Date
Dim strYearMonth As String
Dim strThisMonth As String
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Dim i As Integer
Set dbs = CurrentDb
strThisMonth = Year(Date) & "_" & Month(Date)
strSQL = "SELECT table." & strThisMonth
For i = 1 to 12
datFieldDate = DateAdd("m",i,Date)
strYearMonth = Year(datFieldDate) & "_" & Month(DatFieldDate)
strSQL = strSQL & ", table." & strYearMonth
Next i
strSQL = strSQL & " FROM table;"
Set qdf = dbs.CreateQueryDef("YourQuery_" & strThisMonth, strSQL)
Set qdf = Nothing
Set dbs = Nothing
End Function
If you have a form in Access with a button on it you could create the SQL statement in code as a string, eg:
MyString = "SELECT " & Year(Now) & "_9" & " FROM myTable....."
You can then execute it via code.
You won't be able to create a "standard" query that dynamically builds a list of fields to select.
having this code (which i know the open/executenonquery/close conection in for loop is absolutely horrible).
Public Shared Sub salvarDatos(ByRef conexion As SqlConnection, ByRef datos As List(Of DatoBdReloj))
For i = 0 To datos.Count - 1
Dim laQuery As String = "Insert INTO MARCADASRELOJ (COD_MAR_RELOJ,FECHA_RELOJ,HORA_RELOJ,MINUTOS_RELOJ,NRO_RELOJ,NRO_TARJ) " & _
"VALUES (#codMarReloj,#fechaReloj,#horaReloj,#minutosReloj,#nroReloj,#nroTarj)"
Dim datoReloj As DatoBdReloj = datos.Item(i)
Dim command As SqlCommand = New SqlCommand(laQuery, conexion)
command.Parameters.AddWithValue("codMarReloj", datoReloj.tipoMarca)
command.Parameters.AddWithValue("fechaReloj", datoReloj.fechaHoraMarcaDT)
command.Parameters.AddWithValue("horaReloj", datoReloj.fechaHoraMarcaDT.Hour)
command.Parameters.AddWithValue("minutosReloj", datoReloj.fechaHoraMarcaDT.Minute)
command.Parameters.AddWithValue("nroReloj", datoReloj.idReloj)
command.Parameters.AddWithValue("nroTarj", datoReloj.idUsuario)
conexion.Open()
command.ExecuteNonQuery()
conexion.Close()
Next
End Sub
I don't have much experience with .net , but for what i have read using the AddWithValue method i can prevent sql injections and according to the "book" is the right way to do it (tell me if i'm wrong).
using a sentence like "Insert into xxx (x1,x2,x3) values ("val","val","val"),(...),(...)" to insert multiple rows is not an option for me because my database is running with sql 2005.
How can i take away that horrible open/execute/close inside the for loop to insert multiple rows no matter if it's sql 2005 or 2008 and also keep being secure from sql injections by using the AddWithValue Method?
Thanks! :)
Hello you can use bulkinsert
The code: BulkInserter
How to use it