Added unit tests. Removed overloads which confussed API. Its now possible to create one Picture and insert it into the main document, headers and footers.master
| @@ -66,9 +66,7 @@ namespace Novacode | |||
| foreach (var p in paragraphs) | |||
| { | |||
| if ((p.Xml.ElementsAfterSelf().FirstOrDefault() != null) && (p.Xml.ElementsAfterSelf().First().Name.Equals(DocX.w + "tbl"))) | |||
| { | |||
| p.FollowingTable = new Table(this.Document, p.Xml.ElementsAfterSelf().First()); | |||
| } | |||
| } | |||
| return paragraphs; | |||
| @@ -380,6 +378,68 @@ namespace Novacode | |||
| return Paragraphs.Last(); | |||
| } | |||
| public Table InsertTable(int coloumnCount, int rowCount) | |||
| { | |||
| XElement newTable = HelperFunctions.CreateTable(rowCount, coloumnCount); | |||
| Xml.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().Add(newTable); | |||
| return new Table(Document, newTable); | |||
| } | |||
| public Table InsertTable(int index, int coloumnCount, int rowCount) | |||
| { | |||
| XElement newTable = HelperFunctions.CreateTable(rowCount, coloumnCount); | |||
| Paragraph p = HelperFunctions.GetFirstParagraphEffectedByInsert(Document, index); | |||
| if (p == null) | |||
| Xml.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().AddFirst(newTable); | |||
| else | |||
| { | |||
| XElement[] split = HelperFunctions.SplitParagraph(p, index - p.startIndex); | |||
| p.Xml.ReplaceWith | |||
| ( | |||
| split[0], | |||
| newTable, | |||
| split[1] | |||
| ); | |||
| } | |||
| return new Table(Document, newTable); | |||
| } | |||
| public Table InsertTable(Table t) | |||
| { | |||
| XElement newXElement = new XElement(t.Xml); | |||
| Xml.Add(newXElement); | |||
| Table newTable = new Table(Document, newXElement); | |||
| newTable.Design = t.Design; | |||
| return newTable; | |||
| } | |||
| public Table InsertTable(int index, Table t) | |||
| { | |||
| Paragraph p = HelperFunctions.GetFirstParagraphEffectedByInsert(Document, index); | |||
| XElement[] split = HelperFunctions.SplitParagraph(p, index - p.startIndex); | |||
| XElement newXElement = new XElement(t.Xml); | |||
| p.Xml.ReplaceWith | |||
| ( | |||
| split[0], | |||
| newXElement, | |||
| split[1] | |||
| ); | |||
| Table newTable = new Table(Document, newXElement); | |||
| newTable.Design = t.Design; | |||
| return newTable; | |||
| } | |||
| internal Container(DocX document, XElement xml) | |||
| : base(document, xml) | |||
| { | |||
| @@ -20,6 +20,8 @@ namespace Novacode | |||
| { | |||
| #region Namespaces | |||
| 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 r = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"; | |||
| static internal XNamespace customPropertiesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"; | |||
| static internal XNamespace customVTypesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"; | |||
| @@ -259,12 +261,14 @@ namespace Novacode | |||
| return (Footer)GetHeaderOrFooterByType(type, false); | |||
| } | |||
| private object GetHeaderOrFooterByType(string type, bool b) | |||
| private object GetHeaderOrFooterByType(string type, bool isHeader) | |||
| { | |||
| // Switch which handles either case Header\Footer, this just cuts down on code duplication. | |||
| string reference = "footerReference"; | |||
| if (b) | |||
| if (isHeader) | |||
| reference = "headerReference"; | |||
| // Get the Id of the [default, even or first] [Header or Footer] | |||
| string Id = | |||
| ( | |||
| from e in mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).Descendants() | |||
| @@ -274,22 +278,33 @@ namespace Novacode | |||
| if (Id != null) | |||
| { | |||
| // Get the Xml file for this Header or Footer. | |||
| Uri partUri = mainPart.GetRelationship(Id).TargetUri; | |||
| // Weird problem with PackaePart API. | |||
| if (!partUri.OriginalString.StartsWith("/word/")) | |||
| partUri = new Uri("/word/" + partUri.OriginalString, UriKind.Relative); | |||
| // Get the Part and open a stream to get the Xml file. | |||
| PackagePart part = package.GetPart(partUri); | |||
| XDocument doc; | |||
| using (TextReader tr = new StreamReader(part.GetStream())) | |||
| { | |||
| doc = XDocument.Load(tr); | |||
| if(b) | |||
| return new Header(this, doc.Element(w + "hdr"), part); | |||
| // Header and Footer extend Container. | |||
| Container c; | |||
| if (isHeader) | |||
| c = new Header(this, doc.Element(w + "hdr"), part); | |||
| else | |||
| return new Footer(this, doc.Element(w + "ftr"), part); | |||
| c = new Footer(this, doc.Element(w + "ftr"), part); | |||
| return c; | |||
| } | |||
| } | |||
| // If we got this far something went wrong. | |||
| return null; | |||
| } | |||
| @@ -302,6 +317,7 @@ namespace Novacode | |||
| #region Internal variables defined foreach DocX object | |||
| // Object representation of the .docx | |||
| internal Package package; | |||
| // The mainDocument is loaded into a XDocument object for easy querying and editing | |||
| internal XDocument mainDoc; | |||
| internal XDocument header1; | |||
| @@ -320,6 +336,7 @@ namespace Novacode | |||
| internal DocX(DocX document, XElement xml): base(document, xml) | |||
| { | |||
| } | |||
| /// <summary> | |||
| @@ -784,10 +801,9 @@ namespace Novacode | |||
| /// </example> | |||
| public Table InsertTable(int coloumnCount, int rowCount) | |||
| { | |||
| XElement newTable = HelperFunctions.CreateTable(rowCount, coloumnCount); | |||
| mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().Add(newTable); | |||
| return new Table(this, newTable); | |||
| Table t = base.InsertTable(coloumnCount, rowCount); | |||
| t.mainPart = mainPart; | |||
| return t; | |||
| } | |||
| public Table AddTable(int rowCount, int coloumnCount) | |||
| @@ -830,21 +846,9 @@ namespace Novacode | |||
| /// </example> | |||
| public Table InsertTable(int index, Table t) | |||
| { | |||
| Paragraph p = HelperFunctions.GetFirstParagraphEffectedByInsert(this, index); | |||
| XElement[] split = HelperFunctions.SplitParagraph(p, index - p.startIndex); | |||
| XElement newXElement = new XElement(t.Xml); | |||
| p.Xml.ReplaceWith | |||
| ( | |||
| split[0], | |||
| newXElement, | |||
| split[1] | |||
| ); | |||
| Table newTable = new Table(this, newXElement); | |||
| newTable.Design = t.Design; | |||
| return newTable; | |||
| Table t2 = base.InsertTable(index, t); | |||
| t2.mainPart = mainPart; | |||
| return t2; | |||
| } | |||
| /// <summary> | |||
| @@ -881,13 +885,8 @@ namespace Novacode | |||
| /// </example> | |||
| public Table InsertTable(Table t) | |||
| { | |||
| XElement newXElement = new XElement(t.Xml); | |||
| mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().Add(newXElement); | |||
| Table newTable = new Table(this, newXElement); | |||
| newTable.Design = t.Design; | |||
| return newTable; | |||
| t.mainPart = mainPart; | |||
| return base.InsertTable(t); | |||
| } | |||
| /// <summary> | |||
| @@ -928,27 +927,9 @@ namespace Novacode | |||
| /// </example> | |||
| public Table InsertTable(int index, int coloumnCount, int rowCount) | |||
| { | |||
| XElement newTable = HelperFunctions.CreateTable(rowCount, coloumnCount); | |||
| Paragraph p = HelperFunctions.GetFirstParagraphEffectedByInsert(this, index); | |||
| if (p == null) | |||
| mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).First().AddFirst(newTable); | |||
| else | |||
| { | |||
| XElement[] split = HelperFunctions.SplitParagraph(p, index - p.startIndex); | |||
| p.Xml.ReplaceWith | |||
| ( | |||
| split[0], | |||
| newTable, | |||
| split[1] | |||
| ); | |||
| } | |||
| return new Table(this, newTable); | |||
| Table t = InsertTable(index, coloumnCount, rowCount); | |||
| t.mainPart = mainPart; | |||
| return t; | |||
| } | |||
| /// <summary> | |||
| @@ -1128,23 +1109,75 @@ namespace Novacode | |||
| return document; | |||
| } | |||
| private static void PopulateDocument(DocX document, Package package) | |||
| { | |||
| Headers headers = new Headers(); | |||
| headers.odd = document.GetHeaderByType("default"); | |||
| headers.even = document.GetHeaderByType("even"); | |||
| headers.first = document.GetHeaderByType("first"); | |||
| Footers footers = new Footers(); | |||
| footers.odd = document.GetFooterByType("default"); | |||
| footers.even = document.GetFooterByType("even"); | |||
| footers.first = document.GetFooterByType("first"); | |||
| document.Xml = document.mainDoc.Root.Element(w + "body"); | |||
| document.headers = headers; | |||
| document.footers = footers; | |||
| document.settingsPart = HelperFunctions.CreateOrGetSettingsPart(package); | |||
| } | |||
| private static void PopulateDocument(DocX document, Package package) | |||
| { | |||
| Headers headers = new Headers(); | |||
| headers.odd = document.GetHeaderByType("default"); | |||
| headers.even = document.GetHeaderByType("even"); | |||
| headers.first = document.GetHeaderByType("first"); | |||
| Footers footers = new Footers(); | |||
| footers.odd = document.GetFooterByType("default"); | |||
| footers.even = document.GetFooterByType("even"); | |||
| footers.first = document.GetFooterByType("first"); | |||
| //// Get the sectPr for this document. | |||
| //XElement sectPr = document.mainDoc.Descendants(XName.Get("sectPr", DocX.w.NamespaceName)).Single(); | |||
| //if (sectPr != null) | |||
| //{ | |||
| // // Extract the even header reference | |||
| // var header_even_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "headerReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "even"); | |||
| // string id = header_even_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value; | |||
| // var res = document.mainPart.GetRelationship(id); | |||
| // string ans = res.SourceUri.OriginalString; | |||
| // headers.even.xml_filename = ans; | |||
| // // Extract the odd header reference | |||
| // var header_odd_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "headerReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "default"); | |||
| // string id2 = header_odd_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value; | |||
| // var res2 = document.mainPart.GetRelationship(id2); | |||
| // string ans2 = res2.SourceUri.OriginalString; | |||
| // headers.odd.xml_filename = ans2; | |||
| // // Extract the first header reference | |||
| // var header_first_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "h | |||
| //eaderReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "first"); | |||
| // string id3 = header_first_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value; | |||
| // var res3 = document.mainPart.GetRelationship(id3); | |||
| // string ans3 = res3.SourceUri.OriginalString; | |||
| // headers.first.xml_filename = ans3; | |||
| // // Extract the even footer reference | |||
| // var footer_even_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "footerReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "even"); | |||
| // string id4 = footer_even_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value; | |||
| // var res4 = document.mainPart.GetRelationship(id4); | |||
| // string ans4 = res4.SourceUri.OriginalString; | |||
| // footers.even.xml_filename = ans4; | |||
| // // Extract the odd footer reference | |||
| // var footer_odd_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "footerReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "default"); | |||
| // string id5 = footer_odd_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value; | |||
| // var res5 = document.mainPart.GetRelationship(id5); | |||
| // string ans5 = res5.SourceUri.OriginalString; | |||
| // footers.odd.xml_filename = ans5; | |||
| // // Extract the first footer reference | |||
| // var footer_first_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "footerReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "first"); | |||
| // string id6 = footer_first_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value; | |||
| // var res6 = document.mainPart.GetRelationship(id6); | |||
| // string ans6 = res6.SourceUri.OriginalString; | |||
| // footers.first.xml_filename = ans6; | |||
| //} | |||
| document.Xml = document.mainDoc.Root.Element(w + "body"); | |||
| document.headers = headers; | |||
| document.footers = footers; | |||
| document.settingsPart = HelperFunctions.CreateOrGetSettingsPart(package); | |||
| } | |||
| /// <summary> | |||
| /// Loads a document into a DocX object using a Stream. | |||
| @@ -2634,6 +2667,16 @@ namespace Novacode | |||
| } | |||
| } | |||
| public override List<Table> Tables | |||
| { | |||
| get | |||
| { | |||
| List<Table> l = base.Tables; | |||
| l.ForEach(x => x.mainPart = mainPart); | |||
| return l; | |||
| } | |||
| } | |||
| #region IDisposable Members | |||
| /// <summary> | |||
| @@ -9,7 +9,7 @@ namespace Novacode | |||
| { | |||
| public class Footer : Container | |||
| { | |||
| PackagePart mainPart; | |||
| internal PackagePart mainPart; | |||
| internal Footer(DocX document, XElement xml, PackagePart mainPart): base(document, xml) | |||
| { | |||
| this.mainPart = mainPart; | |||
| @@ -75,7 +75,17 @@ namespace Novacode | |||
| get | |||
| { | |||
| List<Paragraph> l = base.Paragraphs; | |||
| l.ForEach(x => x.PackagePart = mainPart); | |||
| l.ForEach(x => x.mainPart = mainPart); | |||
| return l; | |||
| } | |||
| } | |||
| public override List<Table> Tables | |||
| { | |||
| get | |||
| { | |||
| List<Table> l = base.Tables; | |||
| l.ForEach(x => x.mainPart = mainPart); | |||
| return l; | |||
| } | |||
| } | |||
| @@ -9,7 +9,7 @@ namespace Novacode | |||
| { | |||
| public class Header : Container | |||
| { | |||
| PackagePart mainPart; | |||
| internal PackagePart mainPart; | |||
| internal Header(DocX document, XElement xml, PackagePart mainPart):base(document, xml) | |||
| { | |||
| this.mainPart = mainPart; | |||
| @@ -75,7 +75,17 @@ namespace Novacode | |||
| get | |||
| { | |||
| List<Paragraph> l = base.Paragraphs; | |||
| l.ForEach(x => x.PackagePart = mainPart); | |||
| l.ForEach(x => x.mainPart = mainPart); | |||
| return l; | |||
| } | |||
| } | |||
| public override List<Table> Tables | |||
| { | |||
| get | |||
| { | |||
| List<Table> l = base.Tables; | |||
| l.ForEach(x => x.mainPart = mainPart); | |||
| return l; | |||
| } | |||
| } | |||
| @@ -13,6 +13,21 @@ namespace Novacode | |||
| { | |||
| internal static class HelperFunctions | |||
| { | |||
| internal static void CreateRelsPackagePart(DocX Document, Uri uri) | |||
| { | |||
| PackagePart pp = Document.package.CreatePart(uri, "application/vnd.openxmlformats-package.relationships+xml"); | |||
| using (TextWriter tw = new StreamWriter(pp.GetStream())) | |||
| { | |||
| XDocument d = new XDocument | |||
| ( | |||
| new XDeclaration("1.0", "UTF-8", "yes"), | |||
| new XElement(XName.Get("Relationships", DocX.rel.NamespaceName)) | |||
| ); | |||
| var root = d.Root; | |||
| d.Save(tw); | |||
| } | |||
| } | |||
| internal static int GetSize(XElement Xml) | |||
| { | |||
| switch (Xml.Name.LocalName) | |||
| @@ -17,7 +17,7 @@ namespace Novacode | |||
| /// </summary> | |||
| public class Paragraph : InsertBeforeOrAfter | |||
| { | |||
| PackagePart mainPart; | |||
| internal PackagePart mainPart; | |||
| public PackagePart PackagePart { get { return mainPart; } set { mainPart = value; } } | |||
| // The Append family of functions use this List to apply style. | |||
| @@ -62,7 +62,9 @@ namespace Novacode | |||
| where e.Name.LocalName.Equals("blip") | |||
| select e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")).Value | |||
| ).Single() | |||
| let img = new Image(Document, mainPart.GetRelationship(id)) | |||
| let | |||
| img = new Image(Document, mainPart.GetRelationship(id)) | |||
| select new Picture(Document, p, img) | |||
| ).ToList(); | |||
| @@ -1220,17 +1222,19 @@ namespace Novacode | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Picture InsertPicture(string imageID, string name, string description) | |||
| { | |||
| Picture p = CreatePicture(Document, imageID, name, description); | |||
| Xml.Add(p.Xml); | |||
| return p; | |||
| } | |||
| /// Removed to simplify the API. | |||
| //public Picture InsertPicture(string imageID, string name, string description) | |||
| //{ | |||
| // Picture p = CreatePicture(Document, imageID, name, description); | |||
| // Xml.Add(p.Xml); | |||
| // return p; | |||
| //} | |||
| public Picture InsertPicture(string imageID) | |||
| { | |||
| return InsertPicture(imageID, string.Empty, string.Empty); | |||
| } | |||
| // Removed because it confusses the API. | |||
| //public Picture InsertPicture(string imageID) | |||
| //{ | |||
| // return InsertPicture(imageID, string.Empty, string.Empty); | |||
| //} | |||
| //public Picture InsertPicture(int index, Picture picture) | |||
| //{ | |||
| @@ -1302,31 +1306,32 @@ namespace Novacode | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public Picture InsertPicture(int index, string imageID, string name, string description) | |||
| { | |||
| Picture picture = CreatePicture(Document, imageID, name, description); | |||
| /// Removed to simplify API. | |||
| //public Picture InsertPicture(int index, string imageID, string name, string description) | |||
| //{ | |||
| // Picture picture = CreatePicture(Document, imageID, name, description); | |||
| Run run = GetFirstRunEffectedByEdit(index); | |||
| // Run run = GetFirstRunEffectedByEdit(index); | |||
| if (run == null) | |||
| Xml.Add(picture.Xml); | |||
| else | |||
| { | |||
| // Split this run at the point you want to insert | |||
| XElement[] splitRun = Run.SplitRun(run, index); | |||
| // if (run == null) | |||
| // Xml.Add(picture.Xml); | |||
| // else | |||
| // { | |||
| // // Split this run at the point you want to insert | |||
| // XElement[] splitRun = Run.SplitRun(run, index); | |||
| // Replace the origional run | |||
| run.Xml.ReplaceWith | |||
| ( | |||
| splitRun[0], | |||
| picture.Xml, | |||
| splitRun[1] | |||
| ); | |||
| } | |||
| // // Replace the origional run | |||
| // run.Xml.ReplaceWith | |||
| // ( | |||
| // splitRun[0], | |||
| // picture.Xml, | |||
| // splitRun[1] | |||
| // ); | |||
| // } | |||
| HelperFunctions.RenumberIDs(Document); | |||
| return picture; | |||
| } | |||
| // HelperFunctions.RenumberIDs(Document); | |||
| // return picture; | |||
| //} | |||
| /// <summary> | |||
| /// Create a new Picture. | |||
| @@ -1390,10 +1395,11 @@ namespace Novacode | |||
| return new Picture(document, xml, new Image(document, document.mainPart.GetRelationship(id))); | |||
| } | |||
| public Picture InsertPicture(int index, string imageID) | |||
| { | |||
| return InsertPicture(index, imageID, string.Empty, string.Empty); | |||
| } | |||
| // Removed because it confusses the API. | |||
| //public Picture InsertPicture(int index, string imageID) | |||
| //{ | |||
| // return InsertPicture(index, imageID, string.Empty, string.Empty); | |||
| //} | |||
| /// <summary> | |||
| /// Creates an Edit either a ins or a del with the specified content and date | |||
| @@ -1863,29 +1869,201 @@ namespace Novacode | |||
| /// </example> | |||
| public Paragraph AppendPicture(Picture p) | |||
| { | |||
| if (!p.picture_rels.ContainsKey(mainPart)) | |||
| // Convert the path of this mainPart to its equilivant rels file path. | |||
| string path = mainPart.Uri.OriginalString.Replace("/word/", ""); | |||
| Uri rels_path = new Uri("/word/_rels/" + path + ".rels", UriKind.Relative); | |||
| // Check to see if the rels file exists and create it if not. | |||
| if (!Document.package.PartExists(rels_path)) | |||
| HelperFunctions.CreateRelsPackagePart(Document, rels_path); | |||
| string image_uri_string = p.img.pr.TargetUri.OriginalString; | |||
| // Search for a relationship with a TargetUri that points at this Image. | |||
| var Id = | |||
| ( | |||
| from r in mainPart.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") | |||
| where r.TargetUri.OriginalString == image_uri_string | |||
| select r.Id | |||
| ).SingleOrDefault(); | |||
| // If such a relation dosen't exist, create one. | |||
| if (Id == null) | |||
| { | |||
| // Check to see if a relationship for this Picture exists and create it if not. | |||
| PackageRelationship pr = mainPart.CreateRelationship(p.img.pr.TargetUri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"); | |||
| p.picture_rels.Add(mainPart, pr); | |||
| Id = pr.Id; | |||
| } | |||
| PackageRelationship rel = p.picture_rels[mainPart]; | |||
| // Add the Picture Xml to the end of the Paragragraph Xml. | |||
| Xml.Add(p.Xml); | |||
| XAttribute a_id = | |||
| // Extract the attribute id from the Pictures Xml. | |||
| XAttribute a_id = | |||
| ( | |||
| from e in Xml.Elements().Last().Descendants() | |||
| where e.Name.LocalName.Equals("blip") | |||
| select e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")) | |||
| ).Single(); | |||
| a_id.SetValue(rel.Id); | |||
| // Set its value to the Pictures relationships id. | |||
| a_id.SetValue(Id); | |||
| // For formatting such as .Bold() | |||
| this.runs = Xml.Elements(XName.Get("r", DocX.w.NamespaceName)).Reverse().Take(p.Xml.Elements(XName.Get("r", DocX.w.NamespaceName)).Count()).ToList(); | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Insert a Picture into a Paragraph at the given text index. | |||
| /// If not index is provided defaults to 0. | |||
| /// </summary> | |||
| /// <param name="p">The Picture to insert.</param> | |||
| /// <param name="index">The text index to insert at.</param> | |||
| /// <returns>The modified Paragraph.</returns> | |||
| /// <example> | |||
| /// <code> | |||
| ///Load test document. | |||
| ///using (DocX document = DocX.Create("Test.docx")) | |||
| ///{ | |||
| /// // Add Headers and Footers into this document. | |||
| /// document.AddHeaders(); | |||
| /// document.AddFooters(); | |||
| /// document.DifferentFirstPage = true; | |||
| /// document.DifferentOddAndEvenPages = true; | |||
| /// | |||
| /// // Add an Image to this document. | |||
| /// Novacode.Image img = document.AddImage(directory_documents + "purple.png"); | |||
| /// | |||
| /// // Create a Picture from this Image. | |||
| /// Picture pic = img.CreatePicture(); | |||
| /// | |||
| /// // Main document. | |||
| /// Paragraph p0 = document.InsertParagraph("Hello"); | |||
| /// p0.InsertPicture(pic, 3); | |||
| /// | |||
| /// // Header first. | |||
| /// Paragraph p1 = document.Headers.first.InsertParagraph("----"); | |||
| /// p1.InsertPicture(pic, 2); | |||
| /// | |||
| /// // Header odd. | |||
| /// Paragraph p2 = document.Headers.odd.InsertParagraph("----"); | |||
| /// p2.InsertPicture(pic, 2); | |||
| /// | |||
| /// // Header even. | |||
| /// Paragraph p3 = document.Headers.even.InsertParagraph("----"); | |||
| /// p3.InsertPicture(pic, 2); | |||
| /// | |||
| /// // Footer first. | |||
| /// Paragraph p4 = document.Footers.first.InsertParagraph("----"); | |||
| /// p4.InsertPicture(pic, 2); | |||
| /// | |||
| /// // Footer odd. | |||
| /// Paragraph p5 = document.Footers.odd.InsertParagraph("----"); | |||
| /// p5.InsertPicture(pic, 2); | |||
| /// | |||
| /// // Footer even. | |||
| /// Paragraph p6 = document.Footers.even.InsertParagraph("----"); | |||
| /// p6.InsertPicture(pic, 2); | |||
| /// | |||
| /// // Save this document. | |||
| /// document.Save(); | |||
| ///} | |||
| /// </code> | |||
| /// </example> | |||
| public Paragraph InsertPicture(Picture p, int index = 0) | |||
| { | |||
| // Convert the path of this mainPart to its equilivant rels file path. | |||
| string path = mainPart.Uri.OriginalString.Replace("/word/", ""); | |||
| Uri rels_path = new Uri("/word/_rels/" + path + ".rels", UriKind.Relative); | |||
| // Check to see if the rels file exists and create it if not. | |||
| if (!Document.package.PartExists(rels_path)) | |||
| HelperFunctions.CreateRelsPackagePart(Document, rels_path); | |||
| string image_uri_string = p.img.pr.TargetUri.OriginalString; | |||
| // Search for a relationship with a TargetUri that points at this Image. | |||
| var Id = | |||
| ( | |||
| from r in mainPart.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") | |||
| where r.TargetUri.OriginalString == image_uri_string | |||
| select r.Id | |||
| ).SingleOrDefault(); | |||
| // If such a relation dosen't exist, create one. | |||
| if (Id == null) | |||
| { | |||
| // Check to see if a relationship for this Picture exists and create it if not. | |||
| PackageRelationship pr = mainPart.CreateRelationship(p.img.pr.TargetUri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"); | |||
| Id = pr.Id; | |||
| } | |||
| XAttribute a_id; | |||
| if (index == 0) | |||
| { | |||
| // Add the Picture Xml to the start of the Paragragraph Xml. | |||
| Xml.AddFirst(p.Xml); | |||
| a_id = | |||
| ( | |||
| from e in Xml.Elements().First().Descendants() | |||
| where e.Name.LocalName.Equals("blip") | |||
| select e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")) | |||
| ).Single(); | |||
| } | |||
| else | |||
| { | |||
| // Get the first run effected by this Insert | |||
| Run run = GetFirstRunEffectedByEdit(index); | |||
| XElement p_xml; | |||
| if (run == null) | |||
| { | |||
| // Add this picture as the last element. | |||
| Xml.Add(p.Xml); | |||
| // Extract the picture back out of the DOM. | |||
| p_xml = (XElement)Xml.LastNode; | |||
| } | |||
| else | |||
| { | |||
| // Split this run at the point you want to insert | |||
| XElement[] splitRun = Run.SplitRun(run, index); | |||
| // Replace the origional run. | |||
| 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; | |||
| } | |||
| // Extract the attribute id from the Pictures Xml. | |||
| a_id = | |||
| ( | |||
| from e in p_xml.Descendants() | |||
| where e.Name.LocalName.Equals("blip") | |||
| select e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")) | |||
| ).Single(); | |||
| } | |||
| // Set its value to the Pictures relationships id. | |||
| a_id.SetValue(Id); | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Append text on a new line to this Paragraph. | |||
| /// </summary> | |||
| @@ -168,7 +168,26 @@ namespace Novacode | |||
| /// <summary> | |||
| /// Returns a list of rows in this table. | |||
| /// </summary> | |||
| public List<Row> Rows { get { return rows; } } | |||
| public List<Row> Rows | |||
| { | |||
| get | |||
| { | |||
| List<Row> rows = | |||
| ( | |||
| from r in Xml.Elements(XName.Get("tr", DocX.w.NamespaceName)) | |||
| select new Row(this, Document, r) | |||
| ).ToList(); | |||
| rowCount = rows.Count; | |||
| if (rows.Count > 0) | |||
| if (rows[0].Cells.Count > 0) | |||
| columnCount = rows[0].Cells.Count; | |||
| return rows; | |||
| } | |||
| } | |||
| private TableDesign design; | |||
| internal PackagePart mainPart; | |||
| @@ -179,15 +198,6 @@ namespace Novacode | |||
| this.Xml = xml; | |||
| XElement properties = xml.Element(XName.Get("tblPr", DocX.w.NamespaceName)); | |||
| rows = (from r in xml.Elements(XName.Get("tr", DocX.w.NamespaceName)) | |||
| select new Row(this, document, r)).ToList(); | |||
| rowCount = rows.Count; | |||
| if (rows.Count > 0) | |||
| if (rows[0].Cells.Count > 0) | |||
| columnCount = rows[0].Cells.Count; | |||
| XElement style = properties.Element(XName.Get("tblStyle", DocX.w.NamespaceName)); | |||
| if (style != null) | |||
| @@ -1567,9 +1577,11 @@ namespace Novacode | |||
| } | |||
| internal Table table; | |||
| internal PackagePart mainPart; | |||
| internal Row(Table table, DocX document, XElement xml):base(document, xml) | |||
| { | |||
| this.table = table; | |||
| this.mainPart = table.mainPart; | |||
| } | |||
| /// <summary> | |||
| @@ -1728,9 +1740,11 @@ namespace Novacode | |||
| public class Cell:Container | |||
| { | |||
| internal Row row; | |||
| internal PackagePart mainPart; | |||
| internal Cell(Row row, DocX document, XElement xml):base(document, xml) | |||
| { | |||
| this.row = row; | |||
| this.mainPart = row.mainPart; | |||
| } | |||
| public override List<Paragraph> Paragraphs | |||