Watermark being overwritten on first page

Hello, I have an application that appends a time stamp to only the first page of a word document using the ‘Header First’ Header type. While this works fine, the preexisting watermark that exists in ‘Header Primary’ is being removed once I change the property ‘DifferentFirstPageHeaderFooter’ to true. This is not desired. Is it possible to accomplish this? Below is the code that i am using and the file.

public static string AppendWatermark(Stream fileStream, string fileName)
{
    string sourcePath = @"C:\temp";
    string result = string.Empty;
    try
    {
        //create folder if not exists
        if (!Directory.Exists(sourcePath))
            Directory.CreateDirectory(sourcePath);
        //Get reference to the source document
        Document doc = new Document(fileStream);
        // Create a watermark shape. This will be a WordArt shape.
        // You are free to try other shape types as watermarks.
        Shape watermark = new Shape(doc, ShapeType.TextPlainText);
        // Set up the text of the watermark.
        watermark.TextPath.Text = "Published on: " + DateAndTime.Now;
        watermark.TextPath.FontFamily = "Arial";
        watermark.Width = 300;
        watermark.Height = 8;
        // Text will be directed from the bottom-left to the top-right corner.
        watermark.Rotation = 0;
        // Remove the following two lines if you need a solid black text.
        watermark.Fill.Color = Color.Red; // Try LightGray to get more Word-style watermark
        watermark.StrokeColor = Color.Red; // Try LightGray to get more Word-style watermark
        // Place the watermark in the page center.
        // watermark.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
        // watermark.RelativeVerticalPosition = RelativeVerticalPosition.Page;
        // watermark.WrapType = WrapType.None;
        watermark.VerticalAlignment = VerticalAlignment.Bottom;
        watermark.HorizontalAlignment = HorizontalAlignment.Left;
        // Create a new paragraph and append the watermark to this paragraph.
        Paragraph watermarkPara = new Paragraph(doc);
        watermarkPara.AppendChild(watermark);
        // Insert the watermark into all headers of each document section.
        foreach (Section sect in doc.Sections)
        {
            sect.PageSetup.DifferentFirstPageHeaderFooter = true;
            InsertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HeaderFirst);
        }
        //create new document with desired extension, save in same folder
        doc.Save(sourcePath + fileName);
    }
    catch (Exception ex)
    {
        result = ex.Message;
    }
    return result;
}

private static void InsertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, HeaderFooterType headerType)
{
    HeaderFooter header = sect.HeadersFooters[headerType];
    if (header == null)
    {
        // There is no header of the specified type in the current section, create it.
        header = new HeaderFooter(sect.Document, headerType);
        sect.HeadersFooters.Add(header);
    }
    // Insert a clone of the watermark into the header.
    header.AppendChild(watermarkPara.Clone(true));
}

Hi Fred,

Thanks for your inquiry.

You can try avoiding loosing the content from the primary header by copying the content to the first page header. Please see the code below.

private static void InsertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, HeaderFooterType headerType)
{
    HeaderFooter header = sect.HeadersFooters[headerType];
    if (header == null)
    {
        // There is no header of the specified type in the current section, create it.
        header = new HeaderFooter(sect.Document, headerType);
        sect.HeadersFooters.Add(header);
    }
    // If we are using a header first we can check if there is any existing content in the primary header
    // which won't be displayed now and move them to header first.
    if (headerType == HeaderFooterType.HeaderFirst && sect.PageSetup.DifferentFirstPageHeaderFooter)
    {
        Node[] primaryHeaderNodes = sect.HeadersFooters[HeaderFooterType.HeaderPrimary].ChildNodes.ToArray();
        foreach (Node node in primaryHeaderNodes)
            header.AppendChild(node);
    }
    // Insert a clone of the watermark into the header.
    header.AppendChild(watermarkPara.Clone(true));
}

Also note in your main code you most likely don’t need to interate through all sections in the document as you only want to insert the text into the header first of the first page (first section). You can simply use doc.FirstSection instead.

Thanks,

Thank you for your feedback. After implementing this change I noticed that now all other pages have their watermarks removed. Is there a way to append the new watermark to only the first page while keeping the rest of the document in its original format?

Ive come up with a solution, but its very ugly and im not proud of it at all. im sure theres a better way to do this.

public static string AppendWatermark(Stream fileStream, string fileName)
{
    string sourcePath = ConfigurationManager.AppSettings["SourcePath"];
    string result = string.Empty;
    try
    {
        //create folder if not exists
        if (!Directory.Exists(sourcePath))
            Directory.CreateDirectory(sourcePath);
        //Get reference to the source document
        Document doc = new Document(fileStream);
        // Create a watermark shape. This will be a WordArt shape.
        // You are free to try other shape types as watermarks.
        Shape watermark = new Shape(doc, ShapeType.TextPlainText);
        // Set up the text of the watermark.
        watermark.TextPath.Text = "Published on: " + DateAndTime.Now;
        watermark.TextPath.FontFamily = "Arial";
        watermark.Width = 300;
        watermark.Height = 8;
        // Text will be directed from the bottom-left to the top-right corner.
        watermark.Rotation = 0;
        // Remove the following two lines if you need a solid black text.
        watermark.Fill.Color = Color.Red; // Try LightGray to get more Word-style watermark
        watermark.StrokeColor = Color.Red; // Try LightGray to get more Word-style watermark
        // Place the watermark in the page center.
        // watermark.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
        // watermark.RelativeVerticalPosition = RelativeVerticalPosition.Page;
        // watermark.WrapType = WrapType.None;
        watermark.VerticalAlignment = VerticalAlignment.Bottom;
        watermark.HorizontalAlignment = HorizontalAlignment.Left;
        // Create a new paragraph and append the watermark to this paragraph.
        Paragraph watermarkPara = new Paragraph(doc);
        watermarkPara.AppendChild(watermark);
        // Insert the watermark into all headers of each document section.
        //foreach (Section sect in doc.Sections)
        //{
        ParagraphCollection paragraphCollection;
        doc.FirstSection.PageSetup.DifferentFirstPageHeaderFooter = true;
        if (doc.FirstSection.HeadersFooters[HeaderFooterType.HeaderPrimary] != null && doc.FirstSection.HeadersFooters[HeaderFooterType.HeaderPrimary].Paragraphs.Count > 0)
        {
            paragraphCollection = doc.FirstSection.HeadersFooters[HeaderFooterType.HeaderPrimary].Paragraphs;
            foreach (Paragraph paragraph in paragraphCollection)
            {
                InsertWatermarkIntoHeader(paragraph, doc.FirstSection, HeaderFooterType.HeaderFirst);
            }
        }
        if (doc.FirstSection.HeadersFooters[HeaderFooterType.FooterPrimary] != null && doc.FirstSection.HeadersFooters[HeaderFooterType.FooterPrimary].Paragraphs.Count > 0)
        {
            paragraphCollection = doc.FirstSection.HeadersFooters[HeaderFooterType.FooterPrimary].Paragraphs;
            foreach (Paragraph paragraph in paragraphCollection)
            {
                InsertWatermarkIntoHeader(paragraph, doc.FirstSection, HeaderFooterType.FooterFirst);
            }
        }
        InsertWatermarkIntoHeader(watermarkPara, doc.FirstSection, HeaderFooterType.HeaderFirst);
        //InsertWatermarkIntoHeader(sect.HeadersFooters[HeaderFooterType.HeaderPrimary].FirstParagraph, sect, HeaderFooterType.HeaderPrimary);
        //InsertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HeaderFirst);
        //}
        //create new document with desired extension, save in same folder
        doc.Save(sourcePath + fileName);
    }
    catch (Exception ex)
    {
        result = ex.Message;
    }
    return result;
}

private static void InsertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, HeaderFooterType headerType)
{
    HeaderFooter header = sect.HeadersFooters[headerType];
    if (header == null)
    {
        // There is no header of the specified type in the current section, create it.
        header = new HeaderFooter(sect.Document, headerType);
        sect.HeadersFooters.Add(header);
    }
    // Insert a clone of the watermark into the header.
    header.AppendChild(watermarkPara.Clone(true));
}

Hi Fred,

Thanks for this additional information.

I suppose this is happening because you are still iterating over all sections in the document and applying different header first, when you only need to do this for the first section (according to your original specifications).

In any case you can make this code more resilient by cloning the content into the first page header instead of moving it. Please see the changes below:

if (headerType == HeaderFooterType.HeaderFirst && sect.PageSetup.DifferentFirstPageHeaderFooter)
{
    foreach (Node node in sect.HeadersFooters[HeaderFooterType.HeaderPrimary])
        header.AppendChild(node.Clone(true));
}

Please let us know if this is working for you.

Thanks,

This code got me 95% there, however i ended up using the code above since it worked more consistently. There were some issues with the Footer not showing up on the first page, as well as duplicate page numbers being added to certain files. Ive included them incase you want to take a look at them. Thank you for your help.

Hi Fred,

Thanks for your clarification. It’s great that you have got things working now as expected. Regarding the two bugs with the other code, these could be easily solved by copying the content from the FooterPrimary in the same way as the HeaderPrimary and then by updating fields of the header first and footer first (by calling headerFooter.UpdateFields()).

In any case, as long as the current code it’s working as expected then that’s great. Please feel free to ask us any time you have any queries.

Thanks,