10
votes

I haven't used VB for years, so please forgive me if this turns out to be obvious. I'm trying to write a word vba macro for use in a template which will display a userform and then import the contents of fileA.docx, fileB.docx, or fileC.docx depending on the userform. (After that I'm going to use bookmarks to fill in some form data, I don't know if that's relevant). Files A, B, and C will contain text with some basic formatting such as lists, but nothing fancy.

The solutions I've seen online can copy the contents of file to a new file, but ideally I would like to import the entirety of one of those files into the new, currently unnamed file that I'm getting from the template. I think where I'm running into problems is with switching the selection to one of those files, and then back to the new unnamed document, though I could use a hand to make sure I'm copying correctly as well.


Update: I was making things too hard, though the answers here got me pointed in the right direction (thanks!). In the end I just did

ThisDocument.Activate

Selection.InsertFile("fileA")

which gives me the raw dump of everything that I wanted.

5

5 Answers

7
votes

Using commands such as these you can switch between which Document you're using and copy and paste elements:

ThisDocument.Activate 'Sets the main document active
Documents("Name.doc").Activate 'Activates another document

You can insert, copy and paste things in and out of documents using copy commands.

ThisDocument.Range.InsertAfter("String") 'Insert text

Selection.WholeStory 'Select whole document
Selection.Expand wdParagraph 'Expands your selection to current paragraph
Selection.Copy 'Copy your selection
Documents("name.doc").Activate 'Activate the other document
Selection.EndKey wdStory 'Move to end of document
Selection.PasteAndFormat wdPasteDefault 'Pastes in the content

You can then go and format such, or copy and paste them with original formatting from before.

3
votes

Here is a significant improvement (I think) you will want to incorporate because it:

  1. does not use the clipboard and thus does not make your macro vulnerable to the user changing the contents of the clipboard while your macro is running
  2. does not use a file and thus greatly improve the speed by eliminating I/O and eliminates the potential of having to deal with file system security/permissions, etc. Please do not use .InsertFile() if you are looping through documents you will slow yourself down. Use it once, at the end -only if you have to. The example below shows how to accomplish the same result without using .InsertFile()

The idea is to transfer some portion of text found in 1 source document, to a destination document that is different than the source, and keep the source formatting.

To accomplish the above (skipping the code to open documents):

For Each oTable In oDoc_Source  
'the above could have been anything that returns a Range object
'such as: ActiveDocument.Content.Find.Execute ....

'...
'logic here to identify the table, or text, you are looking for
'...

'I can't believe the MS Dev Center folks could only think
'of .InsertFile(), which is the last resort I would go for, 
'especially if your code runs on a web server [concurrent web requests]!

'SAFEST
'(no user interference on clipboard possible, no need to deal with file i/o and permissions)
'you need a reference to Document.Content, 
'as the act of obtaining a reference "un-collapses" the range, so the below 3 lines must be in that order.
Set oRange =  oDoc_DestinationDoc.Content
oRange.Collapse Direction:=wdCollapseEnd
oRange.FormattedText = oTable.Range

'BRUTE, AND PRONE TO RANDOM ERRORS AND HANGS DUE TO USER INTERFERENCE WITH CLIPBOARD 
'find a way to implement WIHTOUT using the CLIPBOARD altogether to copy the below range object
'it will be easier for PC users to use the clipboard while the macro runs
'and it will probably be safer for the output of this macro to remain uncorrupted

'oTable.Range.Copy
'Set oRange =  oDoc_DestinationDoc.Content
'oRange.Collapse Direction:=wdCollapseEnd
'oRange.Paste


'THE BELOW DOES NOT WORK
' '1) - cannot add a range from another document
' 'adds only text, not the formats and not the table layout
' oTable.Range.TextRetrievalMode.IncludeFieldCodes = True
' oTable.Range.TextRetrievalMode.IncludeHiddenText = True
'  oDoc_DestinationDoc.Content.InsertAfter oTable.Range
'
' '2) - cannot add a range from another document
'  oDoc_DestinationDoc.Content.Tables.Add oTable.Range, iRowMax, iColMax
' 
' '3) - only puts in plain text, and it replaces the range without the .Collapse call
'  oDoc_DestinationDoc.Content.Text = oTable.Range
2
votes

Record a macro...

  1. start in the source document
  2. press ctrl-a to select everything
  3. press ctrl-c to copy it to the clipboard
  4. switch to the target document
  5. press ctrl-v to paste into the document
  6. stop recording

or (assuming word 2007 or later)

  1. start in the target document with the source document closed
  2. on the ribbon click insert > object > Text from file...
  3. navigate to the source document
  4. click the insert button
  5. stop recording

I prefer the second version so I should have put it first

0
votes

I was doing the same thing, tried to select the other document, copy and paste. But it didn't worked (I received an error probably because some other application was using the clipboard, but I am not sure.). So I did a little search and found the perfect solution on Microsoft Dev Center.

https://msdn.microsoft.com/en-us/vba/word-vba/articles/selection-insertfile-method-word

Selection.Collapse Direction:=wdCollapseEnd 
Selection.InsertFile FileName:="C:\TEST.DOC"
0
votes
'set current doc name and path
    Dim docName As String: docName = ActiveDocument.name
    Dim filepath As String: filepath = ActiveDocument.Path
'create a new file
    Documents.Add
'get the path of a current file
    ChangeFileOpenDirectory filepath
'insert content of current file to newly created doc
    Selection.InsertFile _
        FileName:=docName, _
        Range:="", _
        ConfirmConversions:=False, _
        Link:=False, _
        Attachment:=False
'open prompt to save a new file
    With Dialogs(wdDialogFileSaveAs)
        .name = docName & "-copy"
        .Show
    End With