I'm fair at Access vba but Word is a new dialect for me.
I work for a hospital that has an Electronic Medical Record (EMR). We need a specific format and structure for the Nurse’s Clinical Progress Notes that can’t be created and enforced in the EMR. I created a Word vba UserForm, "frmProgNote" attached to a document "ProgNote.doc". FrmProgNote" has textboxes that create the structure we need for documentation and there is a command button that when clicked sends the info from the form to bookmarks in ProgNote.doc and copies all text from the document, including the newly inserted text onto the clipboard. The user then pastes it into the EMR. This all works great (believe it or not) but now they want to have multiple copies of frmProgNote open at the same time so they can move between several patients at once.
I’ve worked on this for 2 days and just can’t get it. I found I could not open multiple instances of Word and have the same form open in more than one. I copied the document and form so now have ProgNote1.doc with frmProgNote1 and ProgNote2.doc with frmProgNote2. I can get both to open BUT if I open frmProgNote1 then open frmProgNote2 the only data I can copy comes from frmProgNote2; the copy button doesn’t copy anything from the first form. I can click on frm1 and get it to take new data but the copy button doesn’t work anymore. Any suggestions? Thanks so much.
The following code gives the basis for creating a new instance of a UserForm.
Private frmNewInstance As Object
Private Sub CommandButton1_Click()
Set frmNewInstance = UserForms.Add(Me.Name)
frmNewInstance.Show
End Sub
Private Sub UserForm_Terminate()
Set frmNewInstance = Nothing
End Sub
It is necessary to control the object-reference, setting it to Nothing when the form instance is closed.
Note that this process is not as robust or reliable as it would be in, for example, VB.NET or C#. In particular, it is more difficult to distinguish between the different instances of the form.
One approach to consider is to use the Tag property of the form:
frmNewInstance.Tag = "OtherOne"
frmNewInstance.Show
Related
I'm trying to optimize the performance of my access frontend. One of the problems I'm stumbling on is how to set a multi-window form to open immediately to a specific record, because at the moment it queries everything twice.
Essentially, I allow my users to open multiple instances of a form. That way, a user can compare multiple records by placing the windows of those forms side by side.
At the moment, my code looks like this:
Set frm = New Form_Name
frm.RecordSource = "select * from Table where id = " & ID 'ID is a variable passed to the method
I'm pretty sure back then this question was one of the building blocks I relied on.
The problem is that on the first line, access already entirely opens the form and does everything the form does when opening, such as Form_Open, Form_Current, and loading subforms. Then, when I set the recordsource, it does all (or most) of that again, which significantly slows down the process of opening the form.
Here are some of the things I've tried:
Changing the Form_Current to recognize that it's being "used" twice and only actually run the code once. The problem is that the code is already very optimized and doesn't seem to be the bottleneck, so this doesn't seem to do much. Actually opening the form seems to be the bottleneck.
Trying to change the properties of the original form so that it opens the specific record I need, but I can't seem to change the properties without it opening the form.
Looking for a way to supply arguments to the form. That doesn't seem to be supported in VBA.
One other idea that popped into my mind was creating a variable in vba with the ID of the record, setting recordsource in the form properties to fetch that variable, but then, when I would open another form and change that ID, the form
I realize that I can do this with DoCmd.OpenForm, but that doesn't give me the option to open multiple instances of the same form.
How can I achieve this? This would mean a significant performance improvement.
OK, so I actually wanted to ask this question. But just before I hit the submit button, I had an idea...
Here's the idea: you set a global variable in VBA, which you then access in the form filter command. In my case I just added Public OpeningID As Long at the top of my VBA module. Then I create a function to get that value:
Public Function getFormID() As Long
getFormID = OpeningID
End Function
Then, in the form, you can set the filter criteria as ID = getFormID(). And then when you open the form instance, you do it like this:
OpeningID = ID
Set frm = New Form_Name
OpenindID = 0 'reset this to make sure that if it's being accessed when it shouldn't, it generates a clear error
The only problem is what happens when you refresh the form, as that will call the method again. When you refresh the form via VBA, you can set the OpeningID beforehand, and to avoid users refreshing the form, you can add this to your form (don't forget to turn on Key Previews in the form settings):
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyF5 Then KeyCode = 0
End Sub
Bang. Forms open almost twice as fast. Awesome.
I have a continuous form (MasterForm) for data entry based on one table. Some records need additional data, which I want to enter in a separate popup form (which has another table behind). This popup form (SlaveForm) opens by means of a click event in the MasterForm which triggers the DoCmd.OpenForm (vba instruction).
How can I “force” the popup form (SlaveForm) to be “in line” with the last current record of the MasterForm, by VBA code, exactly as I can do in a form/subform format (but here access has explicit tools to do that)?
Edit: See uploaded example
https://gofile.io/?c=VvMfiv (I am using an external link, since I was not able to find how I can do that in stackOverflow)
In the example, let us supose that we want to add Wagner's Parsifal Opera. After entering the name Parsifal you choose "Have Characters". It will open the SlaveForm (characters), where you want to write "Parsifal" and "Amfortas". However, I am not able to configure the synchronization between the MasterForm and the SlaveForm.
Any suggestion?
After some more digging, I manage to solve the problem. The BeforeInsert event in the slave form is the key. See uploaded file: https://gofile.io/?c=UxRdM8
In the MasterForm there is a text box (which can be set to be invisible) with the primary key (txtIDWork). After the Slave Form has been loaded, and before inserting a new register in the SlaveForm/Table, the BeforeInsert event (of the SlaveForm) assures that the primary key of the MasterForm (of the current register) is set to the foreign key of the SlaveForm:
Private Sub Form_BeforeInsert(Cancel As Integer)
Me.txtWorkNumber = Forms.frmMaster.txtIDWork
End Sub
where txtWorkNumber is the text box where the foreign key is written (which can be set to be invisible).
have you tried using a subform that is invisible until you need it, then making it visible when you want to enter data, then hide it again once you have filled it in?
Hi GUYS , I will explain my problem:
1- I use object command in excel to bring another excel file see image(1)object_image
2- I want to make command button which links to the object
3-image (2) show the worksheets and forms note when I close the book, the object's book change image all
so what I want is when I click the command button in my first excel it will open the form and allow me to change in the second excel.
this is my code
Private Sub CO1_Click()
Workbooks("Book3").Worksheets("Sheet1").CommandButton1.Value = True
Application.Run Workbooks("Book3").Worksheets("Sheet1").OnAction
trainUserForm.Show
End Sub
please, guys, i need this to finish my work and thx :)
I have a Microsoft Word document with .docm format. A first glance it does not contain any macros (as when clicking the following on the ribbon; View -> Macros -> View macros pops up a window having an empty list).
But when enabling the Developer ribbon tab, and clicking the Visual Basic icon there, and then selecting the Document and ContentControlonEnter from the dropdowns in the VB window the following code appears:
Private Sub Document_ContentControlOnEnter(ByVal ContentControl As ContentControl)
Dim i As Long, j As Long
With ActiveDocument
If ContentControl.Title = "Classification" Then
ContentControl.DropdownListEntries.Clear
For i = 1 To .ContentControls.Count
If Left(.ContentControls(i).Title, 5) = "Level" Then
j = j + 1
ContentControl.DropdownListEntries.Add Text:=j & " - " & .ContentControls(i).Range.Text
End If
Next
End If
End With
End Sub
Selecting the other options in the dropdowns give only "blank" code (that is they contain only function declarations followed by theEnd keyword).
My question is what is the code meant to do?
*
Details:
The Word document in question contains hyperlinks to parts of the same document and a couple of links to Word files and Excel files of the same folder. It also contains lots of content control boxes, which I'm guessing is the focus of the code (as the code contains the ContentControl keyword)
Content controls can trigger macros when the user enters and exits them. Microsoft made the design decision that all content controls should trigger the same "events" - Document_ContentControlOnEnter / Document_ContentControlOnExit - and that the code in the event needs to check which content control was entered / exited.
Content controls are considered as part of the Document because the Document can trigger events. That's why they're in (and MUST be in) the ThisDocument class module.
(Note: View Macros can only show you PUBLIC SUB procedures with no arguments that are located in "normal" code modules. Any Private Sub, any Function, anything that takes a parameter and anything in a class module will not appear in that list. So you can't use that list to determine whether a document contains any code.)
The If ContentControl.Title = "Classification" Then checks which content control was entered. (Note: it usually makes more sense to use Select Case rather than If, especially when the event needs to distinguis between multiple content controls.) What's inside the If only executes if it was a content control with the Title "Classification". (Note that more than one content control can have the same Title, so more than one content control could run the code.)
If another content control is entered, the event is still fired, but nothing happens (in this case).
Catalin Pop correctly explained that the code is, in essence, "resetting" the drop down list.
Legacy Form fields use a similar pattern - macros can fire when the user enters/exits an form field. But the design for that was you had to create a Public Sub and assign that to the form field in the Properties.
I think the logic here is quite simple.
Basically the code searches for a content control named Classification within the entire document.
After it finds it, it clears all of its drowdown entries - like a reset.
After the cleaning part it again searches through the entire document for all content control that start with word "Level" and it collect the text for those controls and their order in appearance.
With this info collected it then fills the dropdown optios for the classification control above. (e.g. 1 Level X, 2 Level Y.. - based on what it finds in the document for controls starting with Level in their name)
I have a database that was create in Access 2010. We recently updated our systems to Access 2013. In Access 2010 I have no errors accessing a form object with
Form_frmName.txtFieldName.Value
However, when using Access 2013 I get a runtime 2424 error stating that "The expression you entered has a field, control, or property name that Microsoft Access can't find. I am accessing from a module.
The module sets these fields visible using
With Form_frmName
.txtFieldName.Visible = True
End With
before attempting to access them.
Has there been any changes in the way form objects are accessed between 2010 and 2013? Is this an issue others have faced?
In Response to #WayneGDunn's questions below
QUOTE:
I need to know exactly what and how you are using this.
1. You have a bound textbox named 'txtFieldName' on a form. As #brad asked, is there a subform, and if so, is this field on the subform?
2. You said the code is in a module, but is the code in the form where the field is defined?
3. Please explain where/what form 'frmQAtab' is (you said your form name was 'frmName', so what is the other, how related?)
4. Is the code in an event? Can you share the entire subroutine?
5. Have you tried creating a dummy query and using the builder to reference the field?
RESPONSE:
1. I have a form (frmMain) with multiple tabbed pages. frmName is one of those tabs, containing the bound field txtFieldName.
2. The module is run from the form the field is in.
3. My apologies frmQAtab is frmName, I just neglected to make that generic in my copy-paste.
4. The event is a button click. The button click runs a sub from a module. That sub makes visible the fields, runs a query based on user input (two date fields), populates the bound fields with the returned record set, then attempts to access them for processing (another query is run to process a complete other set of fields). To post the entire subroutine would be a bit more than I would ask you to chew on. This is legacy code I'm trying to fix, and it's rather large.
5. I have not tried a dummy query. Access is not my field (I'm mainly a C#, scripting, guy.) Is there some suggestions in this area you could give?
One of the following references to your fields should work. I created a form (named 'frmMain'), then created a Tab Control with two tabs. On the first tab, I inserted another form (named 'frm3197'). I also created a text box on the tab control named 'txtFieldName' AND in form 'frm3197'. From a button click on 'frmMain', the following will reference each of those fields.
Private Sub cmdButton1_Click()
Forms![frmMain]![txtFieldName] = Now()
Forms![frmMain]![frm3197].Form![txtFieldName] = Now()
End Sub