I'm trying to automate populating a PDF form from MS Access VBA. The form itself is maintained online and so my process is:
Download the form
Open it in Adobe
Auto-populate fields
Save / send it on to others
All of this I'm doing from Access VBA. I've encountered an issue on step 3, however.
What I noticed was, if I try to populate the field from VBA, it works fine if the field already has a value. However, on a new / blank form, it generates an error.
Specifically, I call it using the document Javascript object (jso) thusly:
jso.xfa.resolveNode("form." & jso.getNthFieldName(0)).rawValue = 'test'
If the form field is not populated, VBA errors, saying the object doesn't have the rawValue property.
I'm guessing some sort of model initialization is forestalled until the form is populated at least once. The field reference exists in the jso.xfa model, but the property itself is otherwise inaccessible.
Is there a way around this other than pre-populating a "dummy" form? I'd rather not have to maintain / update it as the original gets changed online.
Related
I'm trying to load a form in Access in order to get field data from it and store that field text into a variable. I want to transfer it to Microsoft Word (but that's another problem for a different day).
This code goes in the Access Object and it's subroutine is referenced in the modules section
DoCmd.OpenForm "ContactDetails"
Dim NameBoxOne As String
NameBoxOne = Forms!ContactDetails!txtFirstName.Value
I receive:
Run Time Error -2146500594 (800f000e) Method 'Item' of object 'Forms' failed when trying to reference a field.
I suspect this is the case because the form hasn't completely loaded after opening, but that is only a guess.
I inherited a fairly large project at work that is undocumented and written in VB (originally started pre .NET, ended around .NET 2). I'm in the process of updating / refreshing a lot of the code, but have run into an annoying issue that I haven't found the solution for yet. This system utilizes a UI, a Web Service, and a SQL DB.
Problem: I have a Databound Combobox (originally set to DropDownList - I'm changing it to DropDown, which is what started this mess - going back isn't an option) that is tied to a DataSet that comes from a Web Service. When a user types in the item they want manually, the data from the text field doesn't seem to associate itself with the DisplayMember, which forces the WS/SQL query to fail (it is sent a blank value when it's expecting a ValueMember). If the user types in a partial selection and then chooses the value they want from the DisplayMember list using the arrow keys or tab, the query goes off without a problem.
My Question: How do I get the text field to translate to the DisplayMember which will then properly tie itself to the ValueMember which will then allow the query to execute correctly? Sorry for making this sound complicated or convoluted; I'm sure the answer is easy and I'm just glazing over it.
The relevant bit of code is:
With cmbDID
If dtsLU.Tables.Contains(reqTable) = True Then
.DataSource = dtsLU.Tables(reqTable)
.DisplayMember = "zip"
.ValueMember = "gridID"
End If
End With
cmbDID.DataBindings.Clear()
cmbDID.DataBindings.Add("SelectedValue", dtsData, strDT & ".gridID")
I've tried changing "SelectedValue" to "Text", which almost works - but it directly translates to gridID and skips zip which ends up with an incorrect Web Service response since the zip and gridID field values are not synced (zip (DisplayMember) may be 5123 while gridID (ValueMember) may be 6047). I've tried changing "SelectedValue" to "SelectedIndex", and that got me no where.
Any help is greatly appreciated.
EDIT
To add some clarification to the process, the below pseudo code / description is roughly what happens. I could post the whole module, but I feel that would just muddy the whole question even more.
Private Sub A
FormAlpha is created with 1 ComboBox in the form of a DropDown
This DropDown is populated with a DataSet
DataBinding with a blank DataSet is added to the control to keep track of the users input
End Sub
lblSubmit_Click event is triggered on FormAlpha by the user after they have populated the DropDown with their data. lblSubmit_Click calls Private Sub Submit
Private Sub Submit
BindingContext(DropDown DataSet, tableName).EndCurrentEdit() is called
DataSet.HasChanges() is processed
If changes are present, changes are processed
HERE lies the problem
If the user has manually typed in the DropDown field, but not hit an arrow key or tab, then the DataSet registers a change, but returns a null value in all fields - it knows something was entered, but that data apparently didn't pass through the DataSet for the ComboBox (ListItems or SelectedIndex didn't change / fire I'm guessing). If the user selects the item with the arrow keys, the DataSet has the proper input (I'm assuming the Data was validated by the control at this point).
If the processed data is good, a value is entered into the database
If the processed data is bad (empty), an error is returned
End Sub
If the above can't be solved with what I've provided, but someone still knows a better way to handle this type of situation, I'm all ears. Rewriting the module isn't ideal, but fixing this problem is a necessity.
Alright, while this fix may not be ideal, it is a fix none the less.
The bare bones problem was that the text value of the DropDown wasn't causing the data to actually affect the SelectedIndex / SelectedValue of the control unless you interacted with it using the arrow keys or a mouse click. So, while the DropDown would read "1234", in reality the control saw "".
The fix I have in place for this is simply calling comboBox.text = comboBox.text whenever the user hits the submit button.
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
I am trying to export items from my access database into lotus notes. The document I am trying to export to is a stationary, and has all the data written into it, I just need to somehow mark placeholders and then update the values. I have read the documentation and it appears I will need to address fields and then call a method to replace the text like so:
'where body is the field and the following string is what to replace field with
Call doc.ReplaceItemValue("body", "REPLACE BODY")
To be clear, my entire code looks like:
Set session = CreateObject("Notes.NotesSession")
Set maildb = session.GetDatabase("server", "mail\box.nsf")
Set View = maildb.GetView("Stationery")
Set entries = View.AllEntries
Set entry = entries.GetFirstEntry
Set doc = entry.Document
Call doc.ReplaceItemValue("Subject", "Report - " & Date)
'add code here
Call doc.send(False, "person.to.receive#thisemail.com")
End Sub
I have noticed that while perusing documentation, there seems to be an ability to create fields, and then address those fields to update values. So for example, if I have a field named $COST, then one could do:
Call doc.ReplaceItemValue("$COST", "The cost is $3000")
And that field should be updated to reflect the value I passed through the method. My big problem is, even looking through documentation, I cannot figure out where I need to go to add in my custom fields. It seems that the documentation assumes that you know how to create these fields and just address them. Or am I only supposed to create these fields programatically and then fill in the data? My client is Lotus Notes 8. Thanks!
Yes, that is the cool thing about IBM Lotus Notes databases: you can put items (=fields) in a Notes document without a prior definition of fields.
If you create items in a document with doc.ReplaceItemValue() and save or send the document then the items are just there. You can check the items when you open the property box for a selected document. All items are listed on document properties' second tab.
Another question is of course to define fields in a form so that the created items are visible to user without looking at document properties box. Open database in Designer and put the fields in right position and size to form.
Your question and comments telling that you want to create a document, fill it with data and send it to users.
If all users have access to your Notes server then you can create that document in your existing database and send just a link mail to users. This way you can create a good looking form and position all your data fields. Users will access the document in database through link.
An alternative is to create an nice looking HTML file, attach it to the mail and send it.
In this case you would add this code to your example at 'add code here:
Call doc.RemoveItem("Body")
Set rtitem = doc.CreateRichTextItem( "Body" )
Call rtitem.AppendText("your mail text")
Call rtitem.EmbedObject(EMBED_ATTACHMENT, "", "report.html")
Based on the comment thread on #Knut Herrmann's answer, I believe that the solution you really want involves using "stored form". The first argument to the NotesDocument.Send() method is a boolean that specifies whether you want to store the form or not.
Normally, you would use Domino Designer to create a stored form. You would not need Designer rights to anyone's mailbox. You would just need to create an empty database of your own, and put a form into it. You woould change your code to open that database and create the document in there instead of in a mailbox database as you are doing now. (One of the other cool things about Notes is that you don't actually have to be working in a mailbox database in order to mail a document. You can mail any document from any database, as long as you put the approporiate fields into it.)
There is also a way to do this without Domino Designer, and you could even dynamically generate the form with truly custom fields that your code only discovers as it runs. You could do this with DXL, which is an XML format for describing Lotus Notes objects, including forms. You would just need some sample DXL to work from. Preferably that should be of an empty database that contains a simple form that is set up more or less in the layout that you would want, though again you would need Domino Designer for that. You could just use the same mailbox database that your code is currently using, but that will leave you with a lot of extra stuff in the DXL that doesn't need to be there; and given that you're not all that familiar with Notes, it would likely be difficult for you to navigate through it all to find what you need.
Either way, though, you could use the NotesDXLExporter class to generate the DXL file. Your code could manipulate the DXL, adding/changing elements as needed (following the pattern that you see in sample, of course), and they you could use NotesDXLImporter to create the database that your code will actually use to create the document in and mail the message with the stored form.
I need a non-editable field in a word form that can be read in vba.
Currently I use a text field, which is hidden. As in:
ActiveDocument.FormFields("DocID").Select
Selection.Font.Hidden = false
//do read then re-hide it.
However users can still 'tab' in to this text field and overwrite the document ID that is there and thus invalidate the vba macro. And unfortunately that is what happens.
I can set the text field property 'Fill-in enabled' to false which gives the desired effect in the form, i.e the user cannot edit it. However now this text field cannot be read in vba.
ActiveDocument.FormFields("DocID").SomeProperty
//throws error 'The requested member of the collection does not exist'
So my question is, is there a way I can store a hidden variable in a word form that can be read in a vba macro?
Unfortunately this has to be a Word-97 compatible solution.
You could use custom document properties instead, see here:
http://msdn.microsoft.com/en-us/library/aa537154(v=office.11).aspx