View Full Version : Search for files in folder, copy inside and paste it in main document!
linneedshelp
12-02-2015, 04:08 AM
Hello!
I am new in VBA Word and I am struggling with the code, would be great to get some help. : pray2:
I have a folder1 with a Word Document and another folder2 inside. The Word Document is the "Main Document", in it there are headings and after each heading there is the name of the document which belongs to this part. In the folder2 there are a lot of Word Documents, the "Part Documents" which are the Documents belonging to the different headings.
EXAMPLE OF FOLDERS:
Folder1 > Main Document & "Folder2 Parts" >     "Part1.docx" & "Part2.docx" & "Part3.docx" & .....
 
MAIN DOCUMENT: 
In the Main Document there is this text:
1. Heading 1 
            Part1.docx
      2. Heading 2
 
            Part2.docx
 
    3. Heading 3
 
                     Part3.docx
 
 
FUNCTION:
 
Open the Main Document, start the macro, macro begins to search for the variable in the Main document, it finds "Part1.docx", then it goes to the folder2 and searches for the corresponding file with the same name, it copies the inside and replaces the word Part1.docx in the main document for the text inside the file.
Then, the macro searches for the next variable, it finds Part2.docx and goes again to the folder2, searches and finds the file Part2.docx and replaces the word found in the main document for the text which is in the file found in folder2.
 
Has anyone of you and idea how to do this? I hope I explained myself good enough.
 
Any suggestions would be appreciated!
gmayor
12-02-2015, 06:26 AM
Maybe something like
Option Explicit
Sub Example()
'Graham Mayor
Dim oRng As Range
Dim oPara As Paragraph
Dim strFname As String
Const strPath As String = "C:\Path\Folder2\"        'the path with the sub documents
    For Each oPara In ActiveDocument.Paragraphs
        Set oRng = oPara.Range
        oRng.End = oRng.End - 1
        If LCase(oRng.Text) Like "part*.docx" Then
            strFname = oRng.Text
            oRng.Text = ""
            If FileExists(strPath & strFname) Then
                oRng.InsertFile strPath & strFname
            End If
        End If
    Next oPara
lbl_Exit:
    Set oPara = Nothing
    Set oRng = Nothing
    Exit Sub
End Sub
Private Function FileExists(strFullName As String) As Boolean
'Graham Mayor
'strFullName is the name with path of the file to check
Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    If fso.FileExists(strFullName) Then
        FileExists = True
    Else
        FileExists = False
    End If
lbl_Exit:
    Exit Function
End Function
linneedshelp
12-02-2015, 11:53 AM
Hello Graham Mayor,
Thank you really much. This is awesome!
linneedshelp
12-04-2015, 12:12 AM
Hello,
It´s me again. I worked on your macro and now I have the problem that it is not fast enough for big amounts of Word Documents Parts.
The case is: There are a lot of people working on this Main Doument, everyone does one Part...docx and paste it in the Folder2, as everyone uses another Format (like Font Size, Font Name, Headings) I have to format the text after it is paste in the Main Document. Also I wanted to add page numbers. 
I managed to add all this to your macro but it is just working with small documents. As there are going to be more or less 15 part documents with around 5-10 pages each, I used old word documents I found in my computer, named then Part1.docx to Part6.docx and tried the macro. What happend is that it ran 10 minutes and still nothing happend. 
I tried tifferent scenarios:
1) 6 Part Documents with around 35 pages in total just with your code: it worked
2) 6 Part Documents .... with Formatting: not working
3) 2 Part Documents .... with Formatting: working
I belive it is because as I wrote the macro (going to paste it below), it goes through the Main Document, finds Part1.docx, goes to the Folder2, searches for the File Part1.docx and paste the text inside the Main Document. The macro repeats this until he does not find anymore Part().docx.
Now, the macro starts to search for Heading1, everytime it is found its style is changed. This means the macro runs through the Main Document (maybe over 80 Pages) just for searching Heading 1. Then it goes through the main document again, just for searching Heading 2, and after that again just for changing the format of the text (Normal). 
So, basically the macro has to go 3 times through all the Main document. Am I right that the macro is lazy because of that?
Is there a posibility to put all these 3 things into a big If-Clause?
Like: search for x, if x = Heading 1 do that, else if x = Heading 2 do that else, if x = Normal do that else end if
Because this would me the macro just has to go through the Document one time. 
CODE WITH ADDITIONAL FUNCTIONS:
Sub Example()
' Graham Mayor
Application.ScreenUpdating = False
    Dim oRng As Range
    Dim oPara As Paragraph
    Dim strFname As String
    Const strPath As String = " C:\Path\Folder2\" 'the path with the sub documents
    For Each oPara In ActiveDocument.Paragraphs
        Set oRng = oPara.Range
        oRng.End = oRng.End - 1
        If LCase(oRng.Text) Like "part*.docx" Then
            strFname = oRng.Text
            oRng.Text = ""
            If FileExists(strPath & strFname) Then
                oRng.InsertFile strPath & strFname
            End If
        End If
    Next oPara
'CHANGE HEADING 1
    With ActiveDocument.Content.Find
        .ClearFormatting
       .Style = wdStyleHeading1
        'The Do...Loop statement repeats a series of actions each time this style is found.
        Do While .Execute(Forward:=True, Format:=True) = True
                With .Parent
                .Font.Bold = False
                .Font.Name = "Time New Roman"
                .Font.ColorIndex = wdBlack
                .Font.Size = 16
                .Font.Underline = True
                .ParagraphFormat.Alignment = wdAlignParagraphLeft
                .ParagraphFormat.SpaceAfter = 6
                End With
       Loop
    End With
'CHANGE HEADING 2
    With ActiveDocument.Content.Find
        .ClearFormatting
       .Style = wdStyleHeading2
        'The Do...Loop statement repeats a series of actions each time this style is found.
        Do While .Execute(Forward:=True, Format:=True) = True
                With .Parent
                .Font.Bold = False
                .Font.Name = "Time New Roman"
                .Font.ColorIndex = wdBlack
                .Font.Size = 14
                .Font.Underline = True
                .ParagraphFormat.Alignment = wdAlignParagraphLeft
                .ParagraphFormat.SpaceAfter = 6
                End With
       Loop
    End With
'CHANGE NORMAL
    With ActiveDocument.Content.Find
        .ClearFormatting
       .Style = wdStyleNormal
        'The Do...Loop statement repeats a series of actions each time this style is found.
        Do While .Execute(Forward:=True, Format:=True) = True
                With .Parent
                .Font.Bold = False
                .Font.Name = "Time New Roman"
                .Font.ColorIndex = wdBlack
                .Font.Size = 12
                .Font.Underline = False
                .ParagraphFormat.Alignment = wdAlignParagraphJustify
                .ParagraphFormat.SpaceAfter = 6
                End With
       Loop
    End With
'ADD PAGE NUMBER
    With ActiveDocument.Sections(1)
    .Footers(wdHeaderFooterPrimary).PageNumbers.Add _
    PageNumberAlignment:=wdAlignPageNumberCenter, _
    FirstPage:=True
End With
lbl_Exit:
    Set oPara = Nothing
    Set oRng = Nothing
    Exit Sub
End Sub
Private Function FileExists(strFullName As String) As Boolean
     'Graham Mayor
     'strFullName is the name with path of the file to check
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    If fso.FileExists(strFullName) Then
        FileExists = True
    Else
        FileExists = False
    End If
lbl_Exit:
    Exit Function
End Function
gmayor
12-04-2015, 06:31 AM
If you have a lot of paragraphs to process it is inevitably slow, in which case Range.Find is faster. Try the following
Option Explicit
Sub Example()
' Graham Mayor
Dim oRng As Range
Dim strFname As String
Const strPath As String = "C:\Path\Folder2\"        'the path with the sub documents
    Application.ScreenUpdating = False
    'ADD PAGE NUMBER
    With ActiveDocument.Sections(1)
        .Footers(wdHeaderFooterPrimary).PageNumbers.Add _
                PageNumberAlignment:=wdAlignPageNumberCenter, _
                FirstPage:=True
    End With
    Set oRng = ActiveDocument.Range
    With oRng.Find
        Do While .Execute(FindText:="Part[0-9]{1,}.docx", MatchWildcards:=True)
            strFname = oRng.Text
            If FileExists(strPath & strFname) Then
                oRng.Text = ""
                oRng.InsertFile strPath & strFname
            End If
            oRng.Collapse 0
        Loop
    End With
    SetStyles ActiveDocument
lbl_Exit:
    Set oRng = Nothing
    Exit Sub
End Sub
Private Function FileExists(strFullName As String) As Boolean
'Graham Mayor
'strFullName is the name with path of the file to check
Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    If fso.FileExists(strFullName) Then
        FileExists = True
    Else
        FileExists = False
    End If
lbl_Exit:
    Exit Function
End Function
Sub SetStyles(odoc)
Dim oStyle As Style
    For Each oStyle In odoc.Styles
        Select Case oStyle.NameLocal
            Case Is = "Heading 1"
                With oStyle
                    .Font.Bold = False
                    .Font.Name = "Time New Roman"
                    .Font.ColorIndex = wdBlack
                    .Font.Size = 16
                    .Font.Underline = wdUnderlineSingle
                    .ParagraphFormat.Alignment = wdAlignParagraphLeft
                    .ParagraphFormat.SpaceAfter = 6
                End With
            Case Is = "Heading 2"
                With oStyle
                    .Font.Bold = False
                    .Font.Name = "Time New Roman"
                    .Font.ColorIndex = wdBlack
                    .Font.Size = 14
                    .Font.Underline = True
                    .ParagraphFormat.Alignment = wdAlignParagraphLeft
                    .ParagraphFormat.SpaceAfter = 6
                End With
            Case Is = "Normal"
                With oStyle
                    .Font.Bold = False
                    .Font.Name = "Time New Roman"
                    .Font.ColorIndex = wdBlack
                    .Font.Size = 12
                    .Font.Underline = False
                    .ParagraphFormat.Alignment = wdAlignParagraphJustify
                    .ParagraphFormat.SpaceAfter = 6
                End With
             Case Else
        End Select
    Next oStyle
lbl_Exit:
    Exit Sub
End Sub
linneedshelp
12-05-2015, 02:05 PM
Hello,
Thank you for replying.
I feel sorry to ask again but on my Word it's not working completely.
If I copy exact your macro, the programm says there is an Error 5560 because the "search for"  method it is not a valid comparison... Do While .Execute(FindText:="Part[0-9]{1,}.docx", MatchWildcards:=True)
I changed it to Do While .Execute(FindText:="Part*.docx", MatchWildcards:=True) as it was before and then the macro copies and places the text into the Main document but the formatting is not working. I understand the part of calling SetStyles ActiveDocument and tried to place it somewhere else to make it work but I couldn't find a solution.
Is it actually working on your computer?
gmayor
12-06-2015, 02:07 AM
I assume the error occurs because your local Windows regional settings use a semicolonn rather than a comm as list separator. Change the line to 
Do While .Execute(FindText:="Part[0-9]{1;}.docx", MatchWildcards:=True)
The SetStyles macro re-assigns the paragraph styles using the formats from your request. It works fine here, but then I don't have your documents so am unable to judge what you have done with styles in your documents that would prevent it from working.
linneedshelp
12-07-2015, 01:04 AM
Hello, 
I found the problem!!!
By the time I was working on the first Macro you send me, I tried to add the formatting using the German word or the English word for it. (My Word is in German) 
But just the English word "Heading1" in wdStyleHeading1 worked.
The new macro needs the German word: Case Is = "Überschrift 1". 
Thank you for helping me!
gmayor
12-07-2015, 03:12 AM
There was nothing in your original question to suggest a language issue, but that would certainly screw things up. I recently did some work for a private client in Dutch which gave me a headache for much the same reason. You need to insert the local style names as you appear to have discovered. That and the list separator character.:)
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.