I have an access database that I have employer information. Such as name, address, phone number, contact person, business type, etc. There are multiple people entering data & occasionally there is a blank record, because there was an entry started & not finished.
I am trying to use VBA to find the blank record, so I can enter new data in the blank record. Here is the current code.
Private Sub Command107_Click()
If DCount("*", "Blank Query") = "0" Then
MsgBox ("No blank records found. Thank You!")
Else
DoCmd.GoToRecord , , [Queries]![Blank Query2], offset:=1
End If
End Sub
Currently if there is a blank record it hangs on
DoCmd.GoToRecord , , [Queries]![Blank Query2], offset:=1
If there is no blank records, it runs & give the appropriate response.
The only field I am concerned about is, name and address.
Ideally, I would like to have it go to the blank record.
You could use this code:
Dim rst As DAO.Recordset
Dim strSQL As String
strSQL = "select * from tblContacts where " & _
"IsNull([Name]) or IsNull(Address)"
Set rst = CurrentDb.OpenRecordset(strSQL)
If rst.RecordCount <> 0 Then
Me.Recordset.FindFirst "id = " & rst!ID
Else
MsgBox "no blank reocrds found"
End If
rst.Close
DoCmd.GoToRecord will only work if your form is based on your query [Blank Query2].
Apart from that, your syntaxis is incorrect, referring to https://msdn.microsoft.com/en-us/library/office/ff194117.aspx
If this issue occurs on a regular basis, I'd create a form based on [Blank Query2] and add this form to your maintenance / application management frontend (assuming you've split your database into a backend and frontend).
This will give you the ID of the first incomplete Record
RecordID=Nz(DLookup("TablePrimaryKey","TableName","FieldThatCouldBEEmpty IS NULL"),0)
assuming your table has a proper Primary Key. If it does not you can request any field that would help you identify the record, just be sure to change 0 to an appropriate "no record found" value for whatever field you are looking up.
This will just delete any reocrds that are incomplete.
DoCmd.RunSQL "DELETE FROM TableName WHERE FieldThatCouldBEEmpty IS NULL"
Related
I have sub that runs when the database is opened to a specific form and I'm trying to get it to add information in a table.
The table name is UnAuthorizedAccess and the columns in table are ID(auto number), NAME(text), COMPUTERNAME(text), ATTEMPTDATE(date/time).
What commands do I need to use to add a new record to this table? I have a VBA that if they're login information Isn't there is will force close access all together. I'm trying to gather information on the user as well before kicking them out.
I figured this is the easiest way as outlook won't let you send a hidden email from the user unless they first see it.
You can add records to a recordset with the following code, but I am unsure whether you have a field called COMPUTERNAME. You shouldn't need to add the ID value as its an autonumber.
dim Rst as recordset
Set Rst = CurrentDb.OpenRecordset(Name:="UnauthorizedAccess", Type:=RecordsetTypeEnum.dbOpenDynaset)
With Rst
.AddNew
![NAME] = Me.Name.Value
![COMPUTERNAME] = Me.COMPUTERNAME.Value
![ATEMPTDATE] = date()
.Update
End With
As for sending hidden emails, see this question I asked not so long ago. It sends an email via outlook, but remember to reference the Microsoft Outlook Object library in the VBA Editor.
CurrentDB.Execute is the method for executing SQL statements, and INSERT INTO is the SQL statement for adding records to a DB table.
CurrentDB.Execute "INSERT INTO UnAuthorizedAccess (NAME, COMPUTERNAME, ATTEMPTDATE) " & _
"VALUES (" & Your_NAME_Variable & ", " & Your_COMPUTERNAME_Variable & ", " & Now() & ")
Replace Your_NAME_Variable and Your_COMPUTERNAME_Variable with the variables in your code containing these values.
Ok, before anyone tells me that it's a duplicate of another question, I don't think it's the same thing. I'm running a CurrentDb.Execute in VBA in MS Access 2007 and it's after I put the option dbFailOnError that I received this error message:
Error 3218 Could not update; currently locked
Before this, nothing was being done on the table I'm trying to update. Here's the current code in the form module:
Option Compare Database
Private Sub cmdvalidate_Click()
Dim user As String
Dim rs As Recordset
Dim strsql As String
Dim pass As String
Dim f1 As Form_frmMenu
strsql = "SELECT * FROM account WHERE username = '" & Me.txtusername & "'"
'Execute SQL and store in recordset (cannot be stored in a string or integer)
Set rs = CurrentDb.OpenRecordset(strsql)
'Go through recordset and extract first value
If rs.RecordCount > 0 Then
rs.MoveFirst
rs.Edit
pass = rs!Password
' I know it's not the best way to validate password here (since it is
' case insensitive, but it's only for internal use with 3 people in
' the same department. This will considered if there are more people
' who get involved, but for the time being, this is not important.
If pass = Me.txtpassword Then
user = rs!UserName
' MS Access debugger says the error is here
CurrentDb.Execute "UPDATE [Account] SET [Account].[Active] = 'Y' WHERE [Account].[Username] = '" & user & "'", dbFailOnError
MsgBox "Login Successful!"
'DoCmd.OpenForm "frmMenu", , , , , acDialog
Else
MsgBox "Incorrect Username Or Password. Please try again."
End If
Else
MsgBox "Something has gone wrong. Please contact your administrator."
End If
End Sub
My goal at the end of the day is to be able to get the username who logged in. I first tried to use a global variable but it seems that this is not possible with different form modules. So instead, I created the Active field so that I could get the username in other form modules through a SELECT statement.
Some checks I did:
The file is not opened by anyone besides me, I'm 100% sure of it.
The query was initially like below but I added the square brackets just in case there were reserved words:
"UPDATE Account SET Active = 'Y' WHERE Username = '" & user & "'"
Other form modules in the same file do not have this UPDATE issue and there are no other options other than Option Compare Database (the other stuff are Private Subs).
I discovered that I could use Environ("Username") to get the Windows login username in the other modules instead. This is will solve the problem, but I'm still wondering why this query cannot execute the update.
Questions:
If the table is locked, is there a way I can unlock it?
Why is this query getting an error in the first place? What has locked it?
I don't know much, if at all about vb and I'm not even sure how I got on this project...
1.) If the table is locked, is there a way I can unlock it?
I'm not so sure the entire table is locked. Perhaps only the current recordset row is locked. See #2.
2.) Why is this query getting an error in the first place? What has locked it?
The code does rs.Edit. Later, when attempting to UPDATE the table directly, the targeted row is the same row which is currently locked in the recordset. However, there is a lot more code there, which makes it difficult to pin down which statements contribute to the error.
This simplified code sample should clarify what's going on.
strSql = "SELECT * FROM account WHERE username = 'hans'"
Set rs = CurrentDb.OpenRecordset(strSql)
rs.MoveFirst
rs.Edit
CurrentDb.Execute "UPDATE Account SET Active = 'Y' WHERE Username = 'hans'", dbFailOnError
As written, that code triggers error 3218, "Could not update; currently locked", on my system.
This change disables the Edit statement and allows the UPDATE to execute successfully.
'rs.Edit
One way you found to avoid the error was by adding rs.Close before executing the UPDATE. That worked because closing the recordset released that edit lock; if you had actually changed values in that row, you would have needed rs.Update to save them before rs.Close.
However, in the original version, you were only reading values from the recordset, not changing any of them. So rs.Edit was not needed.
Huh, I think I just found out what was causing the error.
Apparently, when a RecordSet is using a table (here the line Set rs = CurrentDb.OpenRecordset(strsql)), the table can be accessed only through the RecordSet and not through CurrentDb.Execute anymore (at least, to update).
Two workarounds I found for my specific situation:
Replace the CurrentDb.Execute by something to update the RecordSet itself (Probably easier):
rs!Active = "Y" ' Change the value of Active
rs.Update ' Update the changes to the RecordSet and thus, table
rs.Close ' Close recordset
Set rs = Nothing ' Unset recordset
Close the RecordSet first, then use CurrentDb.Execute:
rs.Close
Set rs = Nothing
CurrentDb.Execute "UPDATE Account SET Active = 'Y' WHERE Username = '" & user & "'", dbFailOnError
I am using an Access2010 project as frontend, referring to a MS SQL Server 2008 as backend. Within my Access project there is form frmKlientenÜbersicht. This form has a view abfKlientenÜbersicht as dataSource.
Now I am trying to get the current number of records showing up in my form by using this code:
Private Sub Form_Current()
Debug.Print "Form_Current: " & anzahlDatensätze
lblAnzahlDatensätze.Caption = anzahlDatensätze & " Klient(en)"
End Sub
Private Function anzahlDatensätze() As Integer
Dim rs As Recordset
Set rs = Me.RecordsetClone
rs.MoveLast
anzahlDatensätze = rs.RecordCount
End Function
This works fine until I am using some filters. If I am using any filter on my form, the number of records stays unchanged!
What do I have to change to get the current number of records showing up (if filtered or not)?
What is the reason why my code does not show the correct number of records?
EDIT: According to the given comments and answers I tried setting Count([pkKlient] onto a textbox (see new pic) and tried DCount("*", "abfKlientenÜbersicht", me.Filter) from within VBA Code.
Unfortunatelly it seems that the filterClause is not valid when using it as parameter value for DCount. (see pic for filterClause).
As you can see count(..) does not result in a correct number - and the filterClause (generated by access!!) seems not to be valid for use by DCount(..)
If someone wants to try it, on your own, just create an ADP, add a form, add a view, form dataSource is a view, set a filter, and try to get the number of records?!!
Looking forward for any comments/answers/hints!
with VBA, DCount will give you what you need
DCount("*", "MyTable", Me.Filter)
If you want to put this on the form, there's an easier way. use an unbound box, and set it to =count([FieldName])
This count should remain correct, regardless of if it's counted filtered records or not.
Some notes, there are a dozen things that could go wrong with this, it could hardly even be called tested. However, it was returning the correct count for me.
Apparently, the form filter just hides records, whereas this will apply a real filter. However, you need to get the format into the right shape for a valid filter. In the end, a WHERE statement would probably be easier.
Private Sub Form_ApplyFilter(Cancel As Integer, ApplyType As Integer)
With Me.Recordset
''Filter
If ApplyType = 1 Then
''Very, very roughly. Remove form name, use single quotes
''You will need a lot more code for safety
sfilter = Replace(Me.Filter, "[" & Me.Name & "].", "")
sfilter = Replace(sfilter, """", "'")
.Filter = sfilter
MsgBox "Recordset : " & Me.Recordset.RecordCount & vbCrLf _
& "Filtered : " & .RecordCount
Else
''Remove filter - ApplyType 0
.Filter = ""
End If
End With
End Sub
Additional note with similar caveats
You can also set a textbox to something on these lines:
=IIf([FilterOn]=True,DCount("id","ATable",
Replace(Replace([Filter],"[" & [Name] & "].",""),"""","'")),Count([id]))
(Remove the break in the line, it is cosmetic)
I've got a subform (customersAnswersSub) inside of a main form (customersAnswers). Upon someone entering a new customerAnswersSub entry - I wanted it to check for duplicates first.
It has to check across 4 different fields to match first.
This is what I've got so far.
Private Sub Form_BeforeUpdate(Cancel As Integer)
Dim rsGlobals As ADODB.Recordset
Dim sql
Set rsGlobals = New ADODB.Recordset
sql = "Select * From CustomerAnswerD where subscriptionNo=" & _
Me.subscriptionNo & " AND journal=" & Me.Journal & _
" AND volume=" & Me.volume & " AND issue=" & Me.issue
rsGlobals.Open sql, CurrentProject.Connection, adOpenDynamic, adLockOptimistic, adCmdText
If Not rsGlobals.BOF And Not rsGlobals.EOF Then
MsgBox ("Already entered")
Cancel = True
Me.Undo
End If
End Sub
it doesn't do anything - just sits there. when I close the form it'll pop up a - id already exists box.
Any idea, i'm pretty unexperienced when it comes to Access VB.
thank you
it doesn't do anything - just sits there
Just checking, since you said you're inexperienced with Access ... the form update event is not triggered until the record save is attempted. That may not happen automatically as soon as the user enters data into all the fields. However, you can trigger the update by navigating to a different record in the subform, or by a method such as choosing Records->Save Record from Access' (2003) main menu.
I don't see anything wrong with your BeforeUpdate procedure. Still I would convert it use the DCount() function instead of opening an ADO recordset. (See Access' help topic for DCount)
Private Sub Form_BeforeUpdate(Cancel As Integer)
Dim strCriteria As String
strCriteria = "subscriptionNo=" & Me.subscriptionNo & " AND journal=" & Me.Journal & _
" AND volume=" & Me.volume & " AND issue=" & Me.issue
Debug.Print strCriteria
If Dcount("subscriptionNo", "CustomerAnswerD", strCriteria) > 0 Then
MsgBox ("Already entered")
Cancel = True
Me.Undo
End If
End Sub
That assumes your table's subscriptionNo, journal, volume, and issue fields are all numeric data types. If any of them are text type, you will need to enclose the values in quotes within strCriteria.
I added Debug.Print strCriteria so you can view the completed string expression in the Immediate Window. You can also troubleshoot that completed string by copying it and pasting it into SQL View of a new query as the WHERE clause.
Also, consider adding a unique index on subscriptionNo, journal, volume, and issue to your CustomerAnswerD table design. That way you can enforce uniqueness without relying solely on your form to do it. The index will also give you faster performance with the DCount function, or your original recordset SELECT statement.
If you keep your original recordset approach, close the recordset and set the object variable = Nothing before exiting the procedure.
I'm pretty new to MS Access. I'm trying to create a simple form that will basically search for a particular record using a textbox, rather than a drop down box. Essentially a user would be able to enter an ID number and retrieve some other related Info. However, I do not want the user to be able to add any new records to the database. I've been able to get the forms to look the way I want them, but I'm not sure where to place the code (do I create a macro, insert the code into the properties of the button?) Any help is greatly appreciated!
I assume that you have bound your form to a table or a query and that you want to be able to enter the ID manually in a textbox, then press ENTER and load that record's data or display an error message if there is no such record.
As dsteele said, make sure that the form's Data property Allow Addtions is set to No to disallow users from adding records.
Then, from the AfterUpdate event of the textbox, add the following code (assuming that your textbox is named txtGoTo):
Private Sub txtGoTo_AfterUpdate()
If (txtGoTo & vbNullString) = vbNullString Then Exit Sub
Dim rs As DAO.RecordSet
Set rs = Me.RecordsetClone
rs.FindFirst "[ID]=" & txtGoTo
If rs.NoMatch Then
MsgBox "Sorry, no such record '" & txtGoTo & "' was found.", _
vbOKOnly + vbInformation
Else
Me.RecordSet.Bookmark = rs.Bookmark
End If
rs.Close
txtGoTo = Null
End Sub
Note that you will have to change the line rs.FindFirst "[ID]=" & txtGoTo to something that is adequate for your data:
"[ID]=" should be replaced by the field you want to search (it could be "[POReference]=" or something else.
if you are searching by a numeric ID, for instance because the field is an autonumber column, then the code is fine.
Otherwise, if the field you are searching on is a string (say PN12-G) then you have to change the code to:
rs.FindFirst "[ID]=""" & txtGoTo & """"
Failing to use the proper quoting (or quoting where not necessary) will result in errors of the kind Data type mismatch....
As a new user, I would recommend that you have a look at the sample NorthWind project database that is either shiped with older versions of Access or available as a template for download from Access 2007.
There a lots of techniques to learn from as a new Access developer, including other ways to implement record navigation.
Set the form property Data/'Allow Additions' to No.
Either in the AfterUpdate event of the textbox, or in the Click event of a button, you can write code or assign a macro to look up and display the record you want.