I want to create a split form based on a query where the fields are all grouped. The split form will not let me update the records because they are grouped. For instance let's say 10 records all had the same data in a field called "Company Name". Is there any way to make the query updatable such that when I change the data for "Company Name" on the grouped entry it will change for all of the records that are grouped?
Thanks
it is definitively not possible to update a grouped query.
The reason is, that a grouped query cannot contain the key (if you include it, you have no more a grouping, as the key is unique ...)
So Access has no clue, what is grouped and which records should be updated
What you have to do is:
create a form based on the query
add an event "on double-click" to the field you want to change
program a dialog to ask for new value
fire an sql to update
here a sample for steps 2-4
Private Sub DOK_DokumentNr_DblClick(Cancel As Integer)
Dim newvalue As Variant
Dim sSQL As String
newvalue = InputBox("enter new value", "DOC-Number", Me!DOK_DokumentNr.OldValue)
If newvalue <> Me!DOK_DokumentNr.OldValue Then
sSQL = "UPDATE T_Dokument SET DOK_DokumentNr = '" & newvalue & "' "
sSQL = sSQL & "WHERE DOK_DokumentNr = '" & Me!DOK_DokumentNr.OldValue & "'"
DoCmd.SetWarnings False ' to prevent the standard message for modifying data
DoCmd.RunSQL sSQL
DoCmd.SetWarnings True ' reset warnings to default
End If
End Sub
Related
I am creating a form in an Access database that allows a user to import an Excel workbook into the database, then inserts a column with that day's date as a way to log when the record was imported, with the idea that I can later compare this to a master database and update accordingly.
My code is below:
Private Sub btnImport_Click()
'create a new file system object that will check for conditions and import the file as a new table if a valid name is chosen
Dim FSO As New FileSystemObject
Dim strSQL As String
'Dim curDatabase As Object
Dim tableTest As Object
Dim fieldNew As Object
Dim todayDate As Date
Dim tempTable As String
tempTable = "TempTable" & CStr(Date)
'MsgBox TempTable
'If no file name in box
If Nz(Me.txtFileName, "") = "" Then
MsgBox "Please choose a file."
Exit Sub
End If
'If a file name is in box and the file can be located
If FSO.FileExists(Me.txtFileName) Then
fileImport.ImportExcel Me.txtFileName, tempTable
'once it imports the table, it then adds today's date (the upload date)
todayDate = Date
strSQL = "INSERT INTO tempTable (Upload_Date) Values (#" & Date & "#);"
DoCmd.RunSQL strSQL
'DoCmd.RunSQL ("DROP Table TempTable")
Else
'Error message if file can't be found
MsgBox "File not found."
End If
End Sub
Unfortunately, right now I am getting two problems.
The first is
run-time error 3127: The INSERT INTO statement contains an unknown
field name.
I thought I wanted to insert a new field, so I'm a little perplexed by this error.
I'm also getting another error; the compiler doesn't seem to like when I use tempTable for the table name. I'm trying to use a reference to the table name, rather than the actual name of the table itself, because this will end up being a daily upload, so the name of the table that is having this column inserted into it will change every day.
I appreciate any guidance that you can give; I'm fairly new to VBA.
UPDATE: I ended up solving this issue by A. using an UPDATE statement and using CurrentDb.Execute to add the date. I found that this worked for me:
strSQL = "ALTER TABLE TempTable ADD COLUMN Upload_Date DATE;"
strSQL2 = "UPDATE TempTable SET Upload_Date = '" & Date & "'"
DoCmd.RunSQL strSQL
CurrentDb.Execute strSQL2
INSERT INTO doesn't add columns, it just adds rows (with data in existing columns). Look into ALTER TABLE ( https://learn.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/alter-table-statement-microsoft-access-sql )
I'm not sure if it's related, but the table name you use in strSQL is "tempTable", yet the table name you pass to fileImport.ImportExcel is "TempTable" (i.e. the capitalization of the first letter is inconsistent).
If the variable "tempTable" is meant to hold the name of the table (so it can be used for different table names) then it should be outside of the SQL strings:
strSQL= "ALTER TABLE " & tempTable " & " ADD COLUMN Upload_Date DATE;"
strSQL2 = "UPDATE " & tempTable & " SET Upload_Date = '" & Date & "';"
Otherwise you are amending and updating a table called "TempTable" rather than inserting the calculated table name from the variable into the SQL string.
Also note that there should be a semi-colon at the end of strSQL2 as well.
I am working on an MS Access database and have been trying to get an unbound field on a main navigation form to display the LastUserChange that is associated with the record that was last updated.
I have used DMax() to identify the record that was most recently updated, but I can't seem to get the user ID associated with that record to display. I have a field in the table with the date timestamp that stores the user ID with it, so the data is saved in the same table. The code that I have been working on is as follows:
Private Sub Form_Load()
Dim strSQL As String
strSQL = "SELECT tblstatusupdate.LastUserChange" & _
"FROM tblstatusupdate " & _
"WHERE tblstatusupdate.LastChangeDate = DMax("LastChangeDate", "tblStatusUpdate")"
DoCmd.RunSQL strSQL
Me.LastUpdateBy = strSQL
End Sub
The code that I used to get the date of the most recently updated record is:
= DMax("LastChangeDate", "tblStatusUpdate")
Can someone please help me?
Often a mistake of new users in MS Access, DoCmd.RunSQL is reserved for action queries (i.e., INSERT, DELETE, UPDATE, ALTER, CREATE) and not SELECT queries that return a resultset.
However, for your needs consider running nested domain functions in VBA without any SQL calls. DLookUp looks up user with the criteria that its change date matches the max value of table using Dmax. Date literals must be enclosed with # characters and not quotes.
Me.LastUpdatedBy = DLookUp("LastUserChange", "tblStatusUpdate", "LastChangeDate = #" _
& DMax("LastChangeDate", "tblStatusUpdate") & "#")
I'm trying to define a SQL statement to use as the Row Source for a ComboBox on an MSAccess form. The SQL should select records from a table tblI where a particular table field matches a variant parameter varS set by the user; however, if varS is Null or not present in another table tblS, the SQl should select all records in tblI.
I can code the first parts of this (varS matches or is null):
SELECT tblI.ID, tblI.S FROM tblI WHERE ((tblI.S = varS) OR (varS Is Null)) ORDER BY tblI.ID;
Where I'm struggling is incorporating the final element (varS not present in tblS). I can code a test for the absence of varS in tblS:
Is Null(DLookup("[tbls.ID]","tblS","[tblS.ID]= " & varS))
but I can't work out how to incorporate this in the SQL statement. Should this work?
SELECT tblI.ID, tblI.S FROM tblI WHERE tblI.S = varS OR varS Is Null OR DLookup("[tbls.ID]","tblS","[tblS.ID]= " & varS) Is Null ORDER BY tblI.ID;
When run as a query it returns every record in tblS no matter the value of varS.
Table structure:
tblI contains 2 fields, Autonumber ID and Long S
tblS contains 1 field, Autonumber ID
My own approach to this problem would be something like this:
Private Sub SetComboSource(vID as Variant)
Dim sSQL as String
sSQL = "SELECT tblI.ID, tblI.S " & _
"FROM tblI "
If IsNull(vID) = False Then
If IsNumeric(vID) = True Then
If DCount("ID", "tblS", "ID = " Clng(vID)) > 0 Then
sSQL = sSQL & "WHERE tblI.S = " & CLng(vID)
End If
End If
End If
sSQL = sSQL & " ORDER BY tblI.ID"
Me.cboComboBox.RowSource = sSQL
End Sub
BTW, I recommend you give your tables and fields more descriptive names and then use aliasing in your SQL, especially for table names. I also think it's best to avoid using Variant variables. I usually use Longs for something like this and I take a value less than 1 to mean that the user didn't select anything, or selected ALL, or whatever meaning you want to derive from it. In other words, my ID's are always a number greater than zero and an ID of less than 1 in a variable means that the ID is empty. Which I use as a signal to create a new record, or to return all records, or whatever meaning you want to derive from it in the given context.
The following should work;
SELECT tblI.ID, tblI.S
FROM tblI
WHERE tbl.ID=varS
OR varS NOT IN(SELECT ID from tblS)
I haven't a clue as to how to do this. I'm using Access 2007, and coding in VBA and SQL.
Table A has Data, accounts and amounts. Users can use form B to access subsets of the data in A, say, all the rows with amounts between $50 and $100.
When the user is looking at a row, I need to know if there are any other rows with the same account that are excluded from their view. In other words, I need to know if there are rows visible in the parent that aren't visible in the child.
I think a solution is to determine what filters are active on their view, and then I can use dcount to compare. I don't know how to get at the filters that are active in their view, though. And there may be an easier way - I am out of my depth here.
Let us assume that TableA has a primary key ID. Using the current event for the FormB:
Dim rs AS DAO.Recordset
dAmt = Me.Amount
sAcc = Me.Account
''Get a list of visible IDs
With Me.RecordsetClone
.MoveFirst
Do While Not .EOF
If !Amount=dAmt And !Account=sAcc Then
sIDs = sIDs & "," & .ID
End If
.MoveNext
Loop
End with
''Other IDs
sSQL = "SELECT * FROM TableA "
& "WHERE Amount = " & dAmt _
& "Account = '" & sAcc _
& "' ID Not In (" & Mid(sIDs,2) & ")"
CurrentDB.CreateQueryDef("NewQ",sSQL")
Docmd.OpenQuery NewQ
The above is untested, and as it stands, will only run once, if it runs at all, because a new query is created, rather than an existing query being edited.
I'm having some issues with some functionality of my application. There is a particular instance where I have an instance of a 'pending class' on a form for an administrator to review. The form is populated with students associated with this pending class. After their grades are finished, I have a button at the footer that will delete this class from my 'pending' table and add the grades to all of the students. This works.
However, I want to essentially copy this pending class, which just has the class name, date, and teacher to a completed class table before it's deleted from pending. Since no data about this class other than the primary key(class number) persists throughout this form, I can't populate the other fields(class name, date) of the row into my completed class table.
I am trying a "SELECT INTO" operation in VBA to get these values. It's going like this:
dim cname as String
dim classdate as Date
dim pid as integer
dim teacher as String
dim qry as String
pid = [Forms]![frmClasses]![txtID]
qry = "Select className INTO cname FROM tblPending WHERE tblPending.id = " & " ' " & pid & " ' " & ";"
db.execute qry
debug.print qry
debug.print cname
From here, I do the same operations for each other variable, build my INSERT query, and execute it. The problem is-- my select into's are not working. Debug.print shows that the local variables were never initialized from the SELECT INTO statement. Any thoughts?
First, having all classes in one table and just setting a "NotPending" or "Completed" column would be better.
Having two identical tables for classes and moving values from one into the other to indicate status changes is bad database design.
If you really need to do this by using two tables and copying rows, then you need an INSERT INTO query (and not SELECT INTO), as already mentioned by Remou in the comments, because SELECT INTO creates a new table (or overwrites an existing one with the same name, if already there).
The syntax for INSERT INTO looks like this:
INSERT INTO CompletedClassTable (ClassName, Teacher)
SELECT ClassName, Teacher FROM tblPending WHERE id = 123
And finally, you asked this in a comment:
So SELECT INTO is completely different in Access than Oracle? In Oracle and PL/SQL, you can select a row into a variable OR a table. In Access can you not select into a variable?
To load a row into a variable, you need to use a Recordset.
Example code to load your query into a Recordset and output the ClassName field:
Dim RS As DAO.Recordset
Set RS = CurrentDb.OpenRecordset("SELECT * FROM tblPending WHERE id = 123")
If Not RS.EOF Then
Debug.Print RS("classname")
End If
RS.Close
Set RS = Nothing
Seems you want to retrieve a text value, className, from tblPending where tblPending.id matches the value found in your text box, txtID, and store that text value in a string variable named cname.
If that interpretation is correct, you needn't bother with a query and recordset. Just use the DLookup Function to retrieve the value, similar to this untested code sample.
Dim cname As String
Dim pid As Integer
Dim strCriteria As String
pid = [Forms]![frmClasses]![txtID]
strCriteria = "id = " & pid
cname = Nz(DLookup("className", "tblPending", strCriteria), vbNullString)
Debug.Print "cname: '" & cname & "'"
Notes:
I assumed the data type of the id field in tblPending is numeric. If it is actually text data type, change strCriteria like this:
strCriteria = "id = '" & pid & "'"
DLookup() returns Null if no match found. Since we are assigning the function's return value to a string variable, I used Nz() to convert Null to an empty string. Alternatively, you could declare cname As Variant (so that it can accept a Null value) and get rid of Nz().