Programmatically hide big blocks of document

Hello,

There is a large document and based on logic must hide or show sections during mailMerge. Tried to use paragraphs and tables. So far have encountered 2 problems:

  1. Uniquely identifying table/paragraph by some name from code (Node where huge text block with various formatting could be fitted). Maybe for identifying tables AltText property could be used but was not able to find anywhere in Node so far.

  2. Hide selected node during mailMerge. (in case node is used just calling node.Remove() will do the job)

How to solve this very trivial problem? IMHO hiding/showing sections of text in manipulated document should be easy.

Hi Philo,

Thanks for your inquiry.

The HideContent class below implements DocumentVisitor and will hide content in the document depending upon the parameters passed to the HideContent class. You can:

  • Hide the content of an entire section
  • Hide the content between two different styles
  • Hide the content between two runs containing specific strings

Passing the class UnhideContent will make all the content visible again.

Please note that the empty shells of the shapes such as tables, lines, textboxes and images will still remain as only the text gets hidden. Depending upon exactly how you are going to use this functionality will define what you want to do with those left over shapes, you may just want to delete them or store them in a NodeCollection so they can be reinserted later on. If you provide some further information we can give more advice on the matter.

To find further information about implementing the DocumentVisitor interface please see the documentation regarding it here.

Document doc = new Document(@"simple+template.docx");
doc.Accept(new HideContent(doc.Sections[1]));
doc.Accept(new HideContent(doc.Styles["Style3"], doc.Styles["MS_Subheading_noTOC"]));
doc.Accept(new HideContent("This is another", "2008"));
doc.Save(@"simple+template Out Hidden.docx");
doc.Accept(new UnhideContent());
doc.Save(@"simple+template Out Unhidden.docx");

HideContent.cs

using Aspose.Words;
using Aspose.Words.Tables;
using System.Text;
class HideContent: DocumentVisitor
{
    public Section section = null;
    public Style startStyle = null;
    public Style endStyle = null;
    public string startText = null;
    public string endText = null;
    private bool isHiding = false;
    public HideContent(Section sec)
    {
        section = sec;
    }
    public HideContent(Style start, Style end)
    {
        startStyle = start;
        endStyle = end;
    }
    public HideContent(string start, string end)
    {
        startText = start;
        endText = end;
    }
    private bool shouldBeHiding(Node node)
    {
        bool result = false;
        bool hasChanged = false;
        if (section != null)
        {
            if (node.NodeType == section.NodeType)
            {
                if (!isHiding)
                {
                    if (section == node)
                    {
                        hasChanged = true;
                        result = true;
                    }
                }
                else
                {
                    if (node == section)
                    {
                        hasChanged = true;
                        result = false;
                    }
                }
            }
        }
        if (startStyle != null && endStyle != null)
        {
            if (node.NodeType == NodeType.Paragraph)
            {
                Paragraph p = (Paragraph) node;
                if (p.ParagraphFormat.Style == startStyle)
                {
                    hasChanged = true;
                    result = true;
                }
                if (isHiding)
                {
                    if (p.ParagraphFormat.Style == endStyle)
                    {
                        hasChanged = true;
                        result = false;
                    }
                }
            }
        }
        if (!string.IsNullOrEmpty(startText) && !string.IsNullOrEmpty(endText))
        {
            if (node.NodeType == NodeType.Run)
            {
                Run run = (Run) node;
                if (run.Text.Contains(startText))
                {
                    hasChanged = true;
                    result = true;
                }
                if (isHiding)
                {
                    if (run.Text.Contains(endText))
                    {
                        hasChanged = true;
                        result = false;
                    }
                }
            }
        }
        if (!hasChanged)
            return isHiding;
        else
            return result;
    }
    public override VisitorAction VisitFieldStart(Aspose.Words.Fields.FieldStart fieldStart)
    {
        isHiding = shouldBeHiding(fieldStart);
        if (isHiding)
            fieldStart.Font.Hidden = true;
        return VisitorAction.Continue;
    }
    public override VisitorAction VisitFieldSeparator(Aspose.Words.Fields.FieldSeparator fieldSeparator)
    {
        isHiding = shouldBeHiding(fieldSeparator);
        if (isHiding)
            fieldSeparator.Font.Hidden = true;
        return VisitorAction.Continue;
    }
    public override VisitorAction VisitFieldEnd(Aspose.Words.Fields.FieldEnd fieldEnd)
    {
        isHiding = shouldBeHiding(fieldEnd);
        if (isHiding)
            fieldEnd.Font.Hidden = true;
        return VisitorAction.Continue;
    }
    public override VisitorAction VisitRun(Run run)
    {
        isHiding = shouldBeHiding(run);
        if (isHiding)
            run.Font.Hidden = true;
        return VisitorAction.Continue;
    }
    public override VisitorAction VisitParagraphStart(Paragraph paragraph)
    {
        isHiding = shouldBeHiding(paragraph);
        return VisitorAction.Continue;
    }
    public override VisitorAction VisitSectionStart(Section section)
    {
        isHiding = shouldBeHiding(section);
        return VisitorAction.Continue;
    }
    public override VisitorAction VisitSectionEnd(Section section)
    {
        isHiding = shouldBeHiding(section);
        return base.VisitSectionEnd(section);
    }
}

UnhideContent.cs

using Aspose.Words;
using Aspose.Words.Tables;
using System.Text;
class UnhideContent: DocumentVisitor
{
    public UnhideContent()
    {}
    public override VisitorAction VisitFieldStart(Aspose.Words.Fields.FieldStart fieldStart)
    {
        fieldStart.Font.Hidden = false;
        return VisitorAction.Continue;
    }
    public override VisitorAction VisitFieldSeparator(Aspose.Words.Fields.FieldSeparator fieldSeparator)
    {
        fieldSeparator.Font.Hidden = false;
        return VisitorAction.Continue;
    }
    public override VisitorAction VisitFieldEnd(Aspose.Words.Fields.FieldEnd fieldEnd)
    {
        fieldEnd.Font.Hidden = false;
        return VisitorAction.Continue;
    }
    public override VisitorAction VisitRun(Run run)
    {
        run.Font.Hidden = false;
        return VisitorAction.Continue;
    }
}

I hope, this helps.

Best regards,

Hi,

Thanks for a visitor hint. But for tables it works little bit different. Let me share my discoveries (as well i’m open for criticism as well):

[Test]
public void RemoveTablesTest()
{
    var doc = new Document("C:\\Test.docx");
    doc.Accept(new RemoveTables());
    doc.Save(@"C:\\TestResult.docx");
}
class RemoveTables: DocumentVisitor
{
    public override VisitorAction VisitTableStart(Table table)
    {
        table.Remove();
        table.Style.Font.Hidden = true;
        return VisitorAction.SkipThisNode;
    }
    public override VisitorAction VisitTableEnd(Table table)
    {
        table.Remove();
        table.Style.Font.Hidden = true;
        return VisitorAction.SkipThisNode;
    }
}

Noticed that …Font.Hidden = true; sometimes generates unexpected result. So came back to initial idea, (AND IT WORKS GRAND, posting some code maybe anyone could benefit from it):

public static class TemplateDocumentTables
{
    private static readonly Regex RowIfCondition = new Regex(@"##\s*IF\s*[(](?.*?)[)]");
    public static void ShowHideTables(DocumentBuilder builder, string variable, bool show)
    {
        var tables = builder.Document.GetChildNodes(NodeType.Table, true);
        foreach(var table in tables.Cast <Table> ().Where(table => table.FirstRow != null))
        {
            var text = table.FirstRow.GetText();
            if (RowIfCondition.IsMatch(text) && RowIfCondition.Match(text).Groups["name"].Captures[0].Value.Trim() == variable)
            {
                if (show)
                {
                    table.FirstRow.Remove();
                    table.SetBorders(LineStyle.None, 0, Color.White);
                }
                else
                {
                    table.Remove();
                }
            }
        }
    }
}

Where usage:

TemplateDocumentTables.ShowHideTables(wrapper, "ATTITUDE", false);
TemplateDocumentTables.ShowHideTables(wrapper, "PERSONAL", true);

Where declaration in template document:

Hi Philo,

Thanks for your inquiry.

When it comes to deletion of all Tables, you can call Body.Tables.Clear() method. Regarding removing individual Table(s), you can iterate through Table collection and call Table.Remove method or you can access an individual Table by index and remove it.

Did you manage to achieve what you’re looking for or are you still in need of assistance?

Best regards,

Thank you,

everything is grand. I just posted prev solution maybe would be helpful for someone. Just another technique to achieve same result in more simpler way.