Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Openxml - lock all content controls

Tags:

c#

.net

openxml

I want to programmatically lock all content controls so that the user cannot delete them.

I am using the following code, but my problem is that in a few cases I am getting null when calling elem.SdtProperties.ChildElements.First<WP.Lock>().

Can someone help me complete the below mentioned code?

static void MakeContentControlsNonDeletable()
        {
            using (P.WordprocessingDocument wordDoc =
              P.WordprocessingDocument.Open(@"c:\XYZ.docx", true))
            {
                IEnumerable<WP.SdtElement> elements =
                  wordDoc.MainDocumentPart.Document.Descendants<WP.SdtElement>();

                foreach (WP.SdtElement elem in elements)
                {
                    if (elem.SdtProperties != null)
                    {
                        WP.Lock l = elem.SdtProperties.ChildElements.First<WP.Lock>();

                        if (l == null)
                        {
                            //Please help here
                            //Please help here
                            //Please help here
                            //Please help here
                        }

                        if (l.Val != WP.LockingValues.SdtContentLocked && l.Val != WP.LockingValues.SdtLocked)
                        {
                            Console.WriteLine("Unlock content element...");
                            l.Val = WP.LockingValues.SdtLocked;
                        }
                    }
                }
            }
like image 295
Raheel Avatar asked Dec 27 '25 16:12

Raheel


1 Answers

It seems your code is fine. I've had the same problems before in another scenario where there is a certain object and it returns null. I don't know what's wrong with openxml sdk at that point but I can tell you how I did solve mine.

The problem basically is that at certain points deep in the structure you know there is a element that should be interpreted as a Lock object but the sdk can see it only as OpenXmlElement (not its subclass Lock object), so thats why when you do First<WP.Lock>() you expect a Lock object and you know its there but you just get null. What I do is treat everything as OpenXmlElement and forget about the strong typing.

static void MakeContentControlsNonDeletable()
    {
        using (P.WordprocessingDocument wordDoc =
          P.WordprocessingDocument.Open(@"c:\XYZ.docx", true))
        {
            IEnumerable<OpenXmlElement> elements =
              wordDoc.MainDocumentPart.Document.Descendants<>(child => child.LocalName == "sdt");

            foreach (OpenXmlElement elem in elements)
            {
                if (elem.ChildElements.Any(child => child.LocalName == "sdtPr"))
                {
                    OpenXmlElement sdtPr = elem.ChildElements.FirstOrDefault(child => child.LocalName == "sdtPr");
                    OpenXmlElement l = sdtPr.ChildElements.FirstOrDefault(child => child.LocalName == "lock");

                    if (l == null) //At this point if you have your lock object this isn't null
                    {
                        //Please help here
                        //Please help here
                        //Please help here
                    }

                    OpenXmlAttribute valAttribute = l.GetAttribute("val", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
                    if (valAttribute != null) {
                         valAttribute = new OpenXmlAttribute();
                    }

                    if (valAttribute.Value != "sdtContentLocked" && valAttribute.Value != "sdtLocked")
                    {
                        Console.WriteLine("Unlock content element...");
                        valAttribute.Value = "sdtLocked";
                    }
                }
            }
        } 

I know this isn't the way it's supposed to be and I know that all objects should be strongly typed to its respective openxml sdk class but that's something that happens a lot and that's why I do it this way.

Hope it helps

like image 177
eburgos Avatar answered Dec 30 '25 04:12

eburgos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!