0
votes

Problem:-

During a recent rebranding exercise at work, all the word documents (saved as RTF files))

I have word documents that are 2, 3 or even 4MB in size.

Looking at the pictures in the documents I noticed that some are scaled down to 48%, 70%, 88%, whatever. If I cut the image out of the document, paste it into Paint.NET, resize it, paste it back into the document and position it as per the original, I can get the size of the documents down to less than 1/10th of the manually fudged one.

I want to programmatically process 1150 Word documents and find pictures in there that are scaled. I then want to pull the pictures out, resize them, and then put them back in replacing the manually added pictures. Saving disk space.

I am having difficulty navigating the Word Object model and finding pictures programmatically.

This web page on MSDN says you can add them, like this

this.Application.Selection.InlineShapes.AddPicture(@"C:\SamplePicture.jpg");

so I thought using the InlineShapes collection might give me access to the collection of pictures in the document.

I have interop declared.

using Microsoft.Office.Interop.Word;
using Microsoft.Office.Interop;
using Microsoft.Office;

and I open the Word application, and document like this (this works)

private void OpenWordApplication()
{
    _WordApp = new Microsoft.Office.Interop.Word.Application();
    if (chkVisibleWord.CheckState == CheckState.Checked) {
        _WordApp.Visible = true;
    }
    else
    {
        _WordApp.Visible = false;
    }

}

private void OpenTheDocument(string DocumentPath)
{
    _WordDoc = _WordApp.Documents.Open(DocumentPath);
    changesMade = false;
}

When I try to find eh Pictures in the InlineShapes, I can't seem to get hold of them.

_WordApp.Selection.HomeKey(WdUnits.wdStory);

int picCount = _WordApp.ActiveDocument.InlineShapes.Count;
MessageBox.Show(string.Format("There are {0} images in this document", picCount));

I get a message box saying the count is zero.

NOTE: The application opens the documents in Word just fine. It does other things to the documents depending on what checkboxes I have checked on the form, the issue to me seems to be right down at accessing the InlineShapes collection.

Any pointers. I appreciate your attention so far?

Thanks in advance

3
You say that your code snippet doesn't give you what you want. What is it giving you and how is it different from what you want? The Selectionstatements have no bearing on getting a count (the Inline Shapes Collection does not need to have the active document's text selected). If your Using statements and the code establishing _WordApp are correct, you should get an accurate count. Please post additional code including Using statements. - joeschwa
@joeschwa I am getting a count of zero in a document where I know that there is an image. I will amend my question and include a wider scope of the code. - cometbill
SHapes are not necessarily InlineShapes. InlineShapes. There may also be a Shapes collection in each StoryRange (sorry, no time to say more than that right now). - user1379931
@bibadia makes an excellent point. The InlineShapes collection only contains pictures that are placed within the text layer of a document. The Shapes collection contains pictures located everywhere else in the document (headers, footers, pictures floating in front of text, pictures that text wraps around, etc.) Does int picCount = _WordApp.ActiveDocument.Shapes.Count; return the correct number of images in the document? - joeschwa
@bibadia and joeschwa, you both make valid points, and at some point I may dip back into the app to see if this knowledge progresses my app closer to my original goal. Who knows, it might help me next time I have a need to process large numbers of documents. - cometbill

3 Answers

0
votes

The solution we did in the end was to get a tester, who was competent with Microsoft Word, a piece of paper, a pencil and the Paint.Net application.

The tester used the pencil and paper to mark down the dimensions and position of the image, and Paint.Net to resize the image.

I know it wasn't processing the documents / images programmatically, as I first intended, but we had a deadline to get the process completed, and sometimes as a developer you have to make a call when you think that doing things manually is the correct thing to do.

0
votes

Try:

foreach (Microsoft.Office.Interop.Word.Shape s in wordApp.ActiveDocument.Shapes)
{
        ...
}
0
votes

This code will find all the inline pictures in a document. These are indeed inline shapes. So not sure what the issue with the OP's code is.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Office.Interop.Word;

namespace OfficeBench
{
    class Program
    {
        static void Main(string[] args)
        {
            Application app = new Application();
            Document doc = app.Documents.Open(@"c:\scratch\so\4pictures.docx");
            if (doc != null)
            {
                Console.WriteLine($"Number in in-line shapes = {doc.InlineShapes.Count}");
                foreach (InlineShape shape in doc.InlineShapes)
                {
                    Console.WriteLine($"Shape (width,height) = ({shape.Width},{shape.Height})");
                    Console.WriteLine($"Shape type = {shape.Type}");
                    Console.WriteLine();
                    if (shape.Type == WdInlineShapeType.wdInlineShapePicture)
                    {
                        // ...
                    }
                }
                doc.Close();
            }
            else
            {
                Console.WriteLine("Error - Unable to open document.");
            }
        }
    }
}

This produces the output...

Number in in-line shapes = 4
Shape (width,height) = (293.25,164.75)
Shape type = wdInlineShapePicture

Shape (width,height) = (412.5,231.75)
Shape type = wdInlineShapePicture

Shape (width,height) = (226.9,127.5)
Shape type = wdInlineShapePicture

Shape (width,height) = (222.75,125.1)
Shape type = wdInlineShapePicture