Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
211 views
in Technique[技术] by (71.8m points)

c# - Adding multiple lines to a contentcontrol with openxml sdk

I created some functions to fill contentcontrols in word documents. They used to work but suddenly I can't add multiple lines to a contentcontrol. The methods I'm using are below:

       public static IEnumerable<OpenXmlElement> ContentControls(
            this WordprocessingDocument doc)
        {
            foreach (var cc in doc.MainDocumentPart.ContentControls())
                yield return cc;
            foreach (var header in doc.MainDocumentPart.HeaderParts)
                foreach (var cc in header.ContentControls())
                    yield return cc;
            foreach (var footer in doc.MainDocumentPart.FooterParts)
                foreach (var cc in footer.ContentControls())
                    yield return cc;
            if (doc.MainDocumentPart.FootnotesPart != null)
                foreach (var cc in doc.MainDocumentPart.FootnotesPart.ContentControls())
                    yield return cc;
            if (doc.MainDocumentPart.EndnotesPart != null)
                foreach (var cc in doc.MainDocumentPart.EndnotesPart.ContentControls())
                    yield return cc;
        }

        public static SdtElement WithTag(
            this IEnumerable<OpenXmlElement> contentControls, string tagName)
        {
            var props = contentControls.Select(c => c.Elements<SdtProperties>().FirstOrDefault());
            var vals = props?.Select(p => p.GetFirstChild<Tag>().Val);
            var blocks = contentControls.Where(c => c is SdtBlock);
            var prop = props?.Where(p =>
            {
                StringValue val = p.GetFirstChild<Tag>()?.Val;
                bool result = val.HasValue ? val.Value.Equals(tagName, StringComparison.OrdinalIgnoreCase) : false;
                return result;
            }).FirstOrDefault();
            return prop?.Parent as SdtElement;
        }

        public static void ChangeWithTag(
            this IEnumerable<OpenXmlElement> contentControls, string tagName, string newText)
        {
            var cc = contentControls.WithTag(tagName);
            if (cc == null)
                return;
            var r = cc.Descendants<Run>().FirstOrDefault();
            var t = r.Descendants<Text>().FirstOrDefault();
            t.Text = newText;
        }

        public static void ChangeWithTag(
            this IEnumerable<OpenXmlElement> contentControls, string tagName, string[] newText)
        {
            var cc = contentControls.WithTag(tagName);

            if (cc == null)
                return;
            cc.RemoveAllChildren<SdtContentRun>();
            for (int i = 0; i < newText.Length; i++)
            {
                var r = new Run();
                r.Append(new Text() { Text = newText[i] });
                cc.Append(r);
                if (i != newText.Length - 1)
                {
                    r = new Run();
                    r.Append(new Break());
                    cc.Append(r);
                }
            }
        }

The last method isn't working anymore. When I try to open the newly created document I get an error: "Word experienced an error trying to open the file" I tried creating a document with a changed contentcontrol with the code below:

       static void TestFindAndFillTags()
        {
            var filename = Path.Combine(@"......Documents", "one tag.docx");
            byte[] byteArray = File.ReadAllBytes(filename);
            using (MemoryStream mem = new MemoryStream())
            {
                mem.Write(byteArray, 0, (int)byteArray.Length);
                using (WordprocessingDocument doc = WordprocessingDocument.Open(mem, true))
                {
                    var ccs = doc.ContentControls();
                    if (true) //change to add one line or multiple lines
                    {
                        string[] strs = new string[] { "line 1", "line 2", "line 3" };
                        ccs.ChangeWithTag("Results", strs);
                    }
                    else
                        ccs.ChangeWithTag("Results", "Line 1");
                }
                filename = Path.Combine(@"......Documents", "one tag result.docx");
                if (System.IO.File.Exists(filename))
                    System.IO.File.Delete(filename);
                using (FileStream fileStream = new FileStream(filename,System.IO.FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite))
                {
                    mem.WriteTo(fileStream);
                }
            }
        }

The "one tag.docx" document is a word document with one plain text contentcontrol with a tag called Results and the allow carriage returns checkbox checked.

By changing the if statement to false I call the ChangeWithTag function with a string parameter and only one line is added to the contentcontrol. This works.

I tried downgrading the DocumentFormatOpenXml package from version 2.12.1 to 2.11.3 but that didn't help.

I'm sure the ChangeWithTag function with multiple lines used to work. Does anyone have an idea why it stopped working?

question from:https://stackoverflow.com/questions/65936918/adding-multiple-lines-to-a-contentcontrol-with-openxml-sdk

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...