diff --git a/Xceed.Document.NET/AssemblyVersionInfo.cs b/Xceed.Document.NET/AssemblyVersionInfo.cs
index 734fbe34..2913e77d 100644
--- a/Xceed.Document.NET/AssemblyVersionInfo.cs
+++ b/Xceed.Document.NET/AssemblyVersionInfo.cs
@@ -21,7 +21,7 @@ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
internal static class _XceedVersionInfo
{
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
- public const string BaseVersion = "1.8";
+ public const string BaseVersion = "2.0";
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string Version = BaseVersion +
".0.0";
diff --git a/Xceed.Document.NET/Properties/AssemblyInfo.cs b/Xceed.Document.NET/Properties/AssemblyInfo.cs
index 4b74702a..747d5027 100644
--- a/Xceed.Document.NET/Properties/AssemblyInfo.cs
+++ b/Xceed.Document.NET/Properties/AssemblyInfo.cs
@@ -23,10 +23,10 @@ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle( "Xceed Document for .NET" )]
-[assembly: AssemblyDescription( "This assembly implements the classes for Xceed Document for .NET Standard." )]
+[assembly: AssemblyDescription( "This assembly implements the classes for Xceed Document for .NET." )]
[assembly: AssemblyCompany( "Xceed Software Inc." )]
-[assembly: AssemblyProduct( "Xceed Document for .NET Standard" )]
+[assembly: AssemblyProduct( "Xceed Document for .NET" )]
[assembly: AssemblyCopyright( "Copyright (C) Xceed Software Inc. 2009-2021" )]
[assembly: AssemblyCulture("")]
@@ -52,6 +52,13 @@ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
"131b925dcf84a73d22264352eca7c3fcf9387f3eee1d60ac7974f04866e6c72928dc0609abe341" +
"f92cbfb5")]
+[assembly: InternalsVisibleTo( "Xceed.Words.NET5" + ",PublicKey=" +
+ "0024000004800000940000000602000000240000525341310004000001000100d59d8147eb2015" +
+ "ca98a92da860fd766d101271d8c2f545894870fd6183255737d79347bbf5250291ae75651e1150" +
+ "1b7452ee003b80b936614cdda51db8eb6f8fde913e67d45395b480a992be17bf04744a7fe803ea" +
+ "131b925dcf84a73d22264352eca7c3fcf9387f3eee1d60ac7974f04866e6c72928dc0609abe341" +
+ "f92cbfb5")]
+
[assembly: InternalsVisibleTo( "Xceed.PdfCreator.NET" + ",PublicKey=" +
"0024000004800000940000000602000000240000525341310004000001000100d59d8147eb2015" +
"ca98a92da860fd766d101271d8c2f545894870fd6183255737d79347bbf5250291ae75651e1150" +
@@ -66,6 +73,13 @@ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
"131b925dcf84a73d22264352eca7c3fcf9387f3eee1d60ac7974f04866e6c72928dc0609abe341" +
"f92cbfb5")]
+[assembly: InternalsVisibleTo( "Xceed.PdfCreator.NET5" + ",PublicKey=" +
+ "0024000004800000940000000602000000240000525341310004000001000100d59d8147eb2015" +
+ "ca98a92da860fd766d101271d8c2f545894870fd6183255737d79347bbf5250291ae75651e1150" +
+ "1b7452ee003b80b936614cdda51db8eb6f8fde913e67d45395b480a992be17bf04744a7fe803ea" +
+ "131b925dcf84a73d22264352eca7c3fcf9387f3eee1d60ac7974f04866e6c72928dc0609abe341" +
+ "f92cbfb5")]
+
[assembly: InternalsVisibleTo( "UnitTests" + ",PublicKey=" +
"0024000004800000940000000602000000240000525341310004000001000100d59d8147eb2015" +
"ca98a92da860fd766d101271d8c2f545894870fd6183255737d79347bbf5250291ae75651e1150" +
@@ -79,6 +93,8 @@ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
+
+
#pragma warning disable 1699
[assembly: AssemblyDelaySign( false )]
[assembly: AssemblyKeyFile( @"..\..\sn.snk" )]
diff --git a/Xceed.Document.NET/Resources/SignatureLine.emf b/Xceed.Document.NET/Resources/SignatureLine.emf
new file mode 100644
index 00000000..3625a9d3
Binary files /dev/null and b/Xceed.Document.NET/Resources/SignatureLine.emf differ
diff --git a/Xceed.Document.NET/Resources/default_styles.xml.gz b/Xceed.Document.NET/Resources/default_styles.xml.gz
index b1c1a471..4502bac5 100644
Binary files a/Xceed.Document.NET/Resources/default_styles.xml.gz and b/Xceed.Document.NET/Resources/default_styles.xml.gz differ
diff --git a/Xceed.Document.NET/Src/Bookmark.cs b/Xceed.Document.NET/Src/Bookmark.cs
index 7c2ce164..e266915a 100644
--- a/Xceed.Document.NET/Src/Bookmark.cs
+++ b/Xceed.Document.NET/Src/Bookmark.cs
@@ -24,6 +24,7 @@ public string Name
{
get; set;
}
+
public Paragraph Paragraph
{
get; set;
diff --git a/Xceed.Document.NET/Src/Charts/Axis.cs b/Xceed.Document.NET/Src/Charts/Axis.cs
index c46fd2d8..726216fa 100644
--- a/Xceed.Document.NET/Src/Charts/Axis.cs
+++ b/Xceed.Document.NET/Src/Charts/Axis.cs
@@ -15,6 +15,9 @@ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Xml;
using System.Xml.Linq;
namespace Xceed.Document.NET
@@ -25,12 +28,19 @@ namespace Xceed.Document.NET
///
public abstract class Axis
{
+
+ #region Private properties
+
+
+ #endregion
+
+
#region Public Properties
///
/// ID of this Axis
///
- public String Id
+ public string Id
{
get
{
@@ -41,7 +51,7 @@ public String Id
///
/// Return true if this axis is visible
///
- public Boolean IsVisible
+ public bool IsVisible
{
get
{
@@ -60,7 +70,25 @@ public Boolean IsVisible
-#endregion
+
+
+
+
+
+ #endregion
+
+
+
+
+
+
+
+
+
+
+
+
+
#region Internal Properties
diff --git a/Xceed.Document.NET/Src/Charts/Chart.cs b/Xceed.Document.NET/Src/Charts/Chart.cs
index b88a4ffe..c9ce3f52 100644
--- a/Xceed.Document.NET/Src/Charts/Chart.cs
+++ b/Xceed.Document.NET/Src/Charts/Chart.cs
@@ -33,6 +33,9 @@ public abstract class Chart
{
#region Private Members
+ private Paragraph _parentParagraph;
+ private PackageRelationship _packageRelationship;
+
#endregion
@@ -54,13 +57,10 @@ public List Series
get
{
var series = new List();
- var ser = XName.Get( "ser", Document.c.NamespaceName );
- int index = 1;
- foreach( var element in ChartXml.Elements( ser ) )
+ var ser = ChartXml.Elements( XName.Get( "ser", Document.c.NamespaceName ) );
+ foreach( var element in ser )
{
- element.Add( new XElement( XName.Get( "idx", Document.c.NamespaceName ) ), index.ToString() );
series.Add( new Series( element ) );
- ++index;
}
return series;
}
@@ -91,7 +91,12 @@ public ChartLegend Legend
///
public CategoryAxis CategoryAxis
{
- get; private set;
+ get
+ {
+ var catAxXML = ChartRootXml.Descendants( XName.Get( "catAx", Document.c.NamespaceName ) ).SingleOrDefault();
+
+ return ( catAxXML != null ) ? new CategoryAxis( catAxXML ) : null;
+ }
}
///
@@ -99,7 +104,12 @@ public CategoryAxis CategoryAxis
///
public ValueAxis ValueAxis
{
- get; private set;
+ get
+ {
+ var valAxXML = ChartRootXml.Descendants( XName.Get( "valAx", Document.c.NamespaceName ) ).SingleOrDefault();
+
+ return ( valAxXML != null ) ? new ValueAxis( valAxXML ) : null;
+ }
}
///
@@ -220,11 +230,11 @@ public Chart()
// if axes exists, create their
if( this.IsAxisExist )
{
- this.CategoryAxis = new CategoryAxis( "148921728" );
- this.ValueAxis = new ValueAxis( "154227840" );
+ var categoryAxis = new CategoryAxis( "148921728" );
+ var valueAxis = new ValueAxis( "154227840" );
- var axIDcatXml = XElement.Parse( String.Format( @"", this.CategoryAxis.Id ) );
- var axIDvalXml = XElement.Parse( String.Format( @"", this.ValueAxis.Id ) );
+ var axIDcatXml = XElement.Parse( String.Format( @"", categoryAxis.Id ) );
+ var axIDvalXml = XElement.Parse( String.Format( @"", valueAxis.Id ) );
var gapWidth = this.ChartXml.Element( XName.Get( "gapWidth", Document.c.NamespaceName ) );
if( gapWidth != null )
@@ -238,8 +248,8 @@ public Chart()
this.ChartXml.Add( axIDvalXml );
}
- plotAreaXml.Add( this.CategoryAxis.Xml );
- plotAreaXml.Add( this.ValueAxis.Xml );
+ plotAreaXml.Add( categoryAxis.Xml );
+ plotAreaXml.Add( valueAxis.Xml );
}
this.ChartRootXml = this.Xml.Root.Element( XName.Get( "chart", Document.c.NamespaceName ) );
@@ -301,6 +311,33 @@ public void RemoveLegend()
}
}
+ public void Remove()
+ {
+ if( _packageRelationship.Package != null )
+ {
+ _packageRelationship.Package.DeletePart( _packageRelationship.TargetUri );
+ }
+
+ if( _parentParagraph.Document.PackagePart != null )
+ {
+ _parentParagraph.Document.PackagePart.DeleteRelationship( _packageRelationship.Id );
+ }
+
+ // Remove the Xml from document.
+ var parentParagrahChart = _parentParagraph.Xml.Descendants( XName.Get( "chart", Document.c.NamespaceName ) )
+ .FirstOrDefault( c => c.GetAttribute( XName.Get( "id", "http://schemas.openxmlformats.org/officeDocument/2006/relationships" ) ) == _packageRelationship.Id );
+ if( parentParagrahChart != null )
+ {
+ var parentDrawing = parentParagrahChart.Ancestors( XName.Get( "drawing", Document.w.NamespaceName ) ).FirstOrDefault();
+ if( parentDrawing != null )
+ {
+ parentDrawing.Remove();
+ }
+ }
+ }
+
+
+
#endregion
@@ -529,10 +566,10 @@ public void Bind( IList categories, IList values )
for( int index = 0; index < categories.Count; index++ )
{
pt = new XElement( XName.Get( "pt", Document.c.NamespaceName ), new XAttribute( XName.Get( "idx" ), index ),
- new XElement( XName.Get( "v", Document.c.NamespaceName ), categories[ index ].ToString() ) );
+ new XElement( XName.Get( "v", Document.c.NamespaceName ), categories[index].ToString() ) );
_strCache.Add( pt );
pt = new XElement( XName.Get( "pt", Document.c.NamespaceName ), new XAttribute( XName.Get( "idx" ), index ),
- new XElement( XName.Get( "v", Document.c.NamespaceName ), values[ index ].ToString() ) );
+ new XElement( XName.Get( "v", Document.c.NamespaceName ), values[index].ToString() ) );
_numCache.Add( pt );
}
}
diff --git a/Xceed.Document.NET/Src/Container.cs b/Xceed.Document.NET/Src/Container.cs
index ca45391f..1b20617f 100644
--- a/Xceed.Document.NET/Src/Container.cs
+++ b/Xceed.Document.NET/Src/Container.cs
@@ -179,7 +179,12 @@ public virtual List Lists
}
}
}
- lists.Add( list );
+
+ if( list.Items.Count > 0 )
+ {
+ lists.Add( list );
+ }
+
return lists;
}
}
@@ -1028,10 +1033,18 @@ private void InitParagraphs( List paragraphs )
foreach( var p in paragraphs )
{
var nextElement = p.Xml.ElementsAfterSelf().FirstOrDefault();
- if( ( nextElement == null ) && p.IsInSdt() )
+ if ((nextElement == null) && p.IsInSdt())
{
nextElement = p.GetParentSdt().ElementsAfterSelf().FirstOrDefault();
}
+ else if ((nextElement != null) && nextElement.Name.Equals(Document.w + "sdt"))
+ {
+ var sdtContent = nextElement.Element(XName.Get("sdtContent", Document.w.NamespaceName));
+ if (sdtContent != null)
+ {
+ nextElement = sdtContent.Element(XName.Get("tbl", Document.w.NamespaceName));
+ }
+ }
var containsSectionBreak = p.GetOrCreate_pPr().Element( XName.Get( "sectPr", Document.w.NamespaceName ) );
// Add FollowingTable to paragraph....only when paragraph is not the last one from a section.
while( ( nextElement != null ) && ( nextElement.Name.Equals( Document.w + "tbl" ) ) && ( containsSectionBreak == null ) )
diff --git a/Xceed.Document.NET/Src/CustomProperty.cs b/Xceed.Document.NET/Src/CustomProperty.cs
index b65acdb9..d2185c08 100644
--- a/Xceed.Document.NET/Src/CustomProperty.cs
+++ b/Xceed.Document.NET/Src/CustomProperty.cs
@@ -141,7 +141,9 @@ internal CustomProperty( string name, string type, string value, Formatting form
case "bool":
{
- realValue = bool.Parse( value );
+ realValue = ( value == "0" )
+ ? false
+ : ( value == "1" ) ? true : bool.Parse( value );
break;
}
diff --git a/Xceed.Document.NET/Src/Document.cs b/Xceed.Document.NET/Src/Document.cs
index 4c9b7bf8..f917c117 100644
--- a/Xceed.Document.NET/Src/Document.cs
+++ b/Xceed.Document.NET/Src/Document.cs
@@ -29,8 +29,9 @@ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
using System.Net;
using System.Diagnostics;
using System.Drawing.Drawing2D;
-using System.Resources;
-using System.Globalization;
+using System.Reflection;
+using System.ComponentModel;
+
namespace Xceed.Document.NET
{
@@ -66,6 +67,11 @@ public class Document : Container, IDisposable
static internal XNamespace mc = "http://schemas.openxmlformats.org/markup-compatibility/2006";
static internal XNamespace wps = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
static internal XNamespace w14 = "http://schemas.microsoft.com/office/word/2010/wordml";
+ static internal XNamespace w15 = "http://schemas.microsoft.com/office/word/2012/wordml";
+ static internal XNamespace o = "urn:schemas-microsoft-com:office:office";
+ static internal XNamespace d = "http://www.w3.org/2000/09/xmldsig#";
+ static internal XNamespace doffice = "http://schemas.microsoft.com/office/2006/digsig";
+ static internal XNamespace w10 = "urn:schemas-microsoft-com:office:word";
#endregion
#region Private Members
@@ -148,6 +154,48 @@ public override IList Sections
}
}
+ public NoteProperties EndnoteProperties
+ {
+ get
+ {
+ if( this.Sections.Count > 1 )
+ {
+ Debug.WriteLine( "This document contains more than 1 section. Consider using Sections[wantedSection].EndnoteProperties." );
+ }
+ return this.Sections[ 0 ].EndnoteProperties;
+ }
+
+ set
+ {
+ if( this.Sections.Count > 1 )
+ {
+ Debug.WriteLine( "This document contains more than 1 section. Consider using Sections[wantedSection].EndnoteProperties." );
+ }
+ this.Sections[ 0 ].EndnoteProperties = value;
+ }
+ }
+
+ public NoteProperties FootnoteProperties
+ {
+ get
+ {
+ if( this.Sections.Count > 1 )
+ {
+ Debug.WriteLine( "This document contains more than 1 section. Consider using Sections[wantedSection].FootnoteProperties." );
+ }
+ return this.Sections[ 0 ].FootnoteProperties;
+ }
+
+ set
+ {
+ if( this.Sections.Count > 1 )
+ {
+ Debug.WriteLine( "This document contains more than 1 section. Consider using Sections[wantedSection].FootnoteProperties." );
+ }
+ this.Sections[ 0 ].FootnoteProperties = value;
+ }
+ }
+
public float MarginTop
{
get
@@ -896,13 +944,13 @@ public BookmarkCollection Bookmarks
var bookmarks = new BookmarkCollection();
// In Body.
// Faster to search the document.Xml instead of document.Paragraphs.
- var documentBookmarkStartsXml = this.Xml.Descendants(XName.Get("bookmarkStart", Document.w.NamespaceName));
- foreach (var bookmarkStartXml in documentBookmarkStartsXml )
+ var documentBookmarkStartsXml = this.Xml.Descendants( XName.Get( "bookmarkStart", Document.w.NamespaceName ) );
+ foreach( var bookmarkStartXml in documentBookmarkStartsXml )
{
var bookmarkName = bookmarkStartXml.Attribute( XName.Get( "name", Document.w.NamespaceName ) ).Value;
var paragraphXml = bookmarkStartXml.Parent;
- while ((paragraphXml != null) && (paragraphXml.Name != XName.Get("p", Document.w.NamespaceName)))
+ while( ( paragraphXml != null ) && ( paragraphXml.Name != XName.Get( "p", Document.w.NamespaceName ) ) )
{
paragraphXml = paragraphXml.Parent;
}
@@ -922,75 +970,75 @@ public BookmarkCollection Bookmarks
while( ( paragraphXml != null ) && ( paragraphXml.Name != XName.Get( "p", Document.w.NamespaceName ) ) )
{
paragraphXml = paragraphXml.Parent;
- }
+ }
// bookmarkStart is not in a paragraph, get bookmarkEnd.
if( paragraphXml == null )
throw new InvalidDataException( "bookmarkStart and bookmarkEnd are not part of a paragraph. This is currently not supported." );
}
- bookmarks.Add(new Bookmark
+ bookmarks.Add( new Bookmark
{
Name = bookmarkName,
Id = bookmarkStartXml.Attribute( XName.Get( "id", Document.w.NamespaceName ) ).Value,
- Paragraph = new Paragraph(this, paragraphXml, -1) { PackagePart = this.PackagePart }
- });
+ Paragraph = new Paragraph( this, paragraphXml, -1 ) { PackagePart = this.PackagePart }
+ } );
}
- foreach (var section in this.Sections)
+ foreach( var section in this.Sections )
{
// In Headers.
var headers = section.Headers;
- if (headers != null)
+ if( headers != null )
{
- if (headers.Odd != null)
+ if( headers.Odd != null )
{
- foreach (var paragraph in headers.Odd.Paragraphs)
+ foreach( var paragraph in headers.Odd.Paragraphs )
{
- bookmarks.AddRange(paragraph.GetBookmarks());
+ bookmarks.AddRange( paragraph.GetBookmarks() );
}
}
- if (headers.Even != null)
+ if( headers.Even != null )
{
- foreach (var paragraph in headers.Even.Paragraphs)
+ foreach( var paragraph in headers.Even.Paragraphs )
{
- bookmarks.AddRange(paragraph.GetBookmarks());
+ bookmarks.AddRange( paragraph.GetBookmarks() );
}
}
- if (headers.First != null)
+ if( headers.First != null )
{
- foreach (var paragraph in headers.First.Paragraphs)
+ foreach( var paragraph in headers.First.Paragraphs )
{
- bookmarks.AddRange(paragraph.GetBookmarks());
+ bookmarks.AddRange( paragraph.GetBookmarks() );
}
}
}
// In Footers.
var footers = section.Footers;
- if (footers != null)
+ if( footers != null )
{
- if (footers.Odd != null)
+ if( footers.Odd != null )
{
- foreach (var paragraph in footers.Odd.Paragraphs)
+ foreach( var paragraph in footers.Odd.Paragraphs )
{
- bookmarks.AddRange(paragraph.GetBookmarks());
+ bookmarks.AddRange( paragraph.GetBookmarks() );
}
}
- if (footers.Even != null)
+ if( footers.Even != null )
{
- foreach (var paragraph in footers.Even.Paragraphs)
+ foreach( var paragraph in footers.Even.Paragraphs )
{
- bookmarks.AddRange(paragraph.GetBookmarks());
+ bookmarks.AddRange( paragraph.GetBookmarks() );
}
}
- if (footers.First != null)
+ if( footers.First != null )
{
- foreach (var paragraph in footers.First.Paragraphs)
+ foreach( var paragraph in footers.First.Paragraphs )
{
- bookmarks.AddRange(paragraph.GetBookmarks());
+ bookmarks.AddRange( paragraph.GetBookmarks() );
}
}
}
@@ -1022,13 +1070,11 @@ public BookmarkCollection Bookmarks
+ #endregion
+ #region Public Methods
-
-
- #endregion
- #region Public Methods
public override Section InsertSection( bool trackChanges )
{
@@ -1849,6 +1895,172 @@ public Table AddTable( int rowCount, int columnCount )
+ public Footnote AddFootnote( object footnoteContent, Formatting formatting = null )
+ {
+ if( footnoteContent == null )
+ return null;
+
+ var footnotes_package_uri = new Uri( "/word/footnotes.xml", UriKind.Relative );
+
+ if( !this.Document._package.PartExists( footnotes_package_uri ) )
+ {
+ var mainDocPart = HelperFunctions.GetMainDocumentPart( this.Document._package );
+ mainDocPart.CreateRelationship( footnotes_package_uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" );
+
+ // Create default footnotes in _footnotes.
+ this.Document._footnotes = XDocument.Parse
+ ( @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "
+ );
+
+ // Create Footnotes package.
+ var footnotes_package = this.Document._package.CreatePart( footnotes_package_uri, "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", CompressionOption.Maximum );
+ this.Document._footnotesPart = footnotes_package;
+ }
+
+ var newFootnoteId = this.GetMaxId( this.Document._footnotes.Root.LastNode as XElement );
+ if( newFootnoteId < 0 )
+ return null;
+
+ // Create new footnote.
+ var newFootnoteXml = XElement.Parse
+ ( string.Format( @"
+ ", newFootnoteId )
+ );
+
+ // Create new footnote paragraph.
+ var newFootnoteParagraphXml = XElement.Parse(
+ @"
+
+
+
+
+
+
+
+
+
+
+
+
+ " );
+ var newFootnoteParagraph = new Paragraph( this, newFootnoteParagraphXml, 0 ) { PackagePart = _footnotesPart };
+
+ this.UpdateNoteXmlFromContent( newFootnoteXml, newFootnoteParagraph, footnoteContent, formatting );
+
+ // Create new footnote from updated newFootnoteXml.
+ var newFootnote = new Footnote( this, _footnotesPart, newFootnoteXml );
+
+ // Add newFootnote in _footnotes.
+ this.Document._footnotes.Root.Add( newFootnote.Xml );
+
+ return newFootnote;
+ }
+
+ public Endnote AddEndnote( object endnoteContent, Formatting formatting = null )
+ {
+ if( endnoteContent == null )
+ return null;
+
+ var endnotes_package_uri = new Uri( "/word/endnotes.xml", UriKind.Relative );
+
+ if( !this.Document._package.PartExists( endnotes_package_uri ) )
+ {
+ var mainDocPart = HelperFunctions.GetMainDocumentPart( this.Document._package );
+ mainDocPart.CreateRelationship( endnotes_package_uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes" );
+
+ // Create default endnotes in _endnotes.
+ this.Document._endnotes = XDocument.Parse
+ ( @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "
+ );
+
+ // Create Endnotes package.
+ var endnotes_package = this.Document._package.CreatePart( endnotes_package_uri, "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml", CompressionOption.Maximum );
+ this.Document._endnotesPart = endnotes_package;
+ }
+
+ var newEndnoteId = this.GetMaxId( this.Document._endnotes.Root.LastNode as XElement );
+ if( newEndnoteId < 0 )
+ return null;
+
+ // Create new endnote.
+ var newEndnoteXml = XElement.Parse
+ ( string.Format( @"
+ ", newEndnoteId )
+ );
+
+ // Create new endnote paragraph.
+ var newEndnoteParagraphXml = XElement.Parse(
+ @"
+
+
+
+
+
+
+
+
+
+
+
+
+ " );
+ var newEndnoteParagraph = new Paragraph( this, newEndnoteParagraphXml, 0 ) { PackagePart = _endnotesPart };
+
+ this.UpdateNoteXmlFromContent( newEndnoteXml, newEndnoteParagraph, endnoteContent, formatting );
+
+ // Create new endnote from updated newEndnoteXml.
+ var newEndnote = new Endnote( this, _endnotesPart, newEndnoteXml );
+
+ // Add newEndnote in _endnotes.
+ this.Document._endnotes.Root.Add( newEndnote.Xml );
+
+ return newEndnote;
+ }
+
///
/// Applies document template to the document. Document template may include styles, headers, footers, properties, etc. as well as text content.
///
@@ -2009,7 +2221,6 @@ public void ApplyTemplate( Stream templateStream, bool includeContent )
}
finally
{
- _package.Flush();
templatePackage.Close();
PopulateDocument( Document, _package );
}
@@ -2607,7 +2818,19 @@ public void InsertChartAfterParagraph( Chart chart, Paragraph paragraph, float w
///
public List AddList( string listText = null, int level = 0, ListItemType listType = ListItemType.Numbered, int? startNumber = null, bool trackChanges = false, bool continueNumbering = false, Formatting formatting = null )
{
- return AddListItem( new List( this, null ), listText, level, listType, startNumber, trackChanges, continueNumbering, formatting );
+ if( startNumber.HasValue && continueNumbering )
+ throw new InvalidOperationException( "Cannot specify a start number and at the same time continue numbering from another list" );
+
+ var list = new List( this, null );
+ var result = HelperFunctions.CreateItemInList( list, listText, level, listType, startNumber, trackChanges, continueNumbering, formatting );
+ var lastItem = result.Items.LastOrDefault();
+
+ if( lastItem != null )
+ {
+ lastItem.PackagePart = this.PackagePart;
+ }
+
+ return result;
}
@@ -2616,10 +2839,20 @@ public List AddList( string listText = null, int level = 0, ListItemType listTyp
+
+
+
///
/// Add a list item to an existing list
///
- public List AddListItem( List list, string listText, int level = 0, ListItemType listType = ListItemType.Numbered, int? startNumber = null, bool trackChanges = false, bool continueNumbering = false, Formatting formatting = null )
+ public List AddListItem( List list,
+ string listText,
+ int level = 0,
+ ListItemType listType = ListItemType.Numbered,
+ int? startNumber = null,
+ bool trackChanges = false,
+ bool continueNumbering = false,
+ Formatting formatting = null )
{
if( startNumber.HasValue && continueNumbering )
throw new InvalidOperationException( "Cannot specify a start number and at the same time continue numbering from another list" );
@@ -2662,7 +2895,7 @@ public override List InsertList( List list, double fontSize )
/// Insert a list at an index location in the document
///
/// Index in document to insert the list.
- /// The list that was inserted into the document.
+ /// The list that was inserted into the document.
///
public new List InsertList( int index, List list )
{
@@ -2859,6 +3092,8 @@ public void SetDefaultFont( Font fontFamily, double fontSize = 11d, Color? fontC
+
+
#endregion
#region Internal Methods
@@ -2867,6 +3102,11 @@ protected internal virtual void SaveHeadersFooters()
{
}
+
+
+
+
+
internal XDocument GetSettings()
{
if( _settings != null )
@@ -3010,6 +3250,13 @@ internal static Document PostLoad( ref Package package, Document document, Docum
}
}
+ var docType = document._mainDoc.DocumentType;
+ if( ( docType != null ) && !string.IsNullOrEmpty( docType.InternalSubset ) )
+ {
+ if( docType.InternalSubset.Contains( "ENTITY" ) )
+ throw new InvalidDataException( "Document to load contains external entities which are not supported" );
+ }
+
return document;
}
@@ -3035,6 +3282,7 @@ internal static Document Load( Stream stream, Document document, DocumentTypes d
document._package = package;
document._memoryStream = ms;
document._stream = stream;
+
return document;
}
@@ -3056,6 +3304,7 @@ internal static Document Load( string filename, Document document, DocumentTypes
Stream receiveStream = null;
try
{
+ ServicePointManager.SecurityProtocol = ( SecurityProtocolType )3072;
request = ( HttpWebRequest )WebRequest.Create( filename );
response = ( HttpWebResponse )request.GetResponse();
receiveStream = response.GetResponseStream();
@@ -3344,6 +3593,44 @@ internal Image AddImage( object o, string contentType = "image/jpeg" )
}
}
+ internal Image GetImage( Stream stream )
+ {
+ if( stream == null )
+ return null;
+
+ stream.Position = 0;
+
+ var imageParts = new Dictionary();
+ var partLookup = _package.GetParts().ToDictionary( x => x.Uri.ToString(), x => x, StringComparer.Ordinal );
+
+ // all image relationships.
+ var relationshipImages = this.PackagePart.GetRelationshipsByType( RelationshipImage );
+ // take all used images (from relationships)
+ foreach( var item in relationshipImages )
+ {
+ var targetUri = item.TargetUri.ToString();
+ PackagePart part;
+ if( partLookup.TryGetValue( targetUri, out part ) )
+ {
+ // all document's used image parts.
+ imageParts.Add( item, part );
+ }
+ }
+
+ foreach( var entry in imageParts )
+ {
+ // Get the image object for this image part.
+ using( var tempStream = entry.Value.GetStream( FileMode.Open, FileAccess.Read ) )
+ {
+ // Compare this image to the new image being added.
+ if( HelperFunctions.IsSameFile( tempStream, stream ) )
+ return new Image( this, entry.Key );
+ }
+ }
+
+ return null;
+ }
+
internal static void UpdateCorePropertyValue( Document document, string corePropertyName, string corePropertyValue )
{
var matchPattern = string.Format( @"(DOCPROPERTY)?{0}\\\*MERGEFORMAT", corePropertyName ).ToLower();
@@ -3488,10 +3775,23 @@ internal static void UpdateCustomPropertyValue( Document document, CustomPropert
foreach( XElement doc in documents )
{
#region Word 2010+
- foreach( XElement e in doc.Descendants( XName.Get( "instrText", w.NamespaceName ) ) )
+ var instrTexts = doc.Descendants( XName.Get( "instrText", w.NamespaceName ) );
+ for( int i = 0; i < instrTexts.Count(); ++i )
{
+ var e = instrTexts.ElementAt( i );
var attr_value = e.Value.Replace( " ", string.Empty ).Trim();
+ if( attr_value.StartsWith( "DOCPROPERTY" ) && !attr_value.EndsWith( "MERGEFORMAT" ) && ( i < instrTexts.Count() - 1 ) )
+ {
+ var nextInstrText = instrTexts.ElementAt( i + 1 );
+ var nextAttr_value = nextInstrText.Value.Replace( " ", string.Empty ).Trim();
+ if( !nextAttr_value.StartsWith( "DOCPROP" ) && nextAttr_value.EndsWith( "FORMAT" ) )
+ {
+ attr_value += nextAttr_value;
+ i++;
+ }
+ }
+
if( attr_value.Equals( match_value, StringComparison.CurrentCultureIgnoreCase ) )
{
var node = e.Parent.NextNode;
@@ -4506,6 +4806,20 @@ private void merge_styles( PackagePart remote_pp, PackagePart local_pp, XDocumen
+
+
+
+
+
+
+
+
+
+
+
+
+
+
protected void clonePackageRelationship( Document remote_document, PackagePart pp, XDocument remote_mainDoc )
@@ -4874,6 +5188,53 @@ private void InsertChart( Chart chart, Paragraph paragraph, float width = 432f,
p.Xml.Add( chartElement );
}
+ private void UpdateNoteXmlFromContent( XElement noteXml, Paragraph noteParagraph, object footnoteContent, Formatting formatting )
+ {
+ Debug.Assert( noteXml != null, "noteXml should not be null." );
+ Debug.Assert( noteParagraph != null, "noteParagraph should not be null." );
+
+ if( footnoteContent is string )
+ {
+ noteParagraph.InsertText( footnoteContent as string, false, formatting );
+ }
+ else if( footnoteContent is Hyperlink )
+ {
+ noteParagraph.InsertHyperlink( footnoteContent as Hyperlink, noteParagraph.Text.Length );
+ }
+ else if( footnoteContent is Picture )
+ {
+ noteParagraph.InsertPicture( footnoteContent as Picture, noteParagraph.Text.Length );
+ }
+ else if( !( footnoteContent is Table ) )
+ {
+ throw new ArgumentException( "Unknown object received for footnote/endnote. Valid objects are string, Picture, Hyperlink or Table. If other configuration is needed, try using the Note.Paragraphs property and configure the Footnote/Endnote paragraphs." );
+ }
+
+ noteXml.Add( noteParagraph.Xml );
+
+ // Tables need to be added after the newFootnoteParagraph is included inside the newFootnoteXml. This is because table is located after paragraph.
+ if( footnoteContent is Table )
+ {
+ noteParagraph.InsertTableAfterSelf( footnoteContent as Table );
+ }
+ }
+
+ private int GetMaxId( XElement xElement )
+ {
+ if( xElement == null )
+ return -1;
+
+ var lastId = xElement.Attribute( XName.Get( "id", Document.w.NamespaceName ) );
+ if( lastId == null )
+ return -1;
+
+ return Int32.Parse( lastId.Value ) + 1;
+ }
+
+
+
+
+
#endregion
diff --git a/Xceed.Document.NET/Src/Endnote.cs b/Xceed.Document.NET/Src/Endnote.cs
new file mode 100644
index 00000000..087902ea
--- /dev/null
+++ b/Xceed.Document.NET/Src/Endnote.cs
@@ -0,0 +1,69 @@
+/***************************************************************************************
+
+ DocX – DocX is the community edition of Xceed Words for .NET
+
+ Copyright (C) 2009-2020 Xceed Software Inc.
+
+ This program is provided to you under the terms of the XCEED SOFTWARE, INC.
+ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
+ https://github.com/xceedsoftware/DocX/blob/master/license.md
+
+ For more features and fast professional support,
+ pick up Xceed Words for .NET at https://xceed.com/xceed-words-for-net/
+
+ *************************************************************************************/
+
+
+using System.IO.Packaging;
+using System.Xml.Linq;
+
+namespace Xceed.Document.NET
+{
+ public class Endnote: Note
+ {
+ #region Constructor
+
+ internal Endnote( Document document, PackagePart part, XElement xml ) : base( document, part, xml )
+ {
+ }
+
+ #endregion
+
+ #region Overrides
+
+ internal override string GetNoteRefType()
+ {
+ return "endnoteRef";
+ }
+
+ internal override XElement CreateReferenceRunCore( bool customMarkFollows, XElement symbol, Formatting noteNumberFormatting )
+ {
+ var rPr = (noteNumberFormatting != null)
+ ? noteNumberFormatting.Xml
+ : new XElement( XName.Get( "rPr", Document.w.NamespaceName ) );
+
+ rPr.AddFirst( new XElement( XName.Get( "rStyle", Document.w.NamespaceName ),
+ new XAttribute( XName.Get( "val", Document.w.NamespaceName ), "EndnoteReference" ) ) );
+
+ var r = new XElement( XName.Get( "r", Document.w.NamespaceName ) );
+ r.Add( rPr );
+
+ var endNoteReference = new XElement( XName.Get( "endnoteReference", Document.w.NamespaceName ),
+ new XAttribute( XName.Get( "id", Document.w.NamespaceName ), this.Id ) );
+ if( customMarkFollows )
+ {
+ endNoteReference.SetAttributeValue( XName.Get( "customMarkFollows", Document.w.NamespaceName ), "1" );
+ }
+ if( symbol != null )
+ {
+ endNoteReference.Add( symbol );
+ }
+
+ r.Add( endNoteReference );
+
+ return r;
+ }
+
+ #endregion
+ }
+}
diff --git a/Xceed.Document.NET/Src/Font.cs b/Xceed.Document.NET/Src/Font.cs
index 16861de1..90ceb40e 100644
--- a/Xceed.Document.NET/Src/Font.cs
+++ b/Xceed.Document.NET/Src/Font.cs
@@ -18,25 +18,52 @@ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
namespace Xceed.Document.NET
{
- public sealed class Font
+ public sealed class Font
+ {
+ public Font( string name )
{
- public Font(string name)
- {
- if (string.IsNullOrEmpty(name))
- throw new ArgumentNullException(nameof(name));
-
- Name = name;
- }
-
- public string Name
- {
- get;
- private set;
- }
-
- public override string ToString()
- {
- return Name;
- }
+ if( string.IsNullOrEmpty( name ) )
+ throw new ArgumentNullException( nameof( name ) );
+
+ Name = name;
+ }
+
+ public string Name
+ {
+ get;
+ private set;
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+
+ public static bool operator ==( Font x, Font y )
+ {
+ return object.Equals( x, y );
+ }
+
+ public static bool operator !=( Font x, Font y )
+ {
+ return !object.Equals( x, y );
+ }
+
+ public override bool Equals( object obj )
+ {
+ if( obj == null )
+ return false;
+ if( ReferenceEquals( obj, this ) )
+ return true;
+ if( obj.GetType() != this.GetType() )
+ return false;
+ Font rhs = obj as Font;
+ return this.Name == rhs.Name;
+ }
+
+ public override int GetHashCode()
+ {
+ return this.Name.GetHashCode();
}
+ }
}
diff --git a/Xceed.Document.NET/Src/Footnote.cs b/Xceed.Document.NET/Src/Footnote.cs
new file mode 100644
index 00000000..7de026ae
--- /dev/null
+++ b/Xceed.Document.NET/Src/Footnote.cs
@@ -0,0 +1,69 @@
+/***************************************************************************************
+
+ DocX – DocX is the community edition of Xceed Words for .NET
+
+ Copyright (C) 2009-2020 Xceed Software Inc.
+
+ This program is provided to you under the terms of the XCEED SOFTWARE, INC.
+ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
+ https://github.com/xceedsoftware/DocX/blob/master/license.md
+
+ For more features and fast professional support,
+ pick up Xceed Words for .NET at https://xceed.com/xceed-words-for-net/
+
+ *************************************************************************************/
+
+
+using System.IO.Packaging;
+using System.Xml.Linq;
+
+namespace Xceed.Document.NET
+{
+ public class Footnote : Note
+ {
+ #region Constructor
+
+ internal Footnote( Document document, PackagePart part, XElement xml ) : base( document, part, xml )
+ {
+ }
+
+ #endregion
+
+ #region Overrides
+
+ internal override string GetNoteRefType()
+ {
+ return "footnoteRef";
+ }
+
+ internal override XElement CreateReferenceRunCore( bool customMarkFollows, XElement symbol, Formatting noteNumberFormatting )
+ {
+ var rPr = ( noteNumberFormatting != null )
+ ? noteNumberFormatting.Xml
+ : new XElement( XName.Get( "rPr", Document.w.NamespaceName ) );
+
+ rPr.Add( new XElement( XName.Get( "rStyle", Document.w.NamespaceName ),
+ new XAttribute( XName.Get( "val", Document.w.NamespaceName ), "FootnoteReference" ) ) );
+
+ var r = new XElement( XName.Get( "r", Document.w.NamespaceName ) );
+ r.Add( rPr );
+
+ var footNoteReference = new XElement( XName.Get( "footnoteReference", Document.w.NamespaceName ),
+ new XAttribute( XName.Get( "id", Document.w.NamespaceName ), this.Id ) );
+ if( customMarkFollows )
+ {
+ footNoteReference.SetAttributeValue( XName.Get( "customMarkFollows", Document.w.NamespaceName ), "1" );
+ }
+ if( symbol != null )
+ {
+ footNoteReference.Add( symbol );
+ }
+
+ r.Add( footNoteReference );
+
+ return r;
+ }
+
+ #endregion
+ }
+}
diff --git a/Xceed.Document.NET/Src/Formatting.cs b/Xceed.Document.NET/Src/Formatting.cs
index 32dd812c..7d4b177f 100644
--- a/Xceed.Document.NET/Src/Formatting.cs
+++ b/Xceed.Document.NET/Src/Formatting.cs
@@ -162,17 +162,24 @@ public double? Size
{
double? temp = value * 2;
- if( temp - (int)temp == 0 )
+ // Accepting only whole number or half number.
+ if( temp - (int)temp != 0 )
{
- if( value > 0 && value < 1639 )
+ if( value.HasValue )
{
- _size = value;
+ value = Math.Round( value.Value );
}
- else
- throw new ArgumentException( "Size", "Value must be in the range 0 - 1638" );
+ }
+
+ if( value == 0 )
+ return;
+
+ if( value > 0 && value < 1639 )
+ {
+ _size = value;
}
else
- throw new ArgumentException( "Size", "Value must be either a whole or half number, examples: 32, 32.5" );
+ throw new ArgumentException( "Size", "Value must be in the range 0 - 1638" );
}
}
diff --git a/Xceed.Document.NET/Src/HelperFunctions.cs b/Xceed.Document.NET/Src/HelperFunctions.cs
index 4b9abc0e..d793444e 100644
--- a/Xceed.Document.NET/Src/HelperFunctions.cs
+++ b/Xceed.Document.NET/Src/HelperFunctions.cs
@@ -37,7 +37,7 @@ internal enum ResourceType
NumberingDecimal,
Numbering,
Styles,
- Theme
+ Theme,
}
internal static class HelperFunctions
@@ -386,7 +386,7 @@ internal static XDocument DecompressXMLResource( string manifest_resource_name )
// XDocument to load the compressed Xml resource into.
XDocument document;
- // Get a reference to the executing assembly.
+ //// Get a reference to the executing assembly.
Assembly assembly = Assembly.GetExecutingAssembly();
// Open a Stream to the embedded resource.
@@ -412,51 +412,27 @@ internal static string GetResources( ResourceType resType )
{
case ResourceType.DefaultStyle:
{
-#if NETSTANDARD
- return "Xceed.Document.NETStandard.Resources.default_styles.xml.gz";
-#else
return "Xceed.Document.NET.Resources.default_styles.xml.gz";
-#endif
}
case ResourceType.Numbering:
{
-#if NETSTANDARD
- return "Xceed.Document.NETStandard.Resources.numbering.xml.gz";
-#else
return "Xceed.Document.NET.Resources.numbering.xml.gz";
-#endif
}
case ResourceType.NumberingBullet:
{
-#if NETSTANDARD
- return "Xceed.Document.NETStandard.Resources.numbering.default_bullet_abstract.xml.gz";
-#else
return "Xceed.Document.NET.Resources.numbering.default_bullet_abstract.xml.gz";
-#endif
}
case ResourceType.NumberingDecimal:
{
-#if NETSTANDARD
- return "Xceed.Document.NETStandard.Resources.numbering.default_decimal_abstract.xml.gz";
-#else
return "Xceed.Document.NET.Resources.numbering.default_decimal_abstract.xml.gz";
-#endif
}
case ResourceType.Styles:
{
-#if NETSTANDARD
- return "Xceed.Document.NETStandard.Resources.styles.xml.gz";
-#else
return "Xceed.Document.NET.Resources.styles.xml.gz";
-#endif
}
case ResourceType.Theme:
{
-#if NETSTANDARD
- return "Xceed.Document.NETStandard.Resources.theme.xml.gz";
-#else
return "Xceed.Document.NET.Resources.theme.xml.gz";
-#endif
}
}
@@ -495,7 +471,7 @@ internal static XElement CreateEdit( EditType t, DateTime edit_time, object cont
{
if( t == EditType.del )
{
- foreach( object o in (IEnumerable)content )
+ foreach( object o in ( IEnumerable )content )
{
if( o is XElement )
{
@@ -578,6 +554,15 @@ internal static XElement CreateTableCell( double w = 2310 )
+
+
+
+
+
+
+
+
+
internal static void RenumberIDs( Document document )
@@ -773,13 +758,13 @@ internal static XDocument AddDefaultNumberingXml( Package package )
return numberingDoc;
}
- internal static List CreateItemInList( List list,
- string listText,
+ internal static List CreateItemInList( List list,
+ string listText,
int level = 0,
ListItemType listType = ListItemType.Numbered,
- int? startNumber = null,
- bool trackChanges = false,
- bool continueNumbering = false,
+ int? startNumber = null,
+ bool trackChanges = false,
+ bool continueNumbering = false,
Formatting formatting = null )
{
if( list.NumId == 0 )
@@ -826,7 +811,7 @@ internal static List CreateItemInList( List list,
if( startNumber == null )
list.AddItem( new Paragraph( list.Document, newSection, 0, ContainerType.Paragraph ) );
else
- list.AddItemWithStartValue( new Paragraph( list.Document, newSection, 0, ContainerType.Paragraph ), (int)startNumber );
+ list.AddItemWithStartValue( new Paragraph( list.Document, newSection, 0, ContainerType.Paragraph ), ( int )startNumber );
}
return list;
}
@@ -982,6 +967,33 @@ internal static XElement GetAbstractNum( Document document, string numId )
return abstractNumNode;
}
+ internal static IEnumerable GetAbstractNumLevelNodes( Document document, string numId )
+ {
+ var abstractNum = GetAbstractNum( document, numId );
+
+ if( abstractNum != null )
+ {
+ var levelNodes = abstractNum.Elements( XName.Get( "lvl", Document.w.NamespaceName ) );
+ if( levelNodes != null )
+ {
+ return levelNodes;
+ }
+ }
+
+ return null;
+ }
+
+ internal static XElement GetNumberingNumNode( Document document, string numId )
+ {
+ if( document == null )
+ return null;
+ if( numId == null )
+ return null;
+
+ var numNodes = document._numbering.Root.Elements( XName.Get( "num", Document.w.NamespaceName ) );
+ return numNodes?.SingleOrDefault( node => node.Attribute( Document.w + "numId" ).Value.Equals( numId ) ) ?? null;
+ }
+
internal static string GetAbstractNumIdValue( Document document, string numId )
{
if( document == null )
@@ -1157,7 +1169,7 @@ internal static Border GetBorderFromXml( XElement xml )
var bdrStyle = xml.Attribute( XName.Get( "val", Document.w.NamespaceName ) );
if( bdrStyle != null )
{
- borderStyle = (BorderStyle)Enum.Parse( typeof( BorderStyle ), "Tcbs_" + bdrStyle.Value );
+ borderStyle = ( BorderStyle )Enum.Parse( typeof( BorderStyle ), "Tcbs_" + bdrStyle.Value );
}
return new Border( borderStyle, borderSize, borderSpace, borderColor );
diff --git a/Xceed.Document.NET/Src/Hyperlink.cs b/Xceed.Document.NET/Src/Hyperlink.cs
index a18eb800..986855e8 100644
--- a/Xceed.Document.NET/Src/Hyperlink.cs
+++ b/Xceed.Document.NET/Src/Hyperlink.cs
@@ -226,23 +226,18 @@ internal Hyperlink( Document document, XElement instrText, List runs )
this.instrText = instrText;
this.runs = runs;
- try
+ int start = instrText.Value.IndexOf( "HYPERLINK \"" );
+ if( start != -1 )
+ start += "HYPERLINK \"".Length;
+ int end = instrText.Value.IndexOf( "\"", Math.Max( 0, start ));
+ if( start != -1 && end != -1 )
{
- int start = instrText.Value.IndexOf( "HYPERLINK \"" );
- if( start != -1 )
- start += "HYPERLINK \"".Length;
- int end = instrText.Value.IndexOf( "\"", Math.Max( 0, start ));
- if( start != -1 && end != -1 )
- {
- this.uri = new Uri( instrText.Value.Substring( start, end - start ), UriKind.Absolute );
+ this.uri = new Uri( instrText.Value.Substring( start, end - start ), UriKind.Absolute );
- StringBuilder sb = new StringBuilder();
- HelperFunctions.GetTextRecursive( new XElement( XName.Get( "temp", Document.w.NamespaceName ), runs ), ref sb );
- this.text = sb.ToString();
- }
+ StringBuilder sb = new StringBuilder();
+ HelperFunctions.GetTextRecursive( new XElement( XName.Get( "temp", Document.w.NamespaceName ), runs ), ref sb );
+ this.text = sb.ToString();
}
-
- catch( Exception e ) { throw e; }
}
#endregion
diff --git a/Xceed.Document.NET/Src/Image.cs b/Xceed.Document.NET/Src/Image.cs
index b4567b58..09be4963 100644
--- a/Xceed.Document.NET/Src/Image.cs
+++ b/Xceed.Document.NET/Src/Image.cs
@@ -134,6 +134,19 @@ public Picture CreatePicture( float height, float width )
return Paragraph.CreatePicture( _document, _id, string.Empty, string.Empty, width, height );
}
+ public void Remove()
+ {
+ if( _pr.Package != null )
+ {
+ _pr.Package.DeletePart( _pr.TargetUri );
+ }
+
+ if( _document.PackagePart != null )
+ {
+ _document.PackagePart.DeleteRelationship( _id );
+ }
+ }
+
#endregion
}
}
diff --git a/Xceed.Document.NET/Src/List.cs b/Xceed.Document.NET/Src/List.cs
index 8d8dfb91..f2c234c0 100644
--- a/Xceed.Document.NET/Src/List.cs
+++ b/Xceed.Document.NET/Src/List.cs
@@ -18,6 +18,8 @@ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
using System.Linq;
using System.Xml.Linq;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
namespace Xceed.Document.NET
{
@@ -26,6 +28,20 @@ namespace Xceed.Document.NET
///
public class List : InsertBeforeOrAfter
{
+
+ #region Private properties
+
+ private static Random _random = new Random();
+
+ #endregion
+
+ #region Private Members
+
+ private ListItemType? _listType;
+
+
+ #endregion
+
#region Public Properties
///
@@ -51,12 +67,21 @@ public int NumId
///
public ListItemType? ListType
{
- get; private set;
+ get
+ {
+ return _listType;
+ }
}
- #endregion
- #region Internal Properties
+
+
+
+
+
+
+
+
public int AbstractNumId
{
@@ -75,7 +100,6 @@ internal List( Document document, XElement xml )
: base( document, xml )
{
Items = new List();
- ListType = null;
}
#endregion
@@ -100,12 +124,12 @@ public void AddItem( Paragraph paragraph )
if( this.CanAddListItem( paragraph ) )
{
this.NumId = numId;
- if( this.ListType == null )
+ if( _listType == null )
{
var listItemType = HelperFunctions.GetListItemType( paragraph, this.Document );
if( listItemType != null )
{
- this.ListType = listItemType.Equals( "bullet" ) ? ListItemType.Bulleted : ListItemType.Numbered;
+ _listType = listItemType.Equals( "bullet" ) ? ListItemType.Bulleted : ListItemType.Numbered;
}
}
this.Items.Add( paragraph );
@@ -148,42 +172,54 @@ public bool CanAddListItem( Paragraph paragraph )
return false;
}
+
+
public bool ContainsLevel( int ilvl )
{
return Items.Any( i => i.ParagraphNumberProperties.Descendants().First( el => el.Name.LocalName == "ilvl" ).Value == ilvl.ToString() );
}
+ public void Remove()
+ {
+ // Remove AbstractNum and Num from numbering.xml.
+ var abstractNumId = this.GetAbstractNum( this.NumId );
+ if( abstractNumId != null )
+ {
+ abstractNumId.Remove();
+ }
+
+ var numNode = this.Document._numbering.Descendants()
+ .Where( n => n.Name.LocalName == "num" )
+ .FirstOrDefault( node => node.Attribute( Document.w + "numId" ).Value.Equals( this.NumId.ToString() ) );
+ if( numNode != null )
+ {
+ numNode.Remove();
+ }
+
+ // Remove listItems from document.
+ this.Items.ForEach( paragraph => paragraph.Remove( false ) );
+ }
+
#endregion
#region Internal Methods
internal void CreateNewNumberingNumId( int level = 0, ListItemType listType = ListItemType.Numbered, int? startNumber = null, bool continueNumbering = false )
{
- ValidateDocXNumberingPartExists();
- if( Document._numbering.Root == null )
+ int numId, abstractNumId;
+ XElement abstractNumTemplate;
+ SetAbstractNumTemplate( listType, out numId, out abstractNumId, out abstractNumTemplate );
+
+ // When documents contains many lists, generate different "nsid" for each abstractNumTemplate.
+ // Each "nsid" value should be unique.
+ var nsid = abstractNumTemplate.Element( Document.w + "nsid" );
+ var val = nsid.Attribute( Document.w + "val" );
+ if( val != null )
{
- throw new InvalidOperationException( "Numbering section did not instantiate properly." );
+ var newNSidVal = GetRandomHexNumber();
+ nsid.SetAttributeValue( Document.w + "val", newNSidVal );
}
- ListType = listType;
-
- var numId = GetMaxNumId() + 1;
- var abstractNumId = GetMaxAbstractNumId() + 1;
-
- XDocument listTemplate;
- switch( listType )
- {
- case ListItemType.Bulleted:
- listTemplate = HelperFunctions.DecompressXMLResource( HelperFunctions.GetResources( ResourceType.NumberingBullet ) );
- break;
- case ListItemType.Numbered:
- listTemplate = HelperFunctions.DecompressXMLResource( HelperFunctions.GetResources( ResourceType.NumberingDecimal ) );
- break;
- default:
- throw new InvalidOperationException( string.Format( "Unable to deal with ListItemType: {0}.", listType.ToString() ) );
- }
- var abstractNumTemplate = listTemplate.Descendants().Single( d => d.Name.LocalName == "abstractNum" );
- abstractNumTemplate.SetAttributeValue( Document.w + "abstractNumId", abstractNumId );
var abstractNumXml = GetAbstractNumXml( abstractNumId, numId, startNumber, level, continueNumbering );
var abstractNumNode = Document._numbering.Root.Descendants().LastOrDefault( xElement => xElement.Name.LocalName == "abstractNum" );
@@ -205,6 +241,24 @@ internal void CreateNewNumberingNumId( int level = 0, ListItemType listType = Li
NumId = numId;
}
+ internal static string GetRandomHexNumber()
+ {
+ int digits = 8;
+ byte[] buffer = new byte[ digits / 2 ];
+
+ _random.NextBytes( buffer );
+ string result = string.Concat( buffer.Select( x => x.ToString( "X2" ) ).ToArray() );
+ if( digits % 2 == 0 )
+ return result;
+ return result + _random.Next( 16 ).ToString( "X" );
+ }
+
+
+
+
+
+
+
@@ -225,6 +279,94 @@ internal XElement GetAbstractNum( int numId )
#region Private Methods
+ private XDocument GetListTemplate( ListItemType listType )
+ {
+ switch( listType )
+ {
+ case ListItemType.Bulleted:
+ return HelperFunctions.DecompressXMLResource( HelperFunctions.GetResources( ResourceType.NumberingBullet ) );
+ case ListItemType.Numbered:
+ return HelperFunctions.DecompressXMLResource( HelperFunctions.GetResources( ResourceType.NumberingDecimal ) );
+ default:
+ throw new InvalidOperationException( string.Format( "Unable to deal with ListItemType: {0}.", listType.ToString() ) );
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private void SetAbstractNumTemplate( ListItemType listType, out int numId, out int abstractNumId, out XElement abstractNumTemplate )
+ {
+ ValidateDocXNumberingPartExists();
+ if( Document._numbering.Root == null )
+ {
+ throw new InvalidOperationException( "Numbering section did not instantiate properly." );
+ }
+
+ _listType = listType;
+
+ numId = GetMaxNumId() + 1;
+ abstractNumId = GetMaxAbstractNumId() + 1;
+ XDocument listTemplate = GetListTemplate( listType );
+
+ abstractNumTemplate = listTemplate.Descendants().Single( d => d.Name.LocalName == "abstractNum" );
+ abstractNumTemplate.SetAttributeValue( Document.w + "abstractNumId", abstractNumId );
+ }
+
private void UpdateNumberingForLevelStartNumber( int iLevel, int start )
{
// Find num node in numbering.
@@ -279,6 +421,7 @@ private XElement GetAbstractNumXml( int abstractNumId, int numId, int? startNumb
: new XElement( XName.Get( "num", Document.w.NamespaceName ), new XAttribute( Document.w + "numId", numId ), element, levelOverride );
}
+
///
/// Method to determine the last numId for a list element.
/// Also useful for determining the next numId to use for inserting a new list element into the document.
@@ -337,4 +480,5 @@ private void ValidateDocXNumberingPartExists()
#endregion
}
+
}
diff --git a/Xceed.Document.NET/Src/Note.cs b/Xceed.Document.NET/Src/Note.cs
new file mode 100644
index 00000000..cce6dcb6
--- /dev/null
+++ b/Xceed.Document.NET/Src/Note.cs
@@ -0,0 +1,309 @@
+/***************************************************************************************
+
+ DocX – DocX is the community edition of Xceed Words for .NET
+
+ Copyright (C) 2009-2020 Xceed Software Inc.
+
+ This program is provided to you under the terms of the XCEED SOFTWARE, INC.
+ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
+ https://github.com/xceedsoftware/DocX/blob/master/license.md
+
+ For more features and fast professional support,
+ pick up Xceed Words for .NET at https://xceed.com/xceed-words-for-net/
+
+ *************************************************************************************/
+
+
+using System;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Globalization;
+using System.IO.Packaging;
+using System.Linq;
+using System.Xml.Linq;
+
+namespace Xceed.Document.NET
+{
+ public abstract class Note : Container, IParagraphContainer
+ {
+ #region Constants
+
+ internal static int DefaultCustomCharCode = 61440; //"F000"
+
+ #endregion
+
+ #region Private Members
+
+ private int _id;
+ private Symbol _customMark;
+
+ #endregion
+
+ #region Public Properties
+
+ #region CustomMark
+
+ public Symbol CustomMark
+ {
+ get
+ {
+ if( _customMark != null )
+ return _customMark;
+
+ var sym = this.Xml.Descendants( XName.Get( "sym", Document.w.NamespaceName ) ).FirstOrDefault();
+ if( sym != null )
+ {
+ _customMark = new Symbol();
+
+ var font = sym.GetAttribute( XName.Get( "font", Document.w.NamespaceName ) );
+ if( !string.IsNullOrEmpty( font ) )
+ {
+ _customMark.Font = new Font( font );
+ }
+
+ var code = sym.GetAttribute( XName.Get( "char", Document.w.NamespaceName ) );
+ if( !string.IsNullOrEmpty( code ) )
+ {
+ // Do code - "F000".
+ _customMark.Code = int.Parse( code, NumberStyles.HexNumber ) - DefaultCustomCharCode;
+ }
+
+ _customMark.PropertyChanged += this.CustomMark_PropertyChanged;
+
+ return _customMark;
+ }
+
+ return null;
+ }
+
+ set
+ {
+ if( _customMark != null )
+ {
+ _customMark.PropertyChanged -= this.CustomMark_PropertyChanged;
+ }
+
+ _customMark = value;
+
+ if( _customMark != null )
+ {
+ _customMark.PropertyChanged += this.CustomMark_PropertyChanged;
+ }
+
+ this.UpdateCustomMarkXml();
+ }
+ }
+
+ #endregion //CustomMark
+
+ #region Paragraphs
+
+ public override ReadOnlyCollection Paragraphs
+ {
+ get
+ {
+ var paragraphs = base.Paragraphs;
+ foreach( var paragraph in paragraphs )
+ {
+ paragraph.PackagePart = this.PackagePart;
+ }
+ return paragraphs;
+ }
+ }
+
+ #endregion // Paragraphs
+
+ #endregion
+
+ #region Internal Properties
+
+ #region Id
+
+ internal int Id
+ {
+ get
+ {
+ return _id;
+ }
+ }
+
+ #endregion //Id
+
+ #endregion
+
+ #region Constructor
+
+ internal Note( Document document, PackagePart part, XElement xml ) : base( document, xml )
+ {
+ this.PackagePart = part;
+
+ var id = this.Xml.Attribute( XName.Get( "id", Document.w.NamespaceName ) );
+ _id = ( id != null ) ? Int32.Parse( id.Value ) : 0;
+ }
+
+ #endregion
+
+ #region Internal Methods
+
+ internal abstract string GetNoteRefType();
+
+ internal abstract XElement CreateReferenceRunCore( bool customMarkFollows, XElement symbol, Formatting noteNumberFormatting );
+
+ internal XElement CreateReferenceRun( Formatting noteNumberFormatting )
+ {
+ var customMarkFollows = false;
+ XElement symbol = null;
+
+ if( this.CustomMark != null )
+ {
+ customMarkFollows = true;
+
+ var font = this.CustomMark.Font.Name;
+ var code = this.CustomMark.HexCode;
+ symbol = XElement.Parse( string.Format( @"", font, code ) );
+ }
+
+ // Create new reference for paragraph.
+ var referenceRun = this.CreateReferenceRunCore( customMarkFollows, symbol, noteNumberFormatting );
+
+ // When number formatting is used, update the number at the beginning of the note.
+ if( noteNumberFormatting != null )
+ {
+ var rPr = this.Xml.Descendants( XName.Get( "rPr", Document.w.NamespaceName ) ).FirstOrDefault();
+ if( rPr != null )
+ {
+ foreach( var numberFormattingElement in noteNumberFormatting.Xml.Elements() )
+ {
+ var runElement = rPr.Element( numberFormattingElement.Name );
+ // run doesn't contains the property, add it.
+ if( runElement == null )
+ {
+ rPr.Add( numberFormattingElement );
+ }
+ else
+ {
+ runElement.Remove();
+ rPr.Add( numberFormattingElement );
+ }
+ }
+ }
+ }
+
+ return referenceRun;
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private void UpdateCustomMarkXml()
+ {
+ if( _customMark != null )
+ {
+ var sym = new XElement( XName.Get( "sym", Document.w.NamespaceName ) );
+ sym.SetAttributeValue( XName.Get( "char", Document.w.NamespaceName ), _customMark.HexCode );
+ sym.SetAttributeValue( XName.Get( "font", Document.w.NamespaceName ), _customMark.Font.Name );
+
+ var noteRef = this.Xml.Descendants( XName.Get( this.GetNoteRefType(), Document.w.NamespaceName ) ).FirstOrDefault();
+ if( noteRef != null )
+ {
+ noteRef.ReplaceWith( sym );
+ }
+ else
+ {
+ var currentSym = this.Xml.Descendants( XName.Get( "sym", Document.w.NamespaceName ) ).FirstOrDefault();
+ if( currentSym != null )
+ {
+ currentSym.ReplaceWith( sym );
+ }
+ }
+ }
+ else
+ {
+ var currentSym = this.Xml.Descendants( XName.Get( "sym", Document.w.NamespaceName ) ).FirstOrDefault();
+ if( currentSym != null )
+ {
+ currentSym.ReplaceWith( new XElement( XName.Get( this.GetNoteRefType(), Document.w.NamespaceName ) ) );
+ }
+ }
+ }
+
+ #endregion
+
+ #region Event Handlers
+
+ private void CustomMark_PropertyChanged( object sender, PropertyChangedEventArgs e )
+ {
+ this.UpdateCustomMarkXml();
+ }
+
+ #endregion
+ }
+
+
+ public class Symbol : INotifyPropertyChanged
+ {
+ #region Private Members
+
+ private int _code;
+ private Font _font;
+
+ #endregion
+
+ #region Public Properties
+
+ public int Code
+ {
+ get
+ {
+ return _code;
+ }
+ set
+ {
+ _code = value;
+ OnPropertyChanged( "Code" );
+ }
+ }
+
+ public Font Font
+ {
+ get
+ {
+ return _font;
+ }
+ set
+ {
+ _font = value;
+ OnPropertyChanged( "Font" );
+ }
+ }
+
+ #endregion
+
+ #region Internal Properties
+
+ internal string HexCode
+ {
+ get
+ {
+ // Do "F000" + this.code.
+ return ( Footnote.DefaultCustomCharCode + this.Code ).ToString( "X" );
+ }
+ }
+
+ #endregion
+
+ #region INotifyPropertyChanged
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ protected void OnPropertyChanged( string propertyName )
+ {
+ if( PropertyChanged != null )
+ {
+ PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Xceed.Document.NET/Src/NoteProperties.cs b/Xceed.Document.NET/Src/NoteProperties.cs
new file mode 100644
index 00000000..17659846
--- /dev/null
+++ b/Xceed.Document.NET/Src/NoteProperties.cs
@@ -0,0 +1,73 @@
+/***************************************************************************************
+
+ DocX – DocX is the community edition of Xceed Words for .NET
+
+ Copyright (C) 2009-2020 Xceed Software Inc.
+
+ This program is provided to you under the terms of the XCEED SOFTWARE, INC.
+ COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
+ https://github.com/xceedsoftware/DocX/blob/master/license.md
+
+ For more features and fast professional support,
+ pick up Xceed Words for .NET at https://xceed.com/xceed-words-for-net/
+
+ *************************************************************************************/
+
+
+using System.ComponentModel;
+
+namespace Xceed.Document.NET
+{
+ public class NoteProperties : INotifyPropertyChanged
+ {
+ #region Private Members
+
+ private NoteNumberFormat _numberFormat = NoteNumberFormat.number;
+ private int _numberStart = 1;
+
+ #endregion
+
+ #region Public Properties
+
+ public NoteNumberFormat NumberFormat
+ {
+ get
+ {
+ return _numberFormat;
+ }
+ set
+ {
+ _numberFormat = value;
+ OnPropertyChanged( "NumberFormat" );
+ }
+ }
+
+ public int NumberStart
+ {
+ get
+ {
+ return _numberStart;
+ }
+ set
+ {
+ _numberStart = value;
+ OnPropertyChanged( "NumberStart" );
+ }
+ }
+
+ #endregion
+
+ #region INotifyPropertyChanged
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ protected void OnPropertyChanged( string propertyName )
+ {
+ if( PropertyChanged != null )
+ {
+ PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Xceed.Document.NET/Src/Paragraph.cs b/Xceed.Document.NET/Src/Paragraph.cs
index ec9e64f8..a2c55326 100644
--- a/Xceed.Document.NET/Src/Paragraph.cs
+++ b/Xceed.Document.NET/Src/Paragraph.cs
@@ -91,6 +91,22 @@ internal bool? IsListItemBacker
get; set;
}
+ internal int OutlineLevel
+ {
+ get
+ {
+ var pPr = GetOrCreate_pPr();
+ var outlineLvl = pPr.Element( XName.Get( "outlineLvl", Document.w.NamespaceName ) );
+ if( outlineLvl != null )
+ {
+ var val = outlineLvl.Attribute( XName.Get( "val", Document.w.NamespaceName ) );
+ return ( val != null ) ? Int32.Parse( val.Value ) : 0;
+ }
+
+ return 0;
+ }
+ }
+
#endregion
#region Public Properties
@@ -104,6 +120,9 @@ internal bool? IsListItemBacker
+
+
+
public ContainerType ParentContainer
{
get; set;
@@ -258,7 +277,7 @@ public string StyleName
{
get
{
- return this.StyleId;
+ return this.StyleId;
}
set
{
@@ -860,7 +879,7 @@ public bool IsListItem
get
{
IsListItemBacker = IsListItemBacker ?? ( ParagraphNumberProperties != null );
- return (bool)IsListItemBacker;
+ return ( bool )IsListItemBacker;
}
}
@@ -1339,7 +1358,7 @@ public Paragraph InsertHyperlink( Hyperlink h, int index = 0 )
Xml.AddFirst( h.Xml );
// Extract the picture back out of the DOM.
- h_xml = (XElement)Xml.FirstNode;
+ h_xml = ( XElement )Xml.FirstNode;
}
else
{
@@ -1352,7 +1371,7 @@ public Paragraph InsertHyperlink( Hyperlink h, int index = 0 )
Xml.Add( h.Xml );
// Extract the picture back out of the DOM.
- h_xml = (XElement)Xml.LastNode;
+ h_xml = ( XElement )Xml.LastNode;
}
else
{
@@ -1362,16 +1381,16 @@ public Paragraph InsertHyperlink( Hyperlink h, int index = 0 )
// Replace the origional run.
run.Xml.ReplaceWith
(
- splitRun[ 0 ],
+ splitRun[0],
h.Xml,
- splitRun[ 1 ]
+ splitRun[1]
);
// Get the first run effected by this Insert
run = GetFirstRunEffectedByEdit( index );
// The picture has to be the next element, extract it back out of the DOM.
- h_xml = (XElement)run.Xml.NextNode;
+ h_xml = ( XElement )run.Xml.NextNode;
}
}
@@ -1583,7 +1602,7 @@ public void Remove( bool trackChanges )
List temp = new List();
for( int i = 0; i < elements.Count(); i++ )
{
- XElement e = elements[ i ];
+ XElement e = elements[i];
if( e.Name.LocalName != "del" )
{
@@ -1905,6 +1924,7 @@ public void InsertText( int index, string value, bool trackChanges = false, Form
// Timestamp to mark the start of insert
var now = DateTime.Now;
var insert_datetime = new DateTime( now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, DateTimeKind.Utc );
+ var reCalculateIds = false;
// Get the first run effected by this Insert
var run = this.GetFirstRunEffectedByEdit( index );
@@ -1916,6 +1936,7 @@ public void InsertText( int index, string value, bool trackChanges = false, Form
if( trackChanges )
{
insert = CreateEdit( EditType.ins, insert_datetime, insert );
+ reCalculateIds = true;
}
this.Xml.Add( insert );
}
@@ -1990,6 +2011,7 @@ public void InsertText( int index, string value, bool trackChanges = false, Form
if( trackChanges )
{
insert = CreateEdit( EditType.ins, insert_datetime, newRuns );
+ reCalculateIds = true;
}
// Split this Edit at the point you want to insert
@@ -1998,9 +2020,9 @@ public void InsertText( int index, string value, bool trackChanges = false, Form
// Replace the origional run
parentElement.ReplaceWith
(
- splitEdit[ 0 ],
+ splitEdit[0],
insert,
- splitEdit[ 1 ]
+ splitEdit[1]
);
break;
@@ -2012,6 +2034,7 @@ splitEdit[ 1 ]
if( trackChanges && !parentElement.Name.LocalName.Equals( "ins" ) )
{
insert = CreateEdit( EditType.ins, insert_datetime, newRuns );
+ reCalculateIds = true;
}
// Split this run at the point you want to insert
var splitRun = Run.SplitRun( run, index );
@@ -2019,9 +2042,9 @@ splitEdit[ 1 ]
// Replace the origional run
run.Xml.ReplaceWith
(
- splitRun[ 0 ],
+ splitRun[0],
insert,
- splitRun[ 1 ]
+ splitRun[1]
);
break;
@@ -2031,7 +2054,10 @@ splitRun[ 1 ]
_runs = this.Xml.Elements( XName.Get( "r", Document.w.NamespaceName ) ).ToList();
- HelperFunctions.RenumberIDs( Document );
+ if( reCalculateIds )
+ {
+ HelperFunctions.RenumberIDs( Document );
+ }
}
///
@@ -2330,6 +2356,25 @@ select e.Attribute( XName.Get( "embed", "http://schemas.openxmlformats.org/offic
+
+
+
+
+
+
+
+
+ public Paragraph AppendNote( Note note, Formatting noteNumberFormatting = null )
+ {
+ if( note != null )
+ {
+ // Append the note to the paragraph and format the number in the paragraph.
+ this.Xml.Add( note.CreateReferenceRun( noteNumberFormatting ) );
+ }
+
+ return this;
+ }
+
public Paragraph NextParagraph
{
get
@@ -2376,7 +2421,8 @@ public Paragraph AppendEquation( String equation, Alignment align = Alignment.ce
case Alignment.right:
alignString = "right";
break;
- default: alignString = "center";
+ default:
+ alignString = "center";
break;
}
@@ -2500,14 +2546,14 @@ public Paragraph InsertPicture( Picture p, int index = 0 )
firstRun.AddBeforeSelf( p.Xml );
// Extract the picture back out of the DOM.
- p_xml = (XElement)firstRun.PreviousNode;
+ p_xml = ( XElement )firstRun.PreviousNode;
}
else
{
Xml.AddFirst( p.Xml );
// Extract the picture back out of the DOM.
- p_xml = (XElement)Xml.FirstNode;
+ p_xml = ( XElement )Xml.FirstNode;
}
}
else
@@ -2520,7 +2566,7 @@ public Paragraph InsertPicture( Picture p, int index = 0 )
Xml.Add( p.Xml );
// Extract the picture back out of the DOM.
- p_xml = (XElement)Xml.LastNode;
+ p_xml = ( XElement )Xml.LastNode;
}
else
{
@@ -2528,13 +2574,13 @@ public Paragraph InsertPicture( Picture p, int index = 0 )
var splitRun = Run.SplitRun( run, index );
// Replace the origional run.
- run.Xml.ReplaceWith( splitRun[ 0 ], p.Xml, splitRun[ 1 ] );
+ run.Xml.ReplaceWith( splitRun[0], p.Xml, splitRun[1] );
// Get the first run effected by this Insert
run = GetFirstRunEffectedByEdit( index );
// The picture has to be the next element, extract it back out of the DOM.
- p_xml = (XElement)run.Xml.NextNode;
+ p_xml = ( XElement )run.Xml.NextNode;
}
}
@@ -2558,8 +2604,9 @@ select e.Attribute( XName.Get( "embed", "http://schemas.openxmlformats.org/offic
/// Specifies the alignment of the Tab stop.
/// Specifies the horizontal position of the tab stop.
/// Specifies the character used to fill in the space created by a tab.
+ /// The TabStopPosition index to insert at.
/// The modified Paragraph.
- public Paragraph InsertTabStopPosition( Alignment alignment, float position, TabStopPositionLeader leader = TabStopPositionLeader.none )
+ public Paragraph InsertTabStopPosition( Alignment alignment, float position, TabStopPositionLeader leader = TabStopPositionLeader.none, int index = -1 )
{
var pPr = GetOrCreate_pPr();
var tabs = pPr.Element( XName.Get( "tabs", Document.w.NamespaceName ) );
@@ -2614,7 +2661,15 @@ public Paragraph InsertTabStopPosition( Alignment alignment, float position, Tab
}
newTab.SetAttributeValue( XName.Get( "leader", Document.w.NamespaceName ), leaderString );
- tabs.Add( newTab );
+ var tabsList = tabs.Elements().ToList();
+ if( (index >= 0) && (index < tabsList.Count()) )
+ {
+ tabsList[index].AddBeforeSelf( newTab );
+ }
+ else
+ {
+ tabs.Add( newTab );
+ }
return this;
}
@@ -2821,8 +2876,8 @@ public Paragraph UnderlineStyle( UnderlineStyle underlineStyle )
///
public Paragraph FontSize( double fontSize )
{
- double tempSize = (int)fontSize * 2;
- if( tempSize - (int)tempSize == 0 )
+ double tempSize = ( int )fontSize * 2;
+ if( tempSize - ( int )tempSize == 0 )
{
if( !( fontSize > 0 && fontSize < 1639 ) )
throw new ArgumentException( "Size", "Value must be in the range 0 - 1638" );
@@ -3226,7 +3281,7 @@ public Paragraph Spacing( double spacing )
{
spacing *= 20;
- if( spacing - (int)spacing == 0 )
+ if( spacing - ( int )spacing == 0 )
{
if( !( spacing > -1585 && spacing < 1585 ) )
throw new ArgumentException( "Spacing", "Value must be in the range: -1584 - 1584" );
@@ -3505,6 +3560,7 @@ public void RemoveText( int index, int count, bool trackChanges = false, bool re
// The number of characters processed so far
int processed = 0;
+ var reCalculateIds = false;
do
{
@@ -3521,16 +3577,17 @@ public void RemoveText( int index, int count, bool trackChanges = false, bool re
var min = Math.Min( count - processed, run.Xml.ElementsAfterSelf().Sum( e => GetElementTextLength( e ) ) );
var splitEditAfter = this.SplitEdit( parentElement, index + min, EditType.del );
- var temp = this.SplitEdit( splitEditBefore[ 1 ], index + min, EditType.del )[ 1 ];
+ var temp = this.SplitEdit( splitEditBefore[1], index + min, EditType.del )[1];
var middle = Paragraph.CreateEdit( EditType.del, remove_datetime, temp.Elements() );
processed += Paragraph.GetElementTextLength( middle as XElement );
+ reCalculateIds = true;
if( !trackChanges )
{
middle = null;
}
- parentElement.ReplaceWith( splitEditBefore[ 0 ], middle, splitEditAfter[ 0 ] );
+ parentElement.ReplaceWith( splitEditBefore[0], middle, splitEditAfter[0] );
processed += Paragraph.GetElementTextLength( middle as XElement );
break;
@@ -3558,15 +3615,16 @@ public void RemoveText( int index, int count, bool trackChanges = false, bool re
var min = Math.Min( index + ( count - processed ), run.EndIndex );
var splitRunAfter = Run.SplitRun( run, min, EditType.del );
- var middle = Paragraph.CreateEdit( EditType.del, remove_datetime, new List() { Run.SplitRun( new Run( Document, splitRunBefore[ 1 ], run.StartIndex + GetElementTextLength( splitRunBefore[ 0 ] ) ), min, EditType.del )[ 0 ] } );
+ var middle = Paragraph.CreateEdit( EditType.del, remove_datetime, new List() { Run.SplitRun( new Run( Document, splitRunBefore[1], run.StartIndex + GetElementTextLength( splitRunBefore[0] ) ), min, EditType.del )[0] } );
processed = processed + Paragraph.GetElementTextLength( middle as XElement );
+ reCalculateIds = true;
if( !trackChanges )
{
middle = null;
}
- run.Xml.ReplaceWith( splitRunBefore[ 0 ], middle, splitRunAfter[ 1 ] );
+ run.Xml.ReplaceWith( splitRunBefore[0], middle, splitRunAfter[1] );
}
else
{
@@ -3595,7 +3653,10 @@ public void RemoveText( int index, int count, bool trackChanges = false, bool re
_runs = this.Xml.Elements( XName.Get( "r", Document.w.NamespaceName ) ).ToList();
- HelperFunctions.RenumberIDs( Document );
+ if( reCalculateIds )
+ {
+ HelperFunctions.RenumberIDs( Document );
+ }
}
@@ -3747,13 +3808,13 @@ public void ReplaceText( string searchValue,
int lastcap = 0;
for( int k = 0; k < m.Groups.Count; k++ )
{
- var g = m.Groups[ k ];
+ var g = m.Groups[k];
if( ( g == null ) || ( g.Value == "" ) )
continue;
newValue = newValue.Replace( "$" + k.ToString(), g.Value );
lastcap = k;
}
- newValue = newValue.Replace( "$+", m.Groups[ lastcap ].Value );
+ newValue = newValue.Replace( "$+", m.Groups[lastcap].Value );
}
if( m.Index > 0 )
{
@@ -3816,7 +3877,16 @@ public void ReplaceText( string findPattern, Func regexMatchHand
// Replace text when formatting matches.
if( formattingMatch )
{
- var newValue = regexMatchHandler.Invoke( match.Groups[ 1 ].Value );
+ int lastcap = 0;
+ for( int k = 0; k < match.Groups.Count; k++ )
+ {
+ var g = match.Groups[k];
+ if( ( g == null ) || ( g.Value == "" ) )
+ continue;
+ lastcap = k;
+ }
+
+ var newValue = regexMatchHandler.Invoke( match.Groups[lastcap].Value );
this.InsertText( match.Index + match.Value.Length, newValue, trackChanges, newFormatting );
this.RemoveText( match.Index, match.Value.Length, trackChanges, removeEmptyParagraph );
}
@@ -3882,15 +3952,15 @@ public void ReplaceTextWithObject( string searchValue,
{
if( objectToAdd is Picture )
{
- this.InsertPicture( (Picture)objectToAdd, m.Index + m.Length );
+ this.InsertPicture( ( Picture )objectToAdd, m.Index + m.Length );
}
else if( objectToAdd is Hyperlink )
{
- this.InsertHyperlink( (Hyperlink)objectToAdd, m.Index + m.Length );
+ this.InsertHyperlink( ( Hyperlink )objectToAdd, m.Index + m.Length );
}
else if( objectToAdd is Table )
{
- this.InsertTableAfterSelf( (Table)objectToAdd );
+ this.InsertTableAfterSelf( ( Table )objectToAdd );
}
else
{
@@ -4072,9 +4142,9 @@ public void InsertPageNumber( PageNumberFormat pnf, int index = 0 )
var splitEdit = SplitEdit( r.Xml, index, EditType.ins );
r.Xml.ReplaceWith
(
- splitEdit[ 0 ],
+ splitEdit[0],
fldSimple,
- splitEdit[ 1 ]
+ splitEdit[1]
);
}
}
@@ -4185,9 +4255,9 @@ public void InsertPageCount( PageNumberFormat pnf, int index = 0 )
XElement[] splitEdit = SplitEdit( r.Xml, index, EditType.ins );
r.Xml.ReplaceWith
(
- splitEdit[ 0 ],
+ splitEdit[0],
fldSimple,
- splitEdit[ 1 ]
+ splitEdit[1]
);
}
}
@@ -4262,7 +4332,7 @@ public void SetLineSpacing( LineSpacingType spacingType, float spacingFloat )
var spacingTypeAttribute = ( spacingType == LineSpacingType.Before )
? "before"
: ( spacingType == LineSpacingType.After ) ? "after" : "line";
- spacing.SetAttributeValue( XName.Get( spacingTypeAttribute, Document.w.NamespaceName ), ( int )( spacingFloat * 20f ) );
+ spacing.SetAttributeValue( XName.Get( spacingTypeAttribute, Document.w.NamespaceName ), (int)( spacingFloat * 20f ) );
}
///
@@ -4369,7 +4439,7 @@ public IEnumerable GetBookmarks()
{
var bookmarkStart = this.Document.Xml.Descendants( XName.Get( "bookmarkStart", Document.w.NamespaceName ) )
.Where( x => x.Attribute( XName.Get( "id", Document.w.NamespaceName ) )?.Value == id )
- .FirstOrDefault();
+ .LastOrDefault();
if( bookmarks != null )
{
@@ -4417,7 +4487,6 @@ public void InsertAtBookmark( string toInsert, string bookmarkName, Formatting f
var run = HelperFunctions.FormatInput( toInsert, ( formatting != null ) ? formatting.Xml : null );
refPosition.AddBeforeSelf( run );
_runs = this.Xml.Elements( XName.Get( "r", Document.w.NamespaceName ) ).ToList();
- HelperFunctions.RenumberIDs( Document );
}
}
@@ -4441,14 +4510,14 @@ public void ReplaceAtBookmark( string text, string bookmarkName, Formatting form
{
var bookmarkEnds = this.Xml.Descendants( XName.Get( "bookmarkEnd", Document.w.NamespaceName ) );
if( bookmarkEnds.Count() > 1 )
- throw new InvalidDataException("Unsupported exception: Paragraph do not contains the expected bookmarkStart and contains more than 1 bookmarkEnd.");
+ throw new InvalidDataException( "Unsupported exception: Paragraph do not contains the expected bookmarkStart and contains more than 1 bookmarkEnd." );
if( bookmarkEnds.Count() == 0 )
throw new InvalidDataException( "Unsupported exception: Paragraph do not contains a bookmarkStart or a bookmarkEnd." );
bookmarkStartId = bookmarkEnds.First().Attribute( XName.Get( "id", Document.w.NamespaceName ) ).Value;
nextNode = this.Xml.Element( XName.Get( "r", Document.w.NamespaceName ) );
bookmarkStart = this.Xml.Element( XName.Get( "pPr", Document.w.NamespaceName ) );
- }
+ }
XElement nextXElement = null;
while( nextNode != null )
@@ -4530,7 +4599,16 @@ public void RemoveBookmark( string bookmarkName )
var bookmarkEndXml = this.Xml.Descendants( XName.Get( "bookmarkEnd", Document.w.NamespaceName ) )
.Where( x => x.Attribute( XName.Get( "id", Document.w.NamespaceName ) )?.Value == bookmarkStartId )
.FirstOrDefault();
- Debug.Assert( bookmarkEndXml != null, "Can't find bookmark end.");
+ // bookmarkEnd is not part of this paragraph, look for it in Document.
+ if( bookmarkEndXml == null )
+ {
+ bookmarkEndXml = this.Document.Xml.Descendants( XName.Get( "bookmarkEnd", Document.w.NamespaceName ) )
+ .Where( x => x.Attribute( XName.Get( "id", Document.w.NamespaceName ) )?.Value == bookmarkStartId )
+ .FirstOrDefault();
+ }
+
+ if( bookmarkEndXml == null )
+ return;
bookmarkStartXml.Remove();
bookmarkEndXml.Remove();
@@ -4580,7 +4658,7 @@ public Paragraph KeepLinesTogether( bool keepLinesTogether = true )
}
return this;
- }
+ }
[Obsolete( "Instead use : InsertHorizontalLine( HorizontalBorderPosition position, BorderStyle borderStyle, int size, int space, Color? color )" )]
public void InsertHorizontalLine( HorizontalBorderPosition position = HorizontalBorderPosition.bottom, string lineType = "single", int size = 6, int space = 1, string color = "auto" )
@@ -4777,6 +4855,16 @@ internal XElement GetOrCreate_pPr_ind()
return ind;
}
+ internal int GetTabStopPositionsCount()
+ {
+ var pPr = this.GetOrCreate_pPr();
+ var tabs = pPr.Element( XName.Get( "tabs", Document.w.NamespaceName ) );
+ if( tabs == null )
+ return 0;
+
+ return tabs.Elements().Count();
+ }
+
internal void RemoveHyperlinkRecursive( XElement xml, int index, ref int count, ref bool found )
{
if( xml.Name.LocalName.Equals( "hyperlink", StringComparison.CurrentCultureIgnoreCase ) )
@@ -4828,8 +4916,8 @@ static internal Picture CreatePicture( Document document, string id, string name
// ooxml uses image size in EMU :
// image in inches(in) is : pt / 72
// image in EMU is : in * 914400
- cx = Convert.ToInt64( img.Width * (72f / img.HorizontalResolution) * Picture.EmusInPixel);
- cy = Convert.ToInt64( img.Height * (72f / img.VerticalResolution) * Picture.EmusInPixel);
+ cx = Convert.ToInt64( img.Width * ( 72f / img.HorizontalResolution ) * Picture.EmusInPixel );
+ cy = Convert.ToInt64( img.Height * ( 72f / img.VerticalResolution ) * Picture.EmusInPixel );
}
}
@@ -4837,17 +4925,9 @@ static internal Picture CreatePicture( Document document, string id, string name
( string.Format( @"
-
-
-
- left
-
-
- top
-
+
-
@@ -4905,7 +4985,7 @@ internal static XElement CreateEdit( EditType t, DateTime edit_time, object cont
{
if( t == EditType.del )
{
- foreach( object o in (IEnumerable)content )
+ foreach( object o in ( IEnumerable )content )
{
if( o is XElement )
{
@@ -5053,11 +5133,11 @@ internal XElement[] SplitEdit( XElement edit, int index, EditType type )
XElement[] splitRun = Run.SplitRun( run, index, type );
- XElement splitLeft = new XElement( edit.Name, edit.Attributes(), run.Xml.ElementsBeforeSelf(), splitRun[ 0 ] );
+ XElement splitLeft = new XElement( edit.Name, edit.Attributes(), run.Xml.ElementsBeforeSelf(), splitRun[0] );
if( GetElementTextLength( splitLeft ) == 0 )
splitLeft = null;
- XElement splitRight = new XElement( edit.Name, edit.Attributes(), splitRun[ 1 ], run.Xml.ElementsAfterSelf() );
+ XElement splitRight = new XElement( edit.Name, edit.Attributes(), splitRun[1], run.Xml.ElementsAfterSelf() );
if( GetElementTextLength( splitRight ) == 0 )
splitRight = null;
@@ -5077,8 +5157,10 @@ internal string GetOrGenerateRel( Picture p )
// Search for a relationship with a TargetUri that points at this Image.
string id = null;
- foreach( var r in this.PackagePart.GetRelationshipsByType( Document.RelationshipImage ) )
+ var imageRelationships = this.PackagePart.GetRelationshipsByType( Document.RelationshipImage );
+ for( int i = imageRelationships.Count() - 1; i >= 0; --i )
{
+ var r = imageRelationships.ElementAt( i );
if( string.Equals( r.TargetUri.OriginalString, image_uri_string, StringComparison.Ordinal ) )
{
id = r.Id;
@@ -5147,13 +5229,13 @@ internal void ApplyTextFormattingProperty( XName textFormatPropName, string valu
if( content as XAttribute != null )
{
// Add or Update the attribute to the last element
- if( lastElement.Attribute( ( (XAttribute)( content ) ).Name ) == null )
+ if( lastElement.Attribute( ( ( XAttribute )( content ) ).Name ) == null )
{
lastElement.Add( content );
}
else
{
- lastElement.Attribute( ( (XAttribute)( content ) ).Name ).Value = ( (XAttribute)( content ) ).Value;
+ lastElement.Attribute( ( ( XAttribute )( content ) ).Name ).Value = ( ( XAttribute )( content ) ).Value;
}
}
return;
@@ -5185,13 +5267,13 @@ internal void ApplyTextFormattingProperty( XName textFormatPropName, string valu
{
foreach( object property in fontProperties )
{
- if( last.Attribute( ( (XAttribute)( property ) ).Name ) == null )
+ if( last.Attribute( ( ( XAttribute )( property ) ).Name ) == null )
{
last.Add( property );
}
else
{
- last.Attribute( ( (XAttribute)( property ) ).Name ).Value = ( (XAttribute)( property ) ).Value;
+ last.Attribute( ( ( XAttribute )( property ) ).Name ).Value = ( ( XAttribute )( property ) ).Value;
}
}
}
@@ -5199,13 +5281,13 @@ internal void ApplyTextFormattingProperty( XName textFormatPropName, string valu
if( content as XAttribute != null )//If content is an attribute
{
- if( last.Attribute( ( (XAttribute)( content ) ).Name ) == null )
+ if( last.Attribute( ( ( XAttribute )( content ) ).Name ) == null )
{
last.Add( content ); //Add this attribute if element doesn't have it
}
else
{
- last.Attribute( ( (XAttribute)( content ) ).Name ).Value = ( (XAttribute)( content ) ).Value; //Apply value only if element already has it
+ last.Attribute( ( ( XAttribute )( content ) ).Name ).Value = ( ( XAttribute )( content ) ).Value; //Apply value only if element already has it
}
}
else
@@ -5243,7 +5325,7 @@ internal bool IsLineSpacingRuleExactlyOrAtLeast()
var lineRule = spacing.Attribute( XName.Get( "lineRule", Document.w.NamespaceName ) );
if( lineRule != null )
{
- return ( (lineRule.Value == "exact") || ( lineRule.Value == "atLeast" ) );
+ return ( ( lineRule.Value == "exact" ) || ( lineRule.Value == "atLeast" ) );
}
}
@@ -5310,12 +5392,60 @@ internal bool IsInTOC()
if( ( sdt != null ) && ( sdt.Name == XName.Get( "sdt", Document.w.NamespaceName ) ) )
{
return ( sdt.Descendants( XName.Get( "docPartGallery", Document.w.NamespaceName ) )
- .FirstOrDefault( x => x.Attribute( XName.Get( "val", Document.w.NamespaceName ) ).Value == "Table of Contents" ) != null );
+ .FirstOrDefault( x => x.Attribute( XName.Get( "val", Document.w.NamespaceName ) ).Value == "Table of Contents" ) != null );
}
}
return false;
}
+ internal bool IsInTOCVisible()
+ {
+ if( this.IsInTOC() )
+ {
+ var sdtContent = this.Xml.Parent;
+ if( ( sdtContent != null ) && ( sdtContent.Name == XName.Get( "sdtContent", Document.w.NamespaceName ) ) )
+ {
+ if( this.StyleId.StartsWith( "TOC" ) )
+ {
+ var styleDigit = this.StyleId.Where( c => char.IsDigit( c ) );
+ // TOCHeading
+ if( styleDigit.Count() <= 0 )
+ return true;
+
+ var sdt = sdtContent.Parent;
+ if( ( sdt != null ) && ( sdt.Name == XName.Get( "sdt", Document.w.NamespaceName ) ) )
+ {
+ var tocSwitches = sdt.Descendants( XName.Get( "instrText", Document.w.NamespaceName ) ).FirstOrDefault( instrText => instrText.Value.Contains( "TOC" ) );
+ if( tocSwitches != null )
+ {
+ var includedHeadingStylesIndex = tocSwitches.Value.IndexOf( "o" );
+ if( includedHeadingStylesIndex >= 0 )
+ {
+ var bound1 = tocSwitches.Value.IndexOf( "\"", includedHeadingStylesIndex ) + 1;
+ var bound2 = tocSwitches.Value.IndexOf( "\"", bound1 );
+ var includedHeadingStyles = tocSwitches.Value.Substring( bound1, bound2 - bound1 );
+
+ var maxStyle = int.Parse( includedHeadingStyles[includedHeadingStyles.Length - 1].ToString() );
+ int counter = 1;
+ var styleDigitValue = int.Parse( string.Concat( styleDigit ) );
+ while( counter <= maxStyle )
+ {
+ if( styleDigitValue == counter )
+ return true;
+ ++counter;
+ }
+
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
internal List GetSdtContentRuns()
{
List result = null;
@@ -5345,7 +5475,7 @@ internal List GetSdtContentRuns()
internal bool IsInSdt()
{
- return (this.GetParentSdt() != null);
+ return ( this.GetParentSdt() != null );
}
internal XElement GetParentSdt()
@@ -5430,11 +5560,14 @@ private void ApplyFormattingFrom( ref Formatting newFormatting, Formatting sourc
private void RebuildDocProperties()
{
- docProperties =
- (
- from xml in Xml.Descendants( XName.Get( "fldSimple", Document.w.NamespaceName ) )
- select new DocProperty( Document, xml )
- ).ToList();
+ if( this.Xml != null )
+ {
+ docProperties =
+ (
+ from xml in Xml.Descendants( XName.Get( "fldSimple", Document.w.NamespaceName ) )
+ select new DocProperty( Document, xml )
+ ).ToList();
+ }
}
private XElement GetParagraphNumberProperties()
@@ -5485,15 +5618,16 @@ private List