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
| foreach (var p in paragraphs) | foreach (var p in paragraphs) | ||||
| { | { | ||||
| if ((p.Xml.ElementsAfterSelf().FirstOrDefault() != null) && (p.Xml.ElementsAfterSelf().First().Name.Equals(DocX.w + "tbl"))) | 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()); | p.FollowingTable = new Table(this.Document, p.Xml.ElementsAfterSelf().First()); | ||||
| } | |||||
| } | } | ||||
| return paragraphs; | return paragraphs; | ||||
| return Paragraphs.Last(); | 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) | internal Container(DocX document, XElement xml) | ||||
| : base(document, xml) | : base(document, xml) | ||||
| { | { |
| { | { | ||||
| #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 r = "http://schemas.openxmlformats.org/officeDocument/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 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"; | ||||
| return (Footer)GetHeaderOrFooterByType(type, false); | 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"; | string reference = "footerReference"; | ||||
| if (b) | |||||
| if (isHeader) | |||||
| reference = "headerReference"; | reference = "headerReference"; | ||||
| // Get the Id of the [default, even or first] [Header or Footer] | |||||
| string Id = | string Id = | ||||
| ( | ( | ||||
| from e in mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).Descendants() | from e in mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).Descendants() | ||||
| if (Id != null) | if (Id != null) | ||||
| { | { | ||||
| // 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. | |||||
| 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); | ||||
| // Get the Part and open a stream to get the Xml file. | |||||
| PackagePart part = package.GetPart(partUri); | PackagePart part = package.GetPart(partUri); | ||||
| XDocument doc; | XDocument doc; | ||||
| using (TextReader tr = new StreamReader(part.GetStream())) | using (TextReader tr = new StreamReader(part.GetStream())) | ||||
| { | { | ||||
| doc = XDocument.Load(tr); | 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 | 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; | return null; | ||||
| } | } | ||||
| #region Internal variables defined foreach DocX object | #region Internal variables defined foreach DocX object | ||||
| // Object representation of the .docx | // Object representation of the .docx | ||||
| internal Package package; | internal Package package; | ||||
| // The mainDocument is loaded into a XDocument object for easy querying and editing | // The mainDocument is loaded into a XDocument object for easy querying and editing | ||||
| internal XDocument mainDoc; | internal XDocument mainDoc; | ||||
| internal XDocument header1; | internal XDocument header1; | ||||
| internal DocX(DocX document, XElement xml): base(document, xml) | internal DocX(DocX document, XElement xml): base(document, xml) | ||||
| { | { | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// </example> | /// </example> | ||||
| public Table InsertTable(int coloumnCount, int rowCount) | 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) | public Table AddTable(int rowCount, int coloumnCount) | ||||
| /// </example> | /// </example> | ||||
| public Table InsertTable(int index, Table t) | 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> | /// <summary> | ||||
| /// </example> | /// </example> | ||||
| public Table InsertTable(Table t) | 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> | /// <summary> | ||||
| /// </example> | /// </example> | ||||
| public Table InsertTable(int index, int coloumnCount, int rowCount) | 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> | /// <summary> | ||||
| return document; | 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> | /// <summary> | ||||
| /// Loads a document into a DocX object using a Stream. | /// Loads a document into a DocX object using a Stream. | ||||
| } | } | ||||
| } | } | ||||
| public override List<Table> Tables | |||||
| { | |||||
| get | |||||
| { | |||||
| List<Table> l = base.Tables; | |||||
| l.ForEach(x => x.mainPart = mainPart); | |||||
| return l; | |||||
| } | |||||
| } | |||||
| #region IDisposable Members | #region IDisposable Members | ||||
| /// <summary> | /// <summary> |
| { | { | ||||
| public class Footer : Container | public class Footer : Container | ||||
| { | { | ||||
| PackagePart mainPart; | |||||
| internal PackagePart mainPart; | |||||
| internal Footer(DocX document, XElement xml, PackagePart mainPart): base(document, xml) | internal Footer(DocX document, XElement xml, PackagePart mainPart): base(document, xml) | ||||
| { | { | ||||
| this.mainPart = mainPart; | this.mainPart = mainPart; | ||||
| get | get | ||||
| { | { | ||||
| List<Paragraph> l = base.Paragraphs; | 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; | return l; | ||||
| } | } | ||||
| } | } |
| { | { | ||||
| public class Header : Container | public class Header : Container | ||||
| { | { | ||||
| PackagePart mainPart; | |||||
| internal PackagePart mainPart; | |||||
| internal Header(DocX document, XElement xml, PackagePart mainPart):base(document, xml) | internal Header(DocX document, XElement xml, PackagePart mainPart):base(document, xml) | ||||
| { | { | ||||
| this.mainPart = mainPart; | this.mainPart = mainPart; | ||||
| get | get | ||||
| { | { | ||||
| List<Paragraph> l = base.Paragraphs; | 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; | return l; | ||||
| } | } | ||||
| } | } |
| { | { | ||||
| internal static class HelperFunctions | 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) | internal static int GetSize(XElement Xml) | ||||
| { | { | ||||
| switch (Xml.Name.LocalName) | switch (Xml.Name.LocalName) |
| /// </summary> | /// </summary> | ||||
| public class Paragraph : InsertBeforeOrAfter | public class Paragraph : InsertBeforeOrAfter | ||||
| { | { | ||||
| PackagePart mainPart; | |||||
| internal PackagePart mainPart; | |||||
| public PackagePart PackagePart { get { return mainPart; } set { mainPart = value; } } | public PackagePart PackagePart { get { return mainPart; } set { mainPart = value; } } | ||||
| // The Append family of functions use this List to apply style. | // The Append family of functions use this List to apply style. | ||||
| where e.Name.LocalName.Equals("blip") | where e.Name.LocalName.Equals("blip") | ||||
| select e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")).Value | select e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")).Value | ||||
| ).Single() | ).Single() | ||||
| let img = new Image(Document, mainPart.GetRelationship(id)) | |||||
| let | |||||
| img = new Image(Document, mainPart.GetRelationship(id)) | |||||
| select new Picture(Document, p, img) | select new Picture(Document, p, img) | ||||
| ).ToList(); | ).ToList(); | ||||
| /// }// Release this document from memory. | /// }// Release this document from memory. | ||||
| /// </code> | /// </code> | ||||
| /// </example> | /// </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) | //public Picture InsertPicture(int index, Picture picture) | ||||
| //{ | //{ | ||||
| /// }// Release this document from memory. | /// }// Release this document from memory. | ||||
| /// </code> | /// </code> | ||||
| /// </example> | /// </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> | /// <summary> | ||||
| /// Create a new Picture. | /// Create a new Picture. | ||||
| return new Picture(document, xml, new Image(document, document.mainPart.GetRelationship(id))); | 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> | /// <summary> | ||||
| /// Creates an Edit either a ins or a del with the specified content and date | /// Creates an Edit either a ins or a del with the specified content and date | ||||
| /// </example> | /// </example> | ||||
| public Paragraph AppendPicture(Picture p) | 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"); | 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); | 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() | from e in Xml.Elements().Last().Descendants() | ||||
| where e.Name.LocalName.Equals("blip") | where e.Name.LocalName.Equals("blip") | ||||
| select e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")) | select e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")) | ||||
| ).Single(); | ).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(); | 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; | 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> | /// <summary> | ||||
| /// Append text on a new line to this Paragraph. | /// Append text on a new line to this Paragraph. | ||||
| /// </summary> | /// </summary> |
| /// <summary> | /// <summary> | ||||
| /// Returns a list of rows in this table. | /// Returns a list of rows in this table. | ||||
| /// </summary> | /// </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; | private TableDesign design; | ||||
| internal PackagePart mainPart; | internal PackagePart mainPart; | ||||
| this.Xml = xml; | this.Xml = xml; | ||||
| XElement properties = xml.Element(XName.Get("tblPr", DocX.w.NamespaceName)); | 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)); | XElement style = properties.Element(XName.Get("tblStyle", DocX.w.NamespaceName)); | ||||
| if (style != null) | if (style != null) | ||||
| } | } | ||||
| internal Table table; | internal Table table; | ||||
| internal PackagePart mainPart; | |||||
| internal Row(Table table, DocX document, XElement xml):base(document, xml) | internal Row(Table table, DocX document, XElement xml):base(document, xml) | ||||
| { | { | ||||
| this.table = table; | this.table = table; | ||||
| this.mainPart = table.mainPart; | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| public class Cell:Container | public class Cell:Container | ||||
| { | { | ||||
| internal Row row; | internal Row row; | ||||
| internal PackagePart mainPart; | |||||
| internal Cell(Row row, DocX document, XElement xml):base(document, xml) | internal Cell(Row row, DocX document, XElement xml):base(document, xml) | ||||
| { | { | ||||
| this.row = row; | this.row = row; | ||||
| this.mainPart = row.mainPart; | |||||
| } | } | ||||
| public override List<Paragraph> Paragraphs | public override List<Paragraph> Paragraphs |