1
votes

I am trying to write a VBA script to help me with some repetitive operations in a larger Word document. As part of this I need to know how many paragraphs are in a piece of text copied from another word document into the clipboard. (The steps that follow in my intended procedure depend on the paragraph counts.)

I tried this (see below), but got stuck with my approach, as easily visible from my comments in the script:

Sub InsertMultiPara()

'Declarations
   Dim MyData As MSForms.DataObject
   Dim intNumPara As Integer
   Dim strClip As Variant

'Fill them
  Set MyData = New MSForms.DataObject
  MyData.GetFromClipboard
  strClip = MyData.GetText

'Continuing my ideas... various experiments

   'OFF intNumPara = MyData.Paragraphs.Count
        'Error: "Object dosn'nt support this property or method"

   'OFF intNumPara = strClip.Paragraphs.Count
        'Error: "Object required"

'Paste the Clipboard content 
    Selection.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False

'Expand selection to everything just pasted:   
    Selection.MoveUp Unit:=wdParagraph, Count:=intNumPara, Extend:=wdExtend

'Do some other stuff with that range
    Application.Run MacroName:="Normal.MyMacros.Something-nice-and-useful"

End Sub

But, as you see in the comments underneath the 'OFF commented lines: this does not work as I thought it would.

So, actually simple question: how can I implement a pragraph count on stuff that sits in the clipboard (and definitely has paragraphs, as they are there when the clipboard content is pasted).

2
The Clipboard is not part of Word; Word's commands won't work on its content. The content only becomes Word content when it's in a Word document. Possibly, if the content as a string is analysed it would be possible to identify what character code is used to separate paragraphs, then you could get the number of those. But simplest would probably be to paste to a (non-visible, temporary) Word document. Do a Paragraphs.Count on that content, delete the content, paste to the "real" document. That, or the code needs to get the pasted content after-the-fact. - Cindy Meister
@CindyMeister Thanks. I followed your second suggestion and got it working. See my own answer below. - Christian Geiselmann
Ordinarily, one would expect the be able to get the paragraph count of what is to be copied, obviating the need to work it out after the fact. - macropod
@macropod That's actually a good idea. On the other hand it has a usability issue: I then cannot do a standard "Ctrl c" copy in the source document, but I have to know right away that I want to copy this piece of text with that specific procedure. It is more practical fo me just to do the usual "Ctrl c" copying. - Christian Geiselmann
If you're doing a Ctrl-c, you must have something selected - so count the paragraphs selected before whatever your macro does next. - macropod

2 Answers

0
votes

Inspired by Cindy Meister's comment (above) I then found the following solution (which includes first creating a new Word document object, then pasting the clipboard content into it, then reading out its paragraph number):

Sub InsertAndProcessMultipleParagraphs()

'Declarations    
    Dim MyData As MSForms.DataObject
    Dim intNumPara As Integer
    Dim objDoc

'Fill them objects
    Set MyData = New MSForms.DataObject
    MyData.GetFromClipboard

    Set objDoc = Application.Documents.Add
    objDoc.ActiveWindow.Visible = False

'Put clipboard contents into the new document object
    Documents(objDoc).Activate
    Selection.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False

'Read out paragraph number in that document    
    intNumPara = Documents(objDoc).Paragraphs.Count

'Close that document (without nasty questions)     
    Documents(objDoc).Close SaveChanges:=wdDoNotSaveChanges

'By some miracle we should now be back in Word's original target window... 
'Tests show that in practice this is the case. 

'Paste the Clipboard content into target document at current cursor position 
    Selection.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False

'Expand selection to cover all the paragraphs inserted    
    Selection.MoveUp Unit:=wdParagraph, Count:=intNumPara, Extend:=wdExtend

'Do somethign nice and useful with these paragraphs 
    Application.Run MacroName:="Normal.MyMacros.Do-someting-nice-and-useful"

End Sub

I feel, however, a bit disappointed that I have to swing such large and heavy mallet as creating an entire new document object in Word just to count those paragraphs. Creating a doc, switching over to it, pasting stuff there, counting paragraphs, closing the doc... that's a lot of operations for a very basic thing. Isn't there any more lightweight object available that could take the clipboard content and whose paragraph number I then could read out?

Perhaps I will try also the other method: count paragraph marks (carriage returns or so) in the string that can be retrieved from the MyData object...

0
votes

In order to count the paragraphs of content in the Clipboard, using the Word object model, it's first necessary to place that content in a Word document. The Clipboard is not part of Word and doesn't "understand" Word's syntax.

While this can be done use Selection and Activate it's more efficient and less "annoying" to work with the Word objects, instead. In this case, declare a Document object and set the document being added to it. Then it's possible to always use this object variable - no need to activate it, no need to use Documents(index) to address that document.

Also, I'd tend to put these steps in a separate procedure that returns the number of paragraphs. Generally, this makes code easier to read and to maintain.

For example:

Function InsertAndProcessMultipleParagraphs() As Long

'Declarations    
    Dim MyData As MSForms.DataObject
    Dim intNumPara As Integer
    Dim objDoc as Word.Document
    Dim rng as Word.Range

'Fill them objects
'?Probably not needed for this approach?
'    Set MyData = New MSForms.DataObject
'    MyData.GetFromClipboard

    Set objDoc = Application.Documents.Add
    objDoc.ActiveWindow.Visible = False

'Put clipboard contents into the new document object
   Set rng = objDoc.Content
   rng.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False

'Read out paragraph number in that document    
    intNumPara = objDoc.Paragraphs.Count

'Close that document (without nasty questions)     
    objDoc.Close SaveChanges:=wdDoNotSaveChanges   
    InsertAndProcessMultipleParagraphs = intNumPara
End Function

Sub MacroThatUsesTheInfo
   Dim intNumPara as Long

   intNumPara = InsertAndProcessMultipleParagraphs

'Paste the Clipboard content into target document at current cursor position 
    Selection.PasteSpecial Link:=False, DataType:=wdPasteText, Placement:=wdInLine, DisplayAsIcon:=False

'Expand selection to cover all the paragraphs inserted    
    Selection.MoveUp Unit:=wdParagraph, Count:=intNumPara, Extend:=wdExtend

'Do something nice and useful with these paragraphs 
    Application.Run MacroName:="Normal.MyMacros.Do-someting-nice-and-useful"

End Sub