Change the fill color of a shape in a presentation

This topic shows how to use the classes in the Open XML SDK to change the fill color of a shape on the first slide in a presentation programmatically.

Getting a Presentation Object

In the Open XML SDK, the PresentationDocument class represents a presentation document package. To work with a presentation document, first create an instance of the PresentationDocument class, and then work with that instance. To create the class instance from the document call the Open method that uses a file path, and a Boolean value as the second parameter to specify whether a document is editable. To open a document for read/write, specify the value true for this parameter as shown in the following using statement. In this code, the file parameter is a string that represents the path for the file from which you want to open the document.

    using (PresentationDocument ppt = PresentationDocument.Open(docName, true))
    {
        // Insert other code here.
    }

The using statement provides a recommended alternative to the typical .Open, .Save, .Close sequence. It ensures that the Dispose method (internal method used by the Open XML SDK to clean up resources) is automatically called when the closing brace is reached. The block that follows the using statement establishes a scope for the object that is created or named in the using statement, in this case ppt.

The Structure of the Shape Tree

The basic document structure of a PresentationML document consists of a number of parts, among which is the Shape Tree (sp Tree) element.

The following text from the ISO/IEC 29500 specification introduces the overall form of a PresentationML package.

This element specifies all shapes within a slide. Contained within here are all the shapes, either grouped or not, that can be referenced on a given slide. As most objects within a slide are shapes, this represents the majority of content within a slide. Text and effects are attached to shapes that are contained within the spTree** element.

[Example: Consider the following PresentationML** slide

    <p:sld>
      <p:cSld>
        <p:spTree>
          <p:nvGrpSpPr>
          ..
          </p:nvGrpSpPr>
          <p:grpSpPr>
          ..
          </p:grpSpPr>
          <p:sp>
          ..
          </p:sp>
        </p:spTree>
      </p:cSld>
      ..
    </p:sld>

In the above example the shape tree specifies all the shape properties for this slide. end example]

© ISO/IEC29500: 2008.

The following table lists the child elements of the Shape Tree along with the description of each.

Element Description
cxnSp Connection Shape
extLst Extension List with Modification Flag
graphicFrame Graphic Frame
grpSp Group Shape
grpSpPr Group Shape Properties
nvGrpSpPr Non-Visual Properties for a Group Shape
pic Picture
sp Shape

The following XML Schema fragment defines the contents of this element.

    <complexType name="CT_GroupShape">
       <sequence>
           <element name="nvGrpSpPr" type="CT_GroupShapeNonVisual" minOccurs="1" maxOccurs="1"/>
           <element name="grpSpPr" type="a:CT_GroupShapeProperties" minOccurs="1" maxOccurs="1"/>
           <choice minOccurs="0" maxOccurs="unbounded">
              <element name="sp" type="CT_Shape"/>
              <element name="grpSp" type="CT_GroupShape"/>
              <element name="graphicFrame" type="CT_GraphicalObjectFrame"/>
              <element name="cxnSp" type="CT_Connector"/>
              <element name="pic" type="CT_Picture"/>
           </choice>
           <element name="extLst" type="CT_ExtensionListModify" minOccurs="0" maxOccurs="1"/>
       </sequence>
    </complexType>

How the Sample Code Works

After opening the presentation file for read/write access in the using statement, the code gets the presentation part from the presentation document. Then it gets the relationship ID of the first slide, and gets the slide part from the relationship ID.

Note

The test file must have a filled shape as the first shape on the first slide.

    using (PresentationDocument ppt = PresentationDocument.Open(docName, true))
    {
        // Get the relationship ID of the first slide.
        PresentationPart part = ppt.PresentationPart;
        OpenXmlElementList slideIds = part.Presentation.SlideIdList.ChildElements;
        string relId = (slideIds[0] as SlideId).RelationshipId;

        // Get the slide part from the relationship ID.
        SlidePart slide = (SlidePart)part.GetPartById(relId);

The code then gets the shape tree that contains the shape whose fill color is to be changed, and gets the first shape in the shape tree. It then gets the style of the shape and the fill reference of the style, and assigns a new fill color to the shape. Finally it saves the modified presentation.

    if (slide != null)
    {
        // Get the shape tree that contains the shape to change.
        ShapeTree tree = slide.Slide.CommonSlideData.ShapeTree;

        // Get the first shape in the shape tree.
        Shape shape = tree.GetFirstChild<Shape>();

        if (shape != null)
        {
            // Get the style of the shape.
            ShapeStyle style = shape.ShapeStyle;

            // Get the fill reference.
            Drawing.FillReference fillRef = style.FillReference;

            // Set the fill color to SchemeColor Accent 6;
            fillRef.SchemeColor = new Drawing.SchemeColor();
            fillRef.SchemeColor.Val = Drawing.SchemeColorValues.Accent6;

            // Save the modified slide.
            slide.Slide.Save();
        }
    }

Sample Code

Following is the complete sample code that you can use to change the fill color of a shape in a presentation. In your program, you can invoke the method SetPPTShapeColor to change the fill color in the file "Myppt3.pptx" by using the following call.

    string docName = @"C:\Users\Public\Documents\Myppt3.pptx";
    SetPPTShapeColor(docName);

After running the program, examine the file "Myppt3.pptx" to see the change in the fill color.

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using Drawing = DocumentFormat.OpenXml.Drawing;

SetPPTShapeColor(args[0]);

// Change the fill color of a shape.
// The test file must have a filled shape as the first shape on the first slide.
static void SetPPTShapeColor(string docName)
{
    using (PresentationDocument ppt = PresentationDocument.Open(docName, true))
    {
        // Get the relationship ID of the first slide.
        PresentationPart presentationPart = ppt.PresentationPart ?? ppt.AddPresentationPart();
        SlideIdList slideIdList = presentationPart.Presentation.SlideIdList ?? presentationPart.Presentation.AppendChild(new SlideIdList());
        SlideId? slideId = slideIdList.GetFirstChild<SlideId>();

        if (slideId is not null)
        {
            string? relId = slideId.RelationshipId;

            if (relId is not null)
            {
                // Get the slide part from the relationship ID.
                SlidePart slidePart = (SlidePart)presentationPart.GetPartById(relId);

                if (slidePart is not null && slidePart.Slide is not null && slidePart.Slide.CommonSlideData is not null && slidePart.Slide.CommonSlideData.ShapeTree is not null)
                {

                    // Get the shape tree that contains the shape to change.
                    ShapeTree tree = slidePart.Slide.CommonSlideData.ShapeTree;

                    // Get the first shape in the shape tree.
                    Shape? shape = tree.GetFirstChild<Shape>();

                    if (shape is not null && shape.ShapeStyle is not null && shape.ShapeStyle.FillReference is not null)
                    {
                        // Get the style of the shape.
                        ShapeStyle style = shape.ShapeStyle;

                        // Get the fill reference.
                        Drawing.FillReference fillRef = style.FillReference;

                        // Set the fill color to SchemeColor Accent 6;
                        fillRef.SchemeColor = new Drawing.SchemeColor();
                        fillRef.SchemeColor.Val = Drawing.SchemeColorValues.Accent6;

                        // Save the modified slide.
                        slidePart.Slide.Save();
                    }
                }
            }
        }
    }
}