PDA

View Full Version : Solved: Change all shapes in doc to 'inline with text'



MacroShadow
10-17-2012, 05:43 AM
Hello all Experts,

I'm trying to change all shapes in a document to 'inline with text' using the following procedure:


Sub SetPictureLayout()

Dim i As Long

'convert inlineshape picture objects to shape objects
For i = 1 To ActiveDocument.InlineShapes.Count
If ActiveDocument.InlineShapes(1).Type = wdInlineShapePicture Or _
ActiveDocument.InlineShapes(1).Type = wdInlineShapeLinkedPicture Then
ActiveDocument.InlineShapes(1).Select
Selection.InlineShapes(1).ConvertToShape
End If
Next

'modify layout of all image shape object
For i = 1 To ActiveDocument.Shapes.Count
ActiveDocument.Shapes(i).Select
If Selection.ShapeRange.Type = msoPicture Or Selection.ShapeRange.Type = msoLinkedPicture Then
Selection.ShapeRange.Left = wdShapeCenter
Selection.ShapeRange.WrapFormat.Type = wdWrapInline
Debug.Print Selection.ShapeRange.WrapFormat.Type
End If
Next i

End Sub


The weird thing is it won't change the WrapFormat.Type to wdWrapInline, instead it changes it to wdWrapNone.

Any ideas what I may be doing wrong?

Frosty
10-17-2012, 01:09 PM
When I try to do what you're doing simply using the immediate window, I get an error. So I don't think the error is in your code, the error is in your concept.

If you change the .WrapFormat.Type of a .Shape to wdWrapInline -- it disappears from the Shapes/ShapeRange collection and becomes a member of the InlineShapes collection.

I think you're going to need to articulate this pretty differently, because doing a For loop based on the .Count when you're removing things from the collection who's .Count property you're referencing is going to cause an issue. You'll probably need to do For i = ActiveDocument.Shapes.Count to 1 Step -1

From there, rather than doing Selection.ShapeRange.Type ... you probably need to do Selection.ShapeRange(1).Type

And then change your Debug.Print line to be something which refers to the InlineShape (Selection.InlineShapes(1) etc)

But, of course, you don't need to check .WrapFormat because a) it doesn't exist and b) you'd know it already.

However, this is just limited testing on some generic picture shapes... without some representative samples of your actual graphics, this may or may not get you the info you need.

But your entire structure is confusing... because you're trying to go through all inline shapes, convert them to a shape, then go through all shapes, then convert them to inline shapes... why are you doing this? Once it is inline, what does the .Left property matter? It's Inline-- if you want it centered, you should apply paragraph formatting of center alignment if you're trying to center it on the page. The .Left property is only applicable to floating shapes...

If that's not what you're trying to do, you may need to do a mock-up document of what you want on the before/after.

MacroShadow
10-17-2012, 10:21 PM
Where do you get the error? I only used the procedure from the immediate window and the code doesn't err out.

btw, this seems to do what I want. You were right my concept was wrong, all I had to do was convert the pictures to InlineShapes.


Sub ConvertToInline()
Dim i As Integer
For i = ActiveDocument.Shapes.Count To 1 Step -1
Select Case ActiveDocument.Shapes(i).Type
Case msoEmbeddedOLEObject, msoLinkedOLEObject, msoLinkedPicture, msoOLEControlObject, msoPicture, wdInlineShapePicture, wdInlineShapeLinkedPicture
ActiveDocument.Shapes(i).ConvertToInlineShape
End Select
Next i
End Sub

fumei
10-18-2012, 01:21 PM
If you are actioning ALL of the items, why not just do a For Each?

Frosty
10-18-2012, 01:24 PM
Because the for each will breakdown since he's changing the actual number of shapes in the collection when he converts a shape to an inline shape, I think, which requires going through it in reverse order.

There's no way to iterate through a for each backwards, is there?

MacroShadow
10-18-2012, 01:26 PM
Frosty, Couldn't have explained it better myself.

Frosty
10-18-2012, 01:38 PM
MacroShadow-- I got the error when in the immediate window simply by inserting a picture natively, selecting it... and then trying to refer to it. Basically, with a shape selected...
Selection.ShapeRange.Count = 1 as long as the picture is a floating shape. If you convert it to an inline shape, the Selection.ShapeRange.Count = 0 (although the Selection.InlineShapes.Count = 1).

That's why I'd get an error... because you can't try to do something which doesn't exist in the collection you're trying to refer to.

I think your latest code is exactly the right way to handle converting all floating shapes in the main document story to inline shapes. Obviously it wouldn't handle any shapes anchored to the headers/footers or other story ranges, but I'm assuming that's okay.

macropod
10-18-2012, 01:55 PM
Because the for each will breakdown since he's changing the actual number of shapes in the collection when he converts a shape to an inline shape, I think, which requires going through it in reverse order.

There's no way to iterate through a for each backwards, is there?
You could be sneaky:
Sub ConvertToInline()
With ActiveDocument
While .Shapes.Count > 0
.Shapes(1).ConvertToInlineShape
Wend
End With
End Sub

fumei
10-18-2012, 03:07 PM
Frosty: "Because the for each will breakdown since he's changing the actual number of shapes in the collection when he converts a shape to an inline shape"

For Each does not use the number in the collection; that is the point of a For Each - you not use (or need) an index number.


Ummmm, from Help:

Example
This example converts each picture in MyDoc.doc to an inline shape.

For Each s In Documents("MyDoc.doc").Shapes
If s.Type = msoPicture Then
s.ConvertToInlineShape
End If
Next s

macropod
10-18-2012, 03:26 PM
Hi Gerry,

The MS Help example is all very well, but it doesn't work!!!

Frosty
10-18-2012, 03:33 PM
Hehe, that's what I was going to say. I guess MS uses the term "help" loosely. I've always had trouble using a for each loop to delete an object from the collection, which is what the convert function is essentially doing.

fumei
10-18-2012, 05:02 PM
Really. I must admit I had not actually tried it. My bad. Oh well, it would not be the first time MS Help was wonky.

fumei
10-18-2012, 05:13 PM
OK, I just tried it...and, wait for it...it worked. I made a document with three InlineShapes (photos)
Dim oInline As InlineShape
Dim oShape As Shape
Debug.Print ActiveDocument.Shapes.Count ' returns 0
Debug.Print ActiveDocument.InlineShapes.Count 'returns 3

For Each oInline In ActiveDocument.InlineShapes
oInline.ConvertToShape
Next
Debug.Print ActiveDocument.Shapes.Count 'returns 3
Debug.Print ActiveDocument.InlineShapes.Count 'returns 0

For Each oShape In ActiveDocument.Shapes
oShape.ConvertToInlineShape
Next
Debug.Print ActiveDocument.Shapes.Count ' returns 0
Debug.Print ActiveDocument.InlineShapes.Count 'returns 3

It worked.

macropod
10-18-2012, 11:59 PM
When I inserted 6 shapes into a document and ran this:
Sub test()
Dim s As Shape
For Each s In ActiveDocument.Shapes
s.ConvertToInlineShape
Next s
MsgBox ActiveDocument.Shapes.Count
End Sub
the msgbox returned 3. Go figure.

Frosty
10-19-2012, 05:39 AM
I think you're both probably describing inconsistencies between word versions. Shapes have different warts depending on the version of word. I think word 2007/2010 has much different bugs regarding shapes than earlier versions.

I didn't try either code, but in the past (ms help specific examples notwithstanding), I have avoided for each loops (which I love) when trying to add or remove items from the collection. It always seems inconsistent to me (depending on the collection, and what I'm doing with it).

I'm fascinated that it works in Gerry's code, but I'm guessing that's because it's Word 2002 or 2003 (I forget which version is your standard, Gerry)