|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Represents a document.
|
|
|
/// Represents a document.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
public class DocX: Container, IDisposable
|
|
|
|
|
|
|
|
|
public class DocX : Container, IDisposable
|
|
|
{
|
|
|
{
|
|
|
#region Namespaces
|
|
|
#region Namespaces
|
|
|
static internal XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
|
static internal XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
|
static internal XNamespace rel = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
|
static internal XNamespace rel = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
|
|
|
|
|
|
|
static internal XNamespace r = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
|
static internal XNamespace r = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
|
|
|
|
static internal XNamespace m = "http://schemas.openxmlformats.org/officeDocument/2006/math";
|
|
|
static internal XNamespace customPropertiesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
|
|
|
static internal XNamespace customPropertiesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
|
|
|
static internal XNamespace customVTypesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes";
|
|
|
static internal XNamespace customVTypesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes";
|
|
|
#endregion
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
settings.Root.AddFirst(documentProtection);
|
|
|
settings.Root.AddFirst(documentProtection);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Remove editing protection from this document.
|
|
|
/// Remove editing protection from this document.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
|
settings.Descendants(XName.Get("documentProtection", DocX.w.NamespaceName)).Remove();
|
|
|
settings.Descendants(XName.Get("documentProtection", DocX.w.NamespaceName)).Remove();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
public PageLayout PageLayout
|
|
|
|
|
|
|
|
|
public PageLayout PageLayout
|
|
|
{
|
|
|
{
|
|
|
get
|
|
|
get
|
|
|
{
|
|
|
{
|
|
|
|
|
|
|
|
|
/// }
|
|
|
/// }
|
|
|
/// </code>
|
|
|
/// </code>
|
|
|
/// </example>
|
|
|
/// </example>
|
|
|
public Headers Headers
|
|
|
|
|
|
|
|
|
public Headers Headers
|
|
|
{
|
|
|
{
|
|
|
get
|
|
|
|
|
|
|
|
|
get
|
|
|
{
|
|
|
{
|
|
|
return headers;
|
|
|
return headers;
|
|
|
}
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
private Headers headers;
|
|
|
private Headers headers;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
{
|
|
|
XElement body = mainDoc.Root.Element(w + "body");
|
|
|
XElement body = mainDoc.Root.Element(w + "body");
|
|
|
XElement sectPr = body.Element(w + "sectPr");
|
|
|
XElement sectPr = body.Element(w + "sectPr");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (sectPr != null)
|
|
|
if (sectPr != null)
|
|
|
{
|
|
|
{
|
|
|
XElement titlePg = sectPr.Element(w + "titlePg");
|
|
|
XElement titlePg = sectPr.Element(w + "titlePg");
|
|
|
|
|
|
|
|
|
body.Add(new XElement(w + "sectPr", string.Empty));
|
|
|
body.Add(new XElement(w + "sectPr", string.Empty));
|
|
|
|
|
|
|
|
|
sectPr = body.Element(w + "sectPr");
|
|
|
sectPr = body.Element(w + "sectPr");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
titlePg = sectPr.Element(w + "titlePg");
|
|
|
titlePg = sectPr.Element(w + "titlePg");
|
|
|
if (titlePg == null)
|
|
|
if (titlePg == null)
|
|
|
{
|
|
|
{
|
|
|
|
|
|
|
|
|
{
|
|
|
{
|
|
|
// Get the Xml file for this Header or Footer.
|
|
|
// Get the Xml file for this Header or Footer.
|
|
|
Uri partUri = mainPart.GetRelationship(Id).TargetUri;
|
|
|
Uri partUri = mainPart.GetRelationship(Id).TargetUri;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Weird problem with PackaePart API.
|
|
|
// Weird problem with PackaePart API.
|
|
|
if (!partUri.OriginalString.StartsWith("/word/"))
|
|
|
if (!partUri.OriginalString.StartsWith("/word/"))
|
|
|
partUri = new Uri("/word/" + partUri.OriginalString, UriKind.Relative);
|
|
|
partUri = new Uri("/word/" + partUri.OriginalString, UriKind.Relative);
|
|
|
|
|
|
|
|
|
internal Stream stream;
|
|
|
internal Stream stream;
|
|
|
#endregion
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
internal DocX(DocX document, XElement xml): base(document, xml)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
internal DocX(DocX document, XElement xml)
|
|
|
|
|
|
: base(document, xml)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <seealso cref="Paragraph.InsertPicture"/>
|
|
|
/// <seealso cref="Paragraph.InsertPicture"/>
|
|
|
public List<Image> Images
|
|
|
public List<Image> Images
|
|
|
{
|
|
|
{
|
|
|
get
|
|
|
|
|
|
|
|
|
get
|
|
|
{
|
|
|
{
|
|
|
PackageRelationshipCollection imageRelationships = mainPart.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
|
|
|
PackageRelationshipCollection imageRelationships = mainPart.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
|
|
|
if (imageRelationships.Count() > 0)
|
|
|
if (imageRelationships.Count() > 0)
|
|
|
|
|
|
|
|
|
/// <seealso cref="AddCustomProperty"/>
|
|
|
/// <seealso cref="AddCustomProperty"/>
|
|
|
public Dictionary<string, CustomProperty> CustomProperties
|
|
|
public Dictionary<string, CustomProperty> CustomProperties
|
|
|
{
|
|
|
{
|
|
|
get
|
|
|
|
|
|
|
|
|
get
|
|
|
{
|
|
|
{
|
|
|
if (package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
|
|
|
if (package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
|
|
|
{
|
|
|
{
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
|
/// Returns the list of document core properties with corresponding values.
|
|
|
|
|
|
///</summary>
|
|
|
|
|
|
public Dictionary<string, string> CoreProperties
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
|
/// Returns the list of document core properties with corresponding values.
|
|
|
|
|
|
///</summary>
|
|
|
|
|
|
public Dictionary<string, string> CoreProperties
|
|
|
{
|
|
|
{
|
|
|
if (package.PartExists(new Uri("/docProps/core.xml", UriKind.Relative)))
|
|
|
|
|
|
{
|
|
|
|
|
|
PackagePart docProps_Core = package.GetPart(new Uri("/docProps/core.xml", UriKind.Relative));
|
|
|
|
|
|
XDocument corePropDoc;
|
|
|
|
|
|
using (TextReader tr = new StreamReader(docProps_Core.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
|
|
|
corePropDoc = XDocument.Load(tr, LoadOptions.PreserveWhitespace);
|
|
|
|
|
|
|
|
|
|
|
|
// Get all of the core properties in this document
|
|
|
|
|
|
return (from docProperty in corePropDoc.Root.Elements()
|
|
|
|
|
|
select
|
|
|
|
|
|
new KeyValuePair<string, string>(
|
|
|
|
|
|
string.Format(
|
|
|
|
|
|
"{0}:{1}",
|
|
|
|
|
|
corePropDoc.Root.GetPrefixOfNamespace(docProperty.Name.Namespace),
|
|
|
|
|
|
docProperty.Name.LocalName),
|
|
|
|
|
|
docProperty.Value)).ToDictionary(p => p.Key, v => v.Value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (package.PartExists(new Uri("/docProps/core.xml", UriKind.Relative)))
|
|
|
|
|
|
{
|
|
|
|
|
|
PackagePart docProps_Core = package.GetPart(new Uri("/docProps/core.xml", UriKind.Relative));
|
|
|
|
|
|
XDocument corePropDoc;
|
|
|
|
|
|
using (TextReader tr = new StreamReader(docProps_Core.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
|
|
|
corePropDoc = XDocument.Load(tr, LoadOptions.PreserveWhitespace);
|
|
|
|
|
|
|
|
|
|
|
|
// Get all of the core properties in this document
|
|
|
|
|
|
return (from docProperty in corePropDoc.Root.Elements()
|
|
|
|
|
|
select
|
|
|
|
|
|
new KeyValuePair<string, string>(
|
|
|
|
|
|
string.Format(
|
|
|
|
|
|
"{0}:{1}",
|
|
|
|
|
|
corePropDoc.Root.GetPrefixOfNamespace(docProperty.Name.Namespace),
|
|
|
|
|
|
docProperty.Name.LocalName),
|
|
|
|
|
|
docProperty.Value)).ToDictionary(p => p.Key, v => v.Value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
return new Dictionary<string, string>();
|
|
|
|
|
|
|
|
|
return new Dictionary<string, string>();
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Get the Text of this document.
|
|
|
/// Get the Text of this document.
|
|
|
|
|
|
|
|
|
// Create a list of internal and external style elements for easy iteration.
|
|
|
// Create a list of internal and external style elements for easy iteration.
|
|
|
var internal_style_list = internal_word_styles.Root.Elements(XName.Get("style", DocX.w.NamespaceName));
|
|
|
var internal_style_list = internal_word_styles.Root.Elements(XName.Get("style", DocX.w.NamespaceName));
|
|
|
var external_style_list = external_word_styles.Root.Elements(XName.Get("style", DocX.w.NamespaceName));
|
|
|
var external_style_list = external_word_styles.Root.Elements(XName.Get("style", DocX.w.NamespaceName));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Loop through the external style elements
|
|
|
// Loop through the external style elements
|
|
|
foreach (XElement style in external_style_list)
|
|
|
foreach (XElement style in external_style_list)
|
|
|
{
|
|
|
{
|
|
|
|
|
|
|
|
|
string uri_string = rel.TargetUri.ToString();
|
|
|
string uri_string = rel.TargetUri.ToString();
|
|
|
if (!uri_string.StartsWith("/"))
|
|
|
if (!uri_string.StartsWith("/"))
|
|
|
uri_string = "/" + uri_string;
|
|
|
uri_string = "/" + uri_string;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PackagePart external_image_part = rel.Package.GetPart(new Uri("/word" + uri_string, UriKind.RelativeOrAbsolute));
|
|
|
PackagePart external_image_part = rel.Package.GetPart(new Uri("/word" + uri_string, UriKind.RelativeOrAbsolute));
|
|
|
PackagePart internal_image_part = package.CreatePart(new Uri(string.Format("/word/media/image{0}.jpeg", max + 1), UriKind.RelativeOrAbsolute), System.Net.Mime.MediaTypeNames.Image.Jpeg);
|
|
|
PackagePart internal_image_part = package.CreatePart(new Uri(string.Format("/word/media/image{0}.jpeg", max + 1), UriKind.RelativeOrAbsolute), System.Net.Mime.MediaTypeNames.Image.Jpeg);
|
|
|
|
|
|
|
|
|
PackageRelationship pr = internal_word_document.CreateRelationship(internal_image_part.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
|
|
|
PackageRelationship pr = internal_word_document.CreateRelationship(internal_image_part.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var query = from e in external_elements.DescendantsAndSelf()
|
|
|
var query = from e in external_elements.DescendantsAndSelf()
|
|
|
let embed = e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"))
|
|
|
let embed = e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"))
|
|
|
where embed != null && embed.Value == rel.Id
|
|
|
where embed != null && embed.Value == rel.Id
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
#region CustomProperties
|
|
|
#region CustomProperties
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if the external document contains custom properties.
|
|
|
// Check if the external document contains custom properties.
|
|
|
if (document.package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
|
|
|
if (document.package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
|
|
|
{
|
|
|
{
|
|
|
|
|
|
|
|
|
if (!package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
|
|
|
if (!package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
|
|
|
HelperFunctions.CreateCustomPropertiesPart(this);
|
|
|
HelperFunctions.CreateCustomPropertiesPart(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PackagePart internal_docProps_custom = package.GetPart(new Uri("/docProps/custom.xml", UriKind.Relative));
|
|
|
PackagePart internal_docProps_custom = package.GetPart(new Uri("/docProps/custom.xml", UriKind.Relative));
|
|
|
XDocument internal_customPropDoc;
|
|
|
XDocument internal_customPropDoc;
|
|
|
using (TextReader tr = new StreamReader(internal_docProps_custom.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
using (TextReader tr = new StreamReader(internal_docProps_custom.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
|
|
|
|
|
|
foreach (XElement cp in external_customProperties)
|
|
|
foreach (XElement cp in external_customProperties)
|
|
|
{
|
|
|
{
|
|
|
// Does the internal document already have a custom property with this name?
|
|
|
// Does the internal document already have a custom property with this name?
|
|
|
XElement conflict =
|
|
|
|
|
|
|
|
|
XElement conflict =
|
|
|
(
|
|
|
(
|
|
|
from d in internal_customPropDoc.Descendants(XName.Get("property", customPropertiesSchema.NamespaceName))
|
|
|
from d in internal_customPropDoc.Descendants(XName.Get("property", customPropertiesSchema.NamespaceName))
|
|
|
let ExternalName = d.Attribute(XName.Get("name", customPropertiesSchema.NamespaceName))
|
|
|
let ExternalName = d.Attribute(XName.Get("name", customPropertiesSchema.NamespaceName))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// A document can only have one header and one footer.
|
|
|
// A document can only have one header and one footer.
|
|
|
#region Remove external (header & footer) references
|
|
|
#region Remove external (header & footer) references
|
|
|
var externalHeaderAndFooterReferences =
|
|
|
|
|
|
|
|
|
var externalHeaderAndFooterReferences =
|
|
|
(
|
|
|
(
|
|
|
from d in external_elements.Descendants()
|
|
|
from d in external_elements.Descendants()
|
|
|
where d.Name.LocalName == "headerReference" || d.Name.LocalName == "footerReference"
|
|
|
where d.Name.LocalName == "headerReference" || d.Name.LocalName == "footerReference"
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
#endregion
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Insert a new Table at the end of this document.
|
|
|
/// Insert a new Table at the end of this document.
|
|
|
|
|
|
|
|
|
t.mainPart = mainPart;
|
|
|
t.mainPart = mainPart;
|
|
|
return t;
|
|
|
return t;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Creates a document using a Stream.
|
|
|
/// Creates a document using a Stream.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
|
// Create the main document part for this package
|
|
|
// Create the main document part for this package
|
|
|
PackagePart mainDocumentPart = package.CreatePart(new Uri("/word/document.xml", UriKind.Relative), "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml");
|
|
|
PackagePart mainDocumentPart = package.CreatePart(new Uri("/word/document.xml", UriKind.Relative), "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml");
|
|
|
package.CreateRelationship(mainDocumentPart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument");
|
|
|
package.CreateRelationship(mainDocumentPart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Load the document part into a XDocument object
|
|
|
// Load the document part into a XDocument object
|
|
|
using (TextReader tr = new StreamReader(mainDocumentPart.GetStream(FileMode.Create, FileAccess.ReadWrite)))
|
|
|
using (TextReader tr = new StreamReader(mainDocumentPart.GetStream(FileMode.Create, FileAccess.ReadWrite)))
|
|
|
{
|
|
|
{
|
|
|
|
|
|
|
|
|
headers.odd = document.GetHeaderByType("default");
|
|
|
headers.odd = document.GetHeaderByType("default");
|
|
|
headers.even = document.GetHeaderByType("even");
|
|
|
headers.even = document.GetHeaderByType("even");
|
|
|
headers.first = document.GetHeaderByType("first");
|
|
|
headers.first = document.GetHeaderByType("first");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Footers footers = new Footers();
|
|
|
Footers footers = new Footers();
|
|
|
footers.odd = document.GetFooterByType("default");
|
|
|
footers.odd = document.GetFooterByType("default");
|
|
|
footers.even = document.GetFooterByType("even");
|
|
|
footers.even = document.GetFooterByType("even");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//}
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
document.Xml = document.mainDoc.Root.Element(w + "body");
|
|
|
document.Xml = document.mainDoc.Root.Element(w + "body");
|
|
|
document.headers = headers;
|
|
|
document.headers = headers;
|
|
|
|
|
|
|
|
|
document.settingsPart = HelperFunctions.CreateOrGetSettingsPart(package);
|
|
|
document.settingsPart = HelperFunctions.CreateOrGetSettingsPart(package);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// Loads a document into a DocX object using a Stream.
|
|
|
/// Loads a document into a DocX object using a Stream.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
/// <param name="stream">The Stream to load the document from.</param>
|
|
|
/// <param name="stream">The Stream to load the document from.</param>
|
|
|
|
|
|
|
|
|
throw new FileNotFoundException(string.Format("File could not be found {0}", filename));
|
|
|
throw new FileNotFoundException(string.Format("File could not be found {0}", filename));
|
|
|
|
|
|
|
|
|
MemoryStream ms = new MemoryStream();
|
|
|
MemoryStream ms = new MemoryStream();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using (FileStream fs = new FileStream(filename, FileMode.Open))
|
|
|
using (FileStream fs = new FileStream(filename, FileMode.Open))
|
|
|
{
|
|
|
{
|
|
|
byte[] data = new byte[fs.Length];
|
|
|
byte[] data = new byte[fs.Length];
|
|
|
|
|
|
|
|
|
///<exception cref="FileNotFoundException">The document template file not found.</exception>
|
|
|
///<exception cref="FileNotFoundException">The document template file not found.</exception>
|
|
|
public void ApplyTemplate(string templateFilePath)
|
|
|
public void ApplyTemplate(string templateFilePath)
|
|
|
{
|
|
|
{
|
|
|
ApplyTemplate(templateFilePath, true);
|
|
|
|
|
|
|
|
|
ApplyTemplate(templateFilePath, true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
///<summary>
|
|
|
|
|
|
|
|
|
///<exception cref="FileNotFoundException">The document template file not found.</exception>
|
|
|
///<exception cref="FileNotFoundException">The document template file not found.</exception>
|
|
|
public void ApplyTemplate(string templateFilePath, bool includeContent)
|
|
|
public void ApplyTemplate(string templateFilePath, bool includeContent)
|
|
|
{
|
|
|
{
|
|
|
if (!File.Exists(templateFilePath))
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new FileNotFoundException(string.Format("File could not be found {0}", templateFilePath));
|
|
|
|
|
|
}
|
|
|
|
|
|
using (FileStream packageStream = new FileStream(templateFilePath, FileMode.Open, FileAccess.Read))
|
|
|
|
|
|
{
|
|
|
|
|
|
ApplyTemplate(packageStream, includeContent);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
if (!File.Exists(templateFilePath))
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new FileNotFoundException(string.Format("File could not be found {0}", templateFilePath));
|
|
|
|
|
|
}
|
|
|
|
|
|
using (FileStream packageStream = new FileStream(templateFilePath, FileMode.Open, FileAccess.Read))
|
|
|
|
|
|
{
|
|
|
|
|
|
ApplyTemplate(packageStream, includeContent);
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
///<summary>
|
|
|
|
|
|
|
|
|
///<param name="templateStream">The stream of the document template file.</param>
|
|
|
///<param name="templateStream">The stream of the document template file.</param>
|
|
|
public void ApplyTemplate(Stream templateStream)
|
|
|
public void ApplyTemplate(Stream templateStream)
|
|
|
{
|
|
|
{
|
|
|
ApplyTemplate(templateStream, true);
|
|
|
|
|
|
|
|
|
ApplyTemplate(templateStream, true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
///<summary>
|
|
|
|
|
|
|
|
|
///<param name="includeContent">Whether to copy the document template text content to document.</param>
|
|
|
///<param name="includeContent">Whether to copy the document template text content to document.</param>
|
|
|
public void ApplyTemplate(Stream templateStream, bool includeContent)
|
|
|
public void ApplyTemplate(Stream templateStream, bool includeContent)
|
|
|
{
|
|
|
{
|
|
|
Package templatePackage = Package.Open(templateStream);
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
PackagePart documentPart = null;
|
|
|
|
|
|
XDocument documentDoc = null;
|
|
|
|
|
|
foreach (PackagePart packagePart in templatePackage.GetParts())
|
|
|
|
|
|
|
|
|
Package templatePackage = Package.Open(templateStream);
|
|
|
|
|
|
try
|
|
|
{
|
|
|
{
|
|
|
switch (packagePart.Uri.ToString())
|
|
|
|
|
|
{
|
|
|
|
|
|
case "/word/document.xml":
|
|
|
|
|
|
documentPart = packagePart;
|
|
|
|
|
|
using (XmlReader xr = XmlReader.Create(packagePart.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
|
|
|
{
|
|
|
|
|
|
documentDoc = XDocument.Load(xr);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "/_rels/.rels":
|
|
|
|
|
|
if (!this.package.PartExists(packagePart.Uri))
|
|
|
|
|
|
{
|
|
|
|
|
|
this.package.CreatePart(packagePart.Uri, packagePart.ContentType, packagePart.CompressionOption);
|
|
|
|
|
|
}
|
|
|
|
|
|
PackagePart globalRelsPart = this.package.GetPart(packagePart.Uri);
|
|
|
|
|
|
using (
|
|
|
|
|
|
StreamReader tr = new StreamReader(
|
|
|
|
|
|
packagePart.GetStream(FileMode.Open, FileAccess.Read), Encoding.UTF8))
|
|
|
|
|
|
{
|
|
|
|
|
|
using (
|
|
|
|
|
|
StreamWriter tw = new StreamWriter(
|
|
|
|
|
|
globalRelsPart.GetStream(FileMode.Create, FileAccess.Write), Encoding.UTF8))
|
|
|
|
|
|
|
|
|
PackagePart documentPart = null;
|
|
|
|
|
|
XDocument documentDoc = null;
|
|
|
|
|
|
foreach (PackagePart packagePart in templatePackage.GetParts())
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (packagePart.Uri.ToString())
|
|
|
{
|
|
|
{
|
|
|
tw.Write(tr.ReadToEnd());
|
|
|
|
|
|
|
|
|
case "/word/document.xml":
|
|
|
|
|
|
documentPart = packagePart;
|
|
|
|
|
|
using (XmlReader xr = XmlReader.Create(packagePart.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
|
|
|
{
|
|
|
|
|
|
documentDoc = XDocument.Load(xr);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "/_rels/.rels":
|
|
|
|
|
|
if (!this.package.PartExists(packagePart.Uri))
|
|
|
|
|
|
{
|
|
|
|
|
|
this.package.CreatePart(packagePart.Uri, packagePart.ContentType, packagePart.CompressionOption);
|
|
|
|
|
|
}
|
|
|
|
|
|
PackagePart globalRelsPart = this.package.GetPart(packagePart.Uri);
|
|
|
|
|
|
using (
|
|
|
|
|
|
StreamReader tr = new StreamReader(
|
|
|
|
|
|
packagePart.GetStream(FileMode.Open, FileAccess.Read), Encoding.UTF8))
|
|
|
|
|
|
{
|
|
|
|
|
|
using (
|
|
|
|
|
|
StreamWriter tw = new StreamWriter(
|
|
|
|
|
|
globalRelsPart.GetStream(FileMode.Create, FileAccess.Write), Encoding.UTF8))
|
|
|
|
|
|
{
|
|
|
|
|
|
tw.Write(tr.ReadToEnd());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "/word/_rels/document.xml.rels":
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
if (!this.package.PartExists(packagePart.Uri))
|
|
|
|
|
|
{
|
|
|
|
|
|
this.package.CreatePart(packagePart.Uri, packagePart.ContentType, packagePart.CompressionOption);
|
|
|
|
|
|
}
|
|
|
|
|
|
Encoding packagePartEncoding = Encoding.Default;
|
|
|
|
|
|
if (packagePart.Uri.ToString().EndsWith(".xml") || packagePart.Uri.ToString().EndsWith(".rels"))
|
|
|
|
|
|
{
|
|
|
|
|
|
packagePartEncoding = Encoding.UTF8;
|
|
|
|
|
|
}
|
|
|
|
|
|
PackagePart nativePart = this.package.GetPart(packagePart.Uri);
|
|
|
|
|
|
using (
|
|
|
|
|
|
StreamReader tr = new StreamReader(
|
|
|
|
|
|
packagePart.GetStream(FileMode.Open, FileAccess.Read), packagePartEncoding))
|
|
|
|
|
|
{
|
|
|
|
|
|
using (
|
|
|
|
|
|
StreamWriter tw = new StreamWriter(
|
|
|
|
|
|
nativePart.GetStream(FileMode.Create, FileAccess.Write), tr.CurrentEncoding))
|
|
|
|
|
|
{
|
|
|
|
|
|
tw.Write(tr.ReadToEnd());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "/word/_rels/document.xml.rels":
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
if (!this.package.PartExists(packagePart.Uri))
|
|
|
|
|
|
{
|
|
|
|
|
|
this.package.CreatePart(packagePart.Uri, packagePart.ContentType, packagePart.CompressionOption);
|
|
|
|
|
|
}
|
|
|
|
|
|
Encoding packagePartEncoding = Encoding.Default;
|
|
|
|
|
|
if (packagePart.Uri.ToString().EndsWith(".xml") || packagePart.Uri.ToString().EndsWith(".rels"))
|
|
|
|
|
|
{
|
|
|
|
|
|
packagePartEncoding = Encoding.UTF8;
|
|
|
|
|
|
}
|
|
|
|
|
|
PackagePart nativePart = this.package.GetPart(packagePart.Uri);
|
|
|
|
|
|
using (
|
|
|
|
|
|
StreamReader tr = new StreamReader(
|
|
|
|
|
|
packagePart.GetStream(FileMode.Open, FileAccess.Read), packagePartEncoding))
|
|
|
|
|
|
{
|
|
|
|
|
|
using (
|
|
|
|
|
|
StreamWriter tw = new StreamWriter(
|
|
|
|
|
|
nativePart.GetStream(FileMode.Create, FileAccess.Write), tr.CurrentEncoding))
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
if (documentPart != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
string mainContentType = documentPart.ContentType.Replace("template.main", "document.main");
|
|
|
|
|
|
if (this.package.PartExists(documentPart.Uri))
|
|
|
{
|
|
|
{
|
|
|
tw.Write(tr.ReadToEnd());
|
|
|
|
|
|
|
|
|
this.package.DeletePart(documentPart.Uri);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (documentPart != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
string mainContentType = documentPart.ContentType.Replace("template.main", "document.main");
|
|
|
|
|
|
if (this.package.PartExists(documentPart.Uri))
|
|
|
|
|
|
{
|
|
|
|
|
|
this.package.DeletePart(documentPart.Uri);
|
|
|
|
|
|
}
|
|
|
|
|
|
PackagePart documentNewPart = this.package.CreatePart(
|
|
|
|
|
|
documentPart.Uri, mainContentType, documentPart.CompressionOption);
|
|
|
|
|
|
using (XmlWriter xw = XmlWriter.Create(documentNewPart.GetStream(FileMode.Create, FileAccess.Write)))
|
|
|
|
|
|
{
|
|
|
|
|
|
documentDoc.WriteTo(xw);
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach (PackageRelationship documentPartRel in documentPart.GetRelationships())
|
|
|
|
|
|
{
|
|
|
|
|
|
documentNewPart.CreateRelationship(
|
|
|
|
|
|
documentPartRel.TargetUri,
|
|
|
|
|
|
documentPartRel.TargetMode,
|
|
|
|
|
|
documentPartRel.RelationshipType,
|
|
|
|
|
|
documentPartRel.Id);
|
|
|
|
|
|
}
|
|
|
|
|
|
this.mainPart = documentNewPart;
|
|
|
|
|
|
this.mainDoc = documentDoc;
|
|
|
|
|
|
PopulateDocument(this, templatePackage);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!includeContent)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (Paragraph paragraph in this.Paragraphs)
|
|
|
|
|
|
{
|
|
|
|
|
|
paragraph.Remove(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
PackagePart documentNewPart = this.package.CreatePart(
|
|
|
|
|
|
documentPart.Uri, mainContentType, documentPart.CompressionOption);
|
|
|
|
|
|
using (XmlWriter xw = XmlWriter.Create(documentNewPart.GetStream(FileMode.Create, FileAccess.Write)))
|
|
|
|
|
|
{
|
|
|
|
|
|
documentDoc.WriteTo(xw);
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach (PackageRelationship documentPartRel in documentPart.GetRelationships())
|
|
|
|
|
|
{
|
|
|
|
|
|
documentNewPart.CreateRelationship(
|
|
|
|
|
|
documentPartRel.TargetUri,
|
|
|
|
|
|
documentPartRel.TargetMode,
|
|
|
|
|
|
documentPartRel.RelationshipType,
|
|
|
|
|
|
documentPartRel.Id);
|
|
|
|
|
|
}
|
|
|
|
|
|
this.mainPart = documentNewPart;
|
|
|
|
|
|
this.mainDoc = documentDoc;
|
|
|
|
|
|
PopulateDocument(this, templatePackage);
|
|
|
|
|
|
|
|
|
|
|
|
// DragonFire: I added next line and recovered ApplyTemplate method.
|
|
|
|
|
|
// I do it, becouse PopulateDocument(...) writes into field "settingsPart" the part of Template's package
|
|
|
|
|
|
// and after line "templatePackage.Close();" in finally, field "settingsPart" becomes not available and method "Save" throw an exception...
|
|
|
|
|
|
// That's why I recreated settingsParts and unlinked it from Template's package =)
|
|
|
|
|
|
settingsPart = HelperFunctions.CreateOrGetSettingsPart(package);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!includeContent)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (Paragraph paragraph in this.Paragraphs)
|
|
|
|
|
|
{
|
|
|
|
|
|
paragraph.Remove(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
this.package.Flush();
|
|
|
|
|
|
var documentRelsPart = this.package.GetPart(new Uri("/word/_rels/document.xml.rels", UriKind.Relative));
|
|
|
|
|
|
using (TextReader tr = new StreamReader(documentRelsPart.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
|
|
|
|
|
|
finally
|
|
|
{
|
|
|
{
|
|
|
tr.Read();
|
|
|
|
|
|
|
|
|
this.package.Flush();
|
|
|
|
|
|
var documentRelsPart = this.package.GetPart(new Uri("/word/_rels/document.xml.rels", UriKind.Relative));
|
|
|
|
|
|
using (TextReader tr = new StreamReader(documentRelsPart.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
|
|
|
{
|
|
|
|
|
|
tr.Read();
|
|
|
|
|
|
}
|
|
|
|
|
|
templatePackage.Close();
|
|
|
}
|
|
|
}
|
|
|
templatePackage.Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
|
);
|
|
|
);
|
|
|
|
|
|
|
|
|
Hyperlink h = new Hyperlink(this, i);
|
|
|
Hyperlink h = new Hyperlink(this, i);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
h.Text = text;
|
|
|
h.Text = text;
|
|
|
h.Uri = uri;
|
|
|
h.Uri = uri;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using (TextReader tr = new StreamReader(package.GetPart(word_styles_Uri).GetStream()))
|
|
|
using (TextReader tr = new StreamReader(package.GetPart(word_styles_Uri).GetStream()))
|
|
|
word_styles = XDocument.Load(tr);
|
|
|
word_styles = XDocument.Load(tr);
|
|
|
|
|
|
|
|
|
bool hyperlinkStyleExists =
|
|
|
|
|
|
|
|
|
bool hyperlinkStyleExists =
|
|
|
(
|
|
|
(
|
|
|
from s in word_styles.Element(w + "styles").Elements()
|
|
|
from s in word_styles.Element(w + "styles").Elements()
|
|
|
let styleId = s.Attribute(XName.Get("styleId", w.NamespaceName))
|
|
|
let styleId = s.Attribute(XName.Get("styleId", w.NamespaceName))
|
|
|
|
|
|
|
|
|
w + "style",
|
|
|
w + "style",
|
|
|
new XAttribute(w + "type", "character"),
|
|
|
new XAttribute(w + "type", "character"),
|
|
|
new XAttribute(w + "styleId", "Hyperlink"),
|
|
|
new XAttribute(w + "styleId", "Hyperlink"),
|
|
|
new XElement(w + "name", new XAttribute(w + "val", "Hyperlink")),
|
|
|
|
|
|
new XElement(w + "basedOn", new XAttribute(w + "val", "DefaultParagraphFont")),
|
|
|
|
|
|
new XElement(w + "uiPriority", new XAttribute(w + "val", "99")),
|
|
|
|
|
|
|
|
|
new XElement(w + "name", new XAttribute(w + "val", "Hyperlink")),
|
|
|
|
|
|
new XElement(w + "basedOn", new XAttribute(w + "val", "DefaultParagraphFont")),
|
|
|
|
|
|
new XElement(w + "uiPriority", new XAttribute(w + "val", "99")),
|
|
|
new XElement(w + "unhideWhenUsed"),
|
|
|
new XElement(w + "unhideWhenUsed"),
|
|
|
new XElement(w + "rsid", new XAttribute(w + "val", "0005416C")),
|
|
|
|
|
|
|
|
|
new XElement(w + "rsid", new XAttribute(w + "val", "0005416C")),
|
|
|
new XElement
|
|
|
new XElement
|
|
|
(
|
|
|
(
|
|
|
w + "rPr",
|
|
|
w + "rPr",
|
|
|
|
|
|
|
|
|
{
|
|
|
{
|
|
|
XDocument relsPartContent;
|
|
|
XDocument relsPartContent;
|
|
|
using (TextReader tr = new StreamReader(relsPart.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
using (TextReader tr = new StreamReader(relsPart.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
relsPartContent = XDocument.Load(tr);
|
|
|
|
|
|
|
|
|
relsPartContent = XDocument.Load(tr);
|
|
|
|
|
|
|
|
|
IEnumerable<XElement> imageRelationships =
|
|
|
IEnumerable<XElement> imageRelationships =
|
|
|
relsPartContent.Root.Elements().Where
|
|
|
relsPartContent.Root.Elements().Where
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Loop through each image part in this document.
|
|
|
// Loop through each image part in this document.
|
|
|
foreach (PackagePart pp in imageParts)
|
|
|
foreach (PackagePart pp in imageParts)
|
|
|
{
|
|
|
{
|
|
|
|
|
|
|
|
|
// Create a new image part.
|
|
|
// Create a new image part.
|
|
|
imgPartUriPath = string.Format
|
|
|
imgPartUriPath = string.Format
|
|
|
(
|
|
|
(
|
|
|
"/word/media/{0}.{1}",
|
|
|
|
|
|
|
|
|
"/word/media/{0}.{1}",
|
|
|
Guid.NewGuid().ToString(), // The unique part.
|
|
|
Guid.NewGuid().ToString(), // The unique part.
|
|
|
extension
|
|
|
extension
|
|
|
);
|
|
|
);
|
|
|
|
|
|
|
|
|
this.stream = stream;
|
|
|
this.stream = stream;
|
|
|
Save();
|
|
|
Save();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Add a core property to this document. If a core property already exists with the same name it will be replaced. Core property names are case insensitive.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
///<param name="propertyName">The property name.</param>
|
|
|
|
|
|
///<param name="propertyValue">The property value.</param>
|
|
|
|
|
|
///<example>
|
|
|
|
|
|
/// Add a core properties of each type to a document.
|
|
|
|
|
|
/// <code>
|
|
|
|
|
|
/// // Load Example.docx
|
|
|
|
|
|
/// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
|
|
|
|
|
|
/// {
|
|
|
|
|
|
/// // If this document does not contain a core property called 'forename', create one.
|
|
|
|
|
|
/// if (!document.CoreProperties.ContainsKey("forename"))
|
|
|
|
|
|
/// {
|
|
|
|
|
|
/// // Create a new core property called 'forename' and set its value.
|
|
|
|
|
|
/// document.AddCoreProperty("forename", "Cathal");
|
|
|
|
|
|
/// }
|
|
|
|
|
|
///
|
|
|
|
|
|
/// // Get this documents core property called 'forename'.
|
|
|
|
|
|
/// string forenameValue = document.CoreProperties["forename"];
|
|
|
|
|
|
///
|
|
|
|
|
|
/// // Print all of the information about this core property to Console.
|
|
|
|
|
|
/// Console.WriteLine(string.Format("Name: '{0}', Value: '{1}'\nPress any key...", "forename", forenameValue));
|
|
|
|
|
|
///
|
|
|
|
|
|
/// // Save all changes made to this document.
|
|
|
|
|
|
/// document.Save();
|
|
|
|
|
|
/// } // Release this document from memory.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// // Wait for the user to press a key before exiting.
|
|
|
|
|
|
/// Console.ReadKey();
|
|
|
|
|
|
/// </code>
|
|
|
|
|
|
/// </example>
|
|
|
|
|
|
/// <seealso cref="CoreProperties"/>
|
|
|
|
|
|
/// <seealso cref="CustomProperty"/>
|
|
|
|
|
|
/// <seealso cref="CustomProperties"/>
|
|
|
|
|
|
public void AddCoreProperty(string propertyName, string propertyValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
string propertyNamespacePrefix = propertyName.Contains(":") ? propertyName.Split(new[] { ':' })[0] : "cp";
|
|
|
|
|
|
string propertyLocalName = propertyName.Contains(":") ? propertyName.Split(new[] { ':' })[1] : propertyName;
|
|
|
|
|
|
|
|
|
|
|
|
// If this document does not contain a coreFilePropertyPart create one.)
|
|
|
|
|
|
if (!package.PartExists(new Uri("/docProps/core.xml", UriKind.Relative)))
|
|
|
|
|
|
throw new Exception("Core properties part doesn't exist.");
|
|
|
|
|
|
|
|
|
|
|
|
XDocument corePropDoc;
|
|
|
|
|
|
PackagePart corePropPart = package.GetPart(new Uri("/docProps/core.xml", UriKind.Relative));
|
|
|
|
|
|
using (TextReader tr = new StreamReader(corePropPart.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
|
|
|
{
|
|
|
|
|
|
corePropDoc = XDocument.Load(tr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
XElement corePropElement =
|
|
|
|
|
|
(from propElement in corePropDoc.Root.Elements()
|
|
|
|
|
|
where (propElement.Name.LocalName.Equals(propertyLocalName))
|
|
|
|
|
|
select propElement).SingleOrDefault();
|
|
|
|
|
|
if (corePropElement != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
corePropElement.SetValue(propertyValue);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var propertyNamespace = corePropDoc.Root.GetNamespaceOfPrefix(propertyNamespacePrefix);
|
|
|
|
|
|
corePropDoc.Root.Add(new XElement(XName.Get(propertyLocalName, propertyNamespace.NamespaceName), propertyValue));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
using(TextWriter tw = new StreamWriter(corePropPart.GetStream(FileMode.Create, FileAccess.Write)))
|
|
|
|
|
|
{
|
|
|
|
|
|
corePropDoc.Save(tw);
|
|
|
|
|
|
}
|
|
|
|
|
|
UpdateCorePropertyValue(this, propertyLocalName, propertyValue);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static void UpdateCorePropertyValue(DocX document, string corePropertyName, string corePropertyValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
string matchPattern = string.Format(@"(DOCPROPERTY)?{0}\\\*MERGEFORMAT", corePropertyName).ToLower();
|
|
|
|
|
|
foreach (XElement e in document.mainDoc.Descendants(XName.Get("fldSimple", w.NamespaceName)))
|
|
|
|
|
|
{
|
|
|
|
|
|
string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim().ToLower();
|
|
|
|
|
|
|
|
|
|
|
|
if (Regex.IsMatch(attr_value, matchPattern))
|
|
|
|
|
|
{
|
|
|
|
|
|
XElement firstRun = e.Element(w + "r");
|
|
|
|
|
|
XElement firstText = firstRun.Element(w + "t");
|
|
|
|
|
|
XElement rPr = firstText.Element(w + "rPr");
|
|
|
|
|
|
|
|
|
|
|
|
// Delete everything and insert updated text value
|
|
|
|
|
|
e.RemoveNodes();
|
|
|
|
|
|
|
|
|
|
|
|
XElement t = new XElement(w + "t", rPr, corePropertyValue);
|
|
|
|
|
|
Novacode.Text.PreserveSpace(t);
|
|
|
|
|
|
e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#region Headers
|
|
|
|
|
|
|
|
|
|
|
|
IEnumerable<PackagePart> headerParts = from headerPart in document.package.GetParts()
|
|
|
|
|
|
where (Regex.IsMatch(headerPart.Uri.ToString(), @"/word/header\d?.xml"))
|
|
|
|
|
|
select headerPart;
|
|
|
|
|
|
foreach (PackagePart pp in headerParts)
|
|
|
|
|
|
{
|
|
|
|
|
|
XDocument header = XDocument.Load(new StreamReader(pp.GetStream()));
|
|
|
|
|
|
|
|
|
|
|
|
foreach (XElement e in header.Descendants(XName.Get("fldSimple", w.NamespaceName)))
|
|
|
|
|
|
{
|
|
|
|
|
|
string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim().ToLower();
|
|
|
|
|
|
if (Regex.IsMatch(attr_value, matchPattern))
|
|
|
|
|
|
{
|
|
|
|
|
|
XElement firstRun = e.Element(w + "r");
|
|
|
|
|
|
|
|
|
|
|
|
// Delete everything and insert updated text value
|
|
|
|
|
|
e.RemoveNodes();
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Add a core property to this document. If a core property already exists with the same name it will be replaced. Core property names are case insensitive.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
///<param name="propertyName">The property name.</param>
|
|
|
|
|
|
///<param name="propertyValue">The property value.</param>
|
|
|
|
|
|
///<example>
|
|
|
|
|
|
/// Add a core properties of each type to a document.
|
|
|
|
|
|
/// <code>
|
|
|
|
|
|
/// // Load Example.docx
|
|
|
|
|
|
/// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
|
|
|
|
|
|
/// {
|
|
|
|
|
|
/// // If this document does not contain a core property called 'forename', create one.
|
|
|
|
|
|
/// if (!document.CoreProperties.ContainsKey("forename"))
|
|
|
|
|
|
/// {
|
|
|
|
|
|
/// // Create a new core property called 'forename' and set its value.
|
|
|
|
|
|
/// document.AddCoreProperty("forename", "Cathal");
|
|
|
|
|
|
/// }
|
|
|
|
|
|
///
|
|
|
|
|
|
/// // Get this documents core property called 'forename'.
|
|
|
|
|
|
/// string forenameValue = document.CoreProperties["forename"];
|
|
|
|
|
|
///
|
|
|
|
|
|
/// // Print all of the information about this core property to Console.
|
|
|
|
|
|
/// Console.WriteLine(string.Format("Name: '{0}', Value: '{1}'\nPress any key...", "forename", forenameValue));
|
|
|
|
|
|
///
|
|
|
|
|
|
/// // Save all changes made to this document.
|
|
|
|
|
|
/// document.Save();
|
|
|
|
|
|
/// } // Release this document from memory.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// // Wait for the user to press a key before exiting.
|
|
|
|
|
|
/// Console.ReadKey();
|
|
|
|
|
|
/// </code>
|
|
|
|
|
|
/// </example>
|
|
|
|
|
|
/// <seealso cref="CoreProperties"/>
|
|
|
|
|
|
/// <seealso cref="CustomProperty"/>
|
|
|
|
|
|
/// <seealso cref="CustomProperties"/>
|
|
|
|
|
|
public void AddCoreProperty(string propertyName, string propertyValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
string propertyNamespacePrefix = propertyName.Contains(":") ? propertyName.Split(new[] { ':' })[0] : "cp";
|
|
|
|
|
|
string propertyLocalName = propertyName.Contains(":") ? propertyName.Split(new[] { ':' })[1] : propertyName;
|
|
|
|
|
|
|
|
|
|
|
|
// If this document does not contain a coreFilePropertyPart create one.)
|
|
|
|
|
|
if (!package.PartExists(new Uri("/docProps/core.xml", UriKind.Relative)))
|
|
|
|
|
|
throw new Exception("Core properties part doesn't exist.");
|
|
|
|
|
|
|
|
|
|
|
|
XDocument corePropDoc;
|
|
|
|
|
|
PackagePart corePropPart = package.GetPart(new Uri("/docProps/core.xml", UriKind.Relative));
|
|
|
|
|
|
using (TextReader tr = new StreamReader(corePropPart.GetStream(FileMode.Open, FileAccess.Read)))
|
|
|
|
|
|
{
|
|
|
|
|
|
corePropDoc = XDocument.Load(tr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
XElement t = new XElement(w + "t", corePropertyValue);
|
|
|
|
|
|
Novacode.Text.PreserveSpace(t);
|
|
|
|
|
|
e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
|
|
|
|
|
|
|
|
|
XElement corePropElement =
|
|
|
|
|
|
(from propElement in corePropDoc.Root.Elements()
|
|
|
|
|
|
where (propElement.Name.LocalName.Equals(propertyLocalName))
|
|
|
|
|
|
select propElement).SingleOrDefault();
|
|
|
|
|
|
if (corePropElement != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
corePropElement.SetValue(propertyValue);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var propertyNamespace = corePropDoc.Root.GetNamespaceOfPrefix(propertyNamespacePrefix);
|
|
|
|
|
|
corePropDoc.Root.Add(new XElement(XName.Get(propertyLocalName, propertyNamespace.NamespaceName), propertyValue));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create, FileAccess.Write)))
|
|
|
|
|
|
header.Save(tw);
|
|
|
|
|
|
|
|
|
using (TextWriter tw = new StreamWriter(corePropPart.GetStream(FileMode.Create, FileAccess.Write)))
|
|
|
|
|
|
{
|
|
|
|
|
|
corePropDoc.Save(tw);
|
|
|
|
|
|
}
|
|
|
|
|
|
UpdateCorePropertyValue(this, propertyLocalName, propertyValue);
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Footers
|
|
|
|
|
|
IEnumerable<PackagePart> footerParts = from footerPart in document.package.GetParts()
|
|
|
|
|
|
where (Regex.IsMatch(footerPart.Uri.ToString(), @"/word/footer\d?.xml"))
|
|
|
|
|
|
select footerPart;
|
|
|
|
|
|
foreach (PackagePart pp in footerParts)
|
|
|
|
|
|
|
|
|
internal static void UpdateCorePropertyValue(DocX document, string corePropertyName, string corePropertyValue)
|
|
|
{
|
|
|
{
|
|
|
XDocument footer = XDocument.Load(new StreamReader(pp.GetStream()));
|
|
|
|
|
|
|
|
|
string matchPattern = string.Format(@"(DOCPROPERTY)?{0}\\\*MERGEFORMAT", corePropertyName).ToLower();
|
|
|
|
|
|
foreach (XElement e in document.mainDoc.Descendants(XName.Get("fldSimple", w.NamespaceName)))
|
|
|
|
|
|
{
|
|
|
|
|
|
string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim().ToLower();
|
|
|
|
|
|
|
|
|
|
|
|
if (Regex.IsMatch(attr_value, matchPattern))
|
|
|
|
|
|
{
|
|
|
|
|
|
XElement firstRun = e.Element(w + "r");
|
|
|
|
|
|
XElement firstText = firstRun.Element(w + "t");
|
|
|
|
|
|
XElement rPr = firstText.Element(w + "rPr");
|
|
|
|
|
|
|
|
|
|
|
|
// Delete everything and insert updated text value
|
|
|
|
|
|
e.RemoveNodes();
|
|
|
|
|
|
|
|
|
|
|
|
XElement t = new XElement(w + "t", rPr, corePropertyValue);
|
|
|
|
|
|
Novacode.Text.PreserveSpace(t);
|
|
|
|
|
|
e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
foreach (XElement e in footer.Descendants(XName.Get("fldSimple", w.NamespaceName)))
|
|
|
|
|
|
{
|
|
|
|
|
|
string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim().ToLower();
|
|
|
|
|
|
if (Regex.IsMatch(attr_value, matchPattern))
|
|
|
|
|
|
|
|
|
#region Headers
|
|
|
|
|
|
|
|
|
|
|
|
IEnumerable<PackagePart> headerParts = from headerPart in document.package.GetParts()
|
|
|
|
|
|
where (Regex.IsMatch(headerPart.Uri.ToString(), @"/word/header\d?.xml"))
|
|
|
|
|
|
select headerPart;
|
|
|
|
|
|
foreach (PackagePart pp in headerParts)
|
|
|
{
|
|
|
{
|
|
|
XElement firstRun = e.Element(w + "r");
|
|
|
|
|
|
|
|
|
XDocument header = XDocument.Load(new StreamReader(pp.GetStream()));
|
|
|
|
|
|
|
|
|
|
|
|
foreach (XElement e in header.Descendants(XName.Get("fldSimple", w.NamespaceName)))
|
|
|
|
|
|
{
|
|
|
|
|
|
string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim().ToLower();
|
|
|
|
|
|
if (Regex.IsMatch(attr_value, matchPattern))
|
|
|
|
|
|
{
|
|
|
|
|
|
XElement firstRun = e.Element(w + "r");
|
|
|
|
|
|
|
|
|
// Delete everything and insert updated text value
|
|
|
|
|
|
e.RemoveNodes();
|
|
|
|
|
|
|
|
|
// Delete everything and insert updated text value
|
|
|
|
|
|
e.RemoveNodes();
|
|
|
|
|
|
|
|
|
|
|
|
XElement t = new XElement(w + "t", corePropertyValue);
|
|
|
|
|
|
Novacode.Text.PreserveSpace(t);
|
|
|
|
|
|
e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
XElement t = new XElement(w + "t", corePropertyValue);
|
|
|
|
|
|
Novacode.Text.PreserveSpace(t);
|
|
|
|
|
|
e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
|
|
|
|
|
|
|
|
|
using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create, FileAccess.Write)))
|
|
|
|
|
|
header.Save(tw);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Footers
|
|
|
|
|
|
IEnumerable<PackagePart> footerParts = from footerPart in document.package.GetParts()
|
|
|
|
|
|
where (Regex.IsMatch(footerPart.Uri.ToString(), @"/word/footer\d?.xml"))
|
|
|
|
|
|
select footerPart;
|
|
|
|
|
|
foreach (PackagePart pp in footerParts)
|
|
|
|
|
|
{
|
|
|
|
|
|
XDocument footer = XDocument.Load(new StreamReader(pp.GetStream()));
|
|
|
|
|
|
|
|
|
using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create, FileAccess.Write)))
|
|
|
|
|
|
footer.Save(tw);
|
|
|
|
|
|
|
|
|
foreach (XElement e in footer.Descendants(XName.Get("fldSimple", w.NamespaceName)))
|
|
|
|
|
|
{
|
|
|
|
|
|
string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim().ToLower();
|
|
|
|
|
|
if (Regex.IsMatch(attr_value, matchPattern))
|
|
|
|
|
|
{
|
|
|
|
|
|
XElement firstRun = e.Element(w + "r");
|
|
|
|
|
|
|
|
|
|
|
|
// Delete everything and insert updated text value
|
|
|
|
|
|
e.RemoveNodes();
|
|
|
|
|
|
|
|
|
|
|
|
XElement t = new XElement(w + "t", corePropertyValue);
|
|
|
|
|
|
Novacode.Text.PreserveSpace(t);
|
|
|
|
|
|
e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create, FileAccess.Write)))
|
|
|
|
|
|
footer.Save(tw);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
PopulateDocument(document, document.package);
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
PopulateDocument(document, document.package);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Add a custom property to this document. If a custom property already exists with the same name it will be replace. CustomProperty names are case insensitive.
|
|
|
/// Add a custom property to this document. If a custom property already exists with the same name it will be replace. CustomProperty names are case insensitive.
|
|
|
|
|
|
|
|
|
public void AddCustomProperty(CustomProperty cp)
|
|
|
public void AddCustomProperty(CustomProperty cp)
|
|
|
{
|
|
|
{
|
|
|
// If this document does not contain a customFilePropertyPart create one.
|
|
|
// If this document does not contain a customFilePropertyPart create one.
|
|
|
if(!package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
|
|
|
|
|
|
|
|
|
if (!package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
|
|
|
HelperFunctions.CreateCustomPropertiesPart(this);
|
|
|
HelperFunctions.CreateCustomPropertiesPart(this);
|
|
|
|
|
|
|
|
|
XDocument customPropDoc;
|
|
|
XDocument customPropDoc;
|
|
|
|
|
|
|
|
|
UpdateCustomPropertyValue(this, cp.Name, cp.Value.ToString());
|
|
|
UpdateCustomPropertyValue(this, cp.Name, cp.Value.ToString());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
internal static void UpdateCustomPropertyValue(DocX document, string customPropertyName, string customPropertyValue)
|
|
|
internal static void UpdateCustomPropertyValue(DocX document, string customPropertyName, string customPropertyValue)
|
|
|
{
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (attr_value.Equals(match_value, StringComparison.CurrentCultureIgnoreCase))
|
|
|
if (attr_value.Equals(match_value, StringComparison.CurrentCultureIgnoreCase))
|
|
|
{
|
|
|
{
|
|
|
XElement firstRun = e.Element(w + "r");
|
|
|
|
|
|
|
|
|
XElement firstRun = e.Element(w + "r");
|
|
|
XElement firstText = firstRun.Element(w + "t");
|
|
|
XElement firstText = firstRun.Element(w + "t");
|
|
|
XElement rPr = firstText.Element(w + "rPr");
|
|
|
XElement rPr = firstText.Element(w + "rPr");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Create an equation and insert it in the new paragraph
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public override Paragraph InsertEquation(String equation)
|
|
|
|
|
|
{
|
|
|
|
|
|
Paragraph p = base.InsertEquation(equation);
|
|
|
|
|
|
p.PackagePart = mainPart;
|
|
|
|
|
|
return p;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
#region IDisposable Members
|
|
|
#region IDisposable Members
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|