Changes: - Fix to allow font family for a paragraph text to be set and read. (faizanj) - Tightened up how a paragraph is designated as a list item. (faizanj) - Feature add insert next page section (rgborck) - Added examples for the section break and the new next page break. (Randall Borck) - Added Next Page Section break functionality. The new method is called InsertSectionPageBreak(...). (Randall Borck) - Fix for bug with entering more than one numbering. The system was inserting the abstract in the wrong place. Now the abstract sections are grouped at the beginning and the num section is grouped at the end. This should allow word to find the correct list formatting when a document with multiplelists is created from docx. (Randall Borck) - Fix for list defaults to help them be more consistant with MS Word. Bullets were indenting twice that of numbers, now they increase the same amount. (Randall Borck) - Added test for creating text with formatting (fainzanj) - Added capability to detect underlinestyle (fainzanj) - Updated the default values to specify Heading styles. (Randall Borck) - Updated DocX to allow you to create an empty list object. This change is useful for creating a list and then running an iterator or loop to populate it.(Randall Borck) - Fixed issue with multiple lists in the same document. The second list was overwriting the document numbering instead of appending to it. Also updated the default to be numbering instead of bullet. Added an example of how to create lists.(Randall Borck) - Updated list items to allow for a start value. (Randall Borck) - Fixed the Apply Template unit test. (Randall Borck) - Removed unneeded test. (faizanj) - Fixed unit tests. (Randall Borck) - Cleaned up redunant parameters in AddItemList(...) call. (Randall Borck) - Undid signature changes because of issues. (Randall Borck) - Fixed a method signature. (Randall Borck) - Added test for List property (fainzanj) - Added test for List property(fainzanj) - Updated documentation comments and default values. (Randall Borck) - Updates/refactoring changes to list. (Randall Borck) - Added capability to append list to previous list (fainzanj) - Updated docx to support adding a list. Added preliminary list support to allow docx to create a list. Currently missing functionality to add elements to the previous list (so each list can only have 1 element in the creation of new lists so far). (faizanj, brendanjerwin) - Added tests for adding a list (fainzanj) Known issues: - Charts related documents doesn't open in Word 2012 (opens up fine in Word 2010) Additionally: - Removed StrongNameFile.pfx for easy compile - Renamed file UnitTests1.cs into DocXUnitTests.cs - Created Documentation.chm and commited with this releasemaster
| @@ -1,6 +1,6 @@ | |||
| | |||
| Microsoft Visual Studio Solution File, Format Version 11.00 | |||
| # Visual Studio 2010 | |||
| Microsoft Visual Studio Solution File, Format Version 12.00 | |||
| # Visual Studio 2012 | |||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DF41F5CE-8BCB-40CC-835F-54A3DB7D802F}" | |||
| ProjectSection(SolutionItems) = preProject | |||
| DocX.vsmdi = DocX.vsmdi | |||
| @@ -1,10 +1,10 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.IO.Packaging; | |||
| using System.Linq; | |||
| using System.Xml.Linq; | |||
| using System.Text.RegularExpressions; | |||
| using System.IO.Packaging; | |||
| using System.IO; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| { | |||
| @@ -56,9 +56,9 @@ namespace Novacode | |||
| /// }// Release this document from memory. | |||
| /// </code> | |||
| /// </example> | |||
| public virtual List<Paragraph> Paragraphs | |||
| public virtual List<Paragraph> Paragraphs | |||
| { | |||
| get | |||
| get | |||
| { | |||
| List<Paragraph> paragraphs = GetParagraphs(); | |||
| @@ -66,12 +66,99 @@ namespace Novacode | |||
| { | |||
| 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; | |||
| } | |||
| } | |||
| public virtual List<Section> Sections | |||
| { | |||
| get | |||
| { | |||
| var allParas = Paragraphs; | |||
| var parasInASection = new List<Paragraph>(); | |||
| var sections = new List<Section>(); | |||
| foreach (var para in allParas) | |||
| { | |||
| var sectionInPara = para.Xml.Descendants().FirstOrDefault(s => s.Name.LocalName == "sectPr"); | |||
| if (sectionInPara == null) | |||
| { | |||
| parasInASection.Add(para); | |||
| } | |||
| else | |||
| { | |||
| parasInASection.Add(para); | |||
| var section = new Section(Document, sectionInPara) { SectionParagraphs = parasInASection }; | |||
| sections.Add(section); | |||
| parasInASection = new List<Paragraph>(); | |||
| } | |||
| } | |||
| XElement body = Xml.Element(XName.Get("body", DocX.w.NamespaceName)); | |||
| XElement baseSectionXml = body.Element(XName.Get("sectPr", DocX.w.NamespaceName)); | |||
| var baseSection = new Section(Document, baseSectionXml) { SectionParagraphs = parasInASection }; | |||
| sections.Add(baseSection); | |||
| return sections; | |||
| } | |||
| } | |||
| private void GetListItemType(Paragraph p) | |||
| { | |||
| var ilvlNode = p.ParagraphNumberProperties.Descendants().FirstOrDefault(el => el.Name.LocalName == "ilvl"); | |||
| var ilvlValue = ilvlNode.Attribute(DocX.w + "val").Value; | |||
| var numIdNode = p.ParagraphNumberProperties.Descendants().FirstOrDefault(el => el.Name.LocalName == "numId"); | |||
| var numIdValue = numIdNode.Attribute(DocX.w + "val").Value; | |||
| //find num node in numbering | |||
| var numNodes = Document.numbering.Descendants().Where(n => n.Name.LocalName == "num"); | |||
| XElement numNode = numNodes.FirstOrDefault(node => node.Attribute(DocX.w + "numId").Value.Equals(numIdValue)); | |||
| //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; | |||
| internal List<Paragraph> GetParagraphs() | |||
| { | |||
| // Need some memory that can be updated by the recursive search. | |||
| @@ -99,8 +186,12 @@ namespace Novacode | |||
| else | |||
| { | |||
| if (Xml.HasElements) | |||
| { | |||
| foreach (XElement e in Xml.Elements()) | |||
| { | |||
| GetParagraphsRecursive(e, ref index, ref paragraphs); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -118,6 +209,36 @@ namespace Novacode | |||
| } | |||
| } | |||
| public virtual List<List> Lists | |||
| { | |||
| get | |||
| { | |||
| var lists = new List<List>(); | |||
| var list = new List(Document, Xml); | |||
| foreach (var paragraph in Paragraphs) | |||
| { | |||
| if (paragraph.IsListItem) | |||
| { | |||
| if (list.CanAddListItem(paragraph)) | |||
| { | |||
| list.AddItem(paragraph); | |||
| } | |||
| else | |||
| { | |||
| lists.Add(list); | |||
| list = new List(Document, Xml); | |||
| list.AddItem(paragraph); | |||
| } | |||
| } | |||
| } | |||
| lists.Add(list); | |||
| return lists; | |||
| } | |||
| } | |||
| public virtual List<Hyperlink> Hyperlinks | |||
| { | |||
| get | |||
| @@ -225,7 +346,7 @@ namespace Novacode | |||
| // this dictionary is used to collect results and test for uniqueness | |||
| Dictionary<string, int> uniqueResults = new Dictionary<string, int>(); | |||
| foreach (string currValue in rawResults) | |||
| { | |||
| if (!uniqueResults.ContainsKey(currValue)) | |||
| @@ -291,6 +412,8 @@ namespace Novacode | |||
| ); | |||
| } | |||
| GetParent(p); | |||
| return p; | |||
| } | |||
| @@ -359,6 +482,9 @@ namespace Novacode | |||
| Paragraph newParagraph = new Paragraph(Document, newXElement, index); | |||
| Document.paragraphLookup.Add(index, newParagraph); | |||
| GetParent(newParagraph); | |||
| return newParagraph; | |||
| } | |||
| @@ -384,9 +510,126 @@ namespace Novacode | |||
| else | |||
| Xml.Add(newParagraph); | |||
| GetParent(newParagraph); | |||
| return newParagraph; | |||
| } | |||
| private ContainerType GetParentFromXmlName(string xmlName) | |||
| { | |||
| ContainerType parent; | |||
| switch (xmlName) | |||
| { | |||
| case "body": | |||
| parent = ContainerType.Body; | |||
| break; | |||
| case "p": | |||
| parent = ContainerType.Paragraph; | |||
| break; | |||
| case "tbl": | |||
| parent = ContainerType.Table; | |||
| break; | |||
| case "sectPr": | |||
| parent = ContainerType.Section; | |||
| break; | |||
| case "tc": | |||
| parent = ContainerType.Cell; | |||
| break; | |||
| default: | |||
| parent = ContainerType.None; | |||
| break; | |||
| } | |||
| return parent; | |||
| } | |||
| private void GetParent(Paragraph newParagraph) | |||
| { | |||
| var containerType = GetType(); | |||
| switch (containerType.Name) | |||
| { | |||
| case "Body": | |||
| newParagraph.ParentContainer = ContainerType.Body; | |||
| break; | |||
| case "Table": | |||
| newParagraph.ParentContainer = ContainerType.Table; | |||
| break; | |||
| case "TOC": | |||
| newParagraph.ParentContainer = ContainerType.TOC; | |||
| break; | |||
| case "Section": | |||
| newParagraph.ParentContainer = ContainerType.Section; | |||
| break; | |||
| case "Cell": | |||
| newParagraph.ParentContainer = ContainerType.Cell; | |||
| break; | |||
| case "Header": | |||
| newParagraph.ParentContainer = ContainerType.Header; | |||
| break; | |||
| case "Footer": | |||
| newParagraph.ParentContainer = ContainerType.Footer; | |||
| break; | |||
| case "Paragraph": | |||
| newParagraph.ParentContainer = ContainerType.Paragraph; | |||
| break; | |||
| } | |||
| } | |||
| private ListItemType GetListItemType(string styleName) | |||
| { | |||
| ListItemType listItemType; | |||
| switch (styleName) | |||
| { | |||
| case "bullet": | |||
| listItemType = ListItemType.Bulleted; | |||
| break; | |||
| default: | |||
| listItemType = ListItemType.Numbered; | |||
| break; | |||
| } | |||
| return listItemType; | |||
| } | |||
| public virtual void InsertSection() | |||
| { | |||
| InsertSection(false); | |||
| } | |||
| public virtual void InsertSection(bool trackChanges) | |||
| { | |||
| var newParagraphSection = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), new XElement(XName.Get("pPr", DocX.w.NamespaceName), new XElement(XName.Get("sectPr", DocX.w.NamespaceName), new XElement(XName.Get("type", DocX.w.NamespaceName), new XAttribute(DocX.w + "val", "continuous")))) | |||
| ); | |||
| if (trackChanges) | |||
| newParagraphSection = HelperFunctions.CreateEdit(EditType.ins, DateTime.Now, newParagraphSection); | |||
| Xml.Add(newParagraphSection); | |||
| } | |||
| public virtual void InsertSectionPageBreak(bool trackChanges = false) | |||
| { | |||
| var newParagraphSection = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), new XElement(XName.Get("pPr", DocX.w.NamespaceName), new XElement(XName.Get("sectPr", DocX.w.NamespaceName))) | |||
| ); | |||
| if (trackChanges) | |||
| newParagraphSection = HelperFunctions.CreateEdit(EditType.ins, DateTime.Now, newParagraphSection); | |||
| Xml.Add(newParagraphSection); | |||
| } | |||
| public virtual Paragraph InsertParagraph(string text) | |||
| { | |||
| return InsertParagraph(text, false, new Formatting()); | |||
| @@ -409,13 +652,17 @@ namespace Novacode | |||
| Xml.Add(newParagraph); | |||
| return Paragraphs.Last(); | |||
| var paragraphAdded = Paragraphs.Last(); | |||
| GetParent(paragraphAdded); | |||
| return paragraphAdded; | |||
| } | |||
| public virtual Paragraph InsertEquation(string equation) | |||
| { | |||
| Paragraph p = InsertParagraph(); | |||
| p.AppendEquation(equation); | |||
| p.AppendEquation(equation); | |||
| return p; | |||
| } | |||
| @@ -484,7 +731,30 @@ namespace Novacode | |||
| internal Container(DocX document, XElement xml) | |||
| : base(document, xml) | |||
| { | |||
| } | |||
| public List InsertList(List list) | |||
| { | |||
| foreach (var item in list.Items) | |||
| { | |||
| Xml.Add(item.Xml); | |||
| } | |||
| return list; | |||
| } | |||
| public List InsertList(int index, List list) | |||
| { | |||
| Paragraph p = HelperFunctions.GetFirstParagraphEffectedByInsert(Document, index); | |||
| XElement[] split = HelperFunctions.SplitParagraph(p, index - p.startIndex); | |||
| var elements = new List<XElement> { split[0] }; | |||
| elements.AddRange(list.Items.Select(i => new XElement(i.Xml))); | |||
| elements.Add(split[1]); | |||
| p.Xml.ReplaceWith(elements.ToArray()); | |||
| return list; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,13 +1,13 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Xml.Linq; | |||
| using System.Xml; | |||
| using System.IO; | |||
| using System.Text.RegularExpressions; | |||
| using System.IO.Packaging; | |||
| using System.Linq; | |||
| using System.Security.Cryptography; | |||
| using System.Text; | |||
| using System.Text.RegularExpressions; | |||
| using System.Xml; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| { | |||
| @@ -28,6 +28,8 @@ namespace Novacode | |||
| static internal XNamespace wp = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"; | |||
| static internal XNamespace a = "http://schemas.openxmlformats.org/drawingml/2006/main"; | |||
| static internal XNamespace c = "http://schemas.openxmlformats.org/drawingml/2006/chart"; | |||
| internal static XNamespace n = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering"; | |||
| #endregion | |||
| internal float getMarginAttribute(XName name) | |||
| @@ -74,7 +76,7 @@ namespace Novacode | |||
| { | |||
| get | |||
| { | |||
| return getMarginAttribute(XName.Get("top", DocX.w.NamespaceName)); | |||
| return getMarginAttribute(XName.Get("top", DocX.w.NamespaceName)); | |||
| } | |||
| set | |||
| @@ -207,7 +209,7 @@ namespace Novacode | |||
| if (pgSz != null) | |||
| { | |||
| pgSz.SetAttributeValue(XName.Get("h", DocX.w.NamespaceName), value*15); | |||
| pgSz.SetAttributeValue(XName.Get("h", DocX.w.NamespaceName), value * 15); | |||
| } | |||
| } | |||
| } | |||
| @@ -486,7 +488,6 @@ namespace Novacode | |||
| if (value) | |||
| settings.Root.AddFirst(new XElement(w + "evenAndOddHeaders")); | |||
| } | |||
| else | |||
| { | |||
| if (!value) | |||
| @@ -556,7 +557,6 @@ namespace Novacode | |||
| if (value) | |||
| sectPr.Add(new XElement(w + "titlePg", string.Empty)); | |||
| } | |||
| else | |||
| { | |||
| if (!value) | |||
| @@ -583,6 +583,7 @@ namespace Novacode | |||
| 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() | |||
| @@ -622,6 +623,43 @@ namespace Novacode | |||
| return null; | |||
| } | |||
| public List<Section> GetSections() | |||
| { | |||
| var allParas = Paragraphs; | |||
| var parasInASection = new List<Paragraph>(); | |||
| var sections = new List<Section>(); | |||
| foreach (var para in allParas) | |||
| { | |||
| var sectionInPara = para.Xml.Descendants().FirstOrDefault(s => s.Name.LocalName == "sectPr"); | |||
| if (sectionInPara == null) | |||
| { | |||
| parasInASection.Add(para); | |||
| } | |||
| else | |||
| { | |||
| parasInASection.Add(para); | |||
| var section = new Section(Document, sectionInPara) { SectionParagraphs = parasInASection }; | |||
| sections.Add(section); | |||
| parasInASection = new List<Paragraph>(); | |||
| } | |||
| } | |||
| XElement body = mainDoc.Root.Element(XName.Get("body", DocX.w.NamespaceName)); | |||
| XElement baseSectionXml = body.Element(XName.Get("sectPr", DocX.w.NamespaceName)); | |||
| var baseSection = new Section(Document, baseSectionXml) { SectionParagraphs = parasInASection }; | |||
| sections.Add(baseSection); | |||
| return sections; | |||
| } | |||
| // Get the word\document.xml part | |||
| internal PackagePart mainPart; | |||
| @@ -911,8 +949,8 @@ namespace Novacode | |||
| // We don't want to effect the origional XDocument, so create a new one from the old one. | |||
| XDocument remote_mainDoc = new XDocument(remote_document.mainDoc); | |||
| XDocument remote_footnotes = null ; | |||
| if(remote_document.footnotes != null) | |||
| XDocument remote_footnotes = null; | |||
| if (remote_document.footnotes != null) | |||
| remote_footnotes = new XDocument(remote_document.footnotes); | |||
| XDocument remote_endnotes = null; | |||
| @@ -938,7 +976,7 @@ namespace Novacode | |||
| "application/vnd.openxmlformats-officedocument.extended-properties+xml", | |||
| "application/vnd.openxmlformats-package.relationships+xml", | |||
| }; | |||
| List<String> imageContentTypes = new List<string> | |||
| { | |||
| "image/jpeg", | |||
| @@ -1011,7 +1049,7 @@ namespace Novacode | |||
| footnotesPart = packagePart; | |||
| footnotes = remote_footnotes; | |||
| break; | |||
| case "application/vnd.openxmlformats-officedocument.custom-properties+xml": | |||
| break; | |||
| @@ -1117,7 +1155,7 @@ namespace Novacode | |||
| String remote_hash = ComputeMD5HashString(remote_pp.GetStream()); | |||
| var image_parts = package.GetParts().Where(pp => pp.ContentType.Equals(contentType)); | |||
| bool found = false; | |||
| bool found = false; | |||
| foreach (var part in image_parts) | |||
| { | |||
| String local_hash = ComputeMD5HashString(part.GetStream()); | |||
| @@ -1304,7 +1342,7 @@ namespace Novacode | |||
| XAttribute remote_property_name = remote_property.Attribute(XName.Get("name")); | |||
| XAttribute local_property_name = local_property.Attribute(XName.Get("name")); | |||
| if(remote_property != null && local_property_name != null && remote_property_name.Value.Equals(local_property_name.Value)) | |||
| if (remote_property != null && local_property_name != null && remote_property_name.Value.Equals(local_property_name.Value)) | |||
| found = true; | |||
| } | |||
| @@ -1330,7 +1368,7 @@ namespace Novacode | |||
| foreach (var an in remote_abstractNums) | |||
| { | |||
| XAttribute a = an.Attribute(XName.Get("abstractNumId", DocX.w.NamespaceName)); | |||
| if(a != null) | |||
| if (a != null) | |||
| { | |||
| int i; | |||
| if (int.TryParse(a.Value, out i)) | |||
| @@ -1417,7 +1455,7 @@ namespace Novacode | |||
| break; | |||
| } | |||
| } | |||
| if (flag_addFont) | |||
| { | |||
| fontTable.Root.Add(remote_font); | |||
| @@ -1435,7 +1473,7 @@ namespace Novacode | |||
| String value = styleId.Value; | |||
| styleId.Remove(); | |||
| String key = Regex.Replace(temp.ToString(), @"\s+", ""); | |||
| if (!local_styles.ContainsKey(key)) local_styles.Add(key, value); | |||
| if (!local_styles.ContainsKey(key)) local_styles.Add(key, value); | |||
| } | |||
| // Add each remote style to this document. | |||
| @@ -1465,11 +1503,10 @@ namespace Novacode | |||
| guuid = local_value; | |||
| } | |||
| } | |||
| else | |||
| guuid = Guid.NewGuid().ToString(); | |||
| foreach(XElement e in remote_mainDoc.Root.Descendants(XName.Get("pStyle", DocX.w.NamespaceName))) | |||
| foreach (XElement e in remote_mainDoc.Root.Descendants(XName.Get("pStyle", DocX.w.NamespaceName))) | |||
| { | |||
| XAttribute e_styleId = e.Attribute(XName.Get("val", DocX.w.NamespaceName)); | |||
| if (e_styleId != null && e_styleId.Value.Equals(styleId.Value)) | |||
| @@ -1487,7 +1524,7 @@ namespace Novacode | |||
| } | |||
| } | |||
| foreach(XElement e in remote_mainDoc.Root.Descendants(XName.Get("tblStyle", DocX.w.NamespaceName))) | |||
| foreach (XElement e in remote_mainDoc.Root.Descendants(XName.Get("tblStyle", DocX.w.NamespaceName))) | |||
| { | |||
| XAttribute e_styleId = e.Attribute(XName.Get("val", DocX.w.NamespaceName)); | |||
| if (e_styleId != null && e_styleId.Value.Equals(styleId.Value)) | |||
| @@ -1540,7 +1577,7 @@ namespace Novacode | |||
| // Make sure they don't clash by using a uuid. | |||
| styleId.SetValue(guuid); | |||
| styles.Root.Add(remote_style); | |||
| styles.Root.Add(remote_style); | |||
| } | |||
| } | |||
| @@ -1557,7 +1594,7 @@ namespace Novacode | |||
| // Replace all instances of remote_Id in the local document with local_Id | |||
| var elems = remote_mainDoc.Descendants(XName.Get("blip", DocX.a.NamespaceName)); | |||
| foreach(var elem in elems) | |||
| foreach (var elem in elems) | |||
| { | |||
| XAttribute embed = elem.Attribute(XName.Get("embed", DocX.r.NamespaceName)); | |||
| if (embed != null && embed.Value == remote_Id) | |||
| @@ -1658,6 +1695,122 @@ namespace Novacode | |||
| return t; | |||
| } | |||
| /// <summary> | |||
| /// Create a new list with a list item. | |||
| /// </summary> | |||
| /// <param name="listText">The text of the first element in the created list.</param> | |||
| /// <param name="level">The indentation level of the element in the list.</param> | |||
| /// <param name="listType">The type of list to be created: Bulleted or Numbered.</param> | |||
| /// <param name="startNumber">The number start number for the list. </param> | |||
| /// <param name="trackChanges">Enable change tracking</param> | |||
| /// <returns> | |||
| /// The created List. Call AddListItem(...) to add more elements to the list. | |||
| /// Write the list to the Document with InsertList(...) once the list has all the desired | |||
| /// elements, otherwise the list will not be included in the working Document. | |||
| /// </returns> | |||
| public List AddList(string listText = null, int level = 0, ListItemType listType = ListItemType.Numbered, int? startNumber = null, bool trackChanges = false) | |||
| { | |||
| return AddListItem(new List(this, null), listText, level, listType, startNumber, trackChanges); | |||
| } | |||
| /// <summary> | |||
| /// Add a list item to an already existing list. | |||
| /// </summary> | |||
| /// <param name="list">The list to add the new list item to.</param> | |||
| /// <param name="listText">The run text that should be in the new list item.</param> | |||
| /// <param name="level">The indentation level of the new list element.</param> | |||
| /// <param name="startNumber">The number start number for the list. </param> | |||
| /// <param name="trackChanges">Enable change tracking</param> | |||
| /// <param name="listType">Numbered or Bulleted list type. </param> | |||
| /// <returns> | |||
| /// The created List. Call AddListItem(...) to add more elements to the list. | |||
| /// Write the list to the Document with InsertList(...) once the list has all the desired | |||
| /// elements, otherwise the list will not be included in the working Document. | |||
| /// </returns> | |||
| public List AddListItem(List list, string listText, int level = 0, ListItemType listType = ListItemType.Numbered, int? startNumber = null, bool trackChanges = false) | |||
| { | |||
| return HelperFunctions.CreateItemInList(list, listText, level, listType, startNumber, trackChanges); | |||
| } | |||
| /// <summary> | |||
| /// Insert list into the document. | |||
| /// </summary> | |||
| /// <param name="list">The list to insert into the document.</param> | |||
| /// <returns>The list that was inserted into the document.</returns> | |||
| public new List InsertList(List list) | |||
| { | |||
| base.InsertList(list); | |||
| list.Items.ForEach(i => i.mainPart = mainPart); | |||
| return list; | |||
| } | |||
| /// <summary> | |||
| /// Insert a list at an index location in the document. | |||
| /// </summary> | |||
| /// <param name="index">Index in document to insert the list.</param> | |||
| /// <param name="list">The list that was inserted into the document.</param> | |||
| /// <returns></returns> | |||
| public new List InsertList(int index, List list) | |||
| { | |||
| base.InsertList(index, list); | |||
| list.Items.ForEach(i => i.mainPart = mainPart); | |||
| return list; | |||
| } | |||
| internal XDocument AddStylesForList() | |||
| { | |||
| var wordStylesUri = new Uri("/word/styles.xml", UriKind.Relative); | |||
| // If the internal document contains no /word/styles.xml create one. | |||
| if (!package.PartExists(wordStylesUri)) | |||
| HelperFunctions.AddDefaultStylesXml(package); | |||
| // Load the styles.xml into memory. | |||
| XDocument wordStyles; | |||
| using (TextReader tr = new StreamReader(package.GetPart(wordStylesUri).GetStream())) | |||
| wordStyles = XDocument.Load(tr); | |||
| bool listStyleExists = | |||
| ( | |||
| from s in wordStyles.Element(w + "styles").Elements() | |||
| let styleId = s.Attribute(XName.Get("styleId", w.NamespaceName)) | |||
| where (styleId != null && styleId.Value == "ListParagraph") | |||
| select s | |||
| ).Any(); | |||
| if (!listStyleExists) | |||
| { | |||
| var style = new XElement | |||
| ( | |||
| w + "style", | |||
| new XAttribute(w + "type", "paragraph"), | |||
| new XAttribute(w + "styleId", "ListParagraph"), | |||
| new XElement(w + "name", new XAttribute(w + "val", "List Paragraph")), | |||
| new XElement(w + "basedOn", new XAttribute(w + "val", "Normal")), | |||
| new XElement(w + "uiPriority", new XAttribute(w + "val", "34")), | |||
| new XElement(w + "qformat"), | |||
| new XElement(w + "rsid", new XAttribute(w + "val", "00832EE1")), | |||
| new XElement | |||
| ( | |||
| w + "rPr", | |||
| new XElement(w + "ind", new XAttribute(w + "left", "720")), | |||
| new XElement | |||
| ( | |||
| w + "contextualSpacing" | |||
| ) | |||
| ) | |||
| ); | |||
| wordStyles.Element(w + "styles").Add(style); | |||
| // Save the styles document. | |||
| using (TextWriter tw = new StreamWriter(package.GetPart(wordStylesUri).GetStream())) | |||
| wordStyles.Save(tw); | |||
| } | |||
| return wordStyles; | |||
| } | |||
| /// <summary> | |||
| /// Insert a Table into this document. The Table's source can be a completely different document. | |||
| /// </summary> | |||
| @@ -1898,7 +2051,7 @@ namespace Novacode | |||
| internal static void PostCreation(ref Package package) | |||
| { | |||
| XDocument mainDoc, stylesDoc; | |||
| XDocument mainDoc, stylesDoc, numberingDoc; | |||
| #region MainDocumentPart | |||
| // Create the main document part for this package | |||
| @@ -1932,6 +2085,10 @@ namespace Novacode | |||
| stylesDoc = HelperFunctions.AddDefaultStylesXml(package); | |||
| #endregion | |||
| #region NumberingPart | |||
| numberingDoc = HelperFunctions.AddDefaultNumberingXml(package); | |||
| #endregion | |||
| package.Close(); | |||
| } | |||
| @@ -1976,7 +2133,7 @@ namespace Novacode | |||
| footers.first = document.GetFooterByType("first"); | |||
| //// Get the sectPr for this document. | |||
| //XElement sectPr = document.mainDoc.Descendants(XName.Get("sectPr", DocX.w.NamespaceName)).Single(); | |||
| //XElement sect = document.mainDoc.Descendants(XName.Get("sectPr", DocX.w.NamespaceName)).Single(); | |||
| //if (sectPr != null) | |||
| //{ | |||
| @@ -2033,6 +2190,7 @@ namespace Novacode | |||
| var ps = package.GetParts(); | |||
| //document.endnotesPart = HelperFunctions.GetPart(); | |||
| foreach (var rel in document.mainPart.GetRelationships()) | |||
| { | |||
| switch (rel.RelationshipType) | |||
| @@ -2040,13 +2198,13 @@ namespace Novacode | |||
| case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes": | |||
| document.endnotesPart = package.GetPart(new Uri("/word/" + rel.TargetUri.OriginalString.Replace("/word/", ""), UriKind.RelativeOrAbsolute)); | |||
| using (TextReader tr = new StreamReader(document.endnotesPart.GetStream())) | |||
| document.endnotes= XDocument.Load(tr); | |||
| document.endnotes = XDocument.Load(tr); | |||
| break; | |||
| case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes": | |||
| document.footnotesPart = package.GetPart(new Uri("/word/" + rel.TargetUri.OriginalString.Replace("/word/", ""), UriKind.RelativeOrAbsolute)); | |||
| using (TextReader tr = new StreamReader(document.footnotesPart.GetStream())) | |||
| document.footnotes= XDocument.Load(tr); | |||
| document.footnotes = XDocument.Load(tr); | |||
| break; | |||
| case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles": | |||
| @@ -2364,6 +2522,7 @@ namespace Novacode | |||
| tr.Read(); | |||
| } | |||
| templatePackage.Close(); | |||
| PopulateDocument(Document, package); | |||
| } | |||
| } | |||
| @@ -3105,7 +3264,7 @@ namespace Novacode | |||
| // Close the document so that it can be saved. | |||
| package.Flush(); | |||
| #region Save this document back to a file or stream, that was specified by the user at save time. | |||
| if (filename != null) | |||
| { | |||
| @@ -3114,8 +3273,6 @@ namespace Novacode | |||
| fs.Write(memoryStream.ToArray(), 0, (int)memoryStream.Length); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // Set the length of this stream to 0 | |||
| @@ -3565,7 +3722,7 @@ namespace Novacode | |||
| } | |||
| } | |||
| } | |||
| #endregion | |||
| #endregion | |||
| #region < Word 2010 | |||
| foreach (XElement e in doc.Descendants(XName.Get("fldSimple", w.NamespaceName))) | |||
| @@ -3669,6 +3826,16 @@ namespace Novacode | |||
| } | |||
| } | |||
| public override List<List> Lists | |||
| { | |||
| get | |||
| { | |||
| List<List> l = base.Lists; | |||
| l.ForEach(x => x.Items.ForEach(i => i.PackagePart = mainPart)); | |||
| return l; | |||
| } | |||
| } | |||
| public override List<Table> Tables | |||
| { | |||
| get | |||
| @@ -3679,6 +3846,7 @@ namespace Novacode | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Create an equation and insert it in the new paragraph | |||
| /// </summary> | |||
| @@ -61,10 +61,11 @@ | |||
| <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> | |||
| </PropertyGroup> | |||
| <PropertyGroup> | |||
| <SignAssembly>true</SignAssembly> | |||
| <SignAssembly>false</SignAssembly> | |||
| </PropertyGroup> | |||
| <PropertyGroup> | |||
| <AssemblyOriginatorKeyFile>StrongNameFile.pfx</AssemblyOriginatorKeyFile> | |||
| <AssemblyOriginatorKeyFile> | |||
| </AssemblyOriginatorKeyFile> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <Reference Include="System" /> | |||
| @@ -103,7 +104,9 @@ | |||
| <Compile Include="Headers.cs" /> | |||
| <Compile Include="HelperFunctions.cs" /> | |||
| <Compile Include="Hyperlink.cs" /> | |||
| <Compile Include="List.cs" /> | |||
| <Compile Include="PageLayout.cs" /> | |||
| <Compile Include="Section.cs" /> | |||
| <Compile Include="_BaseClasses.cs" /> | |||
| <Compile Include="Table.cs" /> | |||
| <Compile Include="_Enumerations.cs" /> | |||
| @@ -117,9 +120,6 @@ | |||
| <SubType>Code</SubType> | |||
| </Compile> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <None Include="StrongNameFile.pfx" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Content Include="License\License.html" /> | |||
| </ItemGroup> | |||
| @@ -144,6 +144,13 @@ | |||
| <Install>true</Install> | |||
| </BootstrapperPackage> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <EmbeddedResource Include="Resources\numbering.xml.gz" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <EmbeddedResource Include="Resources\numbering.default_bullet_abstract.xml.gz" /> | |||
| <EmbeddedResource Include="Resources\numbering.default_decimal_abstract.xml.gz" /> | |||
| </ItemGroup> | |||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||
| <!-- To modify your build process, add your task inside one of the targets below and uncomment it. | |||
| Other similar extension points exist, see Microsoft.Common.targets. | |||
| @@ -79,11 +79,12 @@ namespace Novacode | |||
| case "position": formatting.Position = Int32.Parse(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))) / 2; break; | |||
| case "kern": formatting.Position = Int32.Parse(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))) / 2; break; | |||
| case "w": formatting.PercentageScale = Int32.Parse(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))); break; | |||
| case "rFonts": break; | |||
| case "rFonts": formatting.FontFamily = new FontFamily(option.GetAttribute(XName.Get("cs", DocX.w.NamespaceName))); break; | |||
| case "vanish": formatting.hidden = true; break; | |||
| case "b": formatting.Bold = true; break; | |||
| case "i": formatting.Italic = true; break; | |||
| case "u": formatting.UnderlineStyle = HelperFunctions.GetUnderlineStyle(option.GetAttribute(XName.Get("val", DocX.w.NamespaceName))); | |||
| break; | |||
| default: break; | |||
| } | |||
| } | |||
| @@ -1,14 +1,14 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.IO.Packaging; | |||
| using System.Xml.Linq; | |||
| using System.Globalization; | |||
| using System.IO; | |||
| using System.Reflection; | |||
| using System.IO.Compression; | |||
| using System.IO.Packaging; | |||
| using System.Linq; | |||
| using System.Reflection; | |||
| using System.Security.Principal; | |||
| using System.Globalization; | |||
| using System.Text; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| { | |||
| @@ -88,7 +88,6 @@ namespace Novacode | |||
| // Update text of last entry. | |||
| last.text += ft.text; | |||
| } | |||
| else | |||
| { | |||
| if (last != null) | |||
| @@ -116,7 +115,7 @@ namespace Novacode | |||
| // e is a w:r element, lets find the rPr element. | |||
| XElement rPr = e.Element(XName.Get("rPr", DocX.w.NamespaceName)); | |||
| FormattedText ft = new FormattedText(); | |||
| ft.text = text; | |||
| ft.index = 0; | |||
| @@ -251,7 +250,6 @@ namespace Novacode | |||
| using (TextWriter tw = new StreamWriter(settingsPart.GetStream())) | |||
| settings.Save(tw); | |||
| } | |||
| else | |||
| settingsPart = package.GetPart(settingsUri); | |||
| return settingsPart; | |||
| @@ -302,6 +300,38 @@ namespace Novacode | |||
| return document; | |||
| } | |||
| /// <summary> | |||
| /// If this document does not contain a /word/numbering.xml add the default one generated by Microsoft Word | |||
| /// when the default bullet, numbered and multilevel lists are added to a blank document | |||
| /// </summary> | |||
| /// <param name="package"></param> | |||
| /// <param name="mainDocumentPart"></param> | |||
| /// <returns></returns> | |||
| internal static XDocument AddDefaultNumberingXml(Package package) | |||
| { | |||
| XDocument numberingDoc; | |||
| // Create the main document part for this package | |||
| PackagePart wordNumbering = package.CreatePart(new Uri("/word/numbering.xml", UriKind.Relative), "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", CompressionOption.Maximum); | |||
| numberingDoc = DecompressXMLResource("Novacode.Resources.numbering.xml.gz"); | |||
| // Save /word/numbering.xml | |||
| using (TextWriter tw = new StreamWriter(wordNumbering.GetStream(FileMode.Create, FileAccess.Write))) | |||
| numberingDoc.Save(tw, SaveOptions.None); | |||
| PackagePart mainDocumentPart = package.GetParts().Single(p => p.ContentType.Equals | |||
| ( | |||
| "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", | |||
| StringComparison.CurrentCultureIgnoreCase | |||
| )); | |||
| mainDocumentPart.CreateRelationship(wordNumbering.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering"); | |||
| return numberingDoc; | |||
| } | |||
| /// <summary> | |||
| /// If this document does not contain a /word/styles.xml add the default one generated by Microsoft Word. | |||
| /// </summary> | |||
| @@ -317,7 +347,7 @@ namespace Novacode | |||
| stylesDoc = HelperFunctions.DecompressXMLResource("Novacode.Resources.default_styles.xml.gz"); | |||
| XElement lang = stylesDoc.Root.Element(XName.Get("docDefaults", DocX.w.NamespaceName)).Element(XName.Get("rPrDefault", DocX.w.NamespaceName)).Element(XName.Get("rPr", DocX.w.NamespaceName)).Element(XName.Get("lang", DocX.w.NamespaceName)); | |||
| lang.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), CultureInfo.CurrentCulture); | |||
| // Save /word/styles.xml | |||
| using (TextWriter tw = new StreamWriter(word_styles.GetStream(FileMode.Create, FileAccess.Write))) | |||
| stylesDoc.Save(tw, SaveOptions.None); | |||
| @@ -335,7 +365,7 @@ namespace Novacode | |||
| return stylesDoc; | |||
| } | |||
| static internal XElement CreateEdit(EditType t, DateTime edit_time, object content) | |||
| internal static XElement CreateEdit(EditType t, DateTime edit_time, object content) | |||
| { | |||
| if (t == EditType.del) | |||
| { | |||
| @@ -418,6 +448,41 @@ namespace Novacode | |||
| ); | |||
| } | |||
| internal static List CreateItemInList(List list, string listText, int level = 0, ListItemType listType = ListItemType.Numbered, int? startNumber = null, bool trackChanges = false) | |||
| { | |||
| if (list.NumId == 0) | |||
| { | |||
| list.CreateNewNumberingNumId(level, listType); | |||
| } | |||
| if (!string.IsNullOrEmpty(listText)) | |||
| { | |||
| var newParagraphSection = new XElement | |||
| ( | |||
| XName.Get("p", DocX.w.NamespaceName), | |||
| new XElement(XName.Get("pPr", DocX.w.NamespaceName), | |||
| new XElement(XName.Get("numPr", DocX.w.NamespaceName), | |||
| new XElement(XName.Get("ilvl", DocX.w.NamespaceName), new XAttribute(DocX.w + "val", level)), | |||
| new XElement(XName.Get("numId", DocX.w.NamespaceName), new XAttribute(DocX.w + "val", list.NumId)))), | |||
| new XElement(XName.Get("r", DocX.w.NamespaceName), new XElement(XName.Get("t", DocX.w.NamespaceName), listText)) | |||
| ); | |||
| if (trackChanges) | |||
| newParagraphSection = CreateEdit(EditType.ins, DateTime.Now, newParagraphSection); | |||
| if (startNumber == null) | |||
| { | |||
| list.AddItem(new Paragraph(list.Document, newParagraphSection, 0, ContainerType.Paragraph)); | |||
| } | |||
| else | |||
| { | |||
| list.AddItemWithStartValue(new Paragraph(list.Document, newParagraphSection, 0, ContainerType.Paragraph), (int)startNumber); | |||
| } | |||
| } | |||
| return list; | |||
| } | |||
| internal static void RenumberIDs(DocX document) | |||
| { | |||
| IEnumerable<XAttribute> trackerIDs = | |||
| @@ -429,7 +494,7 @@ namespace Novacode | |||
| trackerIDs.ElementAt(i).Value = i.ToString(); | |||
| } | |||
| static internal Paragraph GetFirstParagraphEffectedByInsert(DocX document, int index) | |||
| internal static Paragraph GetFirstParagraphEffectedByInsert(DocX document, int index) | |||
| { | |||
| // This document contains no Paragraphs and insertion is at index 0 | |||
| if (document.paragraphLookup.Keys.Count() == 0 && index == 0) | |||
| @@ -498,7 +563,7 @@ namespace Novacode | |||
| return newRuns; | |||
| } | |||
| static internal XElement[] SplitParagraph(Paragraph p, int index) | |||
| internal static XElement[] SplitParagraph(Paragraph p, int index) | |||
| { | |||
| // In this case edit dosent really matter, you have a choice. | |||
| Run r = p.GetFirstRunEffectedByEdit(index, EditType.ins); | |||
| @@ -512,7 +577,6 @@ namespace Novacode | |||
| before = new XElement(p.Xml.Name, p.Xml.Attributes(), r.Xml.Parent.ElementsBeforeSelf(), split[0]); | |||
| after = new XElement(p.Xml.Name, p.Xml.Attributes(), r.Xml.Parent.ElementsAfterSelf(), split[1]); | |||
| } | |||
| else if (r.Xml.Parent.Name.LocalName == "del") | |||
| { | |||
| split = p.SplitEdit(r.Xml.Parent, index, EditType.del); | |||
| @@ -520,7 +584,6 @@ namespace Novacode | |||
| before = new XElement(p.Xml.Name, p.Xml.Attributes(), r.Xml.Parent.ElementsBeforeSelf(), split[0]); | |||
| after = new XElement(p.Xml.Name, p.Xml.Attributes(), r.Xml.Parent.ElementsAfterSelf(), split[1]); | |||
| } | |||
| else | |||
| { | |||
| split = Run.SplitRun(r, index); | |||
| @@ -542,7 +605,7 @@ namespace Novacode | |||
| /// Bug found and fixed by trnilse. To see the change, | |||
| /// please compare this release to the previous release using TFS compare. | |||
| /// --> | |||
| static internal bool IsSameFile(Stream streamOne, Stream streamTwo) | |||
| internal static bool IsSameFile(Stream streamOne, Stream streamTwo) | |||
| { | |||
| int file1byte, file2byte; | |||
| @@ -572,5 +635,51 @@ namespace Novacode | |||
| return ((file1byte - file2byte) == 0); | |||
| } | |||
| internal static UnderlineStyle GetUnderlineStyle(string underlineStyle) | |||
| { | |||
| switch (underlineStyle) | |||
| { | |||
| case "single": | |||
| return UnderlineStyle.singleLine; | |||
| case "double": | |||
| return UnderlineStyle.doubleLine; | |||
| case "thick": | |||
| return UnderlineStyle.thick; | |||
| case "dotted": | |||
| return UnderlineStyle.dotted; | |||
| case "dottedHeavy": | |||
| return UnderlineStyle.dottedHeavy; | |||
| case "dash": | |||
| return UnderlineStyle.dash; | |||
| case "dashedHeavy": | |||
| return UnderlineStyle.dashedHeavy; | |||
| case "dashLong": | |||
| return UnderlineStyle.dashLong; | |||
| case "dashLongHeavy": | |||
| return UnderlineStyle.dashLongHeavy; | |||
| case "dotDash": | |||
| return UnderlineStyle.dotDash; | |||
| case "dashDotHeavy": | |||
| return UnderlineStyle.dashDotHeavy; | |||
| case "dotDotDash": | |||
| return UnderlineStyle.dotDotDash; | |||
| case "dashDotDotHeavy": | |||
| return UnderlineStyle.dashDotDotHeavy; | |||
| case "wave": | |||
| return UnderlineStyle.wave; | |||
| case "wavyHeavy": | |||
| return UnderlineStyle.wavyHeavy; | |||
| case "wavyDouble": | |||
| return UnderlineStyle.wavyDouble; | |||
| case "words": | |||
| return UnderlineStyle.words; | |||
| default: | |||
| return UnderlineStyle.none; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,13 +1,14 @@ | |||
| using System; | |||
| using System.Collections; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Xml.Linq; | |||
| using System.Text.RegularExpressions; | |||
| using System.Security.Principal; | |||
| using System.IO.Packaging; | |||
| using System.IO; | |||
| using System.Drawing; | |||
| using System.Globalization; | |||
| using System.IO; | |||
| using System.IO.Packaging; | |||
| using System.Linq; | |||
| using System.Security.Principal; | |||
| using System.Text.RegularExpressions; | |||
| using System.Xml.Linq; | |||
| namespace Novacode | |||
| @@ -26,6 +27,70 @@ namespace Novacode | |||
| // This paragraphs text alignment | |||
| private Alignment alignment; | |||
| public ContainerType ParentContainer; | |||
| private XElement ParagraphNumberPropertiesBacker { get; set; } | |||
| /// <summary> | |||
| /// Fetch the paragraph number properties for a list element. | |||
| /// </summary> | |||
| public XElement ParagraphNumberProperties | |||
| { | |||
| get | |||
| { | |||
| return ParagraphNumberPropertiesBacker ?? (ParagraphNumberPropertiesBacker = GetParagraphNumberProperties()); | |||
| } | |||
| } | |||
| private XElement GetParagraphNumberProperties() | |||
| { | |||
| var numPrNode = Xml.Descendants().FirstOrDefault(el => el.Name.LocalName == "numPr"); | |||
| if (numPrNode != null) | |||
| { | |||
| var numIdNode = numPrNode.Descendants().First(numId => numId.Name.LocalName == "numId"); | |||
| var numIdAttribute = numIdNode.Attribute(DocX.w + "val"); | |||
| if (numIdAttribute != null && numIdAttribute.Value.Equals("0")) | |||
| { | |||
| return null; | |||
| } | |||
| } | |||
| return numPrNode; | |||
| } | |||
| private bool? IsListItemBacker { get; set; } | |||
| /// <summary> | |||
| /// Determine if this paragraph is a list element. | |||
| /// </summary> | |||
| public bool IsListItem | |||
| { | |||
| get | |||
| { | |||
| IsListItemBacker = IsListItemBacker ?? (ParagraphNumberProperties != null); | |||
| return (bool)IsListItemBacker; | |||
| } | |||
| } | |||
| private int? IndentLevelBacker { get; set; } | |||
| /// <summary> | |||
| /// If this element is a list item, get the indentation level of the list item. | |||
| /// </summary> | |||
| public int? IndentLevel | |||
| { | |||
| get | |||
| { | |||
| if (!IsListItem) | |||
| { | |||
| return null; | |||
| } | |||
| return IndentLevelBacker ?? (IndentLevelBacker = int.Parse(ParagraphNumberProperties.Descendants().First(el => el.Name.LocalName == "ilvl").GetAttribute(DocX.w + "val"))); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Determine if the list element is a numbered list of bulleted list element | |||
| /// </summary> | |||
| public ListItemType ListItemType; | |||
| internal int startIndex, endIndex; | |||
| /// <summary> | |||
| @@ -48,7 +113,7 @@ namespace Novacode | |||
| /// } | |||
| /// </code> | |||
| /// </example> | |||
| public List<Picture> Pictures | |||
| public List<Picture> Pictures | |||
| { | |||
| get | |||
| { | |||
| @@ -67,7 +132,7 @@ namespace Novacode | |||
| select new Picture(Document, p, img) | |||
| ).ToList(); | |||
| return pictures; | |||
| } | |||
| } | |||
| @@ -96,10 +161,10 @@ namespace Novacode | |||
| /// } | |||
| /// </code> | |||
| /// </example> | |||
| public List<Hyperlink> Hyperlinks | |||
| public List<Hyperlink> Hyperlinks | |||
| { | |||
| get | |||
| { | |||
| get | |||
| { | |||
| List<Hyperlink> hyperlinks = new List<Hyperlink>(); | |||
| List<XElement> hyperlink_elements = | |||
| @@ -150,7 +215,7 @@ namespace Novacode | |||
| hyperlinks.Add(h); | |||
| } | |||
| catch(Exception){} | |||
| catch (Exception) { } | |||
| break; | |||
| } | |||
| @@ -168,35 +233,35 @@ namespace Novacode | |||
| ///</summary> | |||
| public string StyleName | |||
| { | |||
| get | |||
| { | |||
| var element = this.GetOrCreate_pPr(); | |||
| var styleElement = element.Element(XName.Get("pStyle", DocX.w.NamespaceName)); | |||
| if (styleElement != null) | |||
| { | |||
| var attr = styleElement.Attribute(XName.Get("val", DocX.w.NamespaceName)); | |||
| if (attr != null && !string.IsNullOrEmpty(attr.Value)) | |||
| { | |||
| return attr.Value; | |||
| } | |||
| } | |||
| return "Normal"; | |||
| } | |||
| set | |||
| { | |||
| if (string.IsNullOrEmpty(value)) | |||
| get | |||
| { | |||
| value = "Normal"; | |||
| var element = this.GetOrCreate_pPr(); | |||
| var styleElement = element.Element(XName.Get("pStyle", DocX.w.NamespaceName)); | |||
| if (styleElement != null) | |||
| { | |||
| var attr = styleElement.Attribute(XName.Get("val", DocX.w.NamespaceName)); | |||
| if (attr != null && !string.IsNullOrEmpty(attr.Value)) | |||
| { | |||
| return attr.Value; | |||
| } | |||
| } | |||
| return "Normal"; | |||
| } | |||
| var element = this.GetOrCreate_pPr(); | |||
| var styleElement = element.Element(XName.Get("pStyle", DocX.w.NamespaceName)); | |||
| if (styleElement == null) | |||
| set | |||
| { | |||
| element.Add(new XElement(XName.Get("pStyle", DocX.w.NamespaceName))); | |||
| styleElement = element.Element(XName.Get("pStyle", DocX.w.NamespaceName)); | |||
| if (string.IsNullOrEmpty(value)) | |||
| { | |||
| value = "Normal"; | |||
| } | |||
| var element = this.GetOrCreate_pPr(); | |||
| var styleElement = element.Element(XName.Get("pStyle", DocX.w.NamespaceName)); | |||
| if (styleElement == null) | |||
| { | |||
| element.Add(new XElement(XName.Get("pStyle", DocX.w.NamespaceName))); | |||
| styleElement = element.Element(XName.Get("pStyle", DocX.w.NamespaceName)); | |||
| } | |||
| styleElement.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), value); | |||
| } | |||
| styleElement.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), value); | |||
| } | |||
| } | |||
| // A collection of field type DocProperty. | |||
| @@ -212,8 +277,10 @@ namespace Novacode | |||
| get { return docProperties; } | |||
| } | |||
| internal Paragraph(DocX document, XElement xml, int startIndex):base(document, xml) | |||
| { | |||
| internal Paragraph(DocX document, XElement xml, int startIndex, ContainerType parent = ContainerType.None) | |||
| : base(document, xml) | |||
| { | |||
| ParentContainer = parent; | |||
| this.startIndex = startIndex; | |||
| this.endIndex = startIndex + GetElementTextLength(xml); | |||
| @@ -316,9 +383,9 @@ namespace Novacode | |||
| /// </code> | |||
| /// </example> | |||
| /// </summary> | |||
| public Direction Direction | |||
| public Direction Direction | |||
| { | |||
| get | |||
| get | |||
| { | |||
| XElement pPr = GetOrCreate_pPr(); | |||
| XElement bidi = pPr.Element(XName.Get("bidi", DocX.w.NamespaceName)); | |||
| @@ -339,7 +406,7 @@ namespace Novacode | |||
| if (direction == Direction.RightToLeft) | |||
| { | |||
| if(bidi == null) | |||
| if (bidi == null) | |||
| pPr.Add(new XElement(XName.Get("bidi", DocX.w.NamespaceName))); | |||
| } | |||
| @@ -413,12 +480,12 @@ namespace Novacode | |||
| /// } | |||
| /// </code> | |||
| /// </example> | |||
| public float IndentationFirstLine | |||
| public float IndentationFirstLine | |||
| { | |||
| get | |||
| get | |||
| { | |||
| XElement pPr = GetOrCreate_pPr(); | |||
| XElement ind = GetOrCreate_pPr_ind(); | |||
| XElement ind = GetOrCreate_pPr_ind(); | |||
| XAttribute firstLine = ind.Attribute(XName.Get("firstLine", DocX.w.NamespaceName)); | |||
| if (firstLine != null) | |||
| @@ -426,7 +493,7 @@ namespace Novacode | |||
| return 0.0f; | |||
| } | |||
| set | |||
| { | |||
| if (IndentationFirstLine != value) | |||
| @@ -435,7 +502,7 @@ namespace Novacode | |||
| XElement pPr = GetOrCreate_pPr(); | |||
| XElement ind = GetOrCreate_pPr_ind(); | |||
| // Paragraph can either be firstLine or hanging (Remove hanging). | |||
| XAttribute hanging = ind.Attribute(XName.Get("hanging", DocX.w.NamespaceName)); | |||
| if (hanging != null) | |||
| @@ -446,7 +513,7 @@ namespace Novacode | |||
| if (firstLine != null) | |||
| firstLine.Value = indentation; | |||
| else | |||
| ind.Add(new XAttribute(XName.Get("firstLine", DocX.w.NamespaceName), indentation)); | |||
| ind.Add(new XAttribute(XName.Get("firstLine", DocX.w.NamespaceName), indentation)); | |||
| } | |||
| } | |||
| } | |||
| @@ -474,10 +541,10 @@ namespace Novacode | |||
| /// </example> | |||
| public float IndentationHanging | |||
| { | |||
| get | |||
| get | |||
| { | |||
| XElement pPr = GetOrCreate_pPr(); | |||
| XElement ind = GetOrCreate_pPr_ind(); | |||
| XElement ind = GetOrCreate_pPr_ind(); | |||
| XAttribute hanging = ind.Attribute(XName.Get("hanging", DocX.w.NamespaceName)); | |||
| if (hanging != null) | |||
| @@ -494,7 +561,7 @@ namespace Novacode | |||
| XElement pPr = GetOrCreate_pPr(); | |||
| XElement ind = GetOrCreate_pPr_ind(); | |||
| // Paragraph can either be firstLine or hanging (Remove firstLine). | |||
| XAttribute firstLine = ind.Attribute(XName.Get("firstLine", DocX.w.NamespaceName)); | |||
| if (firstLine != null) | |||
| @@ -531,7 +598,7 @@ namespace Novacode | |||
| ///} | |||
| /// </code> | |||
| /// </example> | |||
| public float IndentationBefore | |||
| public float IndentationBefore | |||
| { | |||
| get | |||
| { | |||
| @@ -544,7 +611,7 @@ namespace Novacode | |||
| return 0.0f; | |||
| } | |||
| set | |||
| { | |||
| if (IndentationBefore != value) | |||
| @@ -557,7 +624,7 @@ namespace Novacode | |||
| string indentation = ((indentationBefore / 0.1) * 57).ToString(); | |||
| XAttribute left = ind.Attribute(XName.Get("left", DocX.w.NamespaceName)); | |||
| if(left != null) | |||
| if (left != null) | |||
| left.Value = indentation; | |||
| else | |||
| ind.Add(new XAttribute(XName.Get("left", DocX.w.NamespaceName), indentation)); | |||
| @@ -916,7 +983,7 @@ namespace Novacode | |||
| /// This function was added by Brian Campbell aka chickendelicious on Jun 16 2010 | |||
| /// Thank you Brian. | |||
| /// --> | |||
| public Paragraph InsertHyperlink(Hyperlink h, int index = 0) | |||
| public Paragraph InsertHyperlink(Hyperlink h, int index = 0) | |||
| { | |||
| // Convert the path of this mainPart to its equilivant rels file path. | |||
| string path = mainPart.Uri.OriginalString.Replace("/word/", ""); | |||
| @@ -976,7 +1043,7 @@ namespace Novacode | |||
| h_xml.SetAttributeValue(DocX.r + "id", Id); | |||
| } | |||
| return this; | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| @@ -1183,14 +1250,14 @@ namespace Novacode | |||
| /// <summary> | |||
| /// Gets or set this Paragraphs text alignment. | |||
| /// </summary> | |||
| public Alignment Alignment | |||
| { | |||
| get | |||
| { | |||
| public Alignment Alignment | |||
| { | |||
| get | |||
| { | |||
| XElement pPr = GetOrCreate_pPr(); | |||
| XElement jc = pPr.Element(XName.Get("jc", DocX.w.NamespaceName)); | |||
| if(jc != null) | |||
| if (jc != null) | |||
| { | |||
| XAttribute a = jc.Attribute(XName.Get("val", DocX.w.NamespaceName)); | |||
| @@ -1202,11 +1269,11 @@ namespace Novacode | |||
| case "both": return Novacode.Alignment.both; | |||
| } | |||
| } | |||
| return Novacode.Alignment.left; | |||
| } | |||
| set | |||
| set | |||
| { | |||
| alignment = value; | |||
| @@ -1215,7 +1282,7 @@ namespace Novacode | |||
| if (alignment != Novacode.Alignment.left) | |||
| { | |||
| if(jc == null) | |||
| if (jc == null) | |||
| pPr.Add(new XElement(XName.Get("jc", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), alignment.ToString()))); | |||
| else | |||
| jc.Attribute(XName.Get("val", DocX.w.NamespaceName)).Value = alignment.ToString(); | |||
| @@ -1223,10 +1290,10 @@ namespace Novacode | |||
| else | |||
| { | |||
| if (jc != null) | |||
| jc.Remove(); | |||
| if (jc != null) | |||
| jc.Remove(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /// <summary> | |||
| @@ -1258,7 +1325,7 @@ namespace Novacode | |||
| List<XElement> elements = Xml.Elements().ToList(); | |||
| List<XElement> temp = new List<XElement>(); | |||
| for (int i = 0; i < elements.Count(); i++ ) | |||
| for (int i = 0; i < elements.Count(); i++) | |||
| { | |||
| XElement e = elements[i]; | |||
| @@ -1279,7 +1346,7 @@ namespace Novacode | |||
| } | |||
| if (temp.Count() > 0) | |||
| Xml.Add(CreateEdit(EditType.del, now, temp)); | |||
| Xml.Add(CreateEdit(EditType.del, now, temp)); | |||
| } | |||
| else | |||
| @@ -1317,7 +1384,16 @@ namespace Novacode | |||
| // Returns the underlying XElement's Value property. | |||
| get | |||
| { | |||
| try | |||
| { | |||
| return HelperFunctions.GetFormattedText(Xml); | |||
| } | |||
| catch (Exception) | |||
| { | |||
| return null; | |||
| } | |||
| } | |||
| } | |||
| @@ -1489,7 +1565,7 @@ namespace Novacode | |||
| /// <param name="descr">The description of this Picture.</param> | |||
| static internal Picture CreatePicture(DocX document, string id, string name, string descr) | |||
| { | |||
| PackagePart part = document.package.GetPart(document.mainPart.GetRelationship(id).TargetUri); | |||
| PackagePart part = document.package.GetPart(document.mainPart.GetRelationship(id).TargetUri); | |||
| int cx, cy; | |||
| @@ -1501,7 +1577,7 @@ namespace Novacode | |||
| XElement e = new XElement(DocX.w + "drawing"); | |||
| XElement xml = XElement.Parse | |||
| XElement xml = XElement.Parse | |||
| (string.Format(@" | |||
| <drawing xmlns = ""http://schemas.openxmlformats.org/wordprocessingml/2006/main""> | |||
| <wp:inline distT=""0"" distB=""0"" distL=""0"" distR=""0"" xmlns:wp=""http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing""> | |||
| @@ -1564,14 +1640,14 @@ namespace Novacode | |||
| { | |||
| if (o is XElement) | |||
| { | |||
| XElement e = (o as XElement); | |||
| IEnumerable<XElement> ts = e.DescendantsAndSelf(XName.Get("t", DocX.w.NamespaceName)); | |||
| for(int i = 0; i < ts.Count(); i ++) | |||
| { | |||
| XElement text = ts.ElementAt(i); | |||
| text.ReplaceWith(new XElement(DocX.w + "delText", text.Attributes(), text.Value)); | |||
| } | |||
| XElement e = (o as XElement); | |||
| IEnumerable<XElement> ts = e.DescendantsAndSelf(XName.Get("t", DocX.w.NamespaceName)); | |||
| for (int i = 0; i < ts.Count(); i++) | |||
| { | |||
| XElement text = ts.ElementAt(i); | |||
| text.ReplaceWith(new XElement(DocX.w + "delText", text.Attributes(), text.Value)); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1662,7 +1738,7 @@ namespace Novacode | |||
| Run run = GetFirstRunEffectedByEdit(index, type); | |||
| XElement[] splitRun = Run.SplitRun(run, index, type); | |||
| XElement splitLeft = new XElement(edit.Name, edit.Attributes(), run.Xml.ElementsBeforeSelf(), splitRun[0]); | |||
| if (GetElementTextLength(splitLeft) == 0) | |||
| splitLeft = null; | |||
| @@ -1804,15 +1880,15 @@ namespace Novacode | |||
| /// <param name="value">The System.String to insert.</param> | |||
| /// <param name="trackChanges">Flag this insert as a change.</param> | |||
| /// <param name="formatting">The text formatting.</param> | |||
| public void InsertText(int index, string value, bool trackChanges=false, Formatting formatting = null) | |||
| { | |||
| public void InsertText(int index, string value, bool trackChanges = false, Formatting formatting = null) | |||
| { | |||
| // Timestamp to mark the start of insert | |||
| DateTime now = DateTime.Now; | |||
| DateTime insert_datetime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, DateTimeKind.Utc); | |||
| // Get the first run effected by this Insert | |||
| Run run = GetFirstRunEffectedByEdit(index); | |||
| if (run == null) | |||
| { | |||
| object insert; | |||
| @@ -1820,7 +1896,7 @@ namespace Novacode | |||
| insert = HelperFunctions.FormatInput(value, formatting.Xml); | |||
| else | |||
| insert = HelperFunctions.FormatInput(value, null); | |||
| if (trackChanges) | |||
| insert = CreateEdit(EditType.ins, insert_datetime, insert); | |||
| Xml.Add(insert); | |||
| @@ -2040,8 +2116,8 @@ namespace Novacode | |||
| this.runs = Xml.Elements().Last().Elements(XName.Get("r", DocX.w.NamespaceName)).ToList(); | |||
| return this; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Add an image to a document, create a custom view of that image (picture) and then insert it into a Paragraph using append. | |||
| /// </summary> | |||
| @@ -2395,6 +2471,16 @@ namespace Novacode | |||
| return; | |||
| } | |||
| var contentIsListOfFontProperties = false; | |||
| var fontProps = content as IEnumerable; | |||
| if (fontProps != null) | |||
| { | |||
| foreach (object property in fontProps) | |||
| { | |||
| contentIsListOfFontProperties = (property as XAttribute != null); | |||
| } | |||
| } | |||
| foreach (XElement run in runs) | |||
| { | |||
| rPr = run.Element(XName.Get("rPr", DocX.w.NamespaceName)); | |||
| @@ -2407,6 +2493,22 @@ namespace Novacode | |||
| rPr.SetElementValue(textFormatPropName, value); | |||
| XElement last = rPr.Elements().Last(); | |||
| if (contentIsListOfFontProperties) //if content is a list of attributes, as in the case when specifying a font family | |||
| { | |||
| foreach (object property in fontProps) | |||
| { | |||
| if (last.Attribute(((System.Xml.Linq.XAttribute) (property)).Name) == null) | |||
| { | |||
| last.Add(property); //Add this attribute if element doesn't have it | |||
| } | |||
| else | |||
| { | |||
| last.Attribute(((System.Xml.Linq.XAttribute) (property)).Name).Value = | |||
| ((System.Xml.Linq.XAttribute) (property)).Value; //Apply value only if element already has it | |||
| } | |||
| } | |||
| } | |||
| if (content as System.Xml.Linq.XAttribute != null)//If content is an attribute | |||
| { | |||
| if (last.Attribute(((System.Xml.Linq.XAttribute)(content)).Name) == null) | |||
| @@ -2551,20 +2653,20 @@ namespace Novacode | |||
| private Table followingTable; | |||
| ///<summary> | |||
| /// Returns table following the paragraph. Null if the following element isn't table. | |||
| ///</summary> | |||
| public Table FollowingTable | |||
| { | |||
| get | |||
| { | |||
| return followingTable; | |||
| } | |||
| internal set | |||
| ///<summary> | |||
| /// Returns table following the paragraph. Null if the following element isn't table. | |||
| ///</summary> | |||
| public Table FollowingTable | |||
| { | |||
| followingTable = value; | |||
| get | |||
| { | |||
| return followingTable; | |||
| } | |||
| internal set | |||
| { | |||
| followingTable = value; | |||
| } | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// For use with Append() and AppendLine() | |||
| @@ -2599,7 +2701,7 @@ namespace Novacode | |||
| else | |||
| 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("szCs", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), fontSize * 2)); | |||
| @@ -2671,16 +2773,16 @@ namespace Novacode | |||
| /// </example> | |||
| public Paragraph CapsStyle(CapsStyle capsStyle) | |||
| { | |||
| switch(capsStyle) | |||
| switch (capsStyle) | |||
| { | |||
| case Novacode.CapsStyle.none: | |||
| break; | |||
| default: | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get(capsStyle.ToString(), DocX.w.NamespaceName), string.Empty, null); | |||
| break; | |||
| } | |||
| default: | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get(capsStyle.ToString(), DocX.w.NamespaceName), string.Empty, null); | |||
| break; | |||
| } | |||
| } | |||
| return this; | |||
| @@ -2717,10 +2819,10 @@ namespace Novacode | |||
| break; | |||
| default: | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get("vertAlign", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), script.ToString())); | |||
| break; | |||
| } | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get("vertAlign", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), script.ToString())); | |||
| break; | |||
| } | |||
| } | |||
| return this; | |||
| @@ -2757,10 +2859,10 @@ namespace Novacode | |||
| break; | |||
| default: | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get("highlight", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), highlight.ToString())); | |||
| break; | |||
| } | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get("highlight", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), highlight.ToString())); | |||
| break; | |||
| } | |||
| } | |||
| return this; | |||
| @@ -2797,26 +2899,26 @@ namespace Novacode | |||
| break; | |||
| case Novacode.Misc.outlineShadow: | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get("outline", DocX.w.NamespaceName), string.Empty, null); | |||
| ApplyTextFormattingProperty(XName.Get("shadow", DocX.w.NamespaceName), string.Empty, null); | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get("outline", DocX.w.NamespaceName), string.Empty, null); | |||
| ApplyTextFormattingProperty(XName.Get("shadow", DocX.w.NamespaceName), string.Empty, null); | |||
| break; | |||
| } | |||
| break; | |||
| } | |||
| case Novacode.Misc.engrave: | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get("imprint", DocX.w.NamespaceName), string.Empty, null); | |||
| break; | |||
| } | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get("imprint", DocX.w.NamespaceName), string.Empty, null); | |||
| break; | |||
| } | |||
| default: | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get(misc.ToString(), DocX.w.NamespaceName), string.Empty, null); | |||
| break; | |||
| } | |||
| { | |||
| ApplyTextFormattingProperty(XName.Get(misc.ToString(), DocX.w.NamespaceName), string.Empty, null); | |||
| break; | |||
| } | |||
| } | |||
| return this; | |||
| @@ -2856,7 +2958,7 @@ namespace Novacode | |||
| } | |||
| ApplyTextFormattingProperty(XName.Get(value, DocX.w.NamespaceName), string.Empty, null); | |||
| return this; | |||
| } | |||
| @@ -2904,7 +3006,7 @@ namespace Novacode | |||
| u.SetAttributeValue(XName.Get("color", DocX.w.NamespaceName), underlineColor.ToHex()); | |||
| } | |||
| return this; | |||
| } | |||
| @@ -2937,17 +3039,17 @@ namespace Novacode | |||
| return this; | |||
| } | |||
| public float LineSpacing | |||
| public float LineSpacing | |||
| { | |||
| get | |||
| { | |||
| XElement pPr = GetOrCreate_pPr(); | |||
| XElement spacing = pPr.Element(XName.Get("spacing", DocX.w.NamespaceName)); | |||
| if(spacing != null) | |||
| if (spacing != null) | |||
| { | |||
| XAttribute line = spacing.Attribute(XName.Get("line", DocX.w.NamespaceName)); | |||
| if(line != null) | |||
| if (line != null) | |||
| { | |||
| float f; | |||
| @@ -2972,14 +3074,14 @@ namespace Novacode | |||
| if (spacing - (int)spacing == 0) | |||
| { | |||
| if (!(spacing > -1585 && spacing < 1585)) | |||
| throw new ArgumentException("Spacing", "Value must be in the range: -1584 - 1584"); | |||
| throw new ArgumentException("Spacing", "Value must be in the range: -1584 - 1584"); | |||
| } | |||
| else | |||
| throw new ArgumentException("Spacing", "Value must be either a whole or acurate to one decimal, examples: 32, 32.1, 32.2, 32.9"); | |||
| ApplyTextFormattingProperty(XName.Get("spacing", DocX.w.NamespaceName), string.Empty, new XAttribute(XName.Get("val", DocX.w.NamespaceName), spacing)); | |||
| return this; | |||
| } | |||
| @@ -3206,10 +3308,10 @@ namespace Novacode | |||
| XElement temp = SplitEdit(splitEditBefore[1], index + min, EditType.del)[0]; | |||
| object middle = CreateEdit(EditType.del, remove_datetime, temp.Elements()); | |||
| processed += GetElementTextLength(middle as XElement); | |||
| if (!trackChanges) | |||
| middle = null; | |||
| parentElement.ReplaceWith | |||
| ( | |||
| splitEditBefore[0], | |||
| @@ -3243,7 +3345,7 @@ namespace Novacode | |||
| object middle = CreateEdit(EditType.del, remove_datetime, new List<XElement>() { Run.SplitRun(new Run(Document, splitRunBefore[1], run.StartIndex + GetElementTextLength(splitRunBefore[0])), min, EditType.del)[0] }); | |||
| processed += GetElementTextLength(middle as XElement); | |||
| if (!trackChanges) | |||
| middle = null; | |||
| @@ -3379,7 +3481,7 @@ namespace Novacode | |||
| { | |||
| // Get the next run effected | |||
| Run run = GetFirstRunEffectedByEdit(m.Index + processed); | |||
| // Get this runs properties | |||
| XElement rPr = run.Xml.Element(XName.Get("rPr", DocX.w.NamespaceName)); | |||
| @@ -3403,7 +3505,7 @@ namespace Novacode | |||
| } | |||
| // If the formatting matches, do the replace. | |||
| if(formattingMatch) | |||
| if (formattingMatch) | |||
| { | |||
| InsertText(m.Index + oldValue.Length, newValue, trackChanges, newFormatting); | |||
| RemoveText(m.Index, m.Length, trackChanges); | |||
| @@ -3640,8 +3742,8 @@ namespace Novacode | |||
| public void AppendPageNumber(PageNumberFormat pnf) | |||
| { | |||
| XElement fldSimple = new XElement(XName.Get("fldSimple", DocX.w.NamespaceName)); | |||
| if(pnf == PageNumberFormat.normal) | |||
| if (pnf == PageNumberFormat.normal) | |||
| fldSimple.Add(new XAttribute(XName.Get("instr", DocX.w.NamespaceName), @" PAGE \* MERGEFORMAT ")); | |||
| else | |||
| fldSimple.Add(new XAttribute(XName.Get("instr", DocX.w.NamespaceName), @" PAGE \* ROMAN \* MERGEFORMAT ")); | |||
| @@ -3787,8 +3889,8 @@ namespace Novacode | |||
| Xml.Add(fldSimple); | |||
| } | |||
| public float LineSpacingBefore | |||
| { | |||
| public float LineSpacingBefore | |||
| { | |||
| get | |||
| { | |||
| XElement pPr = GetOrCreate_pPr(); | |||
| @@ -3808,11 +3910,11 @@ namespace Novacode | |||
| return 0.0f; | |||
| } | |||
| set | |||
| { | |||
| SpacingBefore(value); | |||
| } | |||
| } | |||
| } | |||
| public float LineSpacingAfter | |||
| @@ -15,7 +15,7 @@ using System.Runtime.InteropServices; | |||
| [assembly: AssemblyCulture("")] | |||
| // Allow the UnitTests to get at internal stuff. | |||
| [assembly: InternalsVisibleTo("UnitTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001006385bc4fde8d1ddaabf50fca5a7c9fd10cbdc792f9b026945c563221f2799649a4271852f7c2dab8259f8c907e1f45e1643369c85584a8b16cc4763992f897797dd57b03a176f76f507f472075a0026c05f90ff99234a3eec16b1c98bbc987d1b67893a7af1d5b980d5b901a8b8c2665cb4a79eb63e2f897c94d8c1b9ac488ac")] | |||
| [assembly: InternalsVisibleTo("UnitTests")] | |||
| // Setting ComVisible to false makes the types in this assembly not visible | |||
| // to COM components. If you need to access a type in this assembly from | |||
| @@ -8,7 +8,7 @@ | |||
| <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||
| <SchemaVersion>2.0</SchemaVersion> | |||
| <ProjectGuid>{1eb1ee8f-9978-425b-a742-533dcceb4811}</ProjectGuid> | |||
| <SHFBSchemaVersion>1.9.3.0</SHFBSchemaVersion> | |||
| <SHFBSchemaVersion>1.9.5.0</SHFBSchemaVersion> | |||
| <!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual | |||
| Studio adds them anyway --> | |||
| <AssemblyName>Documentation</AssemblyName> | |||
| @@ -20,7 +20,7 @@ | |||
| <Language>en-US</Language> | |||
| <HelpFileFormat>HtmlHelp1</HelpFileFormat> | |||
| <IndentHtml>False</IndentHtml> | |||
| <FrameworkVersion>.NET 4.0.30319</FrameworkVersion> | |||
| <FrameworkVersion>.NET Framework 3.5</FrameworkVersion> | |||
| <KeepLogFile>True</KeepLogFile> | |||
| <DisableCodeBlockComponent>False</DisableCodeBlockComponent> | |||
| <CppCommentsFixup>False</CppCommentsFixup> | |||
| @@ -43,6 +43,15 @@ | |||
| <SccAuxPath>SAK</SccAuxPath> | |||
| <SccLocalPath>SAK</SccLocalPath> | |||
| <WorkingPath>%temp%\</WorkingPath> | |||
| <ApiFilter /> | |||
| <ComponentConfigurations /> | |||
| <HelpAttributes /> | |||
| <NamespaceSummaries /> | |||
| <PlugInConfigurations /> | |||
| <BuildLogFile /> | |||
| <HtmlHelp1xCompilerPath /> | |||
| <HtmlHelp2xCompilerPath /> | |||
| <SandcastlePath /> | |||
| </PropertyGroup> | |||
| <!-- There are no properties for these groups. AnyCPU needs to appear in | |||
| order for Visual Studio to perform the build. The others are optional | |||
| @@ -1,20 +1,20 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using Novacode; | |||
| using System.Data; | |||
| using System.Drawing; | |||
| using System.IO; | |||
| using System.Drawing.Imaging; | |||
| using System.IO; | |||
| using System.Linq; | |||
| using System.Threading.Tasks; | |||
| using System.Data; | |||
| using Novacode; | |||
| namespace Examples | |||
| { | |||
| class Program | |||
| { | |||
| static void Main(string[] args) | |||
| { | |||
| { | |||
| Setup(); | |||
| // Easy | |||
| Console.WriteLine("\nRunning Easy Examples"); | |||
| HelloWorld(); | |||
| @@ -23,6 +23,7 @@ namespace Examples | |||
| HeadersAndFooters(); | |||
| HyperlinksImagesTables(); | |||
| AddList(); | |||
| Equations(); | |||
| @@ -44,6 +45,14 @@ namespace Examples | |||
| Console.ReadKey(); | |||
| } | |||
| private static void Setup() | |||
| { | |||
| if (!Directory.Exists("docs")) | |||
| { | |||
| Directory.CreateDirectory("docs"); | |||
| } | |||
| } | |||
| #region Charts | |||
| private class ChartData | |||
| @@ -316,6 +325,31 @@ namespace Examples | |||
| Console.WriteLine("\tCreated: docs\\HyperlinksImagesTables.docx\n"); | |||
| } | |||
| } | |||
| private static void AddList() | |||
| { | |||
| Console.WriteLine("\tAddList()"); | |||
| using (var document = DocX.Create(@"docs\Lists.docx")) | |||
| { | |||
| var numberedList = document.AddList("First List Item.", 0, ListItemType.Numbered, 2); | |||
| document.AddListItem(numberedList, "First sub list item", 1); | |||
| document.AddListItem(numberedList, "Second List Item."); | |||
| document.AddListItem(numberedList, "Third list item."); | |||
| document.AddListItem(numberedList, "Nested item.", 1); | |||
| document.AddListItem(numberedList, "Second nested item.", 1); | |||
| var bulletedList = document.AddList("First Bulleted Item.", 0, ListItemType.Bulleted); | |||
| document.AddListItem(bulletedList, "Second bullet item"); | |||
| document.AddListItem(bulletedList, "Sub bullet item", 1); | |||
| document.AddListItem(bulletedList, "Second sub bullet item", 1); | |||
| document.AddListItem(bulletedList, "Third bullet item"); | |||
| document.InsertList(numberedList); | |||
| document.InsertList(bulletedList); | |||
| document.Save(); | |||
| Console.WriteLine("\tCreated: docs\\Lists.docx"); | |||
| } | |||
| } | |||
| private static void HeadersAndFooters() | |||
| { | |||
| @@ -386,6 +420,20 @@ namespace Examples | |||
| Paragraph p8 = document.InsertParagraph(); | |||
| p8.AppendLine("Hello Third page."); | |||
| //Insert a next page break, which is a section break combined with a page break | |||
| document.InsertSectionPageBreak(); | |||
| //Insert a paragraph after the "Next" page break | |||
| Paragraph p9 = document.InsertParagraph(); | |||
| p9.Append("Next page section break."); | |||
| //Insert a continuous section break | |||
| document.InsertSection(); | |||
| //Create a paragraph in the new section | |||
| var p10 = document.InsertParagraph(); | |||
| p10.Append("Continuous section paragraph."); | |||
| // Save all changes to this document. | |||
| document.Save(); | |||
| @@ -812,7 +860,6 @@ namespace Examples | |||
| // Save this Bitmap back into the document using a Create\Write stream. | |||
| b.Save(img.GetStream(FileMode.Create, FileAccess.Write), ImageFormat.Png); | |||
| } | |||
| else | |||
| Console.WriteLine("The provided document contains no Images."); | |||
| @@ -37,10 +37,11 @@ | |||
| <WarningLevel>4</WarningLevel> | |||
| </PropertyGroup> | |||
| <PropertyGroup> | |||
| <SignAssembly>true</SignAssembly> | |||
| <SignAssembly>false</SignAssembly> | |||
| </PropertyGroup> | |||
| <PropertyGroup> | |||
| <AssemblyOriginatorKeyFile>StrongNameKey.pfx</AssemblyOriginatorKeyFile> | |||
| <AssemblyOriginatorKeyFile> | |||
| </AssemblyOriginatorKeyFile> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> | |||
| @@ -63,17 +64,24 @@ | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Compile Include="Properties\AssemblyInfo.cs" /> | |||
| <Compile Include="UnitTest1.cs" /> | |||
| <Compile Include="DocXUnitTests.cs" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <None Include="documents\EverybodyHasAHome.docx" /> | |||
| <None Include="documents\Hyperlinks.docx" /> | |||
| <None Include="documents\Images.docx" /> | |||
| <None Include="documents\MovePicture.docx" /> | |||
| <None Include="documents\Paragraphs.docx" /> | |||
| <None Include="documents\ReplaceTests.docx" /> | |||
| <None Include="documents\Tables.docx" /> | |||
| <None Include="documents\Template.dotx" /> | |||
| <None Include="StrongNameKey.pfx" /> | |||
| <None Include="documents\testdoc_OrderedList.docx" /> | |||
| <None Include="documents\testdoc_OrderedUnorderedLists.docx" /> | |||
| <None Include="documents\testdoc_SectionsWithHeadingBreaks.docx" /> | |||
| <None Include="documents\testdoc_SectionsWithSectionBreaks.docx" /> | |||
| <None Include="documents\testdoc_SectionsWithSectionBreaksMultiParagraph.docx" /> | |||
| <None Include="documents\testdoc_UnorderedList.docx" /> | |||
| <None Include="documents\TestParent.docx" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Content Include="documents\green.jpg" /> | |||