VBA Access object code for DropDownList ContentControls - ms-access

I am coding an Access database that will collect user input, then open a Word document and fill out various parts of the document.
The problem I am having is it will only work once for Drop Down Lists. Not sure why or where to look to fix this one. There are three types of items I am programmatically filling in. The first is bookmarks, no problem with this. Second is Content Control Checkboxes, these also work with no problems. The third is Content Control Drop Down Lists, this is where the problem is. First time I open the Access Database it works, but if I click the command button again, nothing (for Drop Downs). The main problem is that it doesn't produce an error message, so I am not sure where to look.
I am guessing it has something to do with the objects I am creating to do the drop down updates? any help would be great:
Dim WordApp As Word.Application
Dim strTemplateLocation As String
Dim dir As String
Dim path As String
Dim wDoc As Word.Document
path = Left(CurrentDb.Name, InStrRev(CurrentDb.Name, "\"))
strTemplateLocation = path & "UserDoc.docx"
On Error Resume Next
Set WordApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Set WordApp = CreateObject("Word.Application")
End If
WordApp.Visible = True
WordApp.WindowState = wdWindowStateMaximize
WordApp.Documents.Add Template:=strTemplateLocation, newtemplate:=False
With WordApp
'Working Bookmark
.Selection.GoTo what:=wdGoToBookmark, Name:="COMPANY": .Selection.TypeText [fac]
'Working checkbox
If Me.RD = True Then: .ActiveDocument.ContentControls(9).Checked = True
'Works ONCE drop down
Dim objCC As ContentControl
Dim objCE As ContentControlListEntry
Dim ListSelection As String
ListSelection = Me.System_Type.ListIndex + 2
Set objCC = ActiveDocument.ContentControls(1): Set objCE = objCC.DropdownListEntries.Item(ListSelection): objCE.Select
End With
Should I be closing out the objCE and objCC at the end or something?

This is probably your problem:
Set objCC = ActiveDocument.ContentControls(1)
It should be
Set objCC = .ActiveDocument.ContentControls(1)
But much better would be:
Set wDoc = WordApp.Documents.Add(Template:=strTemplateLocation, newtemplate:=False)
and then always use wDoc instead of WordApp.ActiveDocument.
See here: VBA ActiveDocument Concerns / Alternatives?

Related

Search through VBA code files in other Access Databases

I read through a pretty thorough response in the link How to search through VBA code files and it works just fine for the current project. However, I'm just feeling slow in opening up other projects and looking through their code.
The response mentioned using OpenDatabase but I'm not seeing examples about the association between the database and the Application.VBE.ActiveVBProject. I've not been lazy about this, but 4 days of searching the web has exhausted my options.
Any help would be really appreciated.
My apologies. Found other way to make this work.
Public Sub FindWordInOtherModules(ByVal pSearchWord As String, sApplicationFilePath As String)
Dim objComponent As VBComponent
' VBComponent requires reference to Microsoft Visual Basic
' for Applications Extensibility; use late binding instead:
Dim lStartLine As Long
Dim lEndLine As Long
Dim lStartColumn As Long
Dim lEndColumn As Long
Dim accApp As Access.Application
Set accApp = New Access.Application
With accApp
.Visible = True
.OpenCurrentDatabase (sApplicationFilePath)
.UserControl = True
'MsgBox .VBE.ActiveVBProject.VBComponents.Count
'MsgBox .CurrentDb.Name
For Each objComponent In .VBE.ActiveVBProject.VBComponents
If objComponent.CodeModule.Find(pSearchWord, lStartLine, lStartColumn, lEndLine, lEndColumn, _
FindWholeWord, MatchCase, PatternSearch) = True Then
MsgBox "Found text " & StringToFind & vbCrLf _
& "Start line: " & lStartLine & vbCrLf _
& "Line text: " & objComponent.CodeModule.Lines(lStartLine, lEndLine - lStartLine + 1), vbOKOnly, objComponent.CodeModule.Name
End If
Next objComponent
End With
accApp.CloseCurrentDatabase
Set accApp = Nothing
End Sub
You should probably add accApp.Quit:
accApp.CloseCurrentDatabase
accApp.Quit
Set accApp = Nothing
before Set accApp = Nothing to speed up closing the application and close it during execution of this code (Public Sub FindWordInOtherModules), on the line accApp.Quit, not later. On my computer mouse is still inactive several seconds after execution such kind of Sub if accApp.Quit is not added.
But there is no need to open another database, because the current database can be only "linked' to it by creating temporary reference:
Private Sub FindWordInOtherModules2()
Dim objComponent As VBComponent
...
...
Dim lEndColumn As Long
Dim ref As Reference
Dim RefName As String
Const FileName = "C:\Users\....mdb"
With Application 'instead of accApp
.References.AddFromFile FileName
'.References.Count because the new one is supposed be the last one (?)
RefName = .References(.References.Count).Name
Dim VBProj As VBProject
For Each VBProj In .VBE.VBProjects
If VBProj.FileName <> .CurrentDb.Name Then Exit For
Next
For Each objComponent In VBProj.VBComponents
'Debug.Print objComponent.Name
...
...
Next
Set objComponent = Nothing '?
Set VBProj = Nothing '?
Set ref = .References(RefName)
.References.Remove ref
Set ref = Nothing '??
End With
End Sub
This seems be faster then opening another database file, but VBA can't be updated.
References.Remove ref removes reference, but VBA folders are still visible in the left panel and all the code works, what is a little disturbing ...
Application.VBE.VBProjects.Remove VBProj doesn't work. It may have something to do with "Trust access to the VBA project object model" option in Trust Center - Macro Settings, which is not available in Access.
But the project is not visible after closing and opening the database.

Microsoft access vba-shift focus from access to word

I am creating and opening a word document through access 2007 vba. The document is created but the focus is not shifted to word. Instead the focus still remains on access form through which am creating the doc. Below is my code:
Dim obj As Word.Application
Dim wor As Word.Document
Dim str As String
str = "C:\hello\folder1\vin.dot"
Set obj = CreateObject("Word.Application")
Set wor = obj.Documents.Add
With wor
.SaveAs str
.Close
End With
obj.Visible = True
obj.Documents.Open str
obj.WindowState = wdWindowStateMaximize
Any sugesstions please.
You can move the focus with AppActivate;
AppActivate "Microsoft Word"
The VBA Word.Application object may have more than one Window associated with it. You may specify which Window to display by using its Caption property.
Since you created a new Word.Application and only created one Document, you may assume that the 1st element (1-based array) is what you want to display in your code.
AppActivate (obj.Windows(1).Caption)
I was able to call the specific window even with other word documents open with the following:
Private Sub but_Click()
'must add tools > references Microsoft Word XX.X Object Library (xx.x is max update)
Dim WordApp As Word.Application
Dim WordDoc As Word.Document
strProjPath = Application.CurrentProject.Path 'get current path
strVerWord = "test" 'i use this to identify paths that can change based on network configs.
posOp = InStr(1, strProjPath, strVerWord) ' find the verification word in the path
strVerPath = "strVerWord filepath\FP\FP\document.docx" 'create string location for document
strPathPlusDBName = Left(strProjPath, posOp - 1) & strVerPath
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = True
Set WordDoc = WordApp.Documents.Open(FileName:=strPathPlusDBName, ReadOnly:=True) 'open word file in read only
AppActivate WordDoc
End Sub

VBA ActiveDocument Concerns / Alternatives?

I'm using VBA in access to open up a protected word template, fill in the data, and then re-protect it.... this way, if the database system goes down, the word template can still be used manually in its protected state.
I have just started using VBA and in this line:
If ActiveDocument.ProtectionType <> wdNoProtection Then
ActiveDocument.Unprotect Password:=""
End If
I'm concerned that whilst running the code in access, that if the user opens up another word document and makes it the focus, that it will occidentally get protected instead of the other. How do I keep active focus on the document I'm writing to... or do I need to reference my document somehow using WordApp.protect (or something similar that works)
Private Sub Command0_Click()
Dim WordApp As Word.Application
Dim strDatabasePath As String
Dim strTemplatePath As String
Dim strTemplate As String
Dim strJobTitle As String
Dim strFile As String
strFile1 = "testcoc.dotx"
strFile2 = "testcoc-private.dotx"
strDatabasePath = CurrentProject.Path & "\"
strTemplatePath = "\templates\"
strTemplate = strDatabasePath & strTemplatePath & strFile2
On Error Resume Next
Set WordApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Set WordApp = CreateObject("Word.Application")
End If
On Error GoTo ErrHandler
WordApp.Visible = True
WordApp.WindowState = wdWindowStateMaximize
WordApp.Documents.Add Template:=strTemplate, NewTemplate:=True
'strJobTitle = DLookup("JobTitle", "Job", "JobNum = " & [JobType])
strJobTitle = DLookup("JobTitle", "Job", "JobNum = 'J0456'")
With WordApp.Selection
'Unprotect the file
If ActiveDocument.ProtectionType <> wdNoProtection Then
ActiveDocument.Unprotect Password:=""
End If
.Goto what:=wdGoToBookmark, Name:="bm_0_4"
.TypeText strJobTitle
End With
'Reprotect the document.
'If ActiveDocument.ProtectionType = wdNoProtection Then
'ActiveDocument.Protect _
'Type:=wdAllowOnlyFormFields, NoReset:=True, Password:=""
'End If
DoEvents
WordApp.Activate
Set WordApp = Nothing
Exit Sub
ErrHandler:
Set WordApp = Nothing
End Sub
Thank You
I haven't tried this but WordApp.Documents.Add Template:=strTemplate, NewTemplate:=True does return the new document. So I would do something like
Dim doc as Word.Document
Set doc = WordApp.Documents.Add(Template:=strTemplate, NewTemplate:=True)
and reference doc throughout my code instead of ActiveDocument. It seems like doing that should get help you avoid the particular situation you're concerned about.

Word Automation: Noneditable

I am using Access to send data to a template I created in Word. After it succesfully sends the data I need to make the open Word Document NON-editable.
Also, I notice that after I am done with the Document it prompts to save. Is it possible to remove this prompt, BUT allow the capability to save.
This is the code I am using to do the Word Automation:
' Create a Word document from template.
Dim WordApp As Word.Application
Dim strTemplateLocation As String
Dim myVariable As String
myVariable = “TEST!!”
' Specify location of template
strTemplateLocation = Left(CurrentDb.Name, InStrRev(CurrentDb.Name, "\")) & "test.dot"
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = True
WordApp.WindowState = wdWindowStateMaximize
WordApp.Documents.Add Template:=strTemplateLocation, NewTemplate:=False
' Replace each bookmark with field contents.
WordApp.Selection.GoTo what:=wdGoToBookmark, Name:="myBookmark"
WordApp.Selection.TypeText myVariable
DoEvents
WordApp.Activate
Set WordApp = Nothing
The Document object has a Saved property which normally changes to False if any changes are made. If you set this property to True then you won't be prompted to save the document when you close it but you can still save it manually (via Save or Save As...) if you want to.
You can use the Protect method of the Document object to restrict the changes which the user can make. For example, you can call it with the parameter wdAllowOnlyReading which will mean that no changes of any kind can be made. You may also need to look at password protecting the document to prevent the user from simply unprotecting it again
This should do what you need. Tested from Excel, not Access, so you'll need to fix the template path
Sub Tester()
' Create a Word document from template.
Dim WordApp As Word.Application
Dim strTemplateLocation As String
Dim myVariable As String
myVariable = "TEST!!"
' Specify location of template
strTemplateLocation = ThisWorkbook.Path & "\test.dotx"
Set WordApp = CreateObject("Word.Application")
With WordApp
.Visible = True
.WindowState = wdWindowStateMaximize
.Documents.Add Template:=strTemplateLocation, NewTemplate:=False
' Replace each bookmark with field contents.
.Selection.GoTo what:=wdGoToBookmark, Name:="myBookmark"
.Selection.TypeText myVariable
DoEvents
With .ActiveDocument
.Protect Type:=wdAllowOnlyReading, Password:="blah"
.Saved = True
End With
.Activate
End With
Set WordApp = Nothing
End Sub

Import MS Word form fields into MS Access

I have created an application form using MS Word and a whole bunch of form fields, and I have an Access db that can import all the data I need from this Word doc, thanks to this:
http://msdn.microsoft.com/en-us/library/aa155434%28office.10%29.aspx
Now everything works just fine (I even managed to get it to import into multiple tables!), but the problem with the above is that I have to manually enter the name of each file one at a time... which is fine if it's just a case of importing the application form as it comes in... but I have quite a lot sitting in a folder that needs entered into the database.
Then I found this:
How to show "Open File" Dialog in Access 2007 VBA?
I've tried to tweak and merge the two to make it work... but as you can guess, to no avail... (it doesn't help when I'm very much an Access novice!)
What I am looking to do is to be able to import a bunch of Word docs / form fields into MS Access by using the Open / Select file dialogue box... what I've got works, but I'd like to make it easier to work with!
Thanks everyone
Jake
##### Codes I been using
Option Compare Database
Option Explicit
Private Sub cmdFileDialog_Click()
' This requires a reference to the Microsoft Office 11.0 Object Library.
Dim fDialog As Office.FileDialog
Dim varFile As Variant
Dim appWord As Word.Application
Dim doc As Word.Document
' Dim cnn As New ADODB.Connection
' Dim rst As New ADODB.Recordset
Dim strDocName As String
Dim blnQuitWord As Boolean
' Clear the list box contents.
' Me.FileList.RowSource = ""
' Set up the File dialog box.
Set fDialog = Application.FileDialog(msoFileDialogFilePicker)
With fDialog
' Allow the user to make multiple selections in the dialog box.
.AllowMultiSelect = True
' Set the title of the dialog box.
.Title = "Select One or More Files"
' Clear out the current filters, and then add your own.
.Filters.Clear
.Filters.Add "Microsoft Word", "*.DOC"
.Filters.Add "All Files", "*.*"
' Show the dialog box. If the .Show method returns True, the
' user picked at least one file. If the .Show method returns
' False, the user clicked Cancel.
If .Show = True Then
' Loop through each file that is selected and then add it to the list box.
For Each varFile In .SelectedItems
' Me.FileList.AddItem varFile
Set appWord = GetObject(, "Word.Application")
Set doc = appWord.Documents.Open(varFile)
' cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
' "Data Source=M:\Medical\GPAppraisal\Contacts & Databases\" & _
' "AppForm.mdb;"
' rst.Open "tbl_Applicants", cnn, _
' adOpenKeyset, adLockOptimistic
' With rst
.addnew
!Title = doc.FormFields("wTitle").Result
!FirstName = doc.FormFields("wFirstName").Result
!LastName = doc.FormFields("wLastName").Result
!Address1 = doc.FormFields("wAddress1").Result
!Address2 = doc.FormFields("wAddress2").Result
!Address3 = doc.FormFields("wAddress3").Result
!City = doc.FormFields("wCity").Result
!PostCode = doc.FormFields("wPostCode").Result
!Email = doc.FormFields("wEmail").Result
!Phone1 = doc.FormFields("wPhone1").Result
!Phone2 = doc.FormFields("wPhone2").Result
!LM = doc.FormFields("wLM").Result
!LMAddress1 = doc.FormFields("wLMAddress1").Result
!LMAddress2 = doc.FormFields("wLMAddress2").Result
!LMAddress3 = doc.FormFields("wLMAddress3").Result
!LMCity = doc.FormFields("wLMCity").Result
!LMPostCode = doc.FormFields("wLMPostCode").Result
!LMEmail = doc.FormFields("wLMEmail").Result
!LMPhone = doc.FormFields("wLMPhone").Result
!LMOK = doc.FormFields("wLMOK").Result
!Probity = doc.FormFields("wProbity").Result
!Practising = doc.FormFields("wPractising").Result
!Signature = doc.FormFields("wSignature").Result
!AppDate = doc.FormFields("wAppDate").Result
!e2011012028 = doc.FormFields("w2011012028").Result
!e2011021725 = doc.FormFields("w2011021725").Result
!e2011030311 = doc.FormFields("w2011030311").Result
!e2011031625 = doc.FormFields("w2011031625").Result
!e20110203 = doc.FormFields("w20110203").Result
!e20110211 = doc.FormFields("w20110211").Result
!e20110322 = doc.FormFields("w20110322").Result
!e20110330 = doc.FormFields("w20110330").Result
.Update
.Close
End With
doc.Close
If blnQuitWord Then appWord.Quit
cnn.Close
MsgBox "Application Imported!"
Cleanup:
' Set rst = Nothing
' Set cnn = Nothing
Set doc = Nothing
Set appWord = Nothing
Next
Else
MsgBox "You clicked Cancel in the file dialog box."
End If
End With
End Sub
#
I've tried to mess with me.tables and me!forms and .add etc etc - obviously I'm a complete novice here!!!
What I want is to be able to import data from form fields in a Word Doc into a MS Access table (which I have managed to do with the first URL in my original post above); by means of selecting the Word doc from the Open/Select dialogue box, instead of manually entering the names of each Word doc.
My apologies if it sounds obvious or simple - Access is not my strong point by any means!
Before I begin I didn't understand why you have so many uncommented lines (lines beginnig mit ' ) in you code example. I assume that most of those lines would normally not bei uncommented and be part of the working code. Or are there artifacts of the Stack Overflow Editor?
I see a few problems, that might to guide you to a solution.
1) When you use
With fDialog
you let this 'open' until the end of the code (even using a second With in between). I would recommend to set you corresponding 'End With' right after you no longer require it. Remeber (or take note): The
With fDialog
[... something]
' Set the title of the dialog box.
.Title = "Select One or More Files"
is really just a shorthand for
fDialog.Title
(i.e. a "naked" . means, that it has to be appendend to the object in the With) so you could do away with the "With" entirely. IN you example I would set the "End With" right before
If .Show = True Then
and then use
If fDialog.Show = True Then
2) I would set
Set appWord = GetObject(, "Word.Application")
outside your For Each loop (don't forget to take Set appWord = Nothing outside the loop as well). Remember that with GetObject you need an runnig Word-instance, otherwise you might want to use
Set appWord = CreateObject("Word.Application")
or to have it both ways, try to get a Word-object, and if it is not available (i.e. Err.Number = 429) create a new one.
On Error Resume Next
Set appWord = GetObject(, "Word.Application")
If Err.Number = 429 Then
Set appWord = CreateObject("Word.Application")
End If
On Error GoTo 0
3) When working or at least while developping using automation I would always set
objword.Visible = True
so you see error messages or other problems right within Word.
HTH for the next steps (in case you have this problem anymore)
Andreas