I've got a bunch of documents that I need to add page numbering in the footer.
I tried writing a macro to do this but after I run there's still no page numbers (in header or footer)
Sub AddPageNumberToFooter()
Call DeleteExistingFooters
With ActiveDocument
.PageSetup.DifferentFirstPageHeaderFooter = False
.Sections(1).Footers(wdHeaderFooterPrimary).PageNumbers.Add
End With
End Sub
Sub DeleteExistingFooters()
Dim iSectionCnt As Integer
iSectionCnt = ActiveDocument.Sections.Count
If iSectionCnt > 0 Then
ActiveDocument.Sections(iSectionCnt).Footers(wdHeaderFooterPrimary).Range.Delete
End If
End Sub
What am I missing?
The following code will add Page #s to all documents lacking them in every page in the selected folder:
Sub UpdateDocumentFooters()
Application.ScreenUpdating = False
Dim strFolder As String, strFile As String
Dim wdDoc As Document, Sctn As Section, HdFt As HeaderFooter
strFolder = GetFolder: If strFolder = "" Then Exit Sub
strFile = Dir(strFolder & "\*.doc", vbNormal)
While strFile <> ""
If strFolder & "\" & strFile <> ThisDocument.FullName Then
Set wdDoc = Documents.Open(FileName:=strFolder & "\" & strFile, _
AddToRecentFiles:=False, Visible:=False)
With wdDoc
For Each Sctn In .Sections
For Each HdFt In Sctn.Footers
With HdFt
If .Exists Then
If Sctn.Index = 1 Then
Call AddPgFld(HdFt)
ElseIf .LinkToPrevious = False Then
Call AddPgFld(HdFt)
End If
End If
End With
Next
Next
.Close SaveChanges:=True
End With
End If
strFile = Dir()
Wend
Set wdDoc = Nothing
Application.ScreenUpdating = True
End Sub
Sub AddPgFld(HdFt As HeaderFooter)
Dim Fld As Field, bFld As Boolean
With HdFt
bFld = False
For Each Fld In .Range.Fields
If Fld.Type = wdFieldPage Then
bFld = True: Exit For
End If
Next
If bFld = False Then
With .Range.Paragraphs.Last.Range
If Len(.Text) > 2 Then .InsertAfter vbCr
End With
With .Range.Paragraphs.Last.Range
.Text = "Page "
.Fields.Add Range:=.Characters.Last, Type:=wdFieldEmpty, Text:="PAGE", PreserveFormatting:=False
.ParagraphFormat.Alignment = wdAlignParagraphCenter
End With
End If
End With
End Sub
Function GetFolder() As String
Dim oFolder As Object
GetFolder = ""
Set oFolder = CreateObject("Shell.Application").BrowseForFolder(0, "Choose a folder", 0)
If (Not oFolder Is Nothing) Then GetFolder = oFolder.Items.Item.Path
Set oFolder = Nothing
End Function
As you are writing that you have a bunch of documents: Could it be that ActiveDocument isn't the correct reference.
This works for me - you can replace ActiveDocument from the test-sub with any other document:
Option Explicit
Sub testPagenumbersForActiveDocument()
dim docToTest as Word.Document
set docToTest = ActiveDocument 'replace ActiveDocument with another doc you have opened
deleteExistingPageNumbers docToTest
addPageNumberToFooter docToTest
End Sub
Sub addPageNumberToFooter(doc As Word.Document)
With doc
.PageSetup.DifferentFirstPageHeaderFooter = False
.Sections(1).Footers(wdHeaderFooterPrimary).PageNumbers.Add
End With
End Sub
Sub deleteExistingPageNumbers(doc As Word.Document)
Dim sec As Section, pn As PageNumber
For Each sec In doc.Sections
For Each pn In sec.Footers(wdHeaderFooterPrimary).PageNumbers
pn.Delete
Next
Next
End Sub
The delete-sub only deletes PageNumbers - this is safer then your version as that will delete the whole footer-text ... which might be not what you want.
Related
I an using a code copied from "Macropod" (sorry if the name is incorrect) to replace every header and footer in a folder of documents with a new header and footer as displayed in the macro document. It is slightly altered to apply to only footers. This works, but my problem is that it leaves an extra paragraph mark on a line by itself at the end of the footer text and I cannot figure out where to add something that would remove the extra paragraph mark. When doing this copy/paste function manually, only a backspace is required to remove the extra paragraph mark. I've tried adding it a few different ways, but it either does nothing or produces an error. The macro text is provided below.
Sub UpdateDocumentFooters()
Application.ScreenUpdating = False
Dim strFolder As String, strFile As String
Dim wdDocTgt As Document, wdDocSrc As Document
Dim Sctn As Section, HdFt As HeaderFooter
strFolder = GetFolder
If strFolder = "" Then Exit Sub
Set wdDocSrc = ActiveDocument
strFile = Dir(strFolder & "\*.doc", vbNormal)
While strFile <> ""
If strFolder & "\" & strFile <> wdDocSrc.FullName Then
Set wdDocTgt = Documents.Open(FileName:=strFolder & "\" & strFile, _
AddToRecentFiles:=False, Visible:=False)
With wdDocTgt
For Each Sctn In .Sections
'For footers
For Each HdFt In Sctn.Footers
With HdFt
If .Exists Then
If Sctn.Index = 1 Then
wdDocSrc.Sections.First.Footers(HdFt.Index).Range.Copy
.Range.PasteAndFormat wdFormatOriginalFormatting
.Range.Characters.Last = vbNullString
ElseIf .LinkToPrevious = False Then
wdDocSrc.Sections.First.Footers(HdFt.Index).Range.Copy
.Range.PasteAndFormat wdFormatOriginalFormatting
.Range.Characters.Last = vbNullString
End If
End If
End With
Next
Next
.Close SaveChanges:=True
End With
End If
strFile = Dir()
Wend
Set wdDocSrc = Nothing: Set wdDocTgt = Nothing
Application.ScreenUpdating = True
End Sub
Function GetFolder() As String
Dim oFolder As Object
GetFolder = ""
Set oFolder = CreateObject("Shell.Application").BrowseForFolder(0, "Choose a folder", 0)
If (Not oFolder Is Nothing) Then GetFolder = oFolder.Items.Item.Path
Set oFolder = Nothing
End Function
Have reviewed the responses below, but no improvement yet.
I start with this:
Footer to Replace
And want to get this:
Desired Footer
But end up with this:
Resulting Footer
I am using a Find and Replace script/macro in MS Word. For the two lines below, how would I adjust this to be case sensitive? Right now it will replace us, bus, ect..
Const strFind As String = "US"
Const strRepl As String = "USA"
Sub BatchProcess()
Dim strFileName As String
Dim strPath As String
Dim oDoc As Document
Dim fDialog As FileDialog
Dim oStory As Range
Dim oRng As Range
Const strFind As String = "2017"
Const strRepl As String = "2018"
Set fDialog = Application.FileDialog(msoFileDialogFolderPicker)
With fDialog
.Title = "Select folder and click OK"
.AllowMultiSelect = False
.InitialView = msoFileDialogViewList
If .Show <> -1 Then
MsgBox "Cancelled By User", , _
"List Folder Contents"
Exit Sub
End If
strPath = fDialog.SelectedItems.Item(1) & "\"
End With
strFileName = Dir$(strPath & "*.docx")
While Len(strFileName) <> 0
WordBasic.DisableAutoMacros 1
Set oDoc = Documents.Open(strPath & strFileName)
For Each oStory In ActiveDocument.StoryRanges
Set oRng = oStory
With oRng.Find
Do While .Execute(FindText:=strFind)
oRng.Text = strRepl
oRng.Collapse wdCollapseEnd
Loop
End With
If oStory.StoryType <> wdMainTextStory Then
While Not (oStory.NextStoryRange Is Nothing)
Set oStory = oStory.NextStoryRange
Set oRng = oStory
With oRng.Find
Do While .Execute(FindText:=strFind)
oRng.Text = strRepl
oRng.Collapse wdCollapseEnd
Loop
End With
Wend
End If
Next oStory
oDoc.SaveAs FileName:=strPath & strFileName
oDoc.Close SaveChanges:=wdDoNotSaveChanges
strFileName = Dir$()
WordBasic.DisableAutoMacros 0
Wend
Set oDoc = Nothing
Set oStory = Nothing
Set oRng = Nothing
End Sub
In response to the post below. I have added the entire code.
The Find and Replace method has a boolean MatchCase property. Set it to True.
Example: In your DoWhile code. Do While .Execute(FindText:=strFind, MatchCase:=True)
Simply matching the case is insufficient if what you're searching for as a whole word might also exist within a larger string. Try:
Sub BatchProcess()
Application.ScreenUpdating = False
Dim strFileName As String, strPath As String
Dim oDoc As Document, oStory As Range
Dim fDialog As FileDialog
Set fDialog = Application.FileDialog(msoFileDialogFolderPicker)
With fDialog
.Title = "Select folder and click OK"
.AllowMultiSelect = False
.InitialView = msoFileDialogViewList
If .Show <> -1 Then
MsgBox "Cancelled By User", , "List Folder Contents"
Exit Sub
End If
strPath = fDialog.SelectedItems.Item(1) & "\"
End With
strFileName = Dir$(strPath & "*.docx")
WordBasic.DisableAutoMacros 1
While Len(strFileName) <> 0
Set oDoc = Documents.Open(strPath & strFileName)
With oDoc
For Each oStory In .StoryRanges
While Not (oStory Is Nothing)
oStory.Find.Execute FindText:="<US>", Replacewith:="USA", Forward:=True, _
Wrap:=wdFindContinue, MatchWildcards:=True, Replace:=wdReplaceAll
Set oStory = oStory.NextStoryRange
Wend
Next oStory
.SaveAs FileName:=strPath & strFileName
.Close SaveChanges:=wdDoNotSaveChanges
End With
strFileName = Dir$()
Wend
WordBasic.DisableAutoMacros 0
Set oDoc = Nothing: Set oStory = Nothing
Application.ScreenUpdating = True
End Sub
Note that I've used wildcards, combined with as the Find expression. That guarantees only whole upper-case words will be matched. you could achieve the same with:
oStory.Find.Execute FindText:="US", Replacewith:="USA", Forward:=True, _
Wrap:=wdFindContinue, MatchWholeWord:=True, MatchCase:=True, Replace:=wdReplaceAll
Note, too, the overall simplification of your code.
I have many documents i need to edit, i have the Version of the document in the Header like "Version #" these documents have different versions, but are all a single integer value. These versions need to +1 so i need to get the number then just add 1 then save.
This is seeming pretty tricky and im not sure its possible. Any Help would be appreciated.
For example.
Old Document
"Version 2"
New Edit
"Version 3"
I can find and replace as i have learned from here.
Try:
Sub UpdateVersions()
Application.ScreenUpdating = False
Dim strFolder As String, strFile As String, strDocNm As String
Dim wdDoc As Document, wdSctn As Section, wdHdFt As HeaderFooter
strDocNm = ActiveDocument.FullName
strFolder = GetFolder: If strFolder = "" Then Exit Sub
strFile = Dir(strFolder & "\*.doc", vbNormal)
While strFile <> ""
If strFolder & "\" & strFile <> strDocNm Then
Set wdDoc = Documents.Open(FileName:=strFolder & "\" & strFile, AddToRecentFiles:=False, Visible:=False)
With wdDoc
For Each wdSctn In .Sections
With wdSctn
For Each wdHdFt In .Headers
With wdHdFt
If .LinkToPrevious = False Then
With .Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "Version [0-9]{1,}"
.Replacement.Text = ""
.Format = False
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
.Execute
End With
Do While .Find.Found = True
.Text = "Version " & Split(.Text, " ")(1) + 1
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
End If
End With
Next
End With
Next
.Close SaveChanges:=True
End With
End If
strFile = Dir()
Wend
Set wdDoc = Nothing
Application.ScreenUpdating = True
End Sub
Function GetFolder() As String
Dim oFolder As Object
GetFolder = ""
Set oFolder = CreateObject("Shell.Application").BrowseForFolder(0, "Choose a folder", 0)
If (Not oFolder Is Nothing) Then GetFolder = oFolder.Items.Item.Path
Set oFolder = Nothing
End Function
This is a quick hack that may do what you wish.
First of all, make sure that you have the Scripting Runtime referenced in the Tools>Project>References menu. Secondly, I have understood that you have more than one document so this lot does everything in a folder.
I have just assumed, for this example, that the folder name is fixed. In Real Life you can modify the code to select the folder and then modify the code to go through sub-folders, but this is (a) a quick hack and (b) out of scope.
Public Sub IncreaseVersionNumbers()
' Make sure that the "Microsoft Scripting Runtime" library is enabled in the Tools>Projects>References
Dim sRootFolder As String
Dim oFSO As Scripting.FileSystemObject
Dim oFolder As Scripting.Folder
Dim oFile As Scripting.File
sRootFolder = "C:\_Documents\VersionNumberTest\" ' You can grab this by a Folder Selection dialog box instead
Set oFSO = New Scripting.FileSystemObject
Set oFolder = oFSO.GetFolder(sRootFolder)
For Each oFile In oFolder.Files
If InStr(1, oFile.Name, ".doc", vbTextCompare) > 0 Then
ProcessDocument (sRootFolder & oFile.Name)
End If
Next oFile
End Sub
Private Sub ProcessDocument(sDocument As String)
Dim oDoc As Word.Document
Dim oSection As Word.Section
Dim oRange As Range
Dim sHeaderText As String
On Error Resume Next
Set oDoc = Documents.Open(sDocument)
For Each oSection In oDoc.Sections
Set oRange = oSection.Headers(wdHeaderFooterPrimary).Range
If Not oRange Is Nothing Then
ProcessHeaderRange oRange
End If
Set oRange = oSection.Headers(wdHeaderFooterFirstPage).Range
If Not oRange Is Nothing Then
ProcessHeaderRange oRange
End If
Set oRange = oSection.Headers(wdHeaderFooterEvenPages).Range
If Not oRange Is Nothing Then
ProcessHeaderRange oRange
End If
Next oSection
oDoc.Close wdSaveChanges
End Sub
Private Sub ProcessHeaderRange(oRange As Range)
Dim sText As String, sNewText As String
Dim nPosn As Long, nStart As Long, nEnd As Long
Dim sVersion As String, nVersion As Long
sText = oRange.Text & " "
nPosn = InStr(1, sText, "Version", vbTextCompare)
If nPosn > 0 Then
nStart = InStr(nPosn, sText, " ")
If nStart > 0 Then
nStart = nStart + 1
nEnd = InStr(nStart, sText, " ")
If nEnd > 0 Then
sVersion = Mid$(sText, nStart, nEnd - nStart)
nVersion = Val(sVersion)
nVersion = nVersion + 1
sNewText = Left$(sText, nStart - 1) & Trim$(Str$(nVersion)) & " " & Right$(sText, Len(sText) - nEnd)
sNewText = Left$(sNewText, Len(sNewText) - 1)
oRange.Text = sNewText
End If
End If
End If
End Sub
This is, as I say, a quick hack so it may not work perfectly but, as always, have backups!
This works by going through each of the three possible headers in each possible section of the document. And if it finds a header in a section then it does what you say.
And this version does go above single digit version numbers. But it's a quick hack, as I say and so needs extra work to make it really bullet-proof. Having said that, it's a reasonable start I would think.
Hope that this helps,
Malc
I have got a lot of word file (~5000) with different header what i read with a macro and merge these multiple word document placed in a folder into one document.
Here the relevant code:
Sub MergeDocs()
Dim rng As Range
Dim MainDoc As Document
Dim strFile As String, strFolder As String
Dim Count As Long
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Pick folder"
.AllowMultiSelect = False
If .Show Then
strFolder = .SelectedItems(1) & Application.PathSeparator
Else
Exit Sub
End If
End With
Set MainDoc = Documents.Add
strFile = Dir$(strFolder & "*.doc") ' can change to .docx
Count = 0
Do Until strFile = ""
Count = Count + 1
Set rng = MainDoc.Range
With rng
.Collapse wdCollapseEnd
If Count > 1 Then
.InsertBreak wdSectionBreakNextPage
.End = MainDoc.Range.End
.Collapse wdCollapseEnd
End If
.InsertFile strFolder & strFile
End With
strFile = Dir$()
Loop
MsgBox ("Files are merged")
lbl_Exit:
Exit Sub
End Sub
It is working, but when I am trying to save file as .txt, the header+footer lose..is it any way which one I can save this header part to a .txt file too? (as I wrote, in every document has got different header.)
EDIT:
Sub MergeDocs()
Dim rng As Range
Dim MainDoc As Document
Dim strFile As String, strFolder As String
Dim Count As Long
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Pick folder"
.AllowMultiSelect = False
If .Show Then
strFolder = .SelectedItems(1) & Application.PathSeparator
Else
Exit Sub
End If
End With
Set MainDoc = Documents.Add
strFile = Dir$(strFolder & "*.doc") ' can change to .docx
Count = 0
Dim doc As Document
Dim head As String, foot As String
Do Until strFile = ""
Set doc = Documents.Open(strFile)
head = doc.Sections(1).Headers(wdHeaderFooterPrimary).Range.Text
foot = doc.Sections(1).Footers(wdHeaderFooterPrimary).Range.Text
doc.Close False
Count = Count + 1
Set rng = MainDoc.Range
With rng
.Collapse wdCollapseEnd
If Count > 1 Then
.InsertBreak wdSectionBreakNextPage
.End = MainDoc.Range.End
.Collapse wdCollapseEnd
End If
.InsertAfter head
.InsertParagraphAfter
.InsertFile strFolder & strFile
.InsertAfter foot
End With
strFile = Dir$()
Loop
MsgBox ("Files are merged")
lbl_Exit:
Exit Sub
End Sub
This is not fully tested but should get you going.
I have only altered your Do loop. Replace, try out and have fun:
Dim doc As Document
Dim head As String, foot As String
Do Until strFile = ""
Set doc = Documents.Open(strFolder & strFile)
head = doc.Sections(1).Headers(wdHeaderFooterPrimary).Range.text
foot = doc.Sections(1).Footers(wdHeaderFooterPrimary).Range.text
doc.Close False
Count = Count + 1
Set rng = MainDoc.Range
With rng
.Collapse wdCollapseEnd
If Count > 1 Then
.InsertBreak wdSectionBreakNextPage
.End = MainDoc.Range.End
.Collapse wdCollapseEnd
End If
.InsertAfter head
.InsertParagraphAfter
.InsertFile strFolder & strFile
.InsertAfter foot
End With
strFile = Dir$()
Loop
For years I have used the VBA code below to change the footer in all Word files in a folder (including subfolders).
It works pretty well, but only to the version Word 2003! Now I'm using Word 2010 and if I start the code I get the error:
Run-time error 5111. The command is not available on this platform
Private Sub Image16_Click()
Dim Suchpfad, oPath
Folder = BrowseForFolder("Sélectionnez le dossier où les fichiers doivent être traitées")
If Len(Folder) = 0 Then
MsgBox "Vous n'avez pas sélectionné un dossier!"
Exit Sub
Else
'ChangeFileOpenDirectory Folder
oPath = Folder
'MsgBox oPath
End If
'**** Fußzeilen löschen
Pfad = oPath
With Application.FileSearch
.LookIn = Pfad
.SearchSubFolders = True
.FileType = msoFileTypeWordDocuments
.Execute
For i = 1 To .FoundFiles.Count
strName = .FoundFiles(i)
WordBasic.DisableAutoMacros
Documents.Open FileName:=strName
Dim Abschnitt As Section
For Each Abschnitt In ActiveDocument.Sections
For j = 1 To 3
On Error Resume Next
Abschnitt.Footers(j).Range.Delete
Next j
Next
If ActiveWindow.View.SplitSpecial <> wdPaneNone Then
ActiveWindow.Panes(2).Close
End If
If ActiveWindow.ActivePane.View.Type = wdNormalView Or ActiveWindow. _
ActivePane.View.Type = wdOutlineView Then
ActiveWindow.ActivePane.View.Type = wdPrintView
End If
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
If Selection.HeaderFooter.IsHeader = True Then
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageFooter
Else
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
End If
Selection.WholeStory
Selection.Font.Name = "Verdana"
Selection.Font.Size = 7
Selection.TypeText Text:="First Line of Footer"
Selection.TypeParagraph
Selection.Font.Size = 6
Selection.TypeText Text:="Second Line of Footer"
ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
ActiveDocument.Save
ActiveDocument.Close
Next
End With
MsgBox "Operation done in " & Pfad & " !!!"
End Sub
I can't figure out this problem and I hope that somebody has a solution.
First you will need a recursive folder parsing routine. This should work.
Public Sub RecursiveFolderParse(Folder, dictFiles As Object, sExt As String)
Dim SubFolder As Variant
Dim File As Variant
For Each SubFolder In Folder.SubFolders
RecursiveFolderParse SubFolder, dictFiles, sExt
Next
For Each File In Folder.Files
If Right$(File.Name, Len(sExt)) = sExt Then
If Not dictFiles.Exists(File.Path) Then
dictFiles.Add File.Path, 1
End If
End If
Next
End Sub
Then to use this routine, here is your main subroutine where you process each file accordingly:
Public Sub ProcessAllFiles()
Dim sFolder As String
Dim dictFiles As Object
Dim FileSystem As Object
Dim vKeys As Variant
Dim sFilename As Variant
Dim sExt As String
' define your folder and the extension to look for
sFolder = "C:\Test"
sExt = "zip"
Set dictFiles = CreateObject("Scripting.Dictionary")
Set FileSystem = CreateObject("Scripting.FileSystemObject")
RecursiveFolderParse FileSystem.GetFolder(sFolder), dictFiles, sExt
vKeys = dictFiles.Keys
For Each sFilename In vKeys
' process file code goes here
MsgBox sFilename
Next
End Sub