Closing a single instance of a form in Access - forms

I am working on a database with a search function that might return multiple records of a form (i.e. a range of client IDs). I can freely navigate using the left/right arrows on the bottom of the form - but what if I am interested in closing a single instance of the form once I am done working in it? Ideally I could complete the tasks required for one client, then close that record and have it switch to the next one.
DoCmd.Close acForm, "Form Name"
does not work here, because it closes the entire form.
Please let me know if this makes sense - thanks!

You've hinted at the answer already in the question. When you run a query to open a form, if the query returns more than one record it's still only opening one form. The arrows at the bottom take you from one record to the next (or previous) but you are still within one form. You can't close down a single record from other records from the same query. Moving from one record to the next saves the changes, so you really shouldn't need to close a record individually.

Add below code in your form and call yourinstanse.Terminate.
Public Sub Terminate()
Me.SetFocus
DoCmd.Close
End Sub

Related

Use ContentControls to insert insert LastSavedBy Name, Date and Time information into Word form

I've set up a word form with different sections, each section to be completed by a separate person.
Each section of the form includes a combination of dropdown lists or free text fields set up using named Content controls.
At the end of each section there is field for the staff member to record their name, the date (calendar icon), and a command button with an associated macro to save the form and protect the data once that section has been completed.
While this enables the data to be protected it does not prevent person A from completing the form and entering person B's name. Note, this would not be expected, but traceability is required for regulatory purposes.
I would like to update the macro to protect the sections, save the file (currently working), and then immediately after saving, have the macro populate another field directly under the manually entered name and date with the Microsoft advanced properties of Last Saved By and the date and time. This would confirm the user.
My macro below (InsertMSSavedDetails()) will extract the Microsoft required data, but only if I manually click on the form and run the macro, and then it saves wherever I click on the form and won't save to the named ContentControl box. I'd like to automate this last step so that it is not reliant upon the user and the data is associated with particular section.
My form includes the following code:
Module
Sub ProtectFieldsSections2()
' protects Sections 1 and 2
If MsgBox("Do you want to Lock and Protect this section from further editing?", vbYesNo) = vbNo
Then Exit Sub
Dim sec As Section
Dim cc As ContentControl
Set sec = ActiveDocument.Sections(2)
For Each cc In sec.Range.ContentControls
cc.LockContents = True
Next cc
End Sub
This document:
Private Sub CommandButton2_Click()
ProtectFieldsSection1
ProtectFieldsSection2
ActiveDocument.Save
End Sub
Current code for Adding Microsoft data - which technically works, but not in the manner I need:
Sub InsertMSSavedDetails()
'
ActiveDocument.SelectContentControlsByTitle ("MSSavedDetails")
Selection.TypeText Text:="Check data: "
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _
"LASTSAVEDBY ", PreserveFormatting:=True
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _
"SAVEDATE \# ""d/MM/yyyy h:mm:ss am/pm"" ", PreserveFormatting:=True
End Sub
Second issue with the above, is that it would only need to be added the once, when Sub CommandButton2_Click is first selected. If I were to update the Sub CommandButton2_Click, how would I stop if from repeating the cycle of save, insert Microsoft data, save, insert Microsoft data?
NOTE: Use of word vs PDF form. Presently, the form is used in word format, converted to PDF, and electronically signed, however this does not allow others to add their information to the remaining sections. Adobe LiveCycler has been used to design PDF forms but there were issues with maintaining images and graphs, and there were other issues experienced with the Adobe reader, so the option is to remain with word.
Thank you.
Not sure I have completely understood the problems, but
The problem with inserting the field codes LASTSAVEDBY and SAVEDATE is that unless you "lock" them, their values will always reflect the most recent save. Also, if you want the fields to go in a content control, you have to use a rich text content control.
Perhaps better to
save the document
get the underlying property values (the ones that LASTSAVEDBY and SAVEDATE display) and insert them
save the document
If you have content controls named (say)
Section1LastSavedBy
Section1SaveDate
Section2LastSavedBy
etc.
then
you know which commandbutton the user clicked so you know which section you are dealing with
your code can then look something like
Private Sub CommandButton2_Click()
ProtectFieldsSection1
ProtectFieldsSection2
With ActiveDocument
.Save
.SelectContentControlsByTitle("Section1LastSavedBy")(1).Range.Text = _
.BuiltinDocumentProperties("Last Author").Value
.SelectContentControlsByTitle("Section1SaveDate")(1).Range.Text = _
format(.BuiltinDocumentProperties("Last Save Time").Value,"D/MM/YYYY h:mm:ss am/pm")
.Save
End With
End Sub
If you want to construct the content control names programmatically based on Section number, you can.
If you want to lock the content controls against further editing, you can.
I am not sure what problem you are encountering here:
"Second issue with the above, is that it would only need to be added the once, when Sub CommandButton2_Click is first selected. If I were to update the Sub CommandButton2_Click, how would I stop if from repeating the cycle of save, insert Microsoft data, save, insert Microsoft data?"
unless you are using a Save event. If that's the problem we could revisit that part.
It's pretty difficult to stop people tampering with data in Word, but personally I would consider saving copies of these values in, e.g., a Custom XML Part (not mapped to the controls) or Document Variables - possibly also encrypt them - you can use Windows crypto APIs for that.
Incidentally, I suspect the problem you have with your existing code is that .SelectContentControlsBYTitle doesn't Select the controls in the normal Word sense. It just returns a collection of controls with that name.

USERNAME-VBA-ACCESS

I have been asked to create a field(FORM) in access that get the USERNAME who has logged in . I created the string VBA Me!EmployeeID = Environ("USERNAME") which is on load. However, I noticed when I click on next record it goes way and wont get updated. I am not VBA expert that why I am here. What string should I write and where should I put it?
Should it be on form properties or the Employee ID field properties and also which part Before update or After?
Use form Current event. This event occurs both when a form is opened and whenever the focus leaves one record and moves to another
Private Sub Form_Current()
Me!EmployeeID = Environ("USERNAME")
End Sub

Microsoft Access 2010 lag in continuous form header subforms

I am a research student working on an access database where I have created a continuous form that is to be used in a sort of scrolling electronic health record format. The header includes information about the patient and the continuous form aspect is a series of patient visits. In the header, I have a few subforms, which populate based on linking on the patient_ID number which is posted in the header (generated by vba macro such that previously reviewed patients aren't revisited). These subforms seem to significantly lag such that they the results from the previous patient stick around going into the next one. The subforms contain user-selected pertinent data. Each form has its own table. They are linked primarily based on patient_ID.
I have tried:
macro on the header detail: on click, refresh. - seems to work, but not very elegant/intuitive
macro on the main form - same as above but on load, click, got focus, lost focus, open, activate -- none of them seem to do anything.
forced requery via vba (see below) on opening/etc of the form. Neither way has worked. Tried to run these on opening the header form.
Public Function RequeryMain()
Dim frmMain As Form
Set frm = Forms("FRM_continuous_reports_patient")
frm.Requery
End Function
Public Function RequeryHeader()
Dim frmHeader As SubForm
Set frmHeader = Forms("FRM_continuous_reports_patient").FRM_continuous_header_working
frmHeader.Requery
End Function
In the end, it is frustrating for users to have to click to clear the form for new entries. It works otherwise.
The end goal is for the form to open and have all the subforms load based on the newest patient_ID. This would likely have to involve a staggered load: (1) VBA script selects the next patient based on certain characteristics and passes the patient_ID to the main form; (2) load main continuous form based on patient_ID submitted to it; (3) load the header subforms and any pertinent data within (although should be blank for the first time these are seen); (4) on completion, back to (1).
From what I understand, this is already how it is working, however the subforms are loading too quickly? How can I fix this?
Hopefully someone can help explain how to remedy this/correct any misunderstandings I have about the mechanics of forms.
I know this will sound odd, but subforms actually load before parent form. Lag in subform display is not something I have encountered. Code should not be needed and likely will not correct. Must be something about the form/subform design, maybe their RecordSource. Would have to examine db to determine.
It is not necessary to create form objects in VBA just to requery. Is code behind the main form? Me.Requery will be enough for the main form. I always give subform container a name different from the object it holds, like ctrPatient. Then just Me.ctrPatient.Requery.
Why not put subforms in Detail section?
To answer your questions, and provide a condensed version of the logic referenced at: https://accessexperts.com/blog/2014/01/07/delay-loading-subforms-in-access/
is to:
In design view, set your subform SourceObject to "" (and save your form)
When you are ready to show the subform, just execute: Me..SourceObject = ""
When you are ready to navigate to the NEXT patient, clear the subform link: Me..SourceObject = ""
Now that should solve the issue of out of sync data between the main and sub.
You don't need to use the CASE statements, but they operate as if you had a bunch of "If" / "ElseIf" all nestled together -- except the CASE makes it easier to follow. It basically gets a value from a variable (i.e. Select Case MyVariable); then checks to see if it equals what you want (Case 1, Case 2, etc.), and if so, does whatever you code.

MS Access: Enter a specific text in a form using command button from another form

I would like to ask for your help on the following issue in MS Access.
I had created a form "CustomerListF", filled with command buttons for each client. For each button, I had created the following code:
Private Sub cmd_outlets_ABC_Click()
DoCmd.OpenForm "OrderFormF"
Forms!OrderFormF!Outlets = "ABC"
End Sub
The button would then open another form "OrderFormF" and enter "ABC" in the textbox named "Outlets". However, I realized the second line of code (Forms!OrderFormF!Outlets = "ABC") would always create a phantom record in my subform, which is located in "OrderFormF", and this record would travel to other clients' forms. This phantom record is usually created when the commandbutton is clicked twice (double clicks or subsequent clicks). It is a headache when the record starts to shift around.
enter image description here
I would like to seek your advice for vba code to edit the second line of code.
Thank you.
This approach for filling the field in opened form is not good. OrderFormF initialization and second line of your code with assigning value to the field may be executed in different sequence, they are not synchronized.
In order to avoid this, you should pass the argument to OrderFormF by another way. I would recommend to use OpenArgs parameter:
DoCmd.OpenForm "OrderFormF",,,,,,"ABC"
And then in Load event of OrderFormF assign the value to textbox:
Me.Outlets = Me.OpenArgs
In this case the "ABC" value will be assigned to first row in the form or to new record, if form is empty. Before assigning you can select the row if you need to assign value not to the first row. Also this way will protect you against double click on button, Load event executed only once during first form opening

How can I increase a form field every time the document is printed?

I know someone which has a single-page MS Word document for receipts.
One headline includes RECEIPT #<number>. At the moment he looks up which number was on the last printed receipt and adjust the receipt number manually to be that number plus one before he prints out a single copy of the document.
I thought this could be improved by using a form field holding the number which is then increased by one every time the document is printed. I didn't found anything supported by MS Word out-of-the-box, but I think that it can be done using VBA. It's years ago that I had to program in this language and I never did anything with form fields in Word and print events.
Can anyone point me in the right direction with some sample code which can do this? Automatic saving of the document after adjusting the number would be welcome, too.
Word lets one control the DocumentBeforePrint event, which I think would give you the result you need. After a Text Form Field has been added to the document itself, add this code to the ThisDocument VBA Declarations section:
Option Explicit
Private WithEvents app As Application
Then edit the Document_Open() sub to read:
Private Sub Document_Open()
Set app = Application
ActiveDocument.Variables("ReceiptNumber").Value = ActiveDocument.FormFields(1).Result
End Sub
Finally, create the DocumentBeforePrint sub with the following code:
Private Sub app_DocumentBeforePrint(ByVal Doc As Document, Cancel As Boolean)
Dialogs(wdDialogFilePrint).Show
With ActiveDocument
.Variables("ReceiptNumber").Value = .Variables("ReceiptNumber").Value + 1
.FormFields(1).Result = .Variables("ReceiptNumber").Value
.Save
End With
Cancel = True
End Sub
This code will launch the Print dialog box and, after printing, increment the counter and Save the document. The Cancel = True line cancels the standard Print dialog box, so that the code does not try to print the document twice. (One can also increment the counter after printing by removing Dialogs(wdDialogFilePrint).Show and Cancel = True.)
I think it's worth mentioning that once the code is in place, set this process up by double-clicking in the document's form field (the one that will contain the receipt number) and select "Number" for the field type and enter the first receipt number that needs to be printed as the "Default number."
Once the form field's defaults are entered, save the document manually and then close it. Now each time it is opened, the contents of the form field will be assigned to the variable and the DocumentBeforePrint event will increment the field upon each printing of the document. Should the user need to reset the field (due to printer jam or some other unforeseen event), he should double-click the field, change the default value, click OK in the dialog box, save the document, and close it (to clear out the previously assigned value for the counter's variable). As before, opening the document will make it ready for printing and incrementing. Hope this helps.