Page 1 of 1

How to add outlook message as a OLE object?

PostPosted: Fri Nov 26, 2010 12:38 am
by Indhu
Hi jason,

Is there possibility to add outlook message as a OLE object in the existing middle of the document? if it possible means could someone please share the code?

Thanks in Advance,

Indhu.

Re: How to add outlook message as a OLE object?

PostPosted: Fri Nov 26, 2010 8:26 am
by jason
Shouldn't be a problem.

Create a docx in Word, and add an outlook message to it.

Save it, and then run it through the docx4j PartsList sample.

That will tell you what you are trying to create.

I think it will contain an EmbeddedPackagePart, or possibly an OleObjectBinaryPart

It may also be instructive to unzip it, and have a look at its contents.

Then you use docx4j to create the same structure.

If you want further help, pls post the sample docx created above (you'll need to zip it up), and the code you've written, pointing out where you got stuck.

Re: How to add outlook message as a OLE object?

PostPosted: Mon Nov 29, 2010 5:00 pm
by Indhu
Hi jason,
As you have told the steps upto 4, i have created the document and inserted the outlook msg as a ole object and then i have also found that inserted object is a OleObjectBinaryPart.

After that i dono how to unzip it.

Here i have attached the document and the coding part. In that OLE template document ontains the existing document and outlook msg like that i want to insert that msg dynamically in the existing document.

Can you please explain me how to unzip and add the ole object.

Thanks in Advance,
Indhu.

Re: How to add outlook message as a OLE object?

PostPosted: Mon Nov 29, 2010 10:31 pm
by jason
To unzip a docx, change its extension from docx to zip, and use an unzip utility.

Here is a basic outline of what you need to do to add the outlook message.

1. create a OleObjectBinaryPart using its constructor

2 inject the outlook message into your OleObjectBinaryPart (it extends BinaryPart, which contains the methods you need). Injecting the outlook message in the correct format may be a challenge. See viewtopic.php?f=6&t=72 for generic embedding info; the web may well contain something more specific to outlook. Refer also to the relevant Microsoft OLE specs.

3 add the part to the main document part, using you main document part's AddTargetPart method. it will return the rel, which you need for the next step

4. the main document part of your sample contained:

Code: Select all
   <w:p>
      <w:r>
        <w:object w:dxaOrig="1454" w:dyaOrig="941">
          <v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
            <v:stroke joinstyle="miter"/>
            <v:formulas>
              <v:f eqn="if lineDrawn pixelLineWidth 0"/>
              <v:f eqn="sum @0 1 0"/>
              <v:f eqn="sum 0 0 @1"/>
              <v:f eqn="prod @2 1 2"/>
              <v:f eqn="prod @3 21600 pixelWidth"/>
              <v:f eqn="prod @3 21600 pixelHeight"/>
              <v:f eqn="sum @0 0 1"/>
              <v:f eqn="prod @6 1 2"/>
              <v:f eqn="prod @7 21600 pixelWidth"/>
              <v:f eqn="sum @8 21600 0"/>
              <v:f eqn="prod @7 21600 pixelHeight"/>
              <v:f eqn="sum @10 21600 0"/>
            </v:formulas>
            <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
            <o:lock v:ext="edit" aspectratio="t"/>
          </v:shapetype>
          <v:shape id="_x0000_i1025" type="#_x0000_t75" style="width:73.2pt;height:46.8pt" o:ole="">
            <v:imagedata r:id="rId4" o:title=""/>
          </v:shape>
          <o:OLEObject Type="Embed" ProgID="Package" ShapeID="_x0000_i1025" DrawAspect="Icon" ObjectID="_1352572164" r:id="rId5"/>
        </w:object>
      </w:r>
    </w:p>


The o:OLEObject contains a reference to the OleObjectBinaryPart; you need to set the rel id so it matches

The rest is the image the user sees on the document surface. It may be optional (you could try removing it and see what happens), but if you keep it, note that it refers to an image:
Code: Select all
<v:imagedata r:id="rId4" o:title=""/>


so you'd need that as well.

Re: How to add outlook message as a OLE object?

PostPosted: Fri Dec 10, 2010 6:07 pm
by Indhu
Hi Jason,

I have created the document and injected the outlook message as a OLE part. The code getting executed successfully. But i can't to open the document.

Here is my code which i have tried....



public class sampleOLE
{
public static JAXBContext context = org.docx4j.jaxb.Context.jc;

public static void main(String[] args) throws Exception
{
String inputfilepath = "Body.docx";
String outputfilepath = "test_OLE.docx";

// 1. Load the Package
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new java.io.File(inputfilepath));

// 2. object to embed
FileInputStream is = new FileInputStream(System.getProperty("user.dir") + "/Hi.msg");
OleObjectBinaryPart olePart = new OleObjectBinaryPart();
olePart.setBinaryData(is);
Relationship relOleObject = wordMLPackage.getMainDocumentPart().addTargetPart(olePart);

// 3. contains $OLEObjectRid
String ml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><w:document xmlns:ve=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\"><w:body><w:p w:rsidR=\"00AC03ED\" w:rsidRPr=\"005062F1\" w:rsidRDefault=\"00090669\" w:rsidP=\"005062F1\"><w:r><w:object w:dxaOrig=\"1540\" w:dyaOrig=\"996\"><v:shapetype id=\"_x0000_t75\" coordsize=\"21600,21600\" o:spt=\"75\" o:preferrelative=\"t\" path=\"m@4@5l@4@11@9@11@9@5xe\" filled=\"f\" stroked=\"f\"><v:stroke joinstyle=\"miter\"/><v:formulas><v:f eqn=\"if lineDrawn pixelLineWidth 0\"/><v:f eqn=\"sum @0 1 0\"/><v:f eqn=\"sum 0 0 @1\"/><v:f eqn=\"prod @2 1 2\"/><v:f eqn=\"prod @3 21600 pixelWidth\"/><v:f eqn=\"prod @3 21600 pixelHeight\"/><v:f eqn=\"sum @0 0 1\"/><v:f eqn=\"prod @6 1 2\"/><v:f eqn=\"prod @7 21600 pixelWidth\"/><v:f eqn=\"sum @8 21600 0\"/><v:f eqn=\"prod @7 21600 pixelHeight\"/><v:f eqn=\"sum @10 21600 0\"/></v:formulas><v:path o:extrusionok=\"f\" gradientshapeok=\"t\" o:connecttype=\"rect\"/><o:lock v:ext=\"edit\" aspectratio=\"t\"/></v:shapetype><v:shape id=\"_x0000_i1025\" type=\"#_x0000_t75\" style=\"width:77.25pt;height:49.5pt\" o:ole=\"\"><v:imagedata r:id=\"rId4\" o:title=\"\"/></v:shape><o:OLEObject Type=\"Embed\" ProgID=\"Package\" ShapeID=\"_x0000_i1025\" DrawAspect=\"Icon\" ObjectID=\"_1353394396\" r:id=\"${OLEObjectRid}\"/></w:object></w:r></w:p><w:sectPr w:rsidR=\"00AC03ED\" w:rsidRPr=\"005062F1\" w:rsidSect=\"00AC03ED\"><w:pgSz w:w=\"12240\" w:h=\"15840\"/><w:pgMar w:top=\"1440\" w:right=\"1440\" w:bottom=\"1440\" w:left=\"1440\" w:header=\"720\" w:footer=\"720\" w:gutter=\"0\"/><w:cols w:space=\"720\"/><w:docGrid w:linePitch=\"360\"/></w:sectPr></w:body></w:document>";

HashMap<String, String> mappings = new HashMap<String, String>();
// mappings.put("OLEObjectRid", relOleObject.getId());
mappings.put("ObjectID","_1353394396" );

wordMLPackage.getMainDocumentPart().addObject(org.docx4j.XmlUtils.unmarshallFromTemplate(ml, mappings ) );

ContentTypeManager ctm = wordMLPackage.getContentTypeManager();

ctm.addDefaultContentType("bin",org.docx4j.openpackaging.contenttype.ContentTypes.OFFICEDOCUMENT_OLE_OBJECT);

// 4. Save it
wordMLPackage.save(new java.io.File(outputfilepath));
System.out.println( "Saved output to:" + outputfilepath );
}
}

Could someone check this and give me a Suggestion where i did wrong.. Here am trying to replace the existing test.msg in a document to new Hi.msg. I have attached the code and message below.

Thanks in Advance,
Indhu.

Re: How to add outlook message as a OLE object?

PostPosted: Fri Dec 10, 2010 7:03 pm
by jason
I think you are probably going wrong at step 2:

Injecting the outlook message in the correct format may be a challenge. See viewtopic.php?f=6&t=72 for generic embedding info; the web may well contain something more specific to outlook. Refer also to the relevant Microsoft OLE specs.


You need to construct the correct format for what you are inserting.

Earlier in this thread, you said:

i have created the document and inserted the outlook msg as a ole object and then i have also found that inserted object is a OleObjectBinaryPart


You should have a look at the format of that object. OleObjectBinaryPart contains 2 methods to help you do this:
Code: Select all
   public void initPOIFSFileSystem() throws IOException
   public void viewFile(boolean verbose) throws IOException


Call initPOIFSFileSystem(); then viewFile(true);

Re: How to add outlook message as a OLE object?

PostPosted: Fri Jan 07, 2011 11:37 pm
by Indhu
Hi Jason,
Thanks for you help.
Now i'm able to,
1. create OleObject.bin
2. add imagePart
3. add OlePart

When i open the document, i can see the image. but when i double click on it, i am getting the following error:

The server application, source file, or item cannot be found.
Make sure the application is properly installed, and that it has not been deleted, moved, renamed, or blocked by policy.


I am attaching the source code and the document in zip format for your reference.

Pls comment where i went wrong?


Source Code:
Code: Select all
package creatingWordDoc;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;

import javax.xml.bind.JAXBContext;

import org.docx4j.XmlUtils;
import org.docx4j.model.datastorage.BindingHandler;
import org.docx4j.model.datastorage.CustomXmlDataStorage;
import org.docx4j.model.datastorage.OpenDoPEHandler;
import org.docx4j.openpackaging.io.SaveToZipFile;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.CustomXmlDataStoragePart;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.Body;
import org.docx4j.wml.Document;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.OleObjectBinaryPart;
import org.docx4j.openpackaging.parts.relationships.Namespaces;
import org.docx4j.relationships.*;
import org.docx4j.openpackaging.contenttype.*;

public class sampleOLE
{
   public static JAXBContext context = org.docx4j.jaxb.Context.jc;

   public static void main(String[] args) throws Exception
   {
      String outputfilepath = "E:/test_OLE.docx";   

      // 1. Load the Package
      WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
      MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
      wordMLPackage.getContentTypeManager().addDefaultContentType("bin", ContentTypes.OFFICEDOCUMENT_OLE_OBJECT);

      
      // 2. creating Image Part
      File file = new File("image1.emf" );
      java.io.InputStream is = new java.io.FileInputStream(file);
      long length = file.length();   
      // You cannot create an array using a long type.
      // It needs to be an int type.
      if (length > Integer.MAX_VALUE) {
         System.out.println("File too large!!");
      }
      byte[] bytes = new byte[(int)length];
      int offset = 0;
      int numRead = 0;
      while (offset < bytes.length
            && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
         offset += numRead;
      }
      // Ensure all the bytes have been read in
      if (offset < bytes.length) {
         System.out.println("Could not completely read file "+file.getName());
      }
      is.close();
      BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);      
      Relationship relImageObject = wordMLPackage.getMainDocumentPart().addTargetPart(imagePart);
      
      
      // 3. creating OLE part
      Part olePart = new OleObjectBinaryPart();
      FileInputStream oleFile = new FileInputStream("E:/Hi.msg");
      ((BinaryPart)olePart).setBinaryData(oleFile);
      ((OleObjectBinaryPart)olePart).initPOIFSFileSystem();
      ((OleObjectBinaryPart)olePart).writePOIFSFileSystem();
      ((OleObjectBinaryPart)olePart).viewFile(true);
      Relationship relOleObject = wordMLPackage.getMainDocumentPart().addTargetPart(olePart);
      

      // 3. contains $OLEObjectRid      
      String ml = "<w:p w:rsidR=\"001563A4\" w:rsidRDefault=\"007223E2\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\"><w:r><w:object w:dxaOrig=\"1543\" w:dyaOrig=\"993\"><v:shapetype id=\"_x0000_t75\" coordsize=\"21600,21600\" o:spt=\"75\" o:preferrelative=\"t\" path=\"m@4@5l@4@11@9@11@9@5xe\" filled=\"f\" stroked=\"f\"><v:stroke joinstyle=\"miter\"/><v:formulas><v:f eqn=\"if lineDrawn pixelLineWidth 0\"/><v:f eqn=\"sum @0 1 0\"/><v:f eqn=\"sum 0 0 @1\"/><v:f eqn=\"prod @2 1 2\"/><v:f eqn=\"prod @3 21600 pixelWidth\"/><v:f eqn=\"prod @3 21600 pixelHeight\"/><v:f eqn=\"sum @0 0 1\"/><v:f eqn=\"prod @6 1 2\"/><v:f eqn=\"prod @7 21600 pixelWidth\"/><v:f eqn=\"sum @8 21600 0\"/><v:f eqn=\"prod @7 21600 pixelHeight\"/><v:f eqn=\"sum @10 21600 0\"/></v:formulas><v:path o:extrusionok=\"f\" gradientshapeok=\"t\" o:connecttype=\"rect\"/><o:lock v:ext=\"edit\" aspectratio=\"t\"/></v:shapetype><v:shape id=\"_x0000_i1025\" type=\"#_x0000_t75\" style=\"width:77.25pt;height:49.5pt\" o:ole=\"\"><v:imagedata r:id=\"${ImageObjectRid}\" o:title=\"\"/></v:shape><o:OLEObject Type=\"Embed\" ProgID=\"Package\" ShapeID=\"_x0000_i1025\" DrawAspect=\"Icon\" ObjectID=\"_1355911853\" r:id=\"${OLEObjectRid}\"/></w:object></w:r></w:p>";
      HashMap<String, String> mappings = new HashMap<String, String>();    
      mappings.put("ImageObjectRid", relImageObject.getId());
      mappings.put("OLEObjectRid", relOleObject.getId());
      wordMLPackage.getMainDocumentPart().addObject(org.docx4j.XmlUtils.unmarshallFromTemplate(ml, mappings));

      
      // 4. Save it      
      wordMLPackage.save(new java.io.File(outputfilepath));
      System.out.println( "Saved output to:" + outputfilepath );
   }
}

Re: How to add outlook message as a OLE object?

PostPosted: Sat Jan 08, 2011 1:19 pm
by jason
Your code:
Code: Select all
// 3. creating OLE part
      Part olePart = new OleObjectBinaryPart();
      FileInputStream oleFile = new FileInputStream("E:/Hi.msg");
      ((BinaryPart)olePart).setBinaryData(oleFile);


does not look like it is doing anything to convert the msg file to an OLE object.

You need to work out how to do that.

Have a look (in a hex editor) at what Word does to a msg file when you embed it via Word. The thing you should be looking at in a hex editor is the resulting OLE part. It will only make sense if you also look at the various documents online which explain the OLE format.

Re: How to add outlook message as a OLE object?

PostPosted: Wed May 22, 2013 7:08 pm
by jason
Plutext now offers a commercial extension for docx4j/pptx4j/xlsx4j called docx4j OLE Helper, which makes it easy to embed an outlook message as an OLE object. Feel free to email sales@plutext.com for more info.