I wrote code in Access database 2016 contains functions and macros, then I move this file to share with some users that don't have Access Application so, I install Access runtime it works well but I face many problems with reference libraries.
I decided to use late binding (by writing EarlyBinding = 0 in a database property of VBA editor)
and uncheck all references except two (I can't uncheck) and covert
Set appWord = New Word.Application
to
Set appWord = CreateObject(Word.Application)
note 1: I have a function to open Word document from Access form.
note 2: I convert the database extension from .accdb to .accdr
after I made changes in late binding and convert the previous statement no message error (for reference) appears but the function of open Word doesn't work.
is there a tool like Access runtime for Word? so I can't open for this reason?
below the code of this function:
Function fillWordForm()
Dim appWord As Object
Dim doc As Object
Dim path As String
Dim myID As String
On Error Resume Next
Error.Clear
'Set appWord = CreateObject("word.application")
Set appWord = CreateObject(Word.Application)
If Err.Number <> 0 Then
'Set appWord = New Word.Application
'Set appWord = CreateObject(Word.Application)
appWord.Visible = True
End If
'path = Application.CurrentProject.path & "\H_F.docx"
'path = "\\ubcdatacenter\Public\UBCIEDatabase\DOC\H_F.docx"
path = "C:\Users\LENOVO\Desktop\UBC Database\H_F.docx"
If FileExists(path) = False Then
MsgBox "Template File Not Found", vbExclamation, "File Not Found"
Else
Set doc = appWord.Documents.Add(path, , True)
myID = DLookup("ID", "Exports_imports_Table", "[ID] = " & Me.ID)
With doc
.FormFields("BookID").Result = [ID]
.FormFields("Book_BC_date").Result = Me.date_BC
.FormFields("Book_AH_date").Result = Me.date_AH
.FormFields("Book_AH_date").Result = Me.date_AH
.FormFields("BookTopic").Result = Me.topic
.FormFields("BookProjectName").Result = Me.projectName
.FormFields("BookCompanyName").Result = Me.companyName
.FormFields("BookContent").Range.Text = Me.content
'Result = Me.content
appWord.Visible = True
appWord.Active
End With
Set doc = Nothing
Set appWord = Nothing
End If
End Function
this code to ensure that file is excite
Function FileExists(ByVal strFile As String, Optional bFindFolders As Boolean) As Boolean
'Purpose: Return True if the file exists, even if it is hidden.
'Arguments: strFile: File name to look for. Current directory searched if no path included.
' bFindFolders. If strFile is a folder, FileExists() returns False unless this argument is True.
'Note: Does not look inside subdirectories for the file.
'Author: Allen Browne. http://allenbrowne.com June, 2006.
Dim lngAttributes As Long
'Include read-only files, hidden files, system files.
lngAttributes = (vbReadOnly Or vbHidden Or vbSystem)
If bFindFolders Then
lngAttributes = (lngAttributes Or vbDirectory) 'Include folders as well.
Else
'Strip any trailing slash, so Dir does not look inside the folder.
Do While Right$(strFile, 1) = "\"
strFile = Left$(strFile, Len(strFile) - 1)
Loop
End If
'If Dir() returns something, the file exists.
On Error Resume Next
FileExists = (Len(Dir(strFile, lngAttributes)) > 0)
End Function
what should also convert to make all code late binding?
Editing
after Mathieu's changes
Function fillWordForm()
Dim appWord As Object
Dim doc As Object
Dim path As String
Dim myID As String
On Error Resume Next
Error.Clear
Set appWord = GetWordApp
If appWord Is Nothing Then
'can't get ahold of Word.Application... now what?
MsgBox "No thing :(((((((((((((("
'Exit Sub
End If
appWord.Visible = True '<~ unconditional
'Set appWord = CreateObject("word.application")
'Set appWord = CreateObject(Word.Application)
'If Err.Number <> 0 Then
'Set appWord = New Word.Application
'Set appWord = CreateObject(Word.Application)
'appWord.Visible = True
'End If
'path = Application.CurrentProject.path & "\H_F.docx"
path = "\\ubcdatacenter\Public\UBCIEDatabase\DOC\H_F.docx"
'path = "C:\Users\LENOVO\Desktop\UBC Database\H_F.docx"
If FileExists(path) = False Then
MsgBox "Template File Not Found", vbExclamation, "File Not Found"
Else
Set doc = appWord.Documents.Add(path, , True)
myID = DLookup("ID", "Exports_imports_Table", "[ID] = " & Me.ID)
With doc
.FormFields("BookID").Result = [ID]
.FormFields("Book_BC_date").Result = Me.date_BC
.FormFields("Book_AH_date").Result = Me.date_AH
.FormFields("Book_AH_date").Result = Me.date_AH
.FormFields("BookTopic").Result = Me.topic
.FormFields("BookProjectName").Result = Me.projectName
.FormFields("BookCompanyName").Result = Me.companyName
.FormFields("BookContent").Range.Text = Me.content
'Result = Me.content
appWord.Visible = True
appWord.Active
End With
Set doc = Nothing
Set appWord = Nothing
End If
End Function
Private Function GetWordApp() As Object
On Error Resume Next
Set GetWordApp = CreateObject("Word.Application")
End Function
'Set appWord = CreateObject("word.application")
Set appWord = CreateObject(Word.Application)
If Err.Number <> 0 Then
'Set appWord = New Word.Application
'Set appWord = CreateObject(Word.Application)
appWord.Visible = True
End If
Several things are wrong with this code. CreateObject wants a ProgID string, and you're giving it Word.Application, which shouldn't even compile (expecting "Object Required" error on the .Application member call, and "Variable not declared"1 on Word). If it compiles, you've referenced the Word object library and need to remove it. The commented-out statement is well-formed.
Now If Err.Number <> 0, then appWord wasn't Set, and its reference is Nothing. That means if CreateObject fails, the code enters an error state and remains in an error state for the remainder of the procedure, because the error is never cleared, and error handling is never restored.
Take the error stuff into its own limited scope:
Private Function GetWordApp() As Object
On Error Resume Next
Set GetWordApp = CreateObject("Word.Application")
End Function
Now your procedure only needs to check if the function returned a valid object reference:
Set appWord = GetWordApp
If appWord Is Nothing Then
'can't get ahold of Word.Application... now what?
Exit Sub
End if
appWord.Visible = True '<~ unconditional
1 assuming Option Explicit is at the top of the module, as it should be.
Related
I am modifying someone's access database. The person has a button to create a report that fills out a preprinted form on a dot matrix printer. Now he would like to print it out on a laser printer. I suggested creating a Word document and have Access fill it out and then he can print however many copies he needs.
The previous programmer created a really nice way to print preview and print the reports. I want to add a button to print it to Word.
I have created a document with bookmarks.
I have added the button and have added the code as follows:
Private Sub Print_Test_Click()
On Error GoTo Err_Print_Test_Click
'Print customer slip for current customer.
Dim wApp As Word.Application
Dim wDoc As Word.Document
Dim dbs As DAO.Database
Dim rs As DAO.Recordset
Dim SelectNum As Long
'Avoid error 429, when Word isn't open.
On Error Resume Next
Err.Clear
'Set wApp object variable to running instance of Word.
Set wApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then
'If Word isn't open, create a new instance of Word.
Set wApp = New Word.Application
End If
Set dbs = CurrentDb
If Me.OpenArgs = "FromViewContracts" Then
Set wDoc = wApp.Documents.Open("C:\Shafer\Contract.dotx", , True)
SelectNum = Forms![PrintDialog]![ContractNum]
Set rs = dbs.OpenRecordset("SELECT * FROM PRINTContract WHERE ContNum = SelectNum")
Else
Set wDoc = wApp.Documents.Open("C:\Shafer\Invoice.dotx", , True)
SelectNum = Forms![PrintDialog]![InvoiceNum]
Set rs = dbs.OpenRecordset("SELECT * FROM PRINTInvoice WHERE InvNum = SelectNum")
End If
If rs.NoMatch Then
MsgBox "Record not found."
GoTo Exit_Print_Test_Click
Else
MsgBox "Customer name: " & rs!Customers.Name
End If
wApp.Visible = True
wDoc.Bookmarks("CustName").Range.Text = Nz(rs!Customers.Name, "")
wDoc.Bookmarks("CustAddress").Range.Text = Nz(rs!Customers.Address, "")
wDoc.Bookmarks("CustCity").Range.Text = Nz(rs!Customers.City, "")
wDoc.Bookmarks("CustState").Range.Text = Nz(rs!Customers.State, "")
wDoc.Bookmarks("CustZip").Range.Text = Nz(rs!Customers.Zip, "")
wDoc.Bookmarks("Date").Range.Text = Nz(rs!Date, "")
wDoc.Bookmarks("ContNum").Range.Text = Nz(rs!ContNum, "")
If Me.OpenArgs = "FromViewContracts" Then
' Contract bookmarks here
Else
wDoc.Bookmarks("InvNum").Range.Text = Nz(rs!InvNum, "")
wDoc.Bookmarks("SalesPerson").Range.Text = Nz(rs!Salesperson, "")
wDoc.Bookmarks("Terms").Range.Text = Nz(rs!Terms.Name, "")
End If
wApp.Visible = True
rs.Close
rsTable.Close
Set wDoc = Nothing
Set wApp = Nothing
Set rs = Nothing
Set rsTable = Nothing
Exit Sub
Exit_Print_Test_Click:
Exit Sub
Err_Print_Test_Click:
MsgBox Err.Description
Resume Exit_Print_Test_Click
End Sub
Here is the problem: When this runs, all I get is "Record Not Found"
If I display the value of InvNum or ContNum I have a value, lets say 18500. If I display the value of SelectNum, I have a value of 18500. But I cannot get it to work.
If I change SelectNum to 18500 in the Select statement, it works.
Please help.
I will describe my problem as points:
I have an Access database with functions & macros
there is a function to fill data into Word document (it works well)
I am using late binding
the database should be available to users who don't have Microsoft Application so I install Access runtime (it works well except the function of Word didn't work)
the code below works on a machine that has Access Application but doesn't on other machines.
How can I get the code to run in the Access Runtime?
Private Sub Command96_Click()
Dim appWord As Object
Set appWord = CreateObject("Word.Application")
Dim doc As Object
'Set doc = CreateDocument("Word.Document")
'Avoid error 429, when Word isn't open.
On Error Resume Next
Err.Clear
'Set appWord object variable to running instance of Word.
Set appWord = GetObject(, "Word.Application")
If Err.Number <> 0 Then
'If Word isn't open, create a new instance of Word.
'Set appWord = New Word.Application
Set appWord = CreateObject("Word.Application")
End If
'Set doc = appWord.Documents.Open("\\ubcdatacenter\Public\UBCIEDatabase\DOC\H_F.docx", , True)
Set doc = appWord.Documents.Open("\\ubcdatacenter\Public\UBCIEDatabase\DOC\H_F.docx")
With doc
.FormFields("BookID").Result = Me!ID
.FormFields("Book_BC_date").Result = Me!date_BC
.FormFields("Book_AH_date").Result = Me!date_AH
.FormFields("Book_AH_date").Result = Me!date_AH
.FormFields("BookTopic").Result = Me!topic
.FormFields("BookProjectName").Result = Me!projectName
.FormFields("BookCompanyName").Result = Me!companyName
.FormFields("BookContent").Range.Text = Me!content
.Visible = True
.Activate
End With
Set doc = Nothing
Set appWord = Nothing
Exit Sub
errHandler:
MsgBox Err.Number & ": " & Err.Description
End Sub
I am new to VBA and obviously I am missing something. My code works for opening a word doc and sending data to it BUT does NOT for an ALREADY OPEN word doc. I keep searching for an answer on how to send info from Excel to an OPEN Word doc/Bookmark and nothing works.
I hope it is okay that I added all the code and the functions called. I really appreciate your help!
What I have so far
Sub ExcelNamesToWordBookmarks()
On Error GoTo ErrorHandler
Dim wrdApp As Object 'Word.Application
Dim wrdDoc As Object 'Word.Document
Dim xlName As Excel.Name
Dim ws As Worksheet
Dim str As String 'cell/name value
Dim cell As Range
Dim celldata As Variant 'added to use in the test
Dim theformat As Variant 'added
Dim BMRange As Object
Dim strPath As String
Dim strFile As String
Dim strPathFile As String
Set wb = ActiveWorkbook
strPath = wb.Path
If strPath = "" Then
MsgBox "Please save your Excel Spreadsheet & try again."
GoTo ErrorExit
End If
'GET FILE & path of Word Doc/Dot
strPathFile = strOpenFilePath 'call a function in MOD1
If strPathFile = "" Then
MsgBox "Please choose a Word Document (DOC*) or Template (DOT*) & try again." 'strPath = Application.TemplatesPath
GoTo ErrorExit
End If
If FileLocked(strPathFile) Then 'Err.Number = 70 if open
'read / write file in use 'do something
'NONE OF THESE WORK
Set wrdApp = GetObject(strPathFile, "Word.Application")
'Set wrdApp = Word.Documents("This is a test doc 2.docx")
'Set wrdApp = GetObject(strPathFile).Application
Else
'all ok 'Create a new Word Session
Set wrdApp = CreateObject("Word.Application")
wrdApp.Visible = True
wrdApp.Activate 'bring word visiable so erros do not get hidden.
'Open document in word
Set wrdDoc = wrdApp.Documents.Open(Filename:=strPathFile) 'Open vs wrdApp.Documents.Add(strPathFile)<=>create new Document1 doc
End If
'Loop through names in the activeworkbook
For Each xlName In wb.Names
If Range(xlName).Cells.Count = 1 Then
celldata = Range(xlName.Value)
'do nothing
Else
For Each cell In Range(xlName)
If str = "" Then
str = cell.Value
Else
str = str & vbCrLf & cell.Value
End If
Next cell
'MsgBox str
celldata = str
End If
'Get format and strip away the spacing, negative color etc etc
'I know this is not right... it works but not best
theformat = Application.Range(xlName).DisplayFormat.NumberFormat
If Len(theformat) > 8 Then
theformat = Left(theformat, 5) 'was 8 but dont need cents
Else
'do nothing for now
End If
If wrdDoc.Bookmarks.Exists(xlName.Name) Then
'Copy the Bookmark's Range.
Set BMRange = wrdDoc.Bookmarks(xlName.Name).Range.Duplicate
BMRange.Text = Format(celldata, theformat)
'Re-insert the bookmark
wrdDoc.Bookmarks.Add xlName.Name, BMRange
End If
Next xlName
'Activate word and display document
With wrdApp
.Selection.Goto What:=1, Which:=2, Name:=1 'PageNumber
.Visible = True
.ActiveWindow.WindowState = wdWindowStateMaximize 'WAS 0 is this needed???
.Activate
End With
GoTo WeAreDone
'Release the Word object to save memory and exit macro
ErrorExit:
MsgBox "Thank you! Bye."
Set wrdDoc = Nothing
Set wrdApp = Nothing
Exit Sub
'Error Handling routine
ErrorHandler:
If Err Then
MsgBox "Error No: " & Err.Number & "; There is a problem"
If Not wrdApp Is Nothing Then
wrdApp.Quit False
End If
Resume ErrorExit
End If
WeAreDone:
Set wrdDoc = Nothing
Set wrdApp = Nothing
End Sub
file picking:
Function strOpenFilePath() As String
Dim intChoice As Integer
Dim iFileSelect As FileDialog 'B
Set iFileSelect = Application.FileDialog(msoFileDialogOpen)
With iFileSelect
.AllowMultiSelect = False 'only allow the user to select one file
.Title = "Please... Select MS-WORD Doc*/Dot* Files"
.Filters.Clear
.Filters.Add "MS-WORD Doc*/Dot* Files", "*.do*"
.InitialView = msoFileDialogViewDetails
End With
'make the file dialog visible to the user
intChoice = Application.FileDialog(msoFileDialogOpen).Show
'determine what choice the user made
If intChoice <> 0 Then
'get the file path selected by the user
strOpenFilePath = Application.FileDialog( _
msoFileDialogOpen).SelectedItems(1)
Else
'nothing yet
End If
End Function
checking if file is open...
Function FileLocked(strFileName As String) As Boolean
On Error Resume Next
' If the file is already opened by another process,
' and the specified type of access is not allowed,
' the Open operation fails and an error occurs.
Open strFileName For Binary Access Read Write Lock Read Write As #1
Close #1
' If an error occurs, the document is currently open.
If Err.Number <> 0 Then
' Display the error number and description.
MsgBox "Function FileLocked Error #" & str(Err.Number) & " - " & Err.Description
FileLocked = True
Err.Clear
End If
End Function
ANSWER BELOW. Backstory... So, after input from you guys and more research I discovered that I needed to set the active word document by using the file selection the user picked and that is then passed via late binding to the sub as an object to process. NOW it works if the word file is not in word OR if it is currently loaded into word AND not even the active document. The below code replaces the code in my original question.
Set Object app as word.
grab the file name.
Make the word doc selected active to manipulate.
Set the word object to the active doc.
THANK YOU EVERYONE!
If FileLocked(strPathFile) Then 'Err.Number = 70 if open
'read / write file in use 'do something
Set wrdApp = GetObject(, "Word.Application")
strPathFile = Right(strPathFile, Len(strPathFile) - InStrRev(strPathFile, "\"))
wrdApp.Documents(strPathFile).Activate ' need to set picked doc as active
Set wrdDoc = wrdApp.ActiveDocument ' works!
This should get you the object you need.
Dim WRDFile As Word.Application
Set WRDFile = GetObject(strPathFile)
'Have Microsoft Word 16.0 Object Library selected in your references
Dim wordapp As Object
Set wordapp = GetObject(, "Word.Application")
wordapp.Documents("documentname").Select
'works if you only have one open word document. In my case, I'm trying to push updates to word links from excel.
I have been tasked with importing the contents of a Microsoft Word Form into my Access database. It's working fine using the following VBA code which is triggered from a form:
Private Sub cmdFileDialog_Click()
On Error GoTo ErrorHandler
Dim objDialog As Object
Dim varFile As Variant
Dim rec, rec2 As Recordset
Dim db As Database
'New Word Document Variables
Dim appWord As Word.Application
Dim doc As Word.Document
Const DEST_TABLE = "ap_behaviour_referrals" 'change to suit
Const PATH_DELIM = "\"
Set objDialog = Application.FileDialog(3)
' Clear listbox contents.
Me.fileList.RowSource = ""
With objDialog
.AllowMultiSelect = False
' Set the title of the dialog box.
.Title = "Please select a behaviour referral to import"
' Clear out the current filters, and add our own.
.Filters.Clear
.Filters.Add "Microsoft Word Forms", "*.docx"
.Filters.Add "All Files", "*.*"
.Show
If .SelectedItems.Count = 0 Then
MsgBox "No file selected."
Else
For Each varFile In .SelectedItems
'New docx Variable Actions
Set appWord = GetObject(, "Word.Application")
Set doc = appWord.Documents.Open(varFile)
Next
Set db = CurrentDb
Set rec = db.OpenRecordset(DEST_TABLE)
With rec
.AddNew
' my data
'preformat the date fields from the form
Dim unformattedpupildob As String
Dim formattedpupildob As Date
unformattedpupildob = doc.FormFields("Text2").Result
unformattedpupildob = Replace(unformattedpupildob, ".", "/")
formattedpupildob = Format(unformattedpupildob, "dd/mm/yy")
'And now insert the record into the table
!pupil_name = doc.FormFields("Text1").Result
!pupil_dob = formattedpupildob
!pupil_yr_grp = doc.FormFields("Text3").Result
!pupil_submitted_eth = doc.FormFields("Text4").Result
!pupil_upn = doc.FormFields("Text5").Result
!pupil_looked_after = doc.FormFields("Text6").Result
!sen_pre_statement = doc.FormFields("Text7").Result
!sen_ehcp = doc.FormFields("Text8").Result
!cat_date_final_ehcp = doc.FormFields("Text9").Result
!num_exclusion = doc.FormFields("Text10").Result
!days_exclusion = doc.FormFields("Text11").Result
!sch_name = doc.FormFields("Text12").Result
!sch_no = doc.FormFields("Text14").Result
!contact_name = doc.FormFields("Text13").Result
!contact_role = doc.FormFields("Text40").Result
!contact_email = doc.FormFields("Text31").Result
.Update
.Close
MsgBox "File Processing Complete"
End With
End If
End With
Set objDialog = Nothing
Me.fileList.RowSource = ""
ExitSub:
Set rec = Nothing
Set db = Nothing
'...and set it to nothing
Exit Sub
ErrorHandler:
If Err.Number <> 0 Then
Msg = "Error # " & Str(Err.Number) & " was generated by " & Err.Source & Chr(13) & "Error Line: " & Erl() & Chr(13) & Err.Description
MsgBox Msg, , "Error", Err.HelpFile, Err.HelpContext
End If
Resume ExitSub
End Sub
All but one of the fields are (badly) bookmarked so I can use this to grab the contents of the field HOWEVER, I've come across an unnamed form field:
Which I need to import and I have no idea how to get the contents of it without a named bookmark.
I have no ability to modify the form since it's controlled by somebody else and is widely distributed, but was wondering if there was any way to pull the contents of this field without it being named?
Thanks!
Like other collections of objects, you can address them either by name (as you do for the other fields) or by numeric index.
For i = 1 To doc.FormFields.Count
Debug.Print i, doc.FormFields(i).Result
Next i
This should give you the index of the field, if you know its content.
Then use !the_answer = doc.FormFields(42).Result in your code. (42 is an example!)
Edit: minimal working example (running in Access):
Public Sub TestWord()
Dim oWord As Word.Application
Dim oDoc As Word.Document
Dim i As Long
Set oWord = CreateObject("Word.Application")
Set oDoc = oWord.Documents.Open("C:\Users\foobar\Documents\Dok1.docx")
oWord.Visible = True
For i = 1 To oDoc.FormFields.Count
Debug.Print i, oDoc.FormFields(i).Name, oDoc.FormFields(i).Result
Next i
oDoc.Close
oWord.Quit
End Sub
The direct window (Ctrl+g) lists all form fields with their index, name = bookmark, and default text.
I whould like to fill a word with values and export to pdf multiple times.
If is use a SaveAs2 the firt time it make a pdf but second or third it doesen't work.
'ActiveDocument.SaveAs2 FileName:="C:\alap\" & fajlneve & ".pdf", FileFormat:=wdFormatPDF
If I use the CutePDf printer, the result is the same, first time i=1 it works, but second it doesen't.
Public compname As String
Public filename As String
Function FillwordForm()
Dim appword As Word.Application
Dim doc As Word.Document
Dim Path As String
On Error Resume Next
Error.Clear
Set appword = GetObject(, "word.application")
If Err.Number <> 0 Then
Set appword = New Word.Application
appword.Visible = True
End If
Path = "C:\pelda\MINTA.docx"
Set doc = appword.Documents.Open(Path, , True)
With doc
.formfields("szerzCegnev").result = compname
End With
appword.Visible = True
appword.Activate
Set doc = Nothing
Set appword = Nothing
appword.ActivePrinter = "CutePDF Writer"
ActiveDocument.PrintOut OutPutFileName:="C:\pelda\" & filename & ".pdf"
ActiveDocument.Close SaveChanges:=wdDoNotSaveChanges
Word.Application.Quit
End Function
'---------------------------------------------------------------
Sub cucc()
For i = 1 To 2
compname = Cells(i, 1)
filename = Cells(i, 2)
Call FillwordForm
Next i
End Sub
can you use:
ActiveDocument.SaveAs2(docname,17);
?
(17 is PDF-format -link to fileformats)
Greetz