Error 4608 : value out of range error in MS Word VBA (only in word 2007) - vba

We have a macro in our word document which exports a PDF for each record in Mail Merge. When creating the doc, word always added a blank page to it, so we had to find a way to delete the last page (blank one). We added the .Range(Lr - 1, TargetDoc.Range.End).Delete line, and it worked perfectly; but only in Word > 2007 - when we tried running the macro in Word 2007, it said :
Option Explicit
Const FOLDER_SAVED As String = "F:\Postcard\" '//Makes sure your folder path ends with a backward slash
Const SOURCE_FILE_PATH As String = "G:\Laptop Data\GoaRegion.xlsm"
Sub TestRun()
Dim MainDoc As Document, TargetDoc As Document
Dim dbPath As String
Dim recordNumber As Long, totalRecord As Long
Dim Lr As Long
Set MainDoc = ActiveDocument
With MainDoc.MailMerge
'// if you want to specify your data, insert a WHERE clause in the SQL statement
.OpenDataSource Name:=SOURCE_FILE_PATH, sqlstatement:="SELECT * FROM [Goa$]"
totalRecord = .DataSource.RecordCount
For recordNumber = 1 To totalRecord
With .DataSource
.ActiveRecord = recordNumber
.FirstRecord = recordNumber
.LastRecord = recordNumber
End With
.Destination = wdSendToNewDocument
.Execute False
Set TargetDoc = ActiveDocument
With TargetDoc
Lr = .GoTo(wdGoToPage, wdGoToLast).Start
.Range(Lr - 1, TargetDoc.Range.End).Delete
End With
TargetDoc.ExportAsFixedFormat FOLDER_SAVED & .DataSource.DataFields("Voter").Value & ".pdf", exportformat:=wdExportFormatPDF
TargetDoc.Close False
Set TargetDoc = Nothing
Next recordNumber
End With
Set MainDoc = Nothing
End Sub
Is there something wrong? Does Word 2007 not support the line .Range(Lr - 1, TargetDoc.Range.End).Delete? Kindly guide... Thanks!

Try this:
If Not Application.Version = "12.0" Then
With TargetDoc
Lr = .GoTo(wdGoToPage, wdGoToLast).Start
.Range(Lr - 1, TargetDoc.Range.End).Delete
End With
End If

Related

Exporting Access Query data into MS word Table

I am trying to find a way to move the data from a query to a table in MS Word. I have attached a picture of the document
Here's the situation: When we close a case out, we need to create a document that includes several pieces of demographic data from that case and list of important dates to that case. The table needs to have some borders (underline on the date), and it needs to be inserted midway through the document (I am thinking bookmarks are the way to go). The document may be sent to other providers off of our network. (I am really hoping the pic attached...)
I have tried using Power Query (which does not allow the user to set parameters or prompt for criteria).
My initial thoughts are to create a recordset from the query and then create a loop to insert the data into the table. However, all the posts I could find seem to only deal with creating the table in word as the sole object. I also can't find how to point the recordset to a bookmark or particular table. The user will generate the document from Access (Right now, I have it where it will put certain dates, like open and close, into the corresponding Form Field in Word template, but I'm stuck at this juncture).
I have minor programming knowledge, just enough to be known as the local expert, when I am merely the only programming fish in the small pond. I would be happy to pointed in the right direction or given some code snippets (I would like to understand why/how they work).
With gratitude, I want to post the code for the solution. Of course, there is probably a better way to do it, but the solution works, and best of all I know why it works.
Public Function concatData() As String
Dim retVal As String
Dim rsHeader As Long, rsCounter As Long
Dim rs As DAO.Recordset
Dim Val As String
Dim strSQL As String
'This code puts the query into a recordset, which is then formatted into a table later
Val = [Forms]![FrmAllTracker]![CaseID]
strSQL = "Select * From QryTrackerInitRecRecv WHERE [CaseID] = " & Val
Set rs = CurrentDb.OpenRecordset(strSQL)
'Get headers
'For rsHeader = 0 To rs.Fields.Count - 1
' retVal = retVal & rs.Fields(rsHeader).Name & vbTab
'Next
'Replace last TAb with a carriage return
'retVal = Left(retVal, Len(retVal) - 1) & vbCr
Do While Not rs.EOF
'Get all records
For rsCounter = 0 To rs.Fields.Count - 1
retVal = retVal & rs.Fields(rsCounter).Value & vbTab
Next
retVal = Left(retVal, Len(retVal) - 1) & vbCr
rs.MoveNext
Loop
concatData = retVal
End Function
Private Sub BtnGenTracker_Click()
If IsNull(Me.CaseClosed) Then
MsgBox "Please Enter a Close Date", _
vbOKOnly + vbInformation
Exit Sub
End If
' Create pointers to Word Document
Dim wd As Word.Application
Dim doc As Word.Document 'doc As Word.Document
Dim bolOpenedWord As Boolean
Dim rng As Range
Dim Tbl As Word.Table
Dim MDate As String
MDate = Format([CaseOpen], "mm-dd-yyyy")
' Get pointer to Word Document
On Error Resume Next
Set wd = GetObject(, "Word.Application")
If Err.Number = 429 Then
' If Word is not opened, open it
Set wd = CreateObject("Word.Application")
bolOpenedWord = True
End If
wd.Visible = True ' Set this to true if you want to see the document open
On Error GoTo 0
Set doc = wd.Documents.Add("\\gsmstore2\COE\Testing Database\TFT1.docx")
DoCmd.OpenForm FormName:="FrmRelRecSenAll"
With doc
On Error Resume Next
'sends particular fields to corresponding FormFields in Word
.FormFields("PtName").Result = [Forms]![FrmAllTracker]![FrmSubTherapyRef].[Form].[Text62]
.FormFields("COENum").Result = Me.COEMR
.FormFields("RefRec").Result = Me.CaseOpen
.FormFields("FirstCont").Result = Me.CaseOpen
.FormFields("InitRecsRecv").Result = DLookup("FirstOfRecordsRec", "QryTrackerInitRecRecvCFFirst")
.FormFields("SuffRecs").Result = Me.SuffRecDate
.FormFields("Init2").Result = Me.InitCaseDate
.FormFields("TeamRev").Result = DLookup("ContactDate", "QryTrackerTeamRev", "[ContactType] = 14")
.FormFields("MCRMeet").Result = DLookup("ContactDate", "QryTrackerTeamRev", "[ContactType] = 6")
.FormFields("MCRMeetAct").Result = DLookup("ContactDate", "QryTrackerTeamRev", "[ContactType] = 6")
.FormFields("FTDate").Result = InputBox("Please enter Date of FT Release", "FT Release", Default)
.FormFields("FirstAppt").Result = InputBox("Please enter Date of 1st offered appt", "1st Offered Date", Default)
.FormFields("AssessDebrief").Result = DLookup("ContactDate", "QryTrackerTeamRev", "[ContactType] = 15")
.FormFields("RptSent").Result = DLookup("ContactDate", "QryTrackerTeamRev", "[ContactType] = 11")
.FormFields("FFollow").Result = DLookup("ContactDate", "QryTrackerTeamRev", "[ContactType] = 12")
.FormFields("LFollow").Result = DLookup("ContactDate", "QryTrackerLFollow")
.FormFields("CaseClosed").Result = Me.CaseClosed
If Not IsNull(DLookup("ContactDate", "QryTrackerTeamRev", "[ContactType] = 4")) Then
.FormFields("Bill").Result = "Yes"
Else
.FormFields("Bill").Result = "No"
End If
.Application.Activate
Set rng = ActiveDocument.Bookmarks("Releases").Range
rng.Text = concatData()
Set Tbl = rng.ConvertToTable
End With
'This foramats the table
With Tbl
.Columns(1).Borders(wdBorderBottom).LineStyle = wdLineStyleSingle
.Columns(1).Borders(wdBorderBottom).LineWidth = wdLineWidth050pt
.Columns(1).Borders.InsideLineStyle = wdLineStyleSingle
.Columns(1).Borders.InsideLineWidth = wdLineWidth050pt
.Columns(1).Width = 125
.Columns(2).Width = 450
.Columns(3).Delete
End With
wd.ActiveDocument.SaveAs2 ("\\Filelocation\COE\Case Files\" & COEMR & "\Tracking Sheet" & " " & MDate & ".docx")
Set doc = Nothing
Set wd = Nothing
Set rg = Nothing
Set Tbl = Nothing
End Sub

DDE - Mail Merge From Excel to Word 2016 using OpenDataSource

I have a old legacy code which is programmed for mail merge. I have a add-in code to populate xls file which in turn should merge the data to word template defined. Code snippet :
Public Sub ProcessForSharePoint(DataSource As Object, MainDoc As Document)
Dim tempPath As String
Dim i As Integer
Dim recordCount As Integer
Dim ActualCount As Integer
Dim ws As Variant
Dim tempName As String
Dim rowEmpty As Boolean
On Error GoTo tempFileError
tempName = Left(MainDoc.name, InStrRev(MainDoc.name, ".") - 1)
tempPath = Environ("TEMP") + "\" + tempName + ".xls"
If (Dir(tempPath) <> "") Then
SetAttr tempPath, vbNormal
Kill tempPath
End If
DataSource.SaveAs (tempPath)
On Error GoTo openDataSourceError
MainDoc.MailMerge.OpenDataSource tempPath, ConfirmConversions:=False, ReadOnly:=False, LinkToSource:=True,
AddToRecentFiles:=False, Revert:=False, Connection:="Entire Spreadsheet", SubType:=wdMergeSubTypeWord2000
recordCount = 0
On Error GoTo wsError
Set ws = DataSource.WorkSheets(1)
Dim r As Integer
Dim c As Integer
' Work out how many rows we have to process
For r = 2 To ws.UsedRange.Rows.Count
rowEmpty = True
For c = 1 To ws.UsedRange.Columns.Count
If Not IsEmpty(ws.Cells(r, c)) Then
rowEmpty = False
Exit For
End If
Next c
If rowEmpty Then
Exit For
End If
recordCount = recordCount + 1
Next r
GoTo DoMerge
wsError:
GoTo CloseMerge
DoMerge:
ActualCount = 0
If (recordCount = 0) Then
OutputDebugString "PSLWordDV: ProcessForSharePoint: No records to process"
GoTo CloseMerge
End If
On Error GoTo mergeError
For i = 1 To recordCount
' .Destination 0 = DOCUMENT, 1 = PRINTER
MainDoc.MailMerge.Destination = 0 'wdSendToNewDocument
MainDoc.MailMerge.SuppressBlankLines = True
With MainDoc.MailMerge.DataSource
.FirstRecord = i 'wdDefaultFirstRecord
.LastRecord = i 'wdDefaultLastRecord
.ActiveRecord = i
End With
MainDoc.MailMerge.Execute Pause:=False
Populate MainDoc, ActiveDocument
ActualCount = ActualCount + 1
Next i
GoTo CloseMerge
When I call this function, my xls files gets open and populate data (I want data from Sheet 1 only). Then my WORD opens (OpenDataSource) and on selection of "Yes" for population on Word --> My code fails and catches the error "462".
On further analysis (not sure correct or not), it seems, there is a problem in :
Set ws = DataSource.WorkSheets(1)
NOTE: If I hard code my recordCount variable to 1 (say) -> merging process works absolutely fine.
Can anyone please help on priority to sort my client issue please.

Publisher VBA MailMerge - Converting to PDF

I have Publisher document with MailMerge records. My goal is to convert each page with each record to separate PDF document.
I have written this code. It generates PDF files with correct names, but for some reason PDFs contain only the second record from MailMerge.
Sub MailMerge()
Dim Lot As MailMergeDataField
Dim Price As MailMergeDataField
Dim Street As MailMergeDataField
Dim i As Long
Dim MainDoc As Document
Set MainDoc = ActiveDocument
With MainDoc
For i = 1 To .MailMerge.DataSource.RecordCount
With .MailMerge
.SuppressBlankLines = True
With .DataSource
.FirstRecord = i
.LastRecord = i
.ActiveRecord = i
Set Lot = .DataFields.Item("Lot")
Set Price = .DataFields.Item("Price")
Set Street = .DataFields.Item("Street")
ThisDocument.ExportAsFixedFormat pbFixedFormatTypePDF, Lot.Value & "-" & Street.Value & ".pdf"
End With
.Execute Pause:=False, Destination:=pbMergeToNewPublication
End With
Next i
End With
End Sub
I guess it needs a little change and everything will work fine, but I can't find out the solution.
I've stumbled into the same problem. I've came up with a sketchy workaround, but it works for me.
The main idea is to create a new '.pub'-file and perform the MailMerge with this file as the destination. After this, it is possible to export the separate PDF's, based on the page numbers from the initial document.
I had some problems with merging large files. That's why I built in the sleep function (based on this thread: There is no Wait Method associated with Application in VisualBasic Word)
Hopefully it helps!
Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
Sub Export_to_seperate_PDFs()
' Variables for MailMerge
Dim naam As MailMergeDataField
Dim i As Long
' Variables for This Document
Dim MainDoc As Document
Dim PathName As String
Dim FileName As String
Set MainDoc = ActiveDocument
PathName = MainDoc.Path
FileName = MainDoc.Name
Npages = MainDoc.Pages.Count
Debug.Print Npages
' Make a new Document called empty.pub in the same directory
Dim NewAppPub As New Publisher.Application
Set AppPub = New Publisher.Application
Set DocPub = AppPub.NewDocument
AppPub.ActiveWindow.Visible = True
DocPub.SaveAs FileName:=PathName & "empty.pub"
AppPub.ActiveDocument.Close
' Perform MailMerge
MainDoc.MailMerge.Execute Pause:=False, Destination:=3, _
FileName:=PathName & "empty.pub"
' try to close any other open publications (this does not seem to work yet)
Dim objDocument As Document
For Each objDocument In Documents
Debug.Print objDocument.Name
If objDocument.Name = "empty.pub" Then
objDocument.SaveAs FileName:=PathName & "empty.pub"
objDocument.Close
ElseIf Not objDocument.Name = FileName Then
objDocument.Close
End If
Next objDocument
' Let the application wait for a couple of seconds
' in order to prevent errors on opening large files
Sleep 15000
NewAppPub.Open FileName:=PathName & "empty.pub"
' Loop through the records and save seperate PDFs'
With MainDoc
For i = 1 To .MailMerge.DataSource.RecordCount
With .MailMerge
.SuppressBlankLines = False
With .DataSource
.FirstRecord = i
.LastRecord = i
.ActiveRecord = i
Set naam = .DataFields.Item("Name")
Debug.Print naam.Value
' Export publication to PDF based on page numbers
NewAppPub.ActiveDocument.ExportAsFixedFormat pbFixedFormatTypePDF, _
PathName & naam.Value & ".pdf", _
From:=((i - 1) * Npages) + 2, _
To:=i * Npages + 1
End With
End With
Next i
End With
End Sub

Using Find in Word from a List in Excel VBA

I am working on an automated peer review macro that would check for certain words and highlight them in a Microsoft Word document. However, I am looking to substitute the WordList = Split(" is , are ,", ",") with a list I created in excel. This would be easier for me to add new words instead of manually typing the words I want highlighted in the code.
For example: A1 has the word " is ", so I am hoping it would be something like Wordlist = Split("A1, A2")
or something like Exlist = Range("A1:A2").value so WordList = Split(ExList)
Is something like that possible? Thank you for your help.
Sub PeerReview()
Dim r As Range
Dim WordList() As String
Dim a As Long
Dim Doc As Document
Dim Response As Integer
'This code will search through all of the open word documents and ask you which ones you would like to peer review.
For Each Doc In Documents
'MsgBox Doc
Response = MsgBox(prompt:="Do you want to peer review " & Doc & "?", Buttons:=vbYesNo)
If Response = vbNo Then GoTo ShortCut
'This code will highlight words that do not belong in the paragraph
WordList = Split(" is , are ,", ",") 'List of words to check for when it is peer-reviewing
Options.DefaultHighlightColorIndex = wdPink *'Highlight when found*
For a = 0 To UBound(WordList())
Set r = ActiveDocument.Range
With r.Find
.Text = WordList(a)
.Replacement.Highlight = wdYellow
.Execute Replace:=wdReplaceAll
End With
Next 'next word
ShortCut:
Next
End Sub
Here are three ways to retrieve an array of words from an external file (Word, Excel, and Text Files) in MS Word. Reading from the text file is by far the fastest.
Results
Word: 0.328125 Seconds
Excel: 1.359130859375 Seconds
Text: 0.008056640625 Seconds
---------- ----------
Get Word List from Word Document
Start Time:12/1/2007 11:03:56 PM
End Time:9/1/2016 12:53:16 AM
Duration:0.328125 Seconds
------------------------------
---------- ----------
Get Word List from Excel
Start Time:12/1/2007 3:05:49 PM
End Time:9/1/2016 12:53:17 AM
Duration:1.359130859375 Seconds
------------------------------
---------- ----------
Get Word List from Text Document
Start Time:11/30/2007 6:16:01 AM
End Time:9/1/2016 12:53:17 AM
Duration:0.008056640625 Seconds
------------------------------
Unit Test
Sub TestWordList()
Dim arData
EventsTimer "Get Word List from Word Document"
arData = GetWordsListDoc
'Debug.Print Join(arData, ",")
EventsTimer "Get Word List from Word Document"
EventsTimer "Get Word List from Excel"
arData = GetWordsListXL
'Debug.Print Join(arData, ",")
EventsTimer "Get Word List from Excel"
EventsTimer "Get Word List from Text Document"
arData = GetWordsListTxt
'Debug.Print Join(arData, ",")
EventsTimer "Get Word List from Text Document"
End Sub
Event Timer
Sub EventsTimer(Optional EventName As String)
Static dict As Object
If dict Is Nothing Then Set dict = CreateObject("Scripting.Dictionary")
If dict.Exists(EventName) Then
Debug.Print
Debug.Print String(10, "-"), String(10, "-")
Debug.Print EventName
Debug.Print ; "Start Time:"; ; Now - dict(EventName)
Debug.Print ; "End Time:"; ; Now
Debug.Print ; "Duration:"; ; Timer - dict(EventName) & " Seconds"
Debug.Print String(10, "-"); String(10, "-"); String(10, "-")
dict.Remove EventName
Else
dict.Add EventName, CDbl(Timer)
End If
If dict.Count = 0 Then Set dict = Nothing
End Sub
Functions to retrieve a word list from MS Word, Ms Excel and a Text File.
Function GetWordsListDoc()
Const FilePath As String = "C:\Users\best buy\Downloads\stackoverfow\Wordlist\WordList.docx"
Dim doc As Word.Document, oWords As Word.Words
Dim x As Long
Dim arData
Set doc = Application.Documents.Open(FileName:=FilePath, ReadOnly:=True)
Set oWords = doc.Words
ReDim arData(oWords.Count - 1)
For x = 1 To oWords.Count
arData(x - 1) = Trim(oWords.Item(x))
Next
doc.Close False
GetWordsListDoc = arData
End Function
Function GetWordsListXL()
Const FilePath As String = "C:\Users\best buy\Downloads\stackoverfow\Wordlist\WordsList.xlsb"
Const xlUp = -4162
Dim arData
Dim x As Long
Dim oExcel As Object, oWorkbook As Object
Set oExcel = CreateObject("Excel.Application")
With oExcel
.Visible = False
Set oWorkbook = .Workbooks.Open(FileName:=FilePath, ReadOnly:=True)
End With
With oWorkbook.Worksheets(1)
arData = .Range("A1", .Range("A" & .Rows.Count).End(xlUp)).Value
arData = oExcel.WorksheetFunction.Transpose(arData)
End With
oWorkbook.Close False
oExcel.Quit
GetWordsListXL = arData
End Function
Function GetWordsListTxt()
Const FilePath As String = "C:\Users\best buy\Downloads\stackoverfow\Wordlist\WordList.txt"
Dim arData, f, fso
Set fso = CreateObject("Scripting.Filesystemobject")
Set f = fso.OpenTextFile(FilePath)
arData = Split(f.ReadAll, vbNewLine)
GetWordsListTxt = arData
End Function

VBA Word macro goes to breakmode

I'm trying to open two documents from excel with vba and call a word macro from this particular excel file.
The macro is working fine in Word and I also get the documents to open and the word macro to start. However when there is a switch from one document to the other the word macro goes to break-mode (which does not happen when I run it from Word instead of Excel).
I use the following code from excel:
Set wordApp = CreateObject("Word.Application")
worddoc = "H:\Word Dummy's\Dummy.docm"
wordApp.Documents.Open worddoc
wordApp.Visible = True
wordApp.Run macroname:="update_dummy", varg1:=client, varg2:=m_ultimo, varg3:=y
In word I have a sub with the parameters defined between breakets and the following code:
worddoc2 = "H:\Word Dummy's\texts.docx"
Word.Application.Activate
Documents.Open worddoc2, ReadOnly:=True
ThisDocument.Activate
Set bmks = ThisDocument.Bookmarks
Can anyone tell me why it does not run from excel and how I can fix this?
Thanks in advance.
I finally found the answer myself after a lot of searching on Google.
I needed to add :
application.EnableEvents=false
To the excel macro.
That was all. Now it works.
My complete code is huge (the macro in excel also opens two other workbooks and runs a macro in them). This part of the code is working for now (so I left it out), but I just want to add the part that it opens a worddoc and adds specific texts in it depending on what client has been chosen in the excel userform. But to show you a better idea how my code looks like, this is in excel (where the client is defined by a userform in another module):
Sub open_models (client as string)
Application.DisplayStatusBar = True
‘determine datatypes
Dim m_integer As Integer
Dim m_ultimo As String
Dim m_primo As String
Dim y As String
Dim y_integer As Integer
Dim y_old As String
Dim y_last As String
Dim wordApp As Object
Dim worddoc As String
'Determine current month and year and previous
m_integer = Format(Now, "mm")
y_integer = Format(Now, "yyyy")
If m_integer <= 9 Then
m_ultimo = "0" & m_integer - 1
m_primo = "0" & m_integer - 2
Else
m_ultimo = m_integer - 1
m_primo = m_integer - 2
End If
If m_integer = 1 Then
y = y_integer - 1
Else
y = y_integer
End If
On Error Resume Next
'open word dummy
Set wordApp = CreateObject("Word.Application")
worddoc = "H:\RAPORTAG\" & y & "\" & y & m_ultimo & "\Dummy.docm"
wordApp.Documents.Open worddoc
wordApp.Visible = True
wordApp.Run macroname:="update_dummy", varg1:=client, varg2:=m_ultimo, varg3:=y, varg4:= worddoc)
On Error GoTo 0
ThisWorkbook.Activate
'reset statusbar and close this workbook
Application.DisplayStatusBar = False
Application.Calculation = xlCalculationAutomatic
Application.DisplayAlerts = True
ThisWorkbook.Close False
End Sub
 
And this is the code in word I am using:
Sub update_dummy(client As String, m_ultimo As String, y As String, worddoc as string)
Dim wordapp As Object
Dim rngStart As Range
Dim rngEnd As Range
Dim worddoc As String
Dim worddoc2 As String
Dim dekkingsgraad As String
Dim bmks As Bookmarks
Dim bmRange As Range
Dim rng As Range
Dim i As Boolean
On Error Resume Next
worddoc2 = "H:\RAPORTAG\" & y & "\" & y & m_ultimo & "\dummytexts.docx"
'open other word
Documents.Open worddoc2, ReadOnly:=True
Documents(worddoc).Activate
Set bmks = Documents(worddoc).Bookmarks
'management summary
If client <> "PMT" Then
i = True
Set rngStart = Documents(worddoc2).Bookmarks("bn0_1_start").Range
Set rngEnd = Documents(worddoc2).Bookmarks("bn0_1_end").Range
End If
If i = True Then
Set rng = Documents(worddoc2).Range(rngStart.Start, rngEnd.End)
rng.Copy
Set bmRange = Documents(worddoc).Bookmarks("bmManagementsummary").Range
bmRange.PasteAndFormat (wdPasteDefault)
End If
i = False
On Error GoTo 0
End Sub
I have 20 more bookmarks that are defined but the code for them is all the same.
I have seen and solved this problem a few times before, the solution I found was odd.
Copy paste all your code into a text
editor, 1 for word, 1 for excel
Delete all the macros in word or excel or better yet, just create
new files.
Paste all the code into word/excel from your text editor.
I've definitely had this 3 or 4 times in Excel and Access. Especially if you previously had a breakpoint at that location.
It sounds stupid but try it and see if that works, this has saved me from insanity a few times.