Page 1 of 1

How to add ActiveX control with docx4j

PostPosted: Fri Nov 14, 2014 1:58 pm
by luomm
Hi there, I'm trying to use ActiveXControlXmlPart to add ActiveX control in docx, but it report an error when I opened this created documents, says can't open file because content is wrong in position /word/activeX/activeX1.xml. Can someone help me with this?
Here is my code:
Code: Select all
WordprocessingMLPackage wordPackage = WordprocessingMLPackage.createPackage();
MainDocumentPart part = wordPackage.getMainDocumentPart();

//[]word/activeX/activeX1.xml
         String proposedRelId = part.getRelationshipsPart().getNextId();
         ActiveXControlXmlPart activeXPart = new ActiveXControlXmlPart();
         activeXPart.setDocument(GetBinaryDataStream(embeddedControlPersistencePart1Data));
         Relationship relActiveX = part.addTargetPart(activeXPart,proposedRelId);

//[]word/activeX/activeX1.bin
//ActiveXControlBinaryPart  is extends ActiveXControlXmlPart , with PartName("/word/activeX/activeX1.bin"), ContentType with ContentTypes.OFFICEDOCUMENT_ACTIVEX_OBJECT,
//and RelationshipType is http://schemas.microsoft.com/office/2006/relationships/activeXControlBinary

         ActiveXControlBinaryPart activeXBinaryPart = new ActiveXControlBinaryPart();
         activeXBinaryPart.setDocument(GetBinaryDataStream(embeddedControlPersistencePart1Data));
         activeXPart.addTargetPart(activeXBinaryPart);

// The image to add
         File file = new File("c:\\1.gif" );
         
         //[]/word/media/iamge1.gif
         BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wordPackage, file);
         Relationship rel = part.addTargetPart(imagePart);
         
         org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
         //w:p
         org.docx4j.wml.P  p = factory.createP();
         //w:r
         org.docx4j.wml.R  run = factory.createR();      
         p.getContent().add(run);
         //w:rPr
         org.docx4j.wml.RPr rPr = factory.createRPr();
         run.getContent().add(rPr);
         org.docx4j.wml.BooleanDefaultTrue bdt = new org.docx4j.wml.BooleanDefaultTrue();
         rPr.setNoProof(bdt);
         //w:pict
         org.docx4j.wml.Pict pict = factory.createPict();
         run.getContent().add(pict);
         
         org.docx4j.vml.ObjectFactory factoryVml = new org.docx4j.vml.ObjectFactory();
         //v:shapetype
         org.docx4j.vml.CTShapetype shapetype = factoryVml.createCTShapetype();
         JAXBElement<org.docx4j.vml.CTShapetype> shapetypeWrapped = factoryVml.createShapetype(shapetype);
         pict.getAnyAndAny().add(shapetypeWrapped);
            shapetype.setCoordsize( "21600,21600");
              shapetype.setVmlId( "_x0000_t201");
              shapetype.setPath( "m,l,21600r21600,l21600,xe");
              //v:stroke
              CTStroke stroke = factoryVml.createCTStroke();
              JAXBElement<org.docx4j.vml.CTStroke> strokeWrapped = factoryVml.createStroke(stroke);
              shapetype.getEGShapeElements().add( strokeWrapped);
                 stroke.setJoinstyle(org.docx4j.vml.STStrokeJoinStyle.MITER);
              //v:path
              CTPath path = factoryVml.createCTPath();
              JAXBElement<org.docx4j.vml.CTPath> pathWrapped = factoryVml.createPath(path);
              shapetype.getEGShapeElements().add( pathWrapped);
                 path.setFillok(org.docx4j.vml.STTrueFalse.F);
                 path.setStrokeok(org.docx4j.vml.STTrueFalse.F);
                 path.setShadowok(org.docx4j.vml.STTrueFalse.F);
                 path.setConnecttype(org.docx4j.vml.officedrawing.STConnectType.RECT);
                 path.setExtrusionok(org.docx4j.vml.officedrawing.STTrueFalse.F);
              //o:lock
              org.docx4j.vml.officedrawing.ObjectFactory factoryOD = new org.docx4j.vml.officedrawing.ObjectFactory();
              org.docx4j.vml.officedrawing.CTLock lock = factoryOD.createCTLock();
              JAXBElement<org.docx4j.vml.officedrawing.CTLock> lockWrapped = factoryOD.createLock(lock);
              shapetype.getEGShapeElements().add(lockWrapped);
                 lock.setExt(org.docx4j.vml.STExt.EDIT);
                 lock.setShapetype(org.docx4j.vml.officedrawing.STTrueFalse.T);
         //v:shape
         org.docx4j.vml.CTShape shape = factoryVml.createCTShape();
         JAXBElement<org.docx4j.vml.CTShape> shapeWrapped = factoryVml.createShape(shape);
         pict.getAnyAndAny().add(shapeWrapped);
            shape.setVmlId("_x0000_s1027");
            shape.setStyle("position:absolute;left:0;text-align:left;margin-left:104.25pt;margin-top:170.7pt;width:133.5pt;height:133.5pt;z-index:251659264;mso-position-horizontal-relative:text;mso-position-vertical-relative:text");
            shape.setStroked(org.docx4j.vml.STTrueFalse.F);
            shape.setType("#_x0000_t201");
            //v:imagedata
            org.docx4j.vml.CTImageData imageData = factoryVml.createCTImageData();            
            JAXBElement<org.docx4j.vml.CTImageData> iamgedataWrapped = factoryVml.createImagedata(imageData);
            shape.getEGShapeElements().add(iamgedataWrapped);
               //r:id
               imageData.setId(rel.getId());
         //w:control
         org.docx4j.wml.CTControl control = factory.createCTControl();
            control.setName("1qaz");
            control.setShapeid("_x0000_s1027");
            control.setId(relActiveX.getId());
         pict.setControl(control);
         
         part.addObject(p);

//                     saveWordPackage(wordPackage, fileName);


The class of ActiveXControlBinaryPart:
Code: Select all
public class ActiveXControlBinaryPart extends ActiveXControlXmlPart{
   public final static String ACTIVEX_BINARY_OBJECT =
         "http://schemas.microsoft.com/office/2006/relationships/activeXControlBinary";
   /* you need
    *
            <rel:Relationships xmlns:rel="http://schemas.openxmlformats.org/package/2006/relationships">
                <rel:Relationship xmlns="" Id="rId1" Target="activeX1.bin" Type="http://schemas.microsoft.com/office/2006/relationships/activeXControlBinary"/>
            </rel:Relationships>
    * 
    */
   
   public ActiveXControlBinaryPart(PartName partName) throws InvalidFormatException {
      super(partName);
   }
   
   public ActiveXControlBinaryPart() throws InvalidFormatException {
      super(new PartName("/word/activeX/activeX1.bin"));
      // TODO
      init();
   }
   
   public void init() {
      
      // Used if this Part is added to [Content_Types].xml
      setContentType(new  org.docx4j.openpackaging.contenttype.ContentType(
            org.docx4j.openpackaging.contenttype.ContentTypes.OFFICEDOCUMENT_ACTIVEX_OBJECT));

      // Used when this Part is added to a rels
      setRelationshipType(ACTIVEX_BINARY_OBJECT);
   }
}


thanks a lot.

Re: How to add ActiveX control with docx4j

PostPosted: Fri Nov 14, 2014 7:04 pm
by jason
Your first step should be to compare the content you have created, with a similar docx which Word is happy with.

You'll need to unzip the files and look at them in an XML editor.

Re: How to add ActiveX control with docx4j

PostPosted: Tue Nov 18, 2014 8:54 pm
by luomm
yes, I compared the similar docx with my docx, they look the same except some font styles.
And I also found the error appeared when I add this codeļ¼š
Code: Select all
org.docx4j.wml.CTControl control = factory.createCTControl();
pict.setControl(control);//org.docx4j.wml.Pict pict = factory.createPict();
control.setName("1qaz");
control.setShapeid("_x0000_s1027");
control.setId(relActiveX.getId());

The code made the docx xml like:
Code: Select all
<w:pict>
               <v:shapetype id="_x0000_t201" coordsize="21600,21600" o:spt="201" path="m,l,21600r21600,l21600,xe">
                  <v:stroke joinstyle="miter"/>
                  <v:path shadowok="f" o:extrusionok="f" strokeok="f" fillok="f" o:connecttype="rect"/>
                  <o:lock v:ext="edit" shapetype="t"/>
               </v:shapetype>
               <v:shape id="_x0000_s1026" type="#_x0000_t201" style="position:absolute;left:0;text-align:left;margin-left:172.5pt;margin-top:86.5pt;width:133.5pt;height:133.5pt;z-index:251658240;mso-position-horizontal-relative:text;mso-position-vertical-relative:text" stroked="f">
                  <v:imagedata r:id="rId7" o:title=""/>
               </v:shape>
               <w:control r:id="rId8" w:name="1qaz" w:shapeid="_x0000_s1026"/>
            </w:pict>


so,where is the problem, I still didn't find it.

Re: How to add ActiveX control with docx4j

PostPosted: Tue Nov 18, 2014 9:22 pm
by jason
Do you have the correct parts at rId7 and rId8? In other words, are you setting those values from what addTargetPart returns?

Re: How to add ActiveX control with docx4j

PostPosted: Wed Nov 19, 2014 12:50 pm
by luomm
Yes, these two are returned from addTargetPart, rId7 is a can display images, and rId8 is an ActiveXControlXmlPart.