Search code examples
c#powerpointopenxmlopenxml-sdk

OpenXML SDK: How to get "Tag" (p:tag) val of a PowerPoint shape?


I need to check all tags on all shapes on all slides. I can select each shape, however I can't see how to get the shape's tags.

For the given DocumentFormat.OpenXml.Presentation.Shape, how can I get the "val" of the tag with name="MOUNTAIN" In my shape, the tag rId is in this structure: p:sp > p:nvSpPr > p:cNvPr > p:nvPr > p:custDataList > p:tags

I'm guessing my code needs to do these steps:

• Get the rId of the p:custDataLst p:tags
• Look up the "Target" file name in the slideX.xml.rels file, based on the rId
• Look in the root/tags folder for the "Target" file
• Get the p:tagLst p:tags and look for the p:tag with name="MOUNTAIN"
   <p:tagLst
       <p:tag name="MOUNTAIN" val="Denali"/>
   </p:tagLst>

Here is how my code iterates through shapes on each slide:

for (int x = 0; x < doc.PresentationPart.SlideParts.Count(); x++)
{
   SlidePart slide = doc.PresentationPart.SlideParts.ElementAt(x);
   ShapeTree tree = slide.Slide.CommonSlideData.ShapeTree;                        
   IEnumerable<DocumentFormat.OpenXml.Presentation.Shape> slShapes = slide.Slide.Descendants<DocumentFormat.OpenXml.Presentation.Shape>();
   foreach (DocumentFormat.OpenXml.Presentation.Shape shape in slShapes)
   {
      //get the specified tag, if it exists
   }
}

I see an example of how to add tags: How to add custom tags to powerpoint slides using OpenXml in c# But I can't figure out how to read the existing tags.

So, how do I get the shape's tags with c#?

I was hoping to do something like this:

IEnumerable<UserDefinedTagsPart> userDefinedTagsParts = shape.NonVisualShapeProperties.ApplicationNonVisualDrawingProperties.CustomerDataList.CustomerDataTags<UserDefinedTagsPart>();
foreach (UserDefinedTagsPart userDefinedTagsPart in userDefinedTagsParts)
{}

but Visual Studio says "ApplicationNonVisualDrawingProperties does not contain a definition for CustomerDataList".

From the OpenXML Productivity Tool, here is the element tree:

TagsElementTree


Solution

  • You and I seem to be working on similar problems. I'm struggling with learning the file format. The following code is working for me, I'm sure it can be optimized.

            public void ReadTags(Shape shape, SlidePart slidePart)
            {
                NonVisualShapeProperties nvsp = shape.NonVisualShapeProperties;
                ApplicationNonVisualDrawingProperties nvdp = nvsp.ApplicationNonVisualDrawingProperties;
                IEnumerable<CustomerDataTags> data_tags = nvdp.Descendants<CustomerDataTags>();
    
                foreach (var data_tag in data_tags)
                {
                    UserDefinedTagsPart shape_tags = slidePart.GetPartById(data_tag.Id) as UserDefinedTagsPart;
    
                    if (shape_tags != null)
                    {
                        foreach (Tag tag in shape_tags.TagList)
                        {
                            Debug.Print($"\t{nvsp.NonVisualDrawingProperties.Name} tag {tag.Name} = '{tag.Val}");
                        }
                    }                
                }
            }