Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 1 addition & 48 deletions DocX/Container.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,45 +80,6 @@ public virtual List<Paragraph> Paragraphs
}



public virtual List<Section> Sections
{
get
{
var allParas = Paragraphs;

var parasInASection = new List<Paragraph>();
var sections = new List<Section>();

foreach (var para in allParas)
{

var sectionInPara = para.Xml.Descendants().FirstOrDefault(s => s.Name.LocalName == "sectPr");

if (sectionInPara == null)
{
parasInASection.Add(para);
}
else
{
parasInASection.Add(para);
var section = new Section(Document, sectionInPara) { SectionParagraphs = parasInASection };
sections.Add(section);
parasInASection = new List<Paragraph>();
}

}

XElement body = Xml.Element(XName.Get("body", DocX.w.NamespaceName));
XElement baseSectionXml = body.Element(XName.Get("sectPr", DocX.w.NamespaceName));
var baseSection = new Section(Document, baseSectionXml) { SectionParagraphs = parasInASection };
sections.Add(baseSection);

return sections;
}
}


private void GetListItemType(Paragraph p)
{
var ilvlNode = p.ParagraphNumberProperties.Descendants().FirstOrDefault(el => el.Name.LocalName == "ilvl");
Expand Down Expand Up @@ -596,15 +557,7 @@ private ListItemType GetListItemType(string styleName)
return listItemType;
}



public virtual void InsertSection()
{

InsertSection(false);
}

public virtual void InsertSection(bool trackChanges)
public virtual void InsertSection(bool trackChanges = false)
{
var newParagraphSection = new XElement
(
Expand Down
19 changes: 3 additions & 16 deletions DocX/DocX.cs
Original file line number Diff line number Diff line change
Expand Up @@ -629,34 +629,21 @@ public List<Section> GetSections()
{

var allParas = Paragraphs;

var parasInASection = new List<Paragraph>();
var sections = new List<Section>();

foreach (var para in allParas)
{

var sectionInPara = para.Xml.Descendants().FirstOrDefault(s => s.Name.LocalName == "sectPr");

if (sectionInPara == null)
if (sectionInPara != null)
{
parasInASection.Add(para);
sections.Add(new Section(Document, sectionInPara));
}
else
{
parasInASection.Add(para);
var section = new Section(Document, sectionInPara) { SectionParagraphs = parasInASection };
sections.Add(section);
parasInASection = new List<Paragraph>();
}

}

XElement body = mainDoc.Root.Element(XName.Get("body", DocX.w.NamespaceName));
XElement baseSectionXml = body.Element(XName.Get("sectPr", DocX.w.NamespaceName));
var baseSection = new Section(Document, baseSectionXml) { SectionParagraphs = parasInASection };
sections.Add(baseSection);

sections.Add(new Section(Document, baseSectionXml));
return sections;
}

Expand Down
124 changes: 116 additions & 8 deletions DocX/Section.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,126 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO.Packaging;
using System.Linq;
using System.Xml.Linq;

namespace Novacode
{
public class Section : Container
{
/// <summary>
/// Please read the specifications at
/// http://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.sectionproperties.aspx
/// </summary>
public class Section : Container
{

public SectionBreakType SectionBreakType;
public SectionBreakType SectionBreakType;

internal Section(DocX document, XElement xml) : base(document, xml)
{
internal Section(DocX document, XElement xml)
: base(document, xml)
{
}

// Section doesn't contain any paragraphs in the xml, so we override the base property
public override List<Paragraph> Paragraphs
{
get
{
if (Xml.Parent == null)
{
throw new ApplicationException("Sections must be either be under a paragraph or the body!");
}

var output = new List<Paragraph>();
var index = 0; // Is required by the recursion
// Based on the specifications:
// For all sections except the final section, the sectPr element is stored as a child element
// of the last paragraph in the section. For the final section, this information is stored as
// the last child element of the body element
// This

var elementsBeforeSection = GetElementsBeforeSection();
// Get last previous section
var lastSectionBefore = elementsBeforeSection.InDocumentOrder().LastOrDefault(el => el.Descendants().Any(s => s.Name.LocalName == "sectPr"));
if (lastSectionBefore != null) // We have to exclude all the previous elements
{
var elementComparer = new XElementEqualityComparer();
elementsBeforeSection = elementsBeforeSection.Except<XElement>(lastSectionBefore.ElementsBeforeSelf(), elementComparer);
// And the previous section element
elementsBeforeSection = elementsBeforeSection.Except<XElement>(new XElement[] { lastSectionBefore }, elementComparer);
}
foreach (var xElement in elementsBeforeSection)
{
GetParagraphsRecursive(xElement, ref index, ref output);
}
return output;
}
}

private IEnumerable<XElement> GetElementsBeforeSection()
{
IEnumerable<XElement> elementsBeforeSection = null;

// If this is a section somewhere inside the document
if (Xml.Parent.Name.LocalName == "pPr") // Get the nodes on the same level as the father
{
elementsBeforeSection = Xml.Parent.Parent.ElementsBeforeSelf();
}
else if (Xml.Parent.Name.LocalName == "body") // This is the final section so we get all children in same level
{
elementsBeforeSection = Xml.ElementsBeforeSelf();
}
else
{
throw new ApplicationException("Sections should be located inside a pPr or body");
}
return elementsBeforeSection;
}

/// <summary>
/// Clear all paragraphs in section
/// </summary>
/// <param name="trackChanges">Keep track of changes</param>
public void Clear(bool trackChanges = false)
{
var paragraphs = Paragraphs;
foreach (var paragraph in paragraphs)
{
paragraph.Remove(trackChanges);
}
}


// Sections don't have paragraphs.
public override Paragraph InsertParagraph(string text, bool trackChanges, Formatting formatting)
{
XElement newParagraph = new XElement
(
XName.Get("p", DocX.w.NamespaceName), new XElement(XName.Get("pPr", DocX.w.NamespaceName)), HelperFunctions.FormatInput(text, formatting.Xml)
);

if (trackChanges)
newParagraph = HelperFunctions.CreateEdit(EditType.ins, DateTime.Now, newParagraph);

//So we have to add it just before the section brake
GetElementsBeforeSection().Last().AddAfterSelf(newParagraph);

var paragraphAdded = Paragraphs.Last();

return paragraphAdded;
}
}

public List<Paragraph> SectionParagraphs { get; set; }
}
public class XElementEqualityComparer : IEqualityComparer<XElement>
{

public bool Equals(XElement x, XElement y)
{
return XElement.DeepEquals(x, y);
}

public int GetHashCode(XElement obj)
{
return obj.GetHashCode();
}
}
}