Преглед на файлове

Merged from GIT source code. Code provided by Randall Borck and Fainzanj

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 release
master
MadBoy_cp преди 12 години
родител
ревизия
22a1bc154a
променени са 17 файла, в които са добавени 3390 реда и са изтрити 1890 реда
  1. 2
    2
      DocX.sln
  2. 280
    10
      DocX/Container.cs
  3. 199
    31
      DocX/DocX.cs
  4. 12
    5
      DocX/DocX.csproj
  5. 3
    2
      DocX/Formatting.cs
  6. 125
    16
      DocX/HelperFunctions.cs
  7. 252
    150
      DocX/Paragraph.cs
  8. 1
    1
      DocX/Properties/AssemblyInfo.cs
  9. Двоични данни
      DocX/Resources/default_styles.xml.gz
  10. Двоични данни
      DocX/Resources/styles.xml.gz
  11. Двоични данни
      DocX/StrongNameFile.pfx
  12. 614
    385
      DocX/_Enumerations.cs
  13. 11
    2
      Documentation/Documentation.shfbproj
  14. Двоични данни
      Documentation/Help/Documentation.chm
  15. 54
    7
      Examples/Program.cs
  16. 1825
    1275
      UnitTests/DocXUnitTests.cs
  17. 12
    4
      UnitTests/UnitTests.csproj

+ 2
- 2
DocX.sln Целия файл

@@ -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

+ 280
- 10
DocX/Container.cs Целия файл

@@ -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;
}
}
}

+ 199
- 31
DocX/DocX.cs Целия файл

@@ -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>

+ 12
- 5
DocX/DocX.csproj Целия файл

@@ -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.

+ 3
- 2
DocX/Formatting.cs Целия файл

@@ -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;
}
}

+ 125
- 16
DocX/HelperFunctions.cs Целия файл

@@ -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;
}
}
}
}

+ 252
- 150
DocX/Paragraph.cs Целия файл

@@ -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

+ 1
- 1
DocX/Properties/AssemblyInfo.cs Целия файл

@@ -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

Двоични данни
DocX/Resources/default_styles.xml.gz Целия файл


Двоични данни
DocX/Resources/styles.xml.gz Целия файл


Двоични данни
DocX/StrongNameFile.pfx Целия файл


+ 614
- 385
DocX/_Enumerations.cs
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 11
- 2
Documentation/Documentation.shfbproj Целия файл

@@ -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

Двоични данни
Documentation/Help/Documentation.chm Целия файл


+ 54
- 7
Examples/Program.cs Целия файл

@@ -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.");

UnitTests/DocXUnitTests.cs
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 12
- 4
UnitTests/UnitTests.csproj Целия файл

@@ -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" />

Loading…
Отказ
Запис