- MergeCellsInRow - allow for merging the rows where the columns don't match (for instance, merge the last column of a row with 6 elements and a row with 3 elements will merge the last column of the row with too few elements) - this is a specific case that I needed... others may need it as well, but I've got a separate branch with this change so it's up to you Container.cs (and baseclasses) - Moved PackagePart to the base class - found an issue where images in a table contained in the header or footer wouldn't display, this keeps track of what part of the doc and passes it to child things, (like inserting a table to a paragraph in the footer will have the correct part) - Add a deep search for paragraphs.. This is to find a bookmark within a textbox or other art.. since a paragraph will wind up with a child paragraph.. (if you are searching for a bookmark like that the second one is the "right" one)master
| return paragraphs.AsReadOnly(); | return paragraphs.AsReadOnly(); | ||||
| } | } | ||||
| } | } | ||||
| public virtual ReadOnlyCollection<Paragraph> ParagraphsDeepSearch | |||||
| { | |||||
| get | |||||
| { | |||||
| List<Paragraph> paragraphs = GetParagraphs(true); | |||||
| 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()); | |||||
| p.ParentContainer = GetParentFromXmlName(p.Xml.Ancestors().First().Name.LocalName); | |||||
| if (p.IsListItem) | |||||
| { | |||||
| GetListItemType(p); | |||||
| } | |||||
| } | |||||
| return paragraphs.AsReadOnly(); | |||||
| } | |||||
| } | |||||
| // <summary> | // <summary> | ||||
| /// Removes paragraph at specified position | /// Removes paragraph at specified position | ||||
| /// </summary> | /// </summary> | ||||
| return true; | return true; | ||||
| } | } | ||||
| ++i; | ++i; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| //find num node in numbering | //find num node in numbering | ||||
| var numNodes = Document.numbering.Descendants().Where(n => n.Name.LocalName == "num"); | var numNodes = Document.numbering.Descendants().Where(n => n.Name.LocalName == "num"); | ||||
| XElement numNode = numNodes.FirstOrDefault(node => node.Attribute(DocX.w + "numId").Value.Equals(numIdValue)); | XElement numNode = numNodes.FirstOrDefault(node => node.Attribute(DocX.w + "numId").Value.Equals(numIdValue)); | ||||
| if (numNode != null) | |||||
| { | |||||
| //Get abstractNumId node and its value from numNode | |||||
| var abstractNumIdNode = numNode.Descendants().First(n => n.Name.LocalName == "abstractNumId"); | |||||
| var abstractNumNodeValue = abstractNumIdNode.Attribute(DocX.w + "val").Value; | |||||
| var abstractNumNodes = Document.numbering.Descendants().Where(n => n.Name.LocalName == "abstractNum"); | |||||
| XElement abstractNumNode = | |||||
| abstractNumNodes.FirstOrDefault(node => node.Attribute(DocX.w + "abstractNumId").Value.Equals(abstractNumNodeValue)); | |||||
| //Find lvl node | |||||
| var lvlNodes = abstractNumNode.Descendants().Where(n => n.Name.LocalName == "lvl"); | |||||
| XElement lvlNode = null; | |||||
| foreach (XElement node in lvlNodes) | |||||
| { | |||||
| if (node.Attribute(DocX.w + "ilvl").Value.Equals(ilvlValue)) | |||||
| { | |||||
| lvlNode = node; | |||||
| break; | |||||
| } | |||||
| } | |||||
| var numFmtNode = lvlNode.Descendants().First(n => n.Name.LocalName == "numFmt"); | |||||
| p.ListItemType = GetListItemType(numFmtNode.Attribute(DocX.w + "val").Value); | |||||
| } | |||||
| if (numNode != null) | |||||
| { | |||||
| //Get abstractNumId node and its value from numNode | |||||
| var abstractNumIdNode = numNode.Descendants().First(n => n.Name.LocalName == "abstractNumId"); | |||||
| var abstractNumNodeValue = abstractNumIdNode.Attribute(DocX.w + "val").Value; | |||||
| var abstractNumNodes = Document.numbering.Descendants().Where(n => n.Name.LocalName == "abstractNum"); | |||||
| XElement abstractNumNode = | |||||
| abstractNumNodes.FirstOrDefault(node => node.Attribute(DocX.w + "abstractNumId").Value.Equals(abstractNumNodeValue)); | |||||
| //Find lvl node | |||||
| var lvlNodes = abstractNumNode.Descendants().Where(n => n.Name.LocalName == "lvl"); | |||||
| XElement lvlNode = null; | |||||
| foreach (XElement node in lvlNodes) | |||||
| { | |||||
| if (node.Attribute(DocX.w + "ilvl").Value.Equals(ilvlValue)) | |||||
| { | |||||
| lvlNode = node; | |||||
| break; | |||||
| } | |||||
| } | |||||
| var numFmtNode = lvlNode.Descendants().First(n => n.Name.LocalName == "numFmt"); | |||||
| p.ListItemType = GetListItemType(numFmtNode.Attribute(DocX.w + "val").Value); | |||||
| } | |||||
| } | } | ||||
| public ContainerType ParentContainer; | public ContainerType ParentContainer; | ||||
| internal List<Paragraph> GetParagraphs() | |||||
| internal List<Paragraph> GetParagraphs(bool deepSearch=false) | |||||
| { | { | ||||
| // Need some memory that can be updated by the recursive search. | // Need some memory that can be updated by the recursive search. | ||||
| int index = 0; | int index = 0; | ||||
| List<Paragraph> paragraphs = new List<Paragraph>(); | List<Paragraph> paragraphs = new List<Paragraph>(); | ||||
| GetParagraphsRecursive(Xml, ref index, ref paragraphs); | |||||
| GetParagraphsRecursive(Xml, ref index, ref paragraphs, deepSearch); | |||||
| return paragraphs; | return paragraphs; | ||||
| } | } | ||||
| internal void GetParagraphsRecursive(XElement Xml, ref int index, ref List<Paragraph> paragraphs) | |||||
| internal void GetParagraphsRecursive(XElement Xml, ref int index, ref List<Paragraph> paragraphs, bool deepSearch=false) | |||||
| { | { | ||||
| // sdtContent are for PageNumbers inside Headers or Footers, don't go any deeper. | // sdtContent are for PageNumbers inside Headers or Footers, don't go any deeper. | ||||
| //if (Xml.Name.LocalName == "sdtContent") | //if (Xml.Name.LocalName == "sdtContent") | ||||
| // return; | // return; | ||||
| var keepSearching = true; | |||||
| if (Xml.Name.LocalName == "p") | if (Xml.Name.LocalName == "p") | ||||
| { | { | ||||
| paragraphs.Add(new Paragraph(Document, Xml, index)); | paragraphs.Add(new Paragraph(Document, Xml, index)); | ||||
| index += HelperFunctions.GetText(Xml).Length; | index += HelperFunctions.GetText(Xml).Length; | ||||
| if (!deepSearch) | |||||
| keepSearching = false; | |||||
| } | } | ||||
| else | |||||
| if (keepSearching && Xml.HasElements) | |||||
| { | { | ||||
| if (Xml.HasElements) | |||||
| foreach (XElement e in Xml.Elements()) | |||||
| { | { | ||||
| foreach (XElement e in Xml.Elements()) | |||||
| { | |||||
| GetParagraphsRecursive(e, ref index, ref paragraphs); | |||||
| } | |||||
| GetParagraphsRecursive(e, ref index, ref paragraphs, deepSearch); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (Paragraphs.Any(p => p.ValidateBookmark(bookmarkName))) return new string[0]; | if (Paragraphs.Any(p => p.ValidateBookmark(bookmarkName))) return new string[0]; | ||||
| nonMatching.Add(bookmarkName); | nonMatching.Add(bookmarkName); | ||||
| } | } | ||||
| return nonMatching.ToArray(); | return nonMatching.ToArray(); | ||||
| } | } | ||||
| XElement newTable = HelperFunctions.CreateTable(rowCount, columnCount); | XElement newTable = HelperFunctions.CreateTable(rowCount, columnCount); | ||||
| Xml.Add(newTable); | Xml.Add(newTable); | ||||
| return new Table(Document, newTable); | |||||
| return new Table(Document, newTable) { mainPart = mainPart}; | |||||
| } | } | ||||
| public Table InsertTable(int index, int rowCount, int columnCount) | public Table InsertTable(int index, int rowCount, int columnCount) | ||||
| } | } | ||||
| return new Table(Document, newTable); | |||||
| return new Table(Document, newTable) { mainPart = mainPart }; | |||||
| } | } | ||||
| public Table InsertTable(Table t) | public Table InsertTable(Table t) | ||||
| XElement newXElement = new XElement(t.Xml); | XElement newXElement = new XElement(t.Xml); | ||||
| Xml.Add(newXElement); | Xml.Add(newXElement); | ||||
| Table newTable = new Table(Document, newXElement); | |||||
| newTable.Design = t.Design; | |||||
| Table newTable = new Table(Document, newXElement) | |||||
| { | |||||
| mainPart = mainPart, | |||||
| Design = t.Design | |||||
| }; | |||||
| return newTable; | return newTable; | ||||
| } | } | ||||
| split[1] | split[1] | ||||
| ); | ); | ||||
| Table newTable = new Table(Document, newXElement); | |||||
| newTable.Design = t.Design; | |||||
| Table newTable = new Table(Document, newXElement) | |||||
| { | |||||
| mainPart = mainPart, | |||||
| Design = t.Design | |||||
| }; | |||||
| return newTable; | return newTable; | ||||
| } | } | ||||
| { | { | ||||
| foreach (var item in list.Items) | foreach (var item in list.Items) | ||||
| { | { | ||||
| // item.Font(System.Drawing.FontFamily fontFamily) | |||||
| // item.Font(System.Drawing.FontFamily fontFamily) | |||||
| Xml.Add(item.Xml); | Xml.Add(item.Xml); | ||||
| } | } |
| return sections; | return sections; | ||||
| } | } | ||||
| // Get the word\document.xml part | |||||
| internal PackagePart mainPart; | |||||
| // Get the word\settings.xml part | // Get the word\settings.xml part | ||||
| internal PackagePart settingsPart; | internal PackagePart settingsPart; | ||||
| return HelperFunctions.GetText(Xml); | return HelperFunctions.GetText(Xml); | ||||
| } | } | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Get the text of each footnote from this document | |||||
| /// </summary> | |||||
| public IEnumerable<string> FootnotesText | |||||
| { | |||||
| get | |||||
| { | |||||
| /// <summary> | |||||
| /// Get the text of each footnote from this document | |||||
| /// </summary> | |||||
| public IEnumerable<string> FootnotesText | |||||
| { | |||||
| get | |||||
| { | |||||
| foreach (XElement footnote in footnotes.Root.Elements(w + "footnote")) | foreach (XElement footnote in footnotes.Root.Elements(w + "footnote")) | ||||
| { | { | ||||
| yield return HelperFunctions.GetText(footnote); | yield return HelperFunctions.GetText(footnote); | ||||
| merge_footnotes(remote_pp, local_pp, remote_mainDoc, remote_document, remote_footnotes); | merge_footnotes(remote_pp, local_pp, remote_mainDoc, remote_document, remote_footnotes); | ||||
| remote_footnotes = footnotes; | remote_footnotes = footnotes; | ||||
| break; | break; | ||||
| case "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml": | case "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml": | ||||
| merge_endnotes(remote_pp, local_pp, remote_mainDoc, remote_document, remote_endnotes); | merge_endnotes(remote_pp, local_pp, remote_mainDoc, remote_document, remote_endnotes); | ||||
| remote_endnotes = endnotes; | remote_endnotes = endnotes; | ||||
| // In my testing I have found cases of Images inside documents that are not referenced | // In my testing I have found cases of Images inside documents that are not referenced | ||||
| var remote_rel = remote_document.mainPart.GetRelationships().Where(r => r.TargetUri.OriginalString.Equals(remote_pp.Uri.OriginalString.Replace("/word/", ""))).FirstOrDefault(); | var remote_rel = remote_document.mainPart.GetRelationships().Where(r => r.TargetUri.OriginalString.Equals(remote_pp.Uri.OriginalString.Replace("/word/", ""))).FirstOrDefault(); | ||||
| if (remote_rel == null) { | if (remote_rel == null) { | ||||
| remote_rel = remote_document.mainPart.GetRelationships().Where(r => r.TargetUri.OriginalString.Equals(remote_pp.Uri.OriginalString)).FirstOrDefault(); | |||||
| if (remote_rel == null) | |||||
| return; | |||||
| remote_rel = remote_document.mainPart.GetRelationships().Where(r => r.TargetUri.OriginalString.Equals(remote_pp.Uri.OriginalString)).FirstOrDefault(); | |||||
| if (remote_rel == null) | |||||
| return; | |||||
| } | } | ||||
| String remote_Id = remote_rel.Id; | String remote_Id = remote_rel.Id; | ||||
| } | } | ||||
| if (!defRelId.Success) | if (!defRelId.Success) | ||||
| { | |||||
| // Replace all instances of remote_Id in the local document with local_Id | |||||
| var elems_local = mainDoc.Descendants(XName.Get("blip", DocX.a.NamespaceName)); | |||||
| foreach (var elem in elems_local) | |||||
| { | |||||
| XAttribute embed = elem.Attribute(XName.Get("embed", DocX.r.NamespaceName)); | |||||
| if (embed != null && embed.Value == remote_Id) | |||||
| { | |||||
| embed.SetValue(new_Id); | |||||
| } | |||||
| } | |||||
| // Replace all instances of remote_Id in the local document with local_Id | |||||
| var v_elems_local = mainDoc.Descendants(XName.Get("imagedata", DocX.v.NamespaceName)); | |||||
| foreach (var elem in v_elems_local) | |||||
| { | |||||
| XAttribute id = elem.Attribute(XName.Get("id", DocX.r.NamespaceName)); | |||||
| if (id != null && id.Value == remote_Id) | |||||
| { | |||||
| id.SetValue(new_Id); | |||||
| } | |||||
| } | |||||
| } | |||||
| { | |||||
| // Replace all instances of remote_Id in the local document with local_Id | |||||
| var elems_local = mainDoc.Descendants(XName.Get("blip", DocX.a.NamespaceName)); | |||||
| foreach (var elem in elems_local) | |||||
| { | |||||
| XAttribute embed = elem.Attribute(XName.Get("embed", DocX.r.NamespaceName)); | |||||
| if (embed != null && embed.Value == remote_Id) | |||||
| { | |||||
| embed.SetValue(new_Id); | |||||
| } | |||||
| } | |||||
| // Replace all instances of remote_Id in the local document with local_Id | |||||
| var v_elems_local = mainDoc.Descendants(XName.Get("imagedata", DocX.v.NamespaceName)); | |||||
| foreach (var elem in v_elems_local) | |||||
| { | |||||
| XAttribute id = elem.Attribute(XName.Get("id", DocX.r.NamespaceName)); | |||||
| if (id != null && id.Value == remote_Id) | |||||
| { | |||||
| id.SetValue(new_Id); | |||||
| } | |||||
| } | |||||
| } | |||||
| // Replace all instances of remote_Id in the local document with local_Id (for shapes as well) | // Replace all instances of remote_Id in the local document with local_Id (for shapes as well) | ||||
| // Checking whether there were more than 0 elements, helped me get rid of exceptions thrown while using InsertDocument | // Checking whether there were more than 0 elements, helped me get rid of exceptions thrown while using InsertDocument | ||||
| if (numbering.Root.Elements(XName.Get("abstractNum", DocX.w.NamespaceName)).Count() > 0) | if (numbering.Root.Elements(XName.Get("abstractNum", DocX.w.NamespaceName)).Count() > 0) | ||||
| numbering.Root.Elements(XName.Get("abstractNum", DocX.w.NamespaceName)).Last().AddAfterSelf(remote_abstractNums); | |||||
| numbering.Root.Elements(XName.Get("abstractNum", DocX.w.NamespaceName)).Last().AddAfterSelf(remote_abstractNums); | |||||
| if (numbering.Root.Elements(XName.Get("num", DocX.w.NamespaceName)).Count() > 0) | if (numbering.Root.Elements(XName.Get("num", DocX.w.NamespaceName)).Count() > 0) | ||||
| numbering.Root.Elements(XName.Get("num", DocX.w.NamespaceName)).Last().AddAfterSelf(remote_nums); | |||||
| numbering.Root.Elements(XName.Get("num", DocX.w.NamespaceName)).Last().AddAfterSelf(remote_nums); | |||||
| } | } | ||||
| private void merge_fonts(PackagePart remote_pp, PackagePart local_pp, XDocument remote_mainDoc, DocX remote) | private void merge_fonts(PackagePart remote_pp, PackagePart local_pp, XDocument remote_mainDoc, DocX remote) | ||||
| } | } | ||||
| } | } | ||||
| // Replace all instances of remote_Id in the local document with local_Id (for shapes as well) | |||||
| // Replace all instances of remote_Id in the local document with local_Id (for shapes as well) | |||||
| var v_elems = remote_mainDoc.Descendants(XName.Get("imagedata", DocX.v.NamespaceName)); | var v_elems = remote_mainDoc.Descendants(XName.Get("imagedata", DocX.v.NamespaceName)); | ||||
| foreach (var elem in v_elems) | foreach (var elem in v_elems) | ||||
| { | { | ||||
| if (!document.paragraphLookup.ContainsKey(paragraph.endIndex)) | if (!document.paragraphLookup.ContainsKey(paragraph.endIndex)) | ||||
| document.paragraphLookup.Add(paragraph.endIndex, paragraph); | document.paragraphLookup.Add(paragraph.endIndex, paragraph); | ||||
| } | } | ||||
| return document; | return document; | ||||
| } | } | ||||
| public void Save() | public void Save() | ||||
| { | { | ||||
| Headers headers = Headers; | Headers headers = Headers; | ||||
| // Save the main document | // Save the main document | ||||
| using (TextWriter tw = new StreamWriter(mainPart.GetStream(FileMode.Create, FileAccess.Write))) | using (TextWriter tw = new StreamWriter(mainPart.GetStream(FileMode.Create, FileAccess.Write))) | ||||
| mainDoc.Save(tw, SaveOptions.None); | mainDoc.Save(tw, SaveOptions.None); | ||||
| customPropDoc.Save(tw, SaveOptions.None); | customPropDoc.Save(tw, SaveOptions.None); | ||||
| // Refresh all fields in this document which display this custom property. | // Refresh all fields in this document which display this custom property. | ||||
| UpdateCustomPropertyValue(this, cp.Name, (cp.Value ?? "").ToString()); | |||||
| UpdateCustomPropertyValue(this, cp.Name, (cp.Value ?? "").ToString()); | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| { | { | ||||
| return InsertTableOfContents("Table of contents", TableOfContentsSwitches.O | TableOfContentsSwitches.H | TableOfContentsSwitches.Z | TableOfContentsSwitches.U); | return InsertTableOfContents("Table of contents", TableOfContentsSwitches.O | TableOfContentsSwitches.H | TableOfContentsSwitches.Z | TableOfContentsSwitches.U); | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Inserts a TOC into the current document. | /// Inserts a TOC into the current document. | ||||
| /// </summary> | /// </summary> |
| } | } | ||||
| } | } | ||||
| 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; |
| public Paragraph PageNumberParagraph; | public Paragraph PageNumberParagraph; | ||||
| 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; |
| internal String text; | internal String text; | ||||
| internal Dictionary<PackagePart, PackageRelationship> hyperlink_rels; | internal Dictionary<PackagePart, PackageRelationship> hyperlink_rels; | ||||
| public PackagePart mainPart; | |||||
| internal int type; | internal int type; | ||||
| internal String id; | internal String id; | ||||
| internal XElement instrText; | internal XElement instrText; |
| /// </summary> | /// </summary> | ||||
| public class Paragraph : InsertBeforeOrAfter | public class Paragraph : InsertBeforeOrAfter | ||||
| { | { | ||||
| internal PackagePart mainPart; | |||||
| 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. | ||||
| internal List<XElement> runs; | internal List<XElement> runs; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /// <summary> | |||||
| public bool IsKeepWithNext | |||||
| { | |||||
| get | |||||
| { | |||||
| var pPr = GetOrCreate_pPr(); | |||||
| var keepWithNextE = pPr.Element(XName.Get("keepNext", DocX.w.NamespaceName)); | |||||
| if (keepWithNextE == null) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| } | |||||
| /// <summary> | |||||
| /// This paragraph will be kept on the same page as the next paragraph | /// This paragraph will be kept on the same page as the next paragraph | ||||
| /// </summary> | /// </summary> | ||||
| /// <example> | /// <example> | ||||
| /// </example> | /// </example> | ||||
| /// <param name="keepWithNext"></param> | /// <param name="keepWithNext"></param> | ||||
| /// <returns></returns> | /// <returns></returns> | ||||
| public Paragraph KeepWithNext(bool keepWithNext = true) | public Paragraph KeepWithNext(bool keepWithNext = true) | ||||
| { | { | ||||
| var pPr = GetOrCreate_pPr(); | var pPr = GetOrCreate_pPr(); | ||||
| keepWithNextE.Remove(); | keepWithNextE.Remove(); | ||||
| } | } | ||||
| return this; | return this; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// <summary> | |||||
| /// Keep all lines in this paragraph together on a page | /// Keep all lines in this paragraph together on a page | ||||
| /// </summary> | /// </summary> | ||||
| /// <example> | /// <example> | ||||
| XAttribute hanging = ind.Attribute(XName.Get("hanging", DocX.w.NamespaceName)); | XAttribute hanging = ind.Attribute(XName.Get("hanging", DocX.w.NamespaceName)); | ||||
| if (hanging != null) | if (hanging != null) | ||||
| return float.Parse(hanging.Value); | |||||
| return float.Parse(hanging.Value) / (57 * 10); | |||||
| return 0.0f; | return 0.0f; | ||||
| } | } | ||||
| XAttribute left = ind.Attribute(XName.Get("left", DocX.w.NamespaceName)); | XAttribute left = ind.Attribute(XName.Get("left", DocX.w.NamespaceName)); | ||||
| if (left != null) | if (left != null) | ||||
| return float.Parse(left.Value); | |||||
| return float.Parse(left.Value) / (57 * 10); | |||||
| return 0.0f; | return 0.0f; | ||||
| } | } | ||||
| else | else | ||||
| throw new ArgumentException("Size", "Value must be either a whole or half number, examples: 32, 32.5"); | throw new ArgumentException("Size", "Value must be either a whole or half number, examples: 32, 32.5"); | ||||
| ApplyTextFormattingProperty(XName.Get("sz", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), fontSize * 2)); | ApplyTextFormattingProperty(XName.Get("sz", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), fontSize * 2)); | ||||
| ApplyTextFormattingProperty(XName.Get("szCs", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), fontSize * 2)); | ApplyTextFormattingProperty(XName.Get("szCs", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), fontSize * 2)); | ||||
| var spacing = pPr.Element(XName.Get("spacing", DocX.w.NamespaceName)); | var spacing = pPr.Element(XName.Get("spacing", DocX.w.NamespaceName)); | ||||
| if (spacingBefore > 0) | if (spacingBefore > 0) | ||||
| { | { | ||||
| if (spacing == null) | |||||
| { | |||||
| if (spacing == null) | |||||
| { | |||||
| spacing = new XElement(XName.Get("spacing", DocX.w.NamespaceName)); | spacing = new XElement(XName.Get("spacing", DocX.w.NamespaceName)); | ||||
| pPr.Add(spacing); | pPr.Add(spacing); | ||||
| } | |||||
| var attr = spacing.Attribute(XName.Get("before", DocX.w.NamespaceName)); | |||||
| if (attr == null) | |||||
| spacing.SetAttributeValue(XName.Get("before", DocX.w.NamespaceName), spacingBefore); | |||||
| else | |||||
| } | |||||
| var attr = spacing.Attribute(XName.Get("before", DocX.w.NamespaceName)); | |||||
| if (attr == null) | |||||
| spacing.SetAttributeValue(XName.Get("before", DocX.w.NamespaceName), spacingBefore); | |||||
| else | |||||
| attr.SetValue(spacingBefore); | attr.SetValue(spacingBefore); | ||||
| } | } | ||||
| if (Math.Abs(spacingBefore) < 0.1f && spacing != null) | if (Math.Abs(spacingBefore) < 0.1f && spacing != null) | ||||
| if (!spacing.HasAttributes) | if (!spacing.HasAttributes) | ||||
| spacing.Remove(); | spacing.Remove(); | ||||
| } | } | ||||
| //ApplyTextFormattingProperty(XName.Get("after", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), spacingAfter)); | |||||
| return this; | return this; | ||||
| } | } |
| * Get the tcPr (table cell properties) element for the first cell in this merge, | * Get the tcPr (table cell properties) element for the first cell in this merge, | ||||
| * null will be returned if no such element exists. | * null will be returned if no such element exists. | ||||
| */ | */ | ||||
| XElement start_tcPr = Rows[startRow].Cells[columnIndex].Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||||
| XElement start_tcPr = null; | |||||
| if(columnIndex > Rows[startRow].Cells.Count) | |||||
| start_tcPr = Rows[startRow].Cells[Rows[startRow].Cells.Count - 1].Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||||
| else | |||||
| start_tcPr = Rows[startRow].Cells[columnIndex].Xml.Element(XName.Get("tcPr", DocX.w.NamespaceName)); | |||||
| if (start_tcPr == null) | if (start_tcPr == null) | ||||
| { | { | ||||
| Rows[startRow].Cells[columnIndex].Xml.SetElementValue(XName.Get("tcPr", DocX.w.NamespaceName), string.Empty); | Rows[startRow].Cells[columnIndex].Xml.SetElementValue(XName.Get("tcPr", DocX.w.NamespaceName), string.Empty); | ||||
| if (r.Cells.Count > c) | if (r.Cells.Count > c) | ||||
| r.Cells[c].Width = widths[c]; | r.Cells[c].Width = widths[c]; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| /// Returns the number of rows in this table. | /// Returns the number of rows in this table. | ||||
| /// </summary> | /// </summary> | ||||
| private TableDesign design; | private TableDesign design; | ||||
| internal PackagePart mainPart; | |||||
| internal Table(DocX document, XElement xml) | internal Table(DocX document, XElement xml) | ||||
| : base(document, xml) | : base(document, xml) | ||||
| } | } | ||||
| } | } | ||||
| /// <summary> | |||||
| /// String containing the Table Caption value (the table's Alternate Text Title) | |||||
| /// </summary> | |||||
| private string _tableCaption; | |||||
| /// <summary> | |||||
| /// Gets or Sets the value of the Table Caption (Alternate Text Title) of this table. | |||||
| /// </summary> | |||||
| public string TableCaption | |||||
| /// <summary> | |||||
| /// String containing the Table Caption value (the table's Alternate Text Title) | |||||
| /// </summary> | |||||
| private string _tableCaption; | |||||
| /// <summary> | |||||
| /// Gets or Sets the value of the Table Caption (Alternate Text Title) of this table. | |||||
| /// </summary> | |||||
| public string TableCaption | |||||
| { | { | ||||
| set | set | ||||
| { | { | ||||
| tblCaption = new XElement(XName.Get("tblCaption", DocX.w.NamespaceName), | tblCaption = new XElement(XName.Get("tblCaption", DocX.w.NamespaceName), | ||||
| new XAttribute(XName.Get("val", DocX.w.NamespaceName), value)); | new XAttribute(XName.Get("val", DocX.w.NamespaceName), value)); | ||||
| tblPr.Add(tblCaption); | |||||
| tblPr.Add(tblCaption); | |||||
| } | } | ||||
| } | } | ||||
| /// </example> | /// </example> | ||||
| /// <param name="borderType">The table border to set</param> | /// <param name="borderType">The table border to set</param> | ||||
| /// <param name="border">Border object to set the table border</param> | /// <param name="border">Border object to set the table border</param> | ||||
| public void SetBorder(TableBorderType borderType, Border border) | |||||
| { | |||||
| /* | |||||
| * Get the tblPr (table properties) element for this Table, | |||||
| * null will be return if no such element exists. | |||||
| */ | |||||
| XElement tblPr = Xml.Element(XName.Get("tblPr", DocX.w.NamespaceName)); | |||||
| if (tblPr == null) | |||||
| { | |||||
| Xml.SetElementValue(XName.Get("tblPr", DocX.w.NamespaceName), string.Empty); | |||||
| tblPr = Xml.Element(XName.Get("tblPr", DocX.w.NamespaceName)); | |||||
| } | |||||
| /* | |||||
| * Get the tblBorders (table borders) element for this Table, | |||||
| * null will be return if no such element exists. | |||||
| */ | |||||
| XElement tblBorders = tblPr.Element(XName.Get("tblBorders", DocX.w.NamespaceName)); | |||||
| if (tblBorders == null) | |||||
| { | |||||
| tblPr.SetElementValue(XName.Get("tblBorders", DocX.w.NamespaceName), string.Empty); | |||||
| tblBorders = tblPr.Element(XName.Get("tblBorders", DocX.w.NamespaceName)); | |||||
| } | |||||
| /* | |||||
| * Get the 'borderType' (table border) element for this Table, | |||||
| * null will be return if no such element exists. | |||||
| */ | |||||
| string tbordertype; | |||||
| tbordertype = borderType.ToString(); | |||||
| // only lower the first char of string (because of insideH and insideV) | |||||
| tbordertype = tbordertype.Substring(0, 1).ToLower() + tbordertype.Substring(1); | |||||
| XElement tblBorderType = tblBorders.Element(XName.Get(borderType.ToString(), DocX.w.NamespaceName)); | |||||
| if (tblBorderType == null) | |||||
| { | |||||
| tblBorders.SetElementValue(XName.Get(tbordertype, DocX.w.NamespaceName), string.Empty); | |||||
| tblBorderType = tblBorders.Element(XName.Get(tbordertype, DocX.w.NamespaceName)); | |||||
| } | |||||
| // get string value of border style | |||||
| string borderstyle = border.Tcbs.ToString().Substring(5); | |||||
| borderstyle = borderstyle.Substring(0, 1).ToLower() + borderstyle.Substring(1); | |||||
| // The val attribute is used for the border style | |||||
| tblBorderType.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), borderstyle); | |||||
| if (border.Tcbs != BorderStyle.Tcbs_nil) | |||||
| { | |||||
| int size; | |||||
| switch (border.Size) | |||||
| { | |||||
| case BorderSize.one: size = 2; break; | |||||
| case BorderSize.two: size = 4; break; | |||||
| case BorderSize.three: size = 6; break; | |||||
| case BorderSize.four: size = 8; break; | |||||
| case BorderSize.five: size = 12; break; | |||||
| case BorderSize.six: size = 18; break; | |||||
| case BorderSize.seven: size = 24; break; | |||||
| case BorderSize.eight: size = 36; break; | |||||
| case BorderSize.nine: size = 48; break; | |||||
| default: size = 2; break; | |||||
| } | |||||
| // The sz attribute is used for the border size | |||||
| tblBorderType.SetAttributeValue(XName.Get("sz", DocX.w.NamespaceName), (size).ToString()); | |||||
| // The space attribute is used for the cell spacing (probably '0') | |||||
| tblBorderType.SetAttributeValue(XName.Get("space", DocX.w.NamespaceName), (border.Space).ToString()); | |||||
| // The color attribute is used for the border color | |||||
| public void SetBorder(TableBorderType borderType, Border border) | |||||
| { | |||||
| /* | |||||
| * Get the tblPr (table properties) element for this Table, | |||||
| * null will be return if no such element exists. | |||||
| */ | |||||
| XElement tblPr = Xml.Element(XName.Get("tblPr", DocX.w.NamespaceName)); | |||||
| if (tblPr == null) | |||||
| { | |||||
| Xml.SetElementValue(XName.Get("tblPr", DocX.w.NamespaceName), string.Empty); | |||||
| tblPr = Xml.Element(XName.Get("tblPr", DocX.w.NamespaceName)); | |||||
| } | |||||
| /* | |||||
| * Get the tblBorders (table borders) element for this Table, | |||||
| * null will be return if no such element exists. | |||||
| */ | |||||
| XElement tblBorders = tblPr.Element(XName.Get("tblBorders", DocX.w.NamespaceName)); | |||||
| if (tblBorders == null) | |||||
| { | |||||
| tblPr.SetElementValue(XName.Get("tblBorders", DocX.w.NamespaceName), string.Empty); | |||||
| tblBorders = tblPr.Element(XName.Get("tblBorders", DocX.w.NamespaceName)); | |||||
| } | |||||
| /* | |||||
| * Get the 'borderType' (table border) element for this Table, | |||||
| * null will be return if no such element exists. | |||||
| */ | |||||
| string tbordertype; | |||||
| tbordertype = borderType.ToString(); | |||||
| // only lower the first char of string (because of insideH and insideV) | |||||
| tbordertype = tbordertype.Substring(0, 1).ToLower() + tbordertype.Substring(1); | |||||
| XElement tblBorderType = tblBorders.Element(XName.Get(borderType.ToString(), DocX.w.NamespaceName)); | |||||
| if (tblBorderType == null) | |||||
| { | |||||
| tblBorders.SetElementValue(XName.Get(tbordertype, DocX.w.NamespaceName), string.Empty); | |||||
| tblBorderType = tblBorders.Element(XName.Get(tbordertype, DocX.w.NamespaceName)); | |||||
| } | |||||
| // get string value of border style | |||||
| string borderstyle = border.Tcbs.ToString().Substring(5); | |||||
| borderstyle = borderstyle.Substring(0, 1).ToLower() + borderstyle.Substring(1); | |||||
| // The val attribute is used for the border style | |||||
| tblBorderType.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), borderstyle); | |||||
| if (border.Tcbs != BorderStyle.Tcbs_nil) | |||||
| { | |||||
| int size; | |||||
| switch (border.Size) | |||||
| { | |||||
| case BorderSize.one: size = 2; break; | |||||
| case BorderSize.two: size = 4; break; | |||||
| case BorderSize.three: size = 6; break; | |||||
| case BorderSize.four: size = 8; break; | |||||
| case BorderSize.five: size = 12; break; | |||||
| case BorderSize.six: size = 18; break; | |||||
| case BorderSize.seven: size = 24; break; | |||||
| case BorderSize.eight: size = 36; break; | |||||
| case BorderSize.nine: size = 48; break; | |||||
| default: size = 2; break; | |||||
| } | |||||
| // The sz attribute is used for the border size | |||||
| tblBorderType.SetAttributeValue(XName.Get("sz", DocX.w.NamespaceName), (size).ToString()); | |||||
| // The space attribute is used for the cell spacing (probably '0') | |||||
| tblBorderType.SetAttributeValue(XName.Get("space", DocX.w.NamespaceName), (border.Space).ToString()); | |||||
| // The color attribute is used for the border color | |||||
| tblBorderType.SetAttributeValue(XName.Get("color", DocX.w.NamespaceName), border.Color.ToHex()); | tblBorderType.SetAttributeValue(XName.Get("color", DocX.w.NamespaceName), border.Color.ToHex()); | ||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// Get a table border | /// Get a table border | ||||
| } | } | ||||
| return b; | return b; | ||||
| } | } | ||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| } | } | ||||
| internal Table table; | internal Table table; | ||||
| internal PackagePart mainPart; | |||||
| internal Row(Table table, DocX document, XElement xml) | internal Row(Table table, DocX document, XElement xml) | ||||
| : base(document, xml) | : base(document, xml) | ||||
| { | { | ||||
| /// <summary> | /// <summary> | ||||
| /// Set to true to make this row the table header row that will be repeated on each page | |||||
| /// </summary> | |||||
| public bool TableHeader | |||||
| { | |||||
| get | |||||
| { | |||||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| XElement tblHeader = trPr.Element(XName.Get("tblHeader", DocX.w.NamespaceName)); | |||||
| if (tblHeader == null) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| else | |||||
| { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| set | |||||
| { | |||||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| if (trPr == null) | |||||
| { | |||||
| Xml.SetElementValue(XName.Get("trPr", DocX.w.NamespaceName), string.Empty); | |||||
| trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| } | |||||
| XElement tblHeader = trPr.Element(XName.Get("tblHeader", DocX.w.NamespaceName)); | |||||
| if (tblHeader == null && value) | |||||
| { | |||||
| trPr.SetElementValue(XName.Get("tblHeader", DocX.w.NamespaceName), string.Empty); | |||||
| } | |||||
| if (tblHeader != null && !value) | |||||
| { | |||||
| tblHeader.Remove(); | |||||
| } | |||||
| } | |||||
| } | |||||
| /// Set to true to make this row the table header row that will be repeated on each page | |||||
| /// </summary> | |||||
| public bool TableHeader | |||||
| { | |||||
| get | |||||
| { | |||||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| XElement tblHeader = trPr.Element(XName.Get("tblHeader", DocX.w.NamespaceName)); | |||||
| if (tblHeader == null) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| else | |||||
| { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| set | |||||
| { | |||||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| if (trPr == null) | |||||
| { | |||||
| Xml.SetElementValue(XName.Get("trPr", DocX.w.NamespaceName), string.Empty); | |||||
| trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| } | |||||
| XElement tblHeader = trPr.Element(XName.Get("tblHeader", DocX.w.NamespaceName)); | |||||
| if (tblHeader == null && value) | |||||
| { | |||||
| trPr.SetElementValue(XName.Get("tblHeader", DocX.w.NamespaceName), string.Empty); | |||||
| } | |||||
| if (tblHeader != null && !value) | |||||
| { | |||||
| tblHeader.Remove(); | |||||
| } | |||||
| } | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// Allow row to break across pages. | /// Allow row to break across pages. | ||||
| /// The default value is true: Word will break the contents of the row across pages. | /// The default value is true: Word will break the contents of the row across pages. | ||||
| /// </summary> | /// </summary> | ||||
| public bool BreakAcrossPages | public bool BreakAcrossPages | ||||
| { | { | ||||
| get | |||||
| { | |||||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| if (trPr == null) | |||||
| return true; | |||||
| XElement trCantSplit = trPr.Element(XName.Get("cantSplit", DocX.w.NamespaceName)); | |||||
| if (trCantSplit == null) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| set | |||||
| { | |||||
| if (value == false) | |||||
| { | |||||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| if (trPr == null) | |||||
| { | |||||
| Xml.SetElementValue(XName.Get("trPr", DocX.w.NamespaceName), string.Empty); | |||||
| trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| } | |||||
| XElement trCantSplit = trPr.Element(XName.Get("cantSplit", DocX.w.NamespaceName)); | |||||
| if (trCantSplit == null) | |||||
| trPr.SetElementValue(XName.Get("cantSplit", DocX.w.NamespaceName), string.Empty); | |||||
| } | |||||
| if (value == true) | |||||
| { | |||||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| if (trPr != null) | |||||
| { | |||||
| XElement trCantSplit = trPr.Element(XName.Get("cantSplit", DocX.w.NamespaceName)); | |||||
| if (trCantSplit != null) | |||||
| trCantSplit.Remove(); | |||||
| } | |||||
| } | |||||
| } | |||||
| get | |||||
| { | |||||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| if (trPr == null) | |||||
| return true; | |||||
| XElement trCantSplit = trPr.Element(XName.Get("cantSplit", DocX.w.NamespaceName)); | |||||
| if (trCantSplit == null) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| set | |||||
| { | |||||
| if (value == false) | |||||
| { | |||||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| if (trPr == null) | |||||
| { | |||||
| Xml.SetElementValue(XName.Get("trPr", DocX.w.NamespaceName), string.Empty); | |||||
| trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| } | |||||
| XElement trCantSplit = trPr.Element(XName.Get("cantSplit", DocX.w.NamespaceName)); | |||||
| if (trCantSplit == null) | |||||
| trPr.SetElementValue(XName.Get("cantSplit", DocX.w.NamespaceName), string.Empty); | |||||
| } | |||||
| if (value == true) | |||||
| { | |||||
| XElement trPr = Xml.Element(XName.Get("trPr", DocX.w.NamespaceName)); | |||||
| if (trPr != null) | |||||
| { | |||||
| XElement trCantSplit = trPr.Element(XName.Get("cantSplit", DocX.w.NamespaceName)); | |||||
| if (trCantSplit != null) | |||||
| trCantSplit.Remove(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| /// <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) | internal Cell(Row row, DocX document, XElement xml) | ||||
| : base(document, xml) | : base(document, xml) | ||||
| { | { | ||||
| //tcW.SetAttributeValue(XName.Get("type", DocX.w.NamespaceName), "auto"); | //tcW.SetAttributeValue(XName.Get("type", DocX.w.NamespaceName), "auto"); | ||||
| //return; | //return; | ||||
| } | |||||
| } | |||||
| // The type attribute needs to be set to dxa which represents "twips" or twentieths of a point. In other words, 1/1440th of an inch. | // The type attribute needs to be set to dxa which represents "twips" or twentieths of a point. In other words, 1/1440th of an inch. | ||||
| tcW.SetAttributeValue(XName.Get("type", DocX.w.NamespaceName), "dxa"); | tcW.SetAttributeValue(XName.Get("type", DocX.w.NamespaceName), "dxa"); | ||||
| public override Table InsertTable(int rowCount, int columnCount) | public override Table InsertTable(int rowCount, int columnCount) | ||||
| { | { | ||||
| Table table = base.InsertTable(rowCount, columnCount); | Table table = base.InsertTable(rowCount, columnCount); | ||||
| table.mainPart = mainPart; | |||||
| InsertParagraph(); //Dmitchern, It is necessary to put paragraph in the end of the cell, without it MS-Word will say that the document is corrupted | InsertParagraph(); //Dmitchern, It is necessary to put paragraph in the end of the cell, without it MS-Word will say that the document is corrupted | ||||
| //IMPORTANT: It will be better to check all methods that work with adding anything to cells | //IMPORTANT: It will be better to check all methods that work with adding anything to cells | ||||
| return table; | return table; | ||||
| public bool NoHorizontalBanding { get; set; } | public bool NoHorizontalBanding { get; set; } | ||||
| public bool NoVerticalBanding { get; set; } | public bool NoVerticalBanding { get; set; } | ||||
| } | } | ||||
| } | } |
| using System; | using System; | ||||
| using System.IO.Packaging; | |||||
| using System.Linq; | using System.Linq; | ||||
| using System.Xml.Linq; | using System.Xml.Linq; | ||||
| /// </summary> | /// </summary> | ||||
| public abstract class DocXElement | public abstract class DocXElement | ||||
| { | { | ||||
| internal PackagePart mainPart; | |||||
| public PackagePart PackagePart { get { return mainPart; } set { mainPart = value; } } | |||||
| /// <summary> | /// <summary> | ||||
| /// This is the actual Xml that gives this element substance. | /// This is the actual Xml that gives this element substance. | ||||
| /// For example, a Paragraphs Xml might look something like the following | /// For example, a Paragraphs Xml might look something like the following | ||||
| /// </r> | /// </r> | ||||
| /// </p> | /// </p> | ||||
| /// </summary> | /// </summary> | ||||
| public XElement Xml { get; set; } | public XElement Xml { get; set; } | ||||
| /// <summary> | /// <summary> | ||||
| /// This is a reference to the DocX object that this element belongs to. | /// This is a reference to the DocX object that this element belongs to. | ||||
| Xml.AddAfterSelf(newTable); | Xml.AddAfterSelf(newTable); | ||||
| XElement newlyInserted = Xml.ElementsAfterSelf().First(); | XElement newlyInserted = Xml.ElementsAfterSelf().First(); | ||||
| return new Table(Document, newlyInserted); | |||||
| return new Table(Document, newlyInserted) { mainPart = mainPart }; | |||||
| } | } | ||||
| public virtual Table InsertTableAfterSelf(Table t) | public virtual Table InsertTableAfterSelf(Table t) | ||||
| Xml.AddAfterSelf(t.Xml); | Xml.AddAfterSelf(t.Xml); | ||||
| XElement newlyInserted = Xml.ElementsAfterSelf().First(); | XElement newlyInserted = Xml.ElementsAfterSelf().First(); | ||||
| //Dmitchern | //Dmitchern | ||||
| return new Table(Document, newlyInserted); //return new table, dont affect parameter table | |||||
| return new Table(Document, newlyInserted) { mainPart = mainPart }; //return new table, dont affect parameter table | |||||
| //t.Xml = newlyInserted; | //t.Xml = newlyInserted; | ||||
| //return t; | //return t; | ||||
| Xml.AddBeforeSelf(newTable); | Xml.AddBeforeSelf(newTable); | ||||
| XElement newlyInserted = Xml.ElementsBeforeSelf().Last(); | XElement newlyInserted = Xml.ElementsBeforeSelf().Last(); | ||||
| return new Table(Document, newlyInserted); | |||||
| return new Table(Document, newlyInserted) { mainPart = mainPart }; | |||||
| } | } | ||||
| public virtual Table InsertTableBeforeSelf(Table t) | public virtual Table InsertTableBeforeSelf(Table t) | ||||
| XElement newlyInserted = Xml.ElementsBeforeSelf().Last(); | XElement newlyInserted = Xml.ElementsBeforeSelf().Last(); | ||||
| //Dmitchern | //Dmitchern | ||||
| return new Table(Document, newlyInserted); //return new table, dont affect parameter table | |||||
| return new Table(Document, newlyInserted) { mainPart=mainPart}; //return new table, dont affect parameter table | |||||
| //t.Xml = newlyInserted; | //t.Xml = newlyInserted; | ||||
| //return t; | //return t; |