I'm currently using the MS Access 2010 template for contacts. I've modified it to do a multiple criteria search, but it's still the same.
What I'd like to know is how to modify the contact details window that opens when you click "open".
Basically, I want it to open the window, but then I want to add two buttons to go to the next person without having to close the window and reopen another one. I've added the buttons, but the window opened is for a specific ID, so it won't go to the next record.
Does anybody know how to open the contact details window for a specific contact but still be able to go through all of them? (them being the contacts given after the search)
EDIT:
Ok, i've just tried to create a clone, but all i get is a error "3251 - this operation is not supported for this type of object. I'm relatively new to VBA code, so its kind of hard to find the issues, but i'm guessing it has something to do with type of recordset (DAO or ADO). Here is what i have:
Private Sub txtOpen_Click()
DoCmd.OpenForm "Contact Details", , , , , acHidden
With Forms![Contact Details]
.Recordset = Me.Recordset.Clone
.RecordsetClone.FindFirst "[ID]=" & Me!ID
If Not .NoMatch Then
.Bookmark = .RecordsetClone.Bookmark
End If
End With
End Sub
I'm currently looking into it though!
I haven't checked the A2010 contacts template, but my guess is that you have a list of results and you select one and click a command button to open the details.
Likely that command button has code something like this:
DoCmd.OpenForm "frmContactDetails", , , "[ContactID]=" & Me!ContactID
...which opens the form and filters it to a single record.
To have a navigable set of records, you'll instead want the form to be filtered to the same set of records as is displayed in the list of search results, and then you'll want to navigate among those. To do that, you'd have to set the criteria to the same criteria that filtered the results list, and then navigate to the currently selected record. I don't know what the criteria are, so I'm just going to represent it with a variable, strCriteria but the requirement is that it be formatted like a SQL WHERE clause without the word "WHERE":
DoCmd.OpenForm "frmContactDetails", , , strCriteria
With Forms!frmContactDetails
.RecordsetClone.FindFirst "[ContactID]=" & Me!ContactID
If Not .NoMatch Then
.Bookmark = .RecordsetClone.Bookmark
End If
End WIth
This opens the form to the same set of records, then navigates to the one with the ContactID of the record that was selected in the results when you clicked the command button to see the details. Once that detail form is loaded with that set of records, you can navigate to the next or previous records as you like.
It may also be possible to open the detail form and assign the form's Recordset to be a clone of the results form's Recordset, but I've never tried that. In that case, it would be something like (untested code, just guessing at how this would be done):
DoCmd.OpenForm "frmContactDetails", , , , , acHidden
With Forms!frmContactDetails
.Recordset = Me.Recordset.Clone
.RecordsetClone.FindFirst "[ContactID]=" & Me!ContactID
If Not .NoMatch Then
.Bookmark = .RecordsetClone.Bookmark
End If
End WIth
Another thing to consider is not having a popup form at all, but use a split form, something that was introduced in A2007, and that I've not had the opportunity to use yet (no clients who've switched fully to A2007/2010). It has a list view and a detail view on the same form.
The old-fashioned way to implement the same thing was to have two subforms on an unbound form, the top form being the list of results, and the top form being a detail form that is tied to the current record of the top form. No code is required, you just set the LinkChild and LinkMaster properties of the detail form like this:
LinkMaster: ListForm.Form!ContactID
LinkChild: ContactID
This approach and the split form both avoid the popup form, which I consider somewhat user-hostile (it needs to be used sparingly).
Which approach you use depends on exactly how you app fits together.
Related
My management wants an access database that can have a way to control which users can see specific fields on a form. For example, if a manager logs in, a form will display the performance rating field. For any other user, the performance rating field will not be visible.
So far the below are some of my options:
1) Use VBA to detect the User Name of the access application and if its Manager's name, then the textbox is visible.
2) Use a username reference table that requires users to login. Users with special access will have the textbox visible.
3) Have a special little button on the form that, if someone clicks, will load a small password dialog and then set the text visible.
Which option would be the most difficult to implement?
The idea of using a Login form for user specific information is something that is available all over the internet. I would suggest a combination of all three of your ideas would be just the perfection solution.
For either of the two methods you have (1 & 2) you first need a Table that will hold the information. The table does not need to be complex (at least not right away). The table should be of the following structure,
tbl_Employees
-------------
EmpID - Auto Number - PK
EmpNam - Text
EmpUserName - Text
EmpPassword - Text - Input Mask (If required)
IsManager - Yes/No - Default - No
Then you will have to create a Form, a basic form that will have three controls, two Text Boxes and one Button. The first text box is where you will enter the Employee User name and the second for Password. Finally a button, behind which the magic happens. The code (simplified) behind the button would be something along the lines of.
Private Sub LogInBtn_Click()
On Error GoTo errOccured
Dim eQryStr As String, empRS As DAO.Recordset
eQryStr = "SELECT EmpID, EmpUserName, EmpPassword, IsManager FROM tbl_Employees WHERE EmpUserName = '" & Me.UserNameTxt & "'"
Set empRS = CurrentDb.OpenRecordset(eQryStr)
If empRS.RecordCount <> 0 Then
If Me.PwdTxt = empRS!EmpPassword Then
If empRS!IsManager Then
DoCmd.OpenForm "ManagerForm"
Else
DoCmd.OpenForm "EmployeeForm"
End If
Me.Visible = False
Else
wrongEntry "Password"
End If
Else
wrongEntry "User Name"
End If
exitOnError:
Set empRS = Nothing
Exit Sub
errOccured:
wrongEntry "User Name/Password"
Resume exitOnError
End Sub
Private Sub wrongEntry(entityStr As String)
MsgBox entityStr & " is incorrect (OR) omitted, please check again.", vbCritical
End Sub
As you can see, I have used
(a) A Recordset object than a simple DLookup. I prefer recordset object, you can use a DLookup, but you have to make sure you handle Null (if the criteria is not met).
(b) A separate Form for Managers and Employees. I imagined there would be a lot more on a managers form that is not available on a Employee form. If you do not wish to go this way, but use one form you can, but you need to inform the opening form of who is logging in - Using the OpenArgs property of the OpenForm method.
Just if you feel to simply avoid all the hassle and use an Password box, to get the access of the TextBox. Simply follow the instructions on this thread - Password Box - A variant of Input Box. Then create a button on the form you currently have, then on click of the button, you simply code the following.
Private Sub AllowAccessButton_Click()
If Call_Password_Box = "yourPassword" Then
Me.yourHiddenTextBox.Visible = True
Else
MsgBox "Sorry you are not authorised to vies this information (OR) Incorrect Password", vbCritical
End If
End Sub
PS: The Hidden text control should be set to invisible, preferable in the Form current event.
I hope this helps.
I've implemented option nr 1 and 2, they we're quite easy to build.
option nr 3 seems equally difficult.
The question within my work environment would be which option would be low in (account)maintenance and which would demand little effort from the users.
From that view option nr.1 has been more successfull.
(And i would rather build different forms in stead of turning the view setting of field ON/OFF)
I've create a form with a tab control in MS-Access.
On one of the tabs I have 2 subform controls showing records from the same table. This table has a field I've called "Status" and can have an entry of either "Open" or "Closed"; the 2 subforms simply show these 2 options filtered as separate groups on the tab control.
I then have a button underneath each of the subforms; the user selects (clicks into) one of the records in either of the subforms and then the button will open a new "Edit" form at the selected record in subform so they can see more information and also toggle the "Status" field to "Open" or "Closed".
When the user presses the "Save and Close" button this saves the changes, closes the "Edit" form, and re-queries the 2 subforms.
What I'm trying to do is get a count of the number "Open" records still showing after the "Edit" form is closed. The count number is then to be passed in to the tab caption for this tab so users can see at a glance how many "open" records are against the record on this main form.
Here's my code so far:
Private Sub cmdAdminIssue_Edit_SaveClose_Click()
' save and close currently open edit form
DoCmd.Close acForm, "tblAdminIssue_Edit", acSaveYes
' requery the subforms to show the effect of the edits made via the edit form
Forms![tblJobs]![tblAdminIssue_Sub_Open].Form.Requery
Forms![tblJobs]![tblAdminIssue_Sub_Closed].Form.Requery
' count number of records still open and pass the number through to the tab control caption property
Dim AdIssOpenCount As Long
AdIssOpenCount = DCount("JobID", "qryAdminIssue_Open", "JobID = '" & Me![JobID] & "'")
Forms![tblJobs]![tab_AdIssues].Caption = "Admin Issues (" & AdIssOpenCount & ")"
End Sub
The above code triggers the error: "The expression you entered refers to an object that is closed or doesn't exist", highlighting my DCount expression in debug.
However I can get the DCount to work independently of the other code above it; they seem to be interfering with each other, but I don't quite understand how.
Referring to the error message above it seems to be suggesting that DCount needs the query I referenced to open in order to run... this doesn't make much sense to me as I thought these kinds of functions do not require you to explicitly open in code an object it's trying to get data from... I'm probably misinterpreting what this error actually means though.
Any explanation of the error and a possible workaround would be much appreciated. Thanks.
While you've clearly done your best to explain the situation it seems pretty complicated.
I'm going to try and break it down a bit, and suggest something you might do.
"I've create a form with a tab control in MS-Access.
On one of the tabs I have 2 subform controls showing records from the same table.
This table has a field I've called "Status" and can have an entry of either "Open"
or "Closed"; the 2 subforms simply show these 2 options filtered as separate groups on
the tab control."
So, you have a form, with 2 subforms. That they're on a tab page shouldnt really be relevant. I'm going to reference the form as frm & the subforms as sf_o & sf_c.
Button underneath each subform (opening the detail form with a double-click might be nicer) - the "save & close" button is presumably in the popup screen; This button is currently performing the save of it's own data, and doing everything else as well.
This is very messy, as it means that the contents of frm cannot be modified without having to make changes to the logic of the save/close button as well. A better approach would be to separate the logic for refreshing the main form from the editting form using a public method in the main form (frm):
Public Sub RefreshData()
sf_o.Form.Requery
sf_c.Form.Requery
'other logic
End Sub
then, you have:
Private sub cmdAdminIssue_Edit_SaveClose_Click()
'save & close logic...
Forms(frm).RefreshData
End sub
Okay now, the other logic. You want to find out how many records are now "Open" and put this information somewhere. In this case, somewhere is a tabpage caption, but this isnt really material.
I never use DCount (DLookup etc) as it is very slow. An alternative (and in this case, much simpler) method would be to use the forms own properties:
tab_AdIssues.Caption = "Admin Issues (" & trim(sf_o.Form.RecordsetClone.RecordCount) & ")"
How's that? Then you dont need to try and figure out what's gone wrong in all that pre-compiled logic which is microsoft access.
Hope this helps
I have a report (ReportX) that I wish to open from two different forms (FormA and FormB) in my database. I wish to do this because FormA and FormB address different aspects of my data, even if they ultimately get to the same output. ReportX is based on data from QueryX.
The problem I have is that QueryX would ideally filter the data based on the current RecordID in the current form. But I don't know how to accomplish this. I'd like to design QueryX so that the criteria for RecordID is essentially CurrentForm!RecordID, but research suggests that I cannot do this. Must I make separate but otherwise identical queries and reports for each form? Or is there a way to use VBA to define the query criteria when I click on the OpenReportX command button?
I already tried using the WHERE condition in the OpenReport command:
DoCmd.OpenReport "ReportX", acViewPreview, ,"RecordID = " & RecordID
but that did not display the results I wished. I need the report header to display/print for each RecordID and the page count in the page footer to reflect only the current/total pages of the RecordID in question. (In other words, if record 1 is one page, record 2 is two pages and record 3 is three pages, then ReportX, when displaying the first page of record 2, should say "Page 1 of 2" and not "Page 2 of 6.") So being able to display and print a single record properly using record filters would also solve my problem.
Which is the least cumbersome/most possible solution?
You should be able to accomplish this using the WHERE condition argument when you open a report:
DoCmd.OpenReport "rptName", acViewPreview, ,"RecordID = " & Me!RecordID
In the case where a I need more control over a Report's recordsource than what the Where condition argument can do for me, I will set the Reports RecordSource to be blank (after designing the report). Next I write code create the correct SQL statement in the Open Report button's Click event, followed by code to open the report and pass in the SQL as an opening argument for the report.
Private Sub cmdOpenReport_Click()
Dim sSQL as string
sSQL = "SELECT * FROM tblWhatever WHERE RecordID = " & Me!RecordID
DoCmd.OpenReport "rptReportName", acViewPreview, , , ,sSQL
End Sub
Then in the report's Open event I write code to set the recordsource:
Private Sub Report_Open(Cancel As Integer)
If IsNull(Me.OpenArgs) = False Then
Me.RecordSource = Me.OpenArgs
End If
End Sub
If neither of those accomplish what you want then you have an issue of a different sort. It's a little difficult for me to understand why you need All Records to show up in the header but only one record in the detail area. And how you expect to accomplish this. You might be best off trying to write a query first that gives you the exact results that your looking for so you know that it can be done.
As a side note, I actually use very few saved queries in my designs. It's not that there's anything wrong with using them, as the option is there for your convenience. I frequently use raw SQL on both forms and reports and set the RecordSource to the SQL on the Form or Reports Open or Load events.
Yes you can point to form data items in a query, and subsequently use that query in a report. The forms need to be open before the report runs. As far as having a header for each record, that is controlled in the settings of the report and how it displays the data.
In the Field, or Critera you can use the format:
[Forms]![frm_Process_Candidates]![QuestionTemplate]
Where frm_Process_Candidates would be the name assigned to your form, and QuestionTemplate is either the name of a control on your form, or a field from the data source of your form.
If you have a sub-form, there will be another [Form] call in the middle there.
[Forms]![frm_Dropdown_Admin]![frm_Dropdown_Admin_Detail].[Form]![text22]
Access should figure it out from there.
I have a text field with a button that filters by a keyword in a form.
Private Sub Command93_Click()
Me.Filter = "(Review Like '*" & Me.Text94 & "*')OR (Status Like '*" & Me.Text94 & "*')"
Me.FilterOn = True
Me.Requery
End Sub
I then have a button that generates the report from that filter.
Private Sub Filter_Click()
DoCmd.OpenReport "rptName", acViewPreview, , Me.Filter
End Sub
The problem is that whenever I hit this button to generate the report, I get a pop up box asking me to Enter Parameter ID and it is asking this for review. If I take the review criteria out (by the way I have many more fields I just used review and status to illustrate the example) then the report generates without any pop up box. The review is part of a notinlist event which opens another form and stores that info in a table review, if that is relevant at all. The report will still generate when I click ok and leave the Enter Parameter ID box blank but I'd like to somehow bypass it for two reasons - the first being the fact that I need other people who are not familiar with access to be able to use it and the second is the idea that if I learn what is causing it I can understand the way access works better. Thanks.
Does your report have a field called Review? If not, you either need to change the recordsource of the report so it is joined with the table that has review, or change your filter so it refers to the field that the report has.
I have a form in an MS Access database which lists Orders with an Order Number with one order per page. At the bottom of the form there is a button which opens another form, to add an item for the order.
I am trying to use vb in MS Access to take the order number and automatically put it in a field in the details form for the new item. I have tried different ways but using OpenArgs seems to be recommended. But the detail form won't open and I get run-time errors.
Here are the details of the problem - advice will be much appreciated:
The forms and field concerned are:
Form with orders is frmPedidoAvifiFind
Form with order-lines for one order is frmPedidoAvifi-dtlAdd (a separate form for adding details but not for viewing existing ones).
Field on both forms for Order Number is PedidoAvifiNo. This is a numeric field in both tables which are linked by a one-to-many relation via this field.
Main form: Button bring up detail form, code as follows:
Code on main form button:
Sub AddDetails_Click()
Dim strDocName As String
strDocName = "frmPedidoAvifi-dtlAdd"
' Open frmPedidoAvifi-dtl form in data entry mode and store PedidoAvifiNo in the form's OpenArgs property.
DoCmd.OpenForm strDocName, , , , acFormAdd, , [frmPedidoAvifiFind]![PedidoAvifiNo]
End Sub
Detail form: On Open property
Private Sub Form_Open()
If Me.OpenArgs <> vbNullString Then
Me.PedidoAvifiNo = Me.OpenArgs
End If
End Sub
Test 1: select an order number on main form so that record shows.
Press button to add orderline. - run-time error '2465' can't find the field "|" referred to. Debug highlights the DoCmd line.
Test 2:
Change openform line to:
DoCmd.OpenForm strDocName, , , , acFormAdd, , Me.PedidoAvifiNo
result: - run-time error 2501 the openForm action was canceled.
Thank you,
Mike Gunner
Reus, Spain
The error you are getting means that you have misspelled the name of the control PedidoAvifiNo.
When you type Me. intellisense will give you a list of available fields, see what you have that is similar to PedidoAvifiNo, or check the properties. It can be very easy to switch one letter and not notice.
As for the second part, you should use the Load event, rather than the Open event on frmPedidoAvifi-dtlAdd, because the controls are not yet available in the Open event.