I have a small query builder on a form I created that allows the user to save the query they built. Works great! Then I realized that they can save multiple queries using the same name. Not good. What I'm doing is when they build the query and choose to save it, I just add the SQL string to a table in one field and a name, that they choose, in another field. Easy enough. So now I figure all I have to do search the Name field and check it against the name the user has chosen. I dont know why, but I cant seem to wrap my mind around it. I can't seem to get the FindRecord to work. Does it return a boolean? Can't I just do something like this...
If DoCmd.FindRecord(userNameVariable) = True Then
msgbox("That name exists")
Else
msgbox(That name doesnt exist)
End If
Now that I look at that, it doesn't give any where to look, such as the table and field name.
DoCmd.FindRecord returns the first record found with that criteria. If you only want to check if that name already exists I think that there is a better way to do what you need.
One way is to build a SQL string like
"SELECT [Name] FROM [Table] WHERE [Name] = '" & userNameVariable & "'",
execute the Query and then test if the recordset is empty. The Code would look like
Dim rs as recordset
Dim strSQL as string
strSQL = "SELECT [Name] FROM [Table] WHERE [Name] = '" & userNameVariable & "'"
Set rs = CurrentDb.OpenRecordset(strSQL)
If rs.RecordCount > 0 Then
msgbox "This Query name already exists, please select another"
End If
According to msdn, it simply goes to the data you searched for. I don't think that's what you need.
Here's what I would do (I'm not saying it's the best method, just what I would do). Assuming the table is called TblName and the field holding the saved name is SQLName then:
If CurrentDb.OpenRecordset( _
"Select count(*) from TblName where SQLName='" & SQLName & "';") _
.Fields(0) > 0 Then
'Do Something
End If
Saved query names are stored in the unsupported MSysObjects table, so in a local database you can look up that table to find if a query exists:
If IsNull(DLookup("name", "msysobjects", "name='" _
& qryname & "' and type=5")) Then
Set qdf = CurrentDb.CreateQueryDef(qryname, sSQL)
Else
MsgBox qryname " already exists."
End If
Related
I have a main "final table" being updated through VBA based on many inputs of a Form and other tables data. I am trying to callout a TextBox object value that exists in a form to the VBA code so user can add a comment to all the data being inserted into the final table.
Dim strComment As String
strComment = TextBox_Comment.Value
strSQL = "INSERT INTO Main_Table (Period, Monthp, Order, Comment)"
strSQL = strSQL & "SELECT ""Weekly"" AS Period, [001_SelectedMonth].Monthp, [001_OrderTable].Order, strComment AS Comment FROM 001_SelectedMonth, 001_OrderTable;"
CurrentDb.Execute strSQL, dbFailOnError
The code works fine when I remove both the "Comment" from the Main Table insertion points and the "strComment AS Comment" part of the code. Otherwise I get the Run-Time Error '3061', Too few parameters. Expected 1.
Question: is there a way for me to callout the text box value to be inserted in the database as a field data for all the data being added or should I use another method to do this?
Example of the final table:
You need a space and proper concatenation:
strSQL = "INSERT INTO Main_Table ([Period], Monthp, [Order], [Comment]) "
strSQL = strSQL & "SELECT 'Weekly' AS [Period], [001_SelectedMonth].Monthp, [001_OrderTable].Order, '" & strComment & "' AS [Comment] FROM 001_SelectedMonth, 001_OrderTable;"
That said, use parameters to avoid the concatenation.
Thanks in advance everyone, Im using vba and MS Access 2016 to work on a restaurant's db.
I need to open a table to get a record which is a table name that I then need to open, its kinda messy but I thought I had it until I started getting the 3078 error. (Btw I just started using access for this project so it could be a simple syntax error I don't see)
The db im working on was made in a half assed way unfortunately so it isn't quietly consistent or well formated and it is half in spanish half in english however I'm sure the table name is correct and exists. If I put the query in access instead of vba and with the name instead of a variable it works just fine. Here's the code.
Sub QRventas()
Dim ventas As DAO.Recordset
Dim qrv As String
'Query daily sales
qrv = (SELECT menus.id, menus.descripcion, Sum(Nz(ComandasD.cantidad)) AS Total FROM ~~long and ugly but working query)
Set ventas = CurrentDb.OpenRecordset(qrv)
Dim receta As DAO.Recordset
Dim qrr As String
Do While Not ventas.EOF
'QR recipes
ventas.MoveNext
qrr = "SELECT ID, Ingredientes, Cantidad FROM [" & ventas(1) & "] GROUP BY ID, Ingredientes, Cantidad;" '<- Error Here
Set receta = CurrentDb.OpenRecordset(qrr) '<- Complains here 3078
Do While Not receta.EOF
'Updating Storage
CurrentDb.Execute "UPDATE Almacen " _
& "SET Cantidad_almacenada = Cantidad_almacenada - (cantidad * Total) " _
& "WHERE ID = " & receta(1) & ";"
receta.MoveNext
Loop
Loop
End Sub
possibly 'Fields' is missing:
qrr = "SELECT ID, Ingredientes, Cantidad FROM [" & ventas.Fields(1) & "]...
If Access complains that the table isn't there, it isn't.
Or, specifically use the Value property of the field.
So insert a debug line and study which table name it was supposed to find:
'QR recipes
ventas.MoveNext
Debug.Print "[" & ventas(1) & "]"
qrr = "SELECT ID, Ingredientes, Cantidad FROM [" & ventas(1).Value & "] GROUP BY ID, Ingredientes, Cantidad;" '<- Error Here
I tried the answers that people posted here but had no luck with them, then I did a "Compact and Repair" and the issue went away...
Thanks everyone again.
I have an Access 2010 database that is going to import data from an excel sheet and append that data to the proper table. The issue I am having is that once imported, the data will not have the customer ID attached to it so the cust_ID field in the table will be null. What I need is a macro that will ask the user who the customer is for each import and then find that customer's ID and put that value into all of the null fields. I have made a lot of different attempts at this (mostly though the macro builder I don't even know where to start with the VBA for this) none of which have shown any results. I think my latest one is close but for some reason it isn't running after the import. I have an "After Insert" macro, and the idea was that it would prompt the user for [Customer Name]
look-up the custID from TBL_Customers then insert that into each of the null fields. Unfortunately after I import my data nothing happens and I'm really not sure why.
Parameters Name: Customer Name
Look Up A Record In TBL_Customers
Where Condition =[TBL_Customers].[FLD_Customer_Name]=[Customer Name]
Alias custName
Look Up A Record In TBL_Customers
Where Condition =[TBL_Customers].[FLD_Customer_PK_ID]=[custName]
Alias custID
For Each Record In TBL_Contacts
Where condition =IsNull([FLD_Contact_FK_Customer_ID])
EditRecord
SetField
Name FLD_Contact_FK_Customer_ID
Value =[custID]
End EditRecord
Another possibility I was thinking would be to have another column in the excel sheet with the customer's name and then Access would just have to look up the cust_ID based on that column. My issue there is I don't know how I would tell Access to import the customer name from the excel sheet find that customer's ID and insert that ID into the proper table, which is why I was leaning toward the first option.
As I said in the comments I've tried a lot of different things but I'm fairly new to VBA/Access and am running out of ideas to try.
Not sure which would be easier/better so any ideas/suggestions/recommendations are greatly appreciated.
Here is a sample of something that might get you going in the right direction. In my case I had a similar situation, importing from excel, but often one piece of data was missing. What I did was had the "users" save the excel docs into subfolders with the customer id's as part of the folder names. Using the Scripting library you can recurse through the subfolders, and I use a custom FindCustomerID function to parse the ID you are looking for from the path name. Once the import happens, the customer id can be added in.
Function ImportBlah(importDir As String, tbl As String)
Dim importPath As String
Dim fs As Scripting.FileSystemObject
Dim fo, x AS Folder
Dim fi AS File
Dim custID As String
Set fs = CreateObject("Scripting.FileSystemObject")
With fs
Set fo = .GetFolder(importDir)
For Each x In fo.SubFolders
For Each fi In x.Files
If Not (fi.Attributes Mod 8 >= 4) Then 'If not a system file
DoCmd.TransferText acImportDelim, "import_specs", tbl, fi, True
custID = FindCustomerID(x.Path)
CurrentDb.Execute "UPDATE " & tbl & " SET FileName = '" _
& fi.ParentFolder.name & "\" & fi.name & "' WHERE FileName IS NULL", _
dbFailOnError 'Add filename to Filename column
CurrentDb.Execute "UPDATE " & tbl & " SET custID = '" & _
custID & "' WHERE custID IS NULL", dbFailOnError 'Add custID to custID column
.MoveFile fi, x & "\Imported\"
End If
Next
Next
End With
End Function
This code requires the reference to the Microsoft Scripting Runtime be enabled.
I couldn't say how to do this with Access macros, but it isn't too hard to do in VBA.
I'd write the macro in excel - import the activex data objects 2.8 library reference.
Start by declaring the connection object - this works for a MySQL server we have set up, you can use the JET driver if you're just connecting over a local network.
Dim cnn As ADODB.Connection
Dim rst As ADODB.Recordset
Set cnn = New ADODB.Connection
cnn.CursorLocation = adUseServer
cnn.Open "Driver={MySQL ODBC 5.2a Driver};Server=myserver;database=my_db;uid=user;pwd=P#ssword"
Set rst = New ADODB.Recordset
rst.CursorLocation = adUseServer
When you have the customer name (Get the name from the user, maybe by an inputbox) ping the DB to retrieve the id and save it.
rst.open "Select id from customers where customername = '" & userSubmittedName & "'",
cnn,adopenforwardonly,adlockbatchoptimistic
dim customerID as integer
customerID = rst.fields("id").Value
Then it's just a matter of inputting the data. Access has the DoCmd.RunSQL command, but in Excel you'd use ADO recordsets. It works like this -
rst.open "Select * from Orders",cnn,adopenforwardonly,adlockbatchoptimistic
Fo r x = 2 to rowCount 'Once you have the number of rows you're inputting saved obviously
rst.addnew
rst.fields("ID") = customerID
rst.fields("OrderAmount") = range("A" & x).value
rst.fields("SaleAmount") = range("B" & x).value
....
rst.update
next x
just wondering when using an expression on a form in a text box, to return a value from a table, can the expression have multiple tables in the expression to return the value?
the tables are linked and I can return the value in a query, so I figured that Access would be able to do it with this method as well????
=DSum("[tblMain]![Revenue]","tblMain","[tblMain]![Quarter]=3 AND [tblMain]![Region]='NorthEast'" AND [tblOffice]![Location]='NewYork'")
this is the expression that I entered into my text box, without the reference to the 2nd table it works fine, but once I had it, I get the flickering error message in the text box (just as on a report)......
I know this method is probably used more in reports than forms, but I am novice, and trying to come up with a dashboard solution that returns lots of facts quickly per department. I am using this in the "Control Source" field of the data tab of the properties window, not VB. Mainly because I do not know how to get it to work with VB.
Thanks for the help as always!
As far as I know, you cannot refer to more than one table or query in a domain aggregate function. As grazird says, how are these tables related? Let us say it is on tblMain ID, you can build a query called, say, qryMainOffice, the SQL (SQL View, Query Design window) would look something like:
SELECT [tblMain].[Revenue],[tblMain]![Quarter],[tblMain]![Region],
[tblOffice]![Location]
FROM tblMain
INNER JOIN tblOffice
ON tblMain.ID = tblOffice.MainID
DSum would then be (remove line break):
=NZ(DSum("[Revenue]","qryMainOffice",
"[Quarter]=3 AND [Region]='NorthEast' AND [Location]='NewYork'"),"Not found")
You could also use a recordset or query in VBA to return the value.
EDIT re COMMENT
To use the above in VBA, you either need to add parameters or use a string:
''Reference: Microsoft DAO 3.x Object Library
Dim rs As DAO.Recordset
Dim db As Database
Dim strSQL as String
Set db= CurrentDB
strSQL = "SELECT Sum(t.[Revenue]) As TotalNY" _
& "FROM tblMain t " _
& "INNER JOIN tblOffice o " _
& "ON t.ID = o.MainID " _
& "WHERE t.[Quarter]=3 AND t.[Region]='NorthEast' " _
& "AND o.[Location]='NewYork' " _
'' I have use aliases for simplicity, t-tblMain, o-tblOffice
'' If you wish to reference a control, use the value, like so:
'' & " AND [Location]='" & Me.txtCity & "'"
'' Dates should be formated to year, month, day
'' For joins, see http://www.devshed.com/c/a/MySQL/Understanding-SQL-Joins/
Set rs = db.OpenRecordset strSQL
If Not rs.EOF Then
Me.txtAnswer = rs!TotNY
Else
Me.txtAnswer = "N/A"
End If
You can also use different queries to return several results that can be shown with a list box or a subform:
strSQL = "SELECT TOP 5 o.[Location]," _
& "Sum(t.[Revenue]) AS TotRevenue" _
& "FROM tblMain t " _
& "INNER JOIN tblOffice o " _
& "ON t.ID = o.MainID " _
& "WHERE t.[Quarter]=3 AND t.[Region]='NorthEast' " _
& "GROUP BY o.[Location]"
The above would return revenue for quarter 3 for all locations in NorthEast region. If you want the top values of each group, you are looking at a more complicated query, which I will leave for now.
How are these tables related? Can you describe the relationship and any primary/foreign keys?
Also, referencing the table name is not necessary in the first parameter of this function (since it is already taken care of in the second one).
For example, your code could be:
=DSum("Revenue","tblMain","Quarter=3 AND Region='NorthEast'" AND [tblOffice]![Location]='NewYork'")
Just trying to save you some keystrokes and increase its readability. :)
I am new to Access. I have a table full of records. I want to write a function to check if any id is null or empty. If so, I want to update it with xxxxx.
The check for id must be run through all tables in a database.
Can anyone provide some sample code?
I'm not sure if you are going to be able to find all tables in the database with Access SQL. Instead, you might want to write up some VBA to loop through the tables and generate some SQL for each table. Something along the lines of:
update TABLE set FIELD = 'xxxxxx' where ID is null
Check out the Nz() function. It leaves fields unaltered unless they're null, when it replaces them by whatever you specify.
For reasonable numbers and sizes of tables, it can be quicker to just
open them
sort by each field in turn
inspect for null values and replace manually
It's good practice to find out where the nulls are coming from and stop them - give fields default values, use Nz() on inputs. And have your code handle any nulls that slip through the net.
I'm calling it the UpdateFieldWhereNull Function, and shown is a Subroutine which calls it (adapted from http://www.aislebyaisle.com/access/vba_backend_code.htm)
It updates all tables in the DbPath parameter (not tested, handle with care):
Function UpdateFieldWhereNull(DbPath As String, fieldName as String, newFieldValue as String) As Boolean
'This links to all the tables that reside in DbPath,
' whether or not they already reside in this database.
'This works when linking to an Access .mdb file, not to ODBC.
'This keeps the same table name on the front end as on the back end.
Dim rs As Recordset
On Error Resume Next
'get tables in back end database
Set rs = CurrentDb.OpenRecordset("SELECT Name " & _
"FROM MSysObjects IN '" & DbPath & "' " & _
"WHERE Type=1 AND Flags=0")
If Err <> 0 Then Exit Function
'update field in tables
While Not rs.EOF
If DbPath <> Nz(DLookup("Database", "MSysObjects", "Name='" & rs!Name & "' And Type=6")) Then
'UPDATE the field with new value if null
DoCmd.RunSQL "UPDATE " & acTable & " SET [" & fieldName & "] = '" & newFieldValue & "' WHERE [" & fieldName & "] IS NULL"
End If
rs.MoveNext
Wend
rs.Close
UpdateFieldWhereNull = True
End Function
Sub CallUpdateFieldWhereNull()
Dim Result As Boolean
'Sample call:
Result = UpdateFieldWhereNull("C:\Program Files\Microsoft Office\Office\Samples\Northwind.mdb", "ID", "xxxxxx")
Debug.Print Result
End Sub