How can I insert and work with images?

I have a program running on a linux server that serves out barcodes for reports. I created a web service in c# that grabs the barcode graphic from the server and returns a base64-encoded string of the barcode image the server creates.

I want to insert this graphic in the upper-right hand corner of the word document and I'm thinking the header is a good place for it, but I'd also like to consider positioning a floating image as well. I've been doing some reading and playing around; By using a bookmark, I've gotten the grahic inserted in the header (the barcode graphic, once inserted should appear in the same place on all pages of the doc, btw).

My questions are:

I want to access the same functionality in the word document as if I were inserting a picture from file using the menu options in Word; how can I control the text wrapping and position of the image

If the image needs to be replaced, how can I select it to delete it and replace it I am currently using the clipboard paste funtionality to insert the image at the bookmark. I see that there is also a method to insert it inline within the bookmark if it's coming from file, but how could I get this from a memorystream instead of a file path Also, how might I do this using an image at a url instead of a file path

Any help is appreciated - even if you can only answer part of this.



Answer this question

How can I insert and work with images?

  • RogMauri

    Hello Ryan,

    wrt insertion and deletion/replacing of the image, you can use the bookmarking concept. Set a bookmark at the desired location and use it to insert your image. If you have to delete/replace it, you can use the same bookmark to identify the image. Unfortunately, there is no way that we can identify an image with some property of it (like ID). We had a similar requirement where we had to insert an image at the end of the document (lil' easier than yours wrt location of the image ) and initially we had tried to use an invisible table as a placeholder and used table.ID to identify it. But that didnt work coz table.ID becomes null when we close the document.

    Hope this helps you in some way

    Regards,
    Pavan

    PS: Pls keep us posted on the solutions that you implement, so that it'll be a learning for us.


  • RAGOpoR

    Hi Ryan

    I sympathize. Graphics aren't Word's strong point; it started life as pure word-processing and that core code...

    If the suggestion at the end doesn't help, if you don't mind, could you re-summarize the exact requirements re position, size, etc I'm going to go into Word-MVP mode, here, and I need all the "params" to work out exactly which settings you're going to need - it's a complicated business.

    Word can position Shapes relative to the text, or to the page. Positioning is in POINTS. The OM will let you convert inches, picas, centimeters, etc. to points with a number of built-in functions, for example: (Word.CentimetersToPoint(singleValueInCentimeters))

    I had a thought during the night about the approach you want to take, using the .NET control, so that you can stream the data in. I can't test the streaming part, but... If I start out with a control that already has a picture, and in the Word document I copy that, then use Edit/Paste Special and paste in picture format (metafile), I get a static graphics object. It's tricky, but it appears to work.

    1. In order to freely position the graphic, but work with an InlineShape, I put the control into a FRAME. The Insert/Frame command is, by default, only available on Word's FORMS toolbar, which the Designer doesn't give access to. So you first need to close the solution, open Word, display the Forms toolbar, hold down ALT and drag the Insert Frame button to (for example) the Insert menu. Close Word and save changes to Normal.dot if you're prompted to do so.

    2. Use this command to draw a frame on your document where you want the control. Type two spaces so that you can later access the Format Frame command in case you need it. (If only a graphical object is in a frame, you can't access the frame.)

    3. Position the cursor between these two spaces, then insert your picture control

    4. Here's the code I figured out (took me a couple of hours) that will
    - copy the control to the clipboard
    - position the cursor at the end of the document (this could be any empty paragraph in your document). I move the selection because it may NOT be in a Windows Form control when you try to paste; Word throws an exception if the selection is in a control.
    - paste-special in a picture format (WMF, others might work, you need to test)
    - remove the control (you can't use CUT because the clipboard doesn't retain the picture information; it must be copy then delete)
    - duplicate the picture range into the frame
    - remove the pasted picture, so that only the one in the frame remains

    private void StaticPic()
    {
    try
    {
    object objWMF = Word.WdPasteDataType.wdPasteMetafilePicture;
    object objInline = Word.WdOLEPlacement.wdInLine;
    object objEndKey = Word.WdUnits.wdStory;
    Word.Application wdApp = this.InnerObject.Application;
    wdApp.Selection.EndKey(ref objEndKey, ref missing);
    Word.Range rngTarget = wdApp.Selection.Range;
    Word.Range rng = this.InnerObject.Frames[1].Range.InlineShapes[1].Range;
    rng.Copy();
    rngTarget.PasteSpecial(ref missing, ref missing, ref objInline, ref missing, ref objWMF, ref missing, ref missing);
    Word.Range rngPic = rngTarget.Paragraphs[1].Range.InlineShapes[1].Range;
    rng.Delete(ref missing, ref missing);
    this.InnerObject.Frames[1].Range.FormattedText = rngPic.FormattedText;
    rngPic.Text = "";
    }
    catch (Exception ex)
    { MessageBox.Show(ex.Message); }

    }



  • kbiesbrock

    You rock, Cindy.  Thanks... I'll try fiddling with that code.  I'm on my way out now, but I was up very late working on this last night and I got it to work well using the URL (so I don't need to use a stream).  The placement is not exactly where I want it yet and I had to experiment to see how to get it in the header correctly.  I'll post the code I came up with next time I get a chance to sit down, but I basically inserted the barcode as an InlineShape in the header and converted it to a Shape so that it is a floating picture within the header.

    Actually, now that I think about it , I don't think I've been successful converting it yet. I have to move the picture which is about 2in x 0.75in to the correct position in the upper right hand corner and so that there is a little bit of a margin around it - maybe 20 pixels or so. Then I should be done.  I'll still play with what you figured out - it may be a better solution once I understand it well.


  • S.Malathi

    Ryan, it works here, for me. Here's the line of code I use

    this.InnerObject.Shapes.AddPicture(filePath, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);



  • I Mrus

    Well, now I am trying to save the image to a temp file and insert it into the document. I'm trying to use AddPicture() from the Shape interface; however, it seems that the method is "not intended to be used directly from your code" ...so I'm not sure how Microsoft proposes that we work with Images in Word. I'm having trouble finding the documentation for this. One would think that since this is an interface that supports the framework that somewhere in the framework there is a method that uses it to add a picture to the document. Just haven't found that yet. I think I'll try to send an email to the team about this and see what they say. I'll post whatever I find.


  • DPalacino

    Hi Ryan

    Word supports two kinds of graphics: InlineShapes and Shapes. The former are by far the more stable, but don't support text wrap formatting. You can, however, insert them in a FRAME (Insert Frame command on the Forms toolbar, in the UI) in order to achieve text wrap. A frame can be bookmarked (see pavan's reply) in order to identify it.

    Shapes can be freely positioned on the page; unfortunately, they can contribute to destabilization of a file. OTOH, you can assign them a NAME property in order to pick them up again easily.

    Assuming you want to use a Shape, then assign the graphic to an object variable as you insert it. Then apply the required formatting to that. In VB-speak:

    Dim shp as Word.Shape

    Set shp = doc.Shapes.AddPicture('Params here)
    shp.Left = 'single value
    shp.Top = 'single value
    'also look at the RelativeHoriztonalPosition and RelativeVerticalPositionProperties

    It's not possible to stream an image into Word, unless you pass it in using the InsertXML method, in valid WordProcessingML. But the AddPicture methods of both the InlineShapes and Shapes collections should accept a URL.



  • Denis Mathews

    Ugh. OK... so I tried the way you were suggesting, but I can't seem to get the graphic positioned where I want it in the top right hand corner so far because it is unclear what the units are and what the width of the document is. Are the values relative or absolute ....So anway, I placed an example of the picture where I want it in the document at design time. Then I was hoping to be able to grab a reference to it at run time, but I'm having a tough time doing that; its not letting me do anything like:

    Word.Shape myPic = doc.Shapes[0];

    so that I can see its properties, and I can't find it in the locals while debugging either... and I thought this was all gonna be so simple - ha! ...sigh.


  • Ben_Pittoors

    ah, the Framework as opposed to Word approach :-) Cool.

    I just did some "fiddling" with Windows form controls, generally, and I notice they can be copied/pasted within Word. Could you, perhaps, insert one at design time (in a frame, I'd think)

    If you need to propagate it (rather than using the header range): Bookmark it. Then where ever you need to display it, insert a REF field that references the bookmark.

    Note that this isn't something I've ever tried (and I haven't time at the moment, or I would), but based on "Word-logic" it ought to work.



  • khushboo Sharan

    Thanks Cindy, I'll try what you suggest and post how it turns out. What I just tried didn't work - since the control is apparently not saved with the document (and I was all excited about being able to use a stream at first) <sigh>:

    Byte[] _barcodeImageBytes;
    ...
    public void InsertBarcode()
    {
    string imageFileName = string.Empty;
    using (BarCodePrompt barcodePrompt = new BarCodePrompt())
    {
    if (barcodePrompt.ShowDialog() == DialogResult.OK)
    {

    barcodeImageService.Service barcodeService = new WordObjectModelCS.barcodeImageService.Service();
    _barcodeImageBytes = Convert.FromBase64String(barcodeService.getBarcode(Int32.Parse(barcodePrompt.ServiceEventId)));

    using (MemoryStream ms = new MemoryStream(_barcodeImageBytes))
    {
    PictureBox pb = this.Controls.AddPictureBox(0, 0, 10, 10, "barcode");
    pb.Image = Image.FromStream((Stream
    )ms);
    pb.Width = pb.Image.Width;
    pb.Height = pb.Image.Height;
    }
    }}}


  • Henrik Goldman

    FWIW, you should be able to insert the graphic directly into the header as a Shape (no need to go the other route and convert). The key is to have the correct Range object...

    Word.Range rng = doc.Sections[1].Headers.[Microsoft.Office.Interop.Word.WdHeaderFooterIndex.wdHeaderFooterPrimary].Range

    Then, if you want to position it at the top/right margin, you can position it relative to the margin (or page):

    Word.Shape shp = doc.Shapes.AddPicture("filename", missing, missing, missing, missing, missing, missing, rng);

    shp.RelativeHorizontalPosition = Word.WdRelativeHorizontalPosition.wdRelativeHorizontalPositionMargin
    shp.Left = Word.WdShapePosition.wdShapeRight;
    shp.RelativeVerticalPosition = Word.WdRelativeVerticalPosition.wdRelativeVerticalPositionMargin;
    shp.Top = Word.WdShapePosition.wdShapeTop;



  • How can I insert and work with images?