For not-too-interested readers: Use the third code snippet.
It’s time for a new post on VBA! Somebody at work is creating a whole lot of training material in Word. Great. Fast forward a couple months, and all of a sudden it’s my job to fix these up. They have all kinds of formatting inconsistencies, and many of the screenshots were resized without preserving their aspect ratios.
I thought, great, I’ll just write some VBA that fixes the screenshots. I quickly came up with something like the following:
Sub resize_all_images_to_page_width() For Each inline_shape In ThisDocument.InlineShapes inline_shape.LockAspectRatio = msoFalse inline_shape.ScaleWidth = 100 inline_shape.ScaleHeight = 100 percent = doc.PageSetup.TextColumns.Width / inline_shape.Width inline_shape.ScaleWidth = percent * 100 inline_shape.ScaleHeight = percent * 100 Next End Sub
This would in theory scale every image to fit to the page’s width.
And it worked. For almost all of the images. For some, it did something incomprehensible (Word 2010) and turned images into a very long and extremely thin strip of pixels. I tried various things (including .Reset) and did some googling, but couldn’t find a better way to fix the images. What I really wanted was to find out an image’s original width and height, just the way it’s displayed in the Format Picture dialog in the Size tab, but there’s no way to access those values.
So to get an image’s original size, I decided to create a new temporary document, copy and paste the image there, set the .ScaleWidth and .ScaleHeight options to 100, and then look at its .Width and .Height properties. Yay, there we go!
I also decided I don’t want to scale images beyond 100% and added some extra logic to handle that. Here’s the result:
Sub resize_all_images_up_to_page_width() Set current_doc = ThisDocument Set new_doc = Documents.Add(DocumentType:=wdNewBlankDocument) current_doc.Activate For Each ishape In current_doc.InlineShapes ' ishape.Copy ' doesn't work ishape.Select ' <work-around> Selection.Copy ' </work-around> new_doc.Content.PasteAndFormat (wdPasteDefault) Set new_ishape = new_doc.InlineShapes(1) new_ishape.LockAspectRatio = msoFalse new_ishape.ScaleWidth = 100 new_ishape.ScaleHeight = 100 ishape.LockAspectRatio = msoFalse If (new_ishape.Width > current_doc.PageSetup.TextColumns.Width) Then ishape.Width = current_doc.PageSetup.TextColumns.Width ishape.Height = (current_doc.PageSetup.TextColumns.Width / new_ishape.Width) * new_ishape.Height Else ishape.Width = new_ishape.Width ishape.Height = new_ishape.Height End If new_ishape.Delete ishape.LockAspectRatio = msoTrue Next End Sub
And finally, we’d like to make sure images don’t get longer than the length of a page:
Sub resize_all_images_up_to_page_width() Set current_doc = ThisDocument Set new_doc = Documents.Add(DocumentType:=wdNewBlankDocument) page_width = current_doc.PageSetup.TextColumns.Width page_height = current_doc.PageSetup.PageHeight - current_doc.PageSetup.TopMargin - current_doc.PageSetup.BottomMargin current_doc.Activate For Each ishape In current_doc.InlineShapes ' ishape.Copy ' doesn't work ishape.Select ' <work-around> Selection.Copy ' </work-around> new_doc.Content.PasteAndFormat (wdPasteDefault) Set new_ishape = new_doc.InlineShapes(1) new_ishape.LockAspectRatio = msoFalse new_ishape.ScaleWidth = 100 new_ishape.ScaleHeight = 100 ishape.LockAspectRatio = msoFalse If (new_ishape.Width > page_width) Then If ((page_width / new_ishape.Width) * new_ishape.Height > page_height) Then ishape.Width = page_height / new_ishape.Height * page_width ishape.Height = page_height Else ishape.Width = page_width ishape.Height = (page_width / new_ishape.Width) * new_ishape.Height End If ElseIf (new_ishape.Height > page_height) Then ' going to be shrinking both height and width, and width is okay already, so it'll be even okayer ishape.Width = page_height / new_ishape.Height * new_ishape.Width ishape.Height = page_height Else ishape.Width = new_ishape.Width ishape.Height = new_ishape.Height End If new_ishape.Delete ishape.LockAspectRatio = msoTrue Next End Sub
Hope this helps! If you have any questions, feel free to leave a comment.
Nice, thanks!
You’re an angel! Right now I am working on a similar matter: A lot of people creating documents with screenshots and giving a *** about proper picture sizing or keeping the page margins empty.
The only thing missing in my code is “I don’t want to blow pictures up beyond 100% of their original size”. It looks very much like I can use your thoughts for this.
Right at the moment I am working with an absolut value in cm to define the max width. Such a good idea to work with the more flexible current_doc.PageSetup.TextColumns.Width. I’ll steal this idea as well and improve my code with it.
Thank you!
This is awesome! Thanks I have been stumped for hours on this issue and these work like magic!