![]() |
|
#1
|
|||
|
|||
|
I have a number of text documents that have .pa where manual page breaks should be. If memory serves, that was how we did manual page breaks in XyWrite. I'd like to develop a macro that would use those .pa delimiters as document ending points. So there would be some text; the macro would grab that text, down to the first occurrence of .pa, and move it to a new file; that first occurrence of .pa would itself be deleted; the newly created file would be saved with some automatic name; and the process would repeat, down to the (new) first occurrence of .pa, until the original file was empty. I've used Word macros, but I don't know a lot about them. After some digging, I found this, and tried to modify it to fit, but I don't know what to substitute for " ActiveDocument.Bookmarks." Code:
Sub BreakOnPage()
' Used to set criteria for moving through the document by page.
Application.Browser.Target = wdBrowsePage
For i = 1 To ActiveDocument.BuiltInDocumentProperties("Number of Pages")
'Select and copy the text to the clipboard
ActiveDocument.Bookmarks(".pa").Range.Copy
' Open new document to paste the content of the clipboard into.
Documents.Add
Selection.Paste
' Removes the break that is copied at the end of the page, if any.
Selection.TypeBackspace
ChangeFileOpenDirectory "D:\"
DocNum = DocNum + 1
ActiveDocument.SaveAs FileName:="test_" & DocNum & ".doc"
ActiveDocument.Close
' Move the selection to the next page in the document
Application.Browser.Next
Next i
ActiveDocument.Close savechanges:=wdDoNotSaveChanges
End Sub
|
|
#2
|
||||
|
||||
|
Try:
Code:
Sub SplitDocument()
Application.ScreenUpdating = False
Dim DocSrc As Document, DocTgt As Document, i As Long
Dim Rng As Range, HdFt As HeaderFooter, j As Long
Set DocSrc = ActiveDocument
With DocSrc
' Create, copy & delete a temporary Section break.
With .Range
Set Rng = .Characters.First
With Rng
.Collapse wdCollapseStart
.InsertBreak Type:=wdSectionBreakNextPage
.Start = .Start - 1
.Copy
.Delete
End With
' Replace all instances of .pa with the copied Section break
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = ".pa"
.Replacement.Text = "^c"
.Forward = True
.Format = False
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
If .Found = False Then Exit Sub
End With
End With
' Process each Section
For i = 1 To .Sections.Count
' Get the whole Section
Set Rng = .Sections(i).Range
' Contract the range to exclude the Section break
With Rng
.MoveEnd wdCharacter, -1
Do While .Characters.Last.Previous.Text = vbCr
.Characters.Last.Previous.Text = vbNullString
Loop
If Len(.Text) > 1 Then
j = j + 1
' Copy the range
.Copy
' Create the output document
Set DocTgt = Documents.Add(Template:=DocSrc.AttachedTemplate.FullName, Visible:=False)
With DocTgt
' Paste contents into the output document, preserving the formatting
.Range.PasteAndFormat (wdFormatOriginalFormatting)
' Delete trailing paragraph breaks & page breaks at the end
While .Characters.Last.Previous = vbCr
.Characters.Last.Previous = vbNullString
Wend
' Replicate the headers & footers
For Each HdFt In DocSrc.Sections(i).Headers
.Sections(1).Headers(HdFt.Index).Range.FormattedText = HdFt.Range.FormattedText
Next
For Each HdFt In DocSrc.Sections(i).Footers
.Sections(1).Footers(HdFt.Index).Range.FormattedText = HdFt.Range.FormattedText
Next
' Save & close the output document
.SaveAs FileName:=Split(DocSrc.FullName, ".doc")(0) & "_" & j & ".docx", _
FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False
.Close SaveChanges:=False
End With
End If
End With
Next
End With
Set Rng = Nothing: Set DocTgt = Nothing: Set DocSrc = Nothing
Application.ScreenUpdating = True
End Sub
__________________
Cheers, Paul Edstein [Fmr MS MVP - Word] |
|
#3
|
||||
|
||||
|
Maybe something like:
Code:
Sub SplitDoc()
Const strName As String = "Test_" 'the name of the files
Const strPath As String = "C:\Path\" 'the folder to save the files
Dim strDocName As String
Dim oDoc As Document
Dim oRng As Range, oSplit As Range
Dim oNewDoc As Document
Dim strDelim As String: strDelim = ".pa"
Dim Counter As Integer: Counter = 1
Dim strOriginalName As String
Set oDoc = ActiveDocument
oDoc.Save
If oDoc.path = "" Then Beep: GoTo lbl_Exit
strOriginalName = oDoc.FullName
Set oRng = oDoc.Range
Application.ScreenUpdating = False
With oRng.Find
Do While .Execute(FindText:=strDelim, MatchWholeWord:=True, MatchCase:=True)
oRng.Text = ""
Set oSplit = oRng
oSplit.Start = ActiveDocument.Range.Start
Set oNewDoc = Documents.Add(strOriginalName)
oNewDoc.Range.FormattedText = oSplit.FormattedText
strDocName = strPath & strName & _
LTrim$(Str$(Counter)) & ".docx"
oNewDoc.SaveAs2 strDocName
oNewDoc.Close
Counter = Counter + 1
oSplit.Text = ""
oRng.Collapse 0
Loop
End With
oDoc.SaveAs2 strDocName
oDoc.Close wdDoNotSaveChanges
Documents.Open strOriginalName
lbl_Exit:
Set oDoc = Nothing
Set oNewDoc = Nothing
Set oRng = Nothing
Set oSplit = Nothing
Exit Sub
End Sub
__________________
Graham Mayor - MS MVP (Word) (2002-2019) Visit my web site for more programming tips and ready made processes www.gmayor.com |
|
#4
|
|||
|
|||
|
OK. To try each of these macros in Word 2010 (which, sorry, I didn't specify previously), I opened one of these *.txt docs and pasted its contents into an empty Word doc. Then I ran these macros, with the following results:
(1) Re: the SplitDocument macro (macropod): "Run-time error '4605': This method or property is not available because no text is selected." Debug button highlights the ".Copy" line (With DocSrc > With .Range > With Rng). I guess there must be a Select command that I could insert somewhere before that? (2) Re: the SplitDoc macro (gmayor): It asked me for a filename. I thought it was offering to save the pasted text as a Word doc, in whole or in part. I offered Doc001. It said, "Run-time error '5152': This is not a valid file name." So then I figured it was asking for the name of an input file. I closed the opened Word doc, ran the macro again, and specified the input .txt file. But then it said, "Run-time error '4248': This command is not available because no document is open." Debug highlighted "Set oDoc = ActiveDocument." I tried again with an open but empty Word doc. It offered the Save As dialog. I entered Doc001.docx. It repeated the 5152 error. This time, Debug highlighted "oDoc.SaveAs2 strDocName." For both of these macros: Once I figure this out, I'll probably comment the macro to clarify the proper opening steps for a complete noob, so I'll be able to use the macro in the future without stumbling around like this. Thank you, both of you, for going to the trouble of working up that code. I have a hard time learning coding unless I put in a lot of time. I did that for batch, back in the day, and also for WordPerfect scripts, which made great sense to me. But for some reason I've had a learning block when it comes to VBA. It always seems like I'd have to devote several months to it, and I can't. |
|
#5
|
||||
|
||||
|
Without knowing which code line was highlighted when the error occurred, it's impossible to comment on why it's happening. Furthermore, with my code, it was assumed the document had already been saved. Your process suggests you're maybe not doing that, in which case the macro will fail. And no, my code doesn't select anything. However, it's possible you'll get an error if there's are .pa strings with nothing else before/after them. I've updated the code to handle that.
__________________
Cheers, Paul Edstein [Fmr MS MVP - Word] |
|
#6
|
||||
|
||||
|
In the case of my macro, the macro starts by saving the document. If it prompts for a name it is because the original document doesn't have a name (which it won't if you have just copied text to a new empty document). Save and name the document!
The macro needs to run on a Word document in docx format not a TXT file. If you have a text file start with Save As and save as DOCX format. Then run the macro with that document on screen.
__________________
Graham Mayor - MS MVP (Word) (2002-2019) Visit my web site for more programming tips and ready made processes www.gmayor.com |
|
#7
|
|||
|
|||
|
gmayor: still the same error when run on x.docx: Run-time error '5152.'" Same line highlighted in Debug as before: "oDoc.SaveAs2 strDocName." The macro opened a new document, but there's nothing in it. The debugger limits my navigation to see what's going on. But when I stop the debugger, the first chunk of text (i.e., text up to the first occurrence of .pa) does get added to the new doc. At that point, I see that the .pa delimiter has been removed from the source doc, but the initial text (i.e., that which has been copied to the new doc) is still in the source doc.
macropod: trying the revised SplitDocument macro on a fresh copy of x.docx, I get the same "Run-time error '4605.'" I get only an hourglass cursor at that point. I click Debug. As before, the "Copy" line is highlighted in the code. Not sure what you meant in saying that you didn't know what code line was highlighted. That's the only thing that seems to be highlighted. Nothing is highlighted in x.docx, as far as I can tell: I can't navigate while the debugger is open, and nothing is highlighted when I close it. |
|
#8
|
||||
|
||||
|
Can you attach a problem document to a post with some representative data (delete anything sensitive)? You do this via the paperclip symbol on the 'Go Advanced' tab at the bottom of this screen.
__________________
Cheers, Paul Edstein [Fmr MS MVP - Word] |
|
#9
|
|||
|
|||
|
Sure. Here you go. These particular letters are pretty trivial, but they should work. Thanks.
|
|
#10
|
||||
|
||||
|
Try the latest code revision.
__________________
Cheers, Paul Edstein [Fmr MS MVP - Word] |
|
#11
|
|||
|
|||
|
That works. We are cruising.
To clarify for posterity, macropod's SplitDocument macro parses Test.docx file of this form: Text Text Text .pa Text Text Text .pa Text Text Text .pa into a series of separate files Text_1.docx, Text_2.docx, et seq., where each file ends at the next .pa delimiter, and that delimiter itself is removed. I have one last question. At present, I have to click OK for each file. It's nice that it displays a dialog showing the top of the next file in the series, but the dialog doesn't allow me to scroll, so I can't use it to confirm that we've got a proper break. For that, apparently I'll have to open the several output files individually. And that's fine. But if that's the way it is, I'd just as soon dispense with the manual confirmation. For that, I suspect we're talking about deleting the MsgBox .Text line. Is that right, and is that all there is to it? |
|
#12
|
||||
|
||||
|
The only ways I can see why the macro I posted would cause that error are
1. That you are using Word 2007 in which case change oDoc.SaveAs2 strDocName to oDoc.SaveAs strDocName or 2. that you have not changed the line Const strPath As String = "C:\Path\" 'the folder to save the files to reflect a path that exists in which to save the documents. Otherwise it splits your test document without issue.
__________________
Graham Mayor - MS MVP (Word) (2002-2019) Visit my web site for more programming tips and ready made processes www.gmayor.com |
|
#13
|
|||
|
|||
|
gmayor -- yes, you're right, silly oversight on my part. Changing the path name fixed that. And this macro has the advantage of not requiring manual approval of each letter.
One remaining issue: in two tests, for the last .pa-delimited document, I get only a blank page. In one, for instance, there are eight pieces of correspondence ending with .pa; each of the first seven get copied into separate .docx files; there is an eighth .docx file, but it is empty; the eighth letter ending with .pa does not get copied into it. Just in the spirit of trying to learn a bit from this, maybe the counter is incrementing at the wrong time? |
|
#14
|
||||
|
||||
|
Quote:
The following version of the previous macro will process a whole folder, so you don't have to manually open each document. As coded, the macro assumes your XyWrite documents have a .txt extension; if not, change the two .txt references in the code to the correct extension. Code:
Sub SplitDocuments()
Application.ScreenUpdating = False
Dim strFolder As String, strFile As String, strDocNm As String
Dim DocSrc As Document, DocTgt As Document, i As Long
Dim Rng As Range, HdFt As HeaderFooter, j As Long
strDocNm = ActiveDocument.FullName
strFolder = GetFolder
If strFolder = "" Then Exit Sub
strFile = Dir(strFolder & "\*.txt", vbNormal)
While strFile <> ""
If strFolder & "\" & strFile <> strDocNm Then
Set DocSrc = Documents.Open(FileName:=strFolder & "\" & strFile, _
ConfirmConversions:=False, AddToRecentFiles:=False, Visible:=False)
With DocSrc
' Create, copy & delete a temporary Section break.
With .Range
Set Rng = .Characters.First
With Rng
.Collapse wdCollapseStart
.InsertBreak Type:=wdSectionBreakNextPage
.Start = .Start - 1
.Copy
.Delete
End With
' Replace all instances of .pa with the copied Section break
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = ".pa"
.Replacement.Text = "^c"
.Forward = True
.Format = False
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
End With
' Process each Section
j = 0
For i = 1 To .Sections.Count
' Get the whole Section
Set Rng = .Sections(i).Range
' Contract the range to exclude the Section break
With Rng
.MoveEnd wdCharacter, -1
Do While .Characters.Last.Previous.Text = vbCr
.Characters.Last.Previous.Text = vbNullString
Loop
If Len(.Text) > 1 Then
j = j + 1
' Copy the range
.Copy
' Create the output document
Set DocTgt = Documents.Add(Template:=DocSrc.AttachedTemplate.FullName, Visible:=False)
With DocTgt
' Paste contents into the output document, preserving the formatting
.Range.PasteAndFormat (wdFormatOriginalFormatting)
' Delete trailing paragraph breaks & page breaks at the end
While .Characters.Last.Previous = vbCr
.Characters.Last.Previous = vbNullString
Wend
' Replicate the headers & footers
For Each HdFt In DocSrc.Sections(i).Headers
.Sections(1).Headers(HdFt.Index).Range.FormattedText = HdFt.Range.FormattedText
Next
For Each HdFt In DocSrc.Sections(i).Footers
.Sections(1).Footers(HdFt.Index).Range.FormattedText = HdFt.Range.FormattedText
Next
' Save & close the output document
.SaveAs FileName:=Split(DocSrc.FullName, ".txt")(0) & "_" & j & ".docx", _
FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False
.Close SaveChanges:=False
End With
End If
End With
Next
.Close SaveChanges:=False
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
__________________
Cheers, Paul Edstein [Fmr MS MVP - Word] |
|
#15
|
||||
|
||||
|
Quote:
That being the case remove the line to save the document before it is closed Code:
'oDoc.SaveAs2 strDocName
oDoc.Close wdDoNotSaveChanges
Code:
End With
strDocName = strPath & strName & _
LTrim$(Str$(Counter)) & ".docx"
oDoc.SaveAs2 strDocName
oDoc.Close wdDoNotSaveChanges
Documents.Open strOriginalName
__________________
Graham Mayor - MS MVP (Word) (2002-2019) Visit my web site for more programming tips and ready made processes www.gmayor.com |
|
| Tags |
| macro, page break, split |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| How to divide a landscape page into 2 parts | rtcary | Word | 1 | 01-17-2018 12:07 AM |
| One long string of text with ; as the delimiter | Laurie B. | Excel | 1 | 02-28-2015 03:02 AM |
Split file using variable delimiter
|
kramer74 | Word VBA | 7 | 09-01-2014 12:12 AM |
| How do I edit text in Quick Parts? | TommyVincent | Word | 4 | 07-30-2014 01:51 PM |
| divide page into 4 parts | aclark17 | Word | 4 | 01-17-2012 09:04 AM |