Parcourir la source

Cathal: Added DocX (HeaderText & FooterText) properties

Cathal: Added overloads to ReplaceText for Format checking and replacement.

Joel: Added Row.MergeCells
Joel: Added Row.Height property
Joel: Added Cell.Width property

A huge thanks to Joel: The first user to submit working & tested functions\properties for inclusion in DocX.
master
coffeycathal_cp il y a 16 ans
Parent
révision
c01d8d428e
8 fichiers modifiés avec 613 ajouts et 26 suppressions
  1. 36
    0
      ConsoleApplication1/Properties/AssemblyInfo.cs
  2. 4
    1
      DocX.sln
  3. 10
    0
      DocX.vssscc
  4. 147
    16
      DocX/DocX.cs
  5. 1
    0
      DocX/Enumerations.cs
  6. 165
    6
      DocX/Paragraph.cs
  7. 1
    1
      DocX/Run.cs
  8. 249
    2
      DocX/Table.cs

+ 36
- 0
ConsoleApplication1/Properties/AssemblyInfo.cs Voir le fichier

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ConsoleApplication1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft IT")]
[assembly: AssemblyProduct("ConsoleApplication1")]
[assembly: AssemblyCopyright("Copyright © Microsoft IT 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 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
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("69b4f03f-dc03-4e14-923d-6fd03ea8ff0c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

+ 4
- 1
DocX.sln Voir le fichier

@@ -7,13 +7,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Global
GlobalSection(TeamFoundationVersionControl) = preSolution
SccNumberOfProjects = 2
SccNumberOfProjects = 3
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
SccTeamFoundationServer = https://tfs08.codeplex.com/
SccLocalPath0 = .
SccProjectUniqueName1 = DocX\\DocX.csproj
SccProjectName1 = DocX
SccLocalPath1 = DocX
SccProjectUniqueName2 = ConsoleApplication1\\ConsoleApplication1.csproj
SccProjectName2 = ConsoleApplication1
SccLocalPath2 = ConsoleApplication1
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU

+ 10
- 0
DocX.vssscc Voir le fichier

@@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
}

+ 147
- 16
DocX/DocX.cs Voir le fichier

@@ -410,17 +410,14 @@ namespace Novacode
foreach (Paragraph p in paragraphs)
{
MatchCollection mc = Regex.Matches(p.Text, Regex.Escape(str), options);
var query =
(
from m in mc.Cast<Match>()
select m.Index + p.startIndex
).ToList();
List<int> indexes = p.FindAll(str, options);
list.AddRange(query);
for (int i = 0; i < indexes.Count(); i++)
indexes[0] += p.startIndex;
list.AddRange(indexes);
}
return list;
}
@@ -456,6 +453,67 @@ namespace Novacode
}
}
internal string GetCollectiveText(List<PackagePart> list)
{
string text = string.Empty;
foreach (var hp in list)
{
using (TextReader tr = new StreamReader(hp.GetStream()))
{
XDocument d = XDocument.Load(tr);
StringBuilder sb = new StringBuilder();
// Loop through each text item in this run
foreach (XElement descendant in d.Descendants())
{
switch (descendant.Name.LocalName)
{
case "tab":
sb.Append("\t");
break;
case "br":
sb.Append("\n");
break;
case "t":
goto case "delText";
case "delText":
sb.Append(descendant.Value);
break;
default: break;
}
}
text += "\n" + sb.ToString();
}
}
return text;
}
/// <summary>
/// Gets the concatenated text of all header files in this document.
/// </summary>
public string HeaderText
{
get
{
return GetCollectiveText(headers);
}
}
/// <summary>
/// Gets the concatenated text of all footer files in this document.
/// </summary>
public string FooterText
{
get
{
return GetCollectiveText(footers);
}
}
/// <summary>
/// Insert the contents of another document at the end of this document.
/// </summary>
@@ -498,7 +556,7 @@ namespace Novacode
external_elements = internal_body.Elements().Reverse().TakeWhile((i, j) => j < count);
#endregion
#region /word/settings.xml
#region /word/styles.xml
Uri word_styles_Uri = new Uri("/word/styles.xml", UriKind.Relative);
// If the external document has a styles.xml, we need to insert its elements into the internal documents styles.xml.
@@ -698,7 +756,30 @@ namespace Novacode
{
return InsertParagraph(index, text, trackChanges, null);
}
/// <summary>
/// Insert a new Paragraph at the end of this document.
/// </summary>
/// <returns>A new Paragraph.</returns>
/// <example>
/// Inserting a new Paragraph at the end of a document.
/// <code>
/// // Load a document.
/// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
/// {
/// // Insert a new Paragraph at the end of this document.
/// document.InsertParagraph();
///
/// // Save all changes made to this document.
/// document.Save();
/// }// Release this document from memory
/// </code>
/// </example>
public Paragraph InsertParagraph()
{
return InsertParagraph(string.Empty, false);
}
/// <summary>
/// Insert a Paragraph into this document, this Paragraph may have come from the same or another document.
/// </summary>
@@ -2206,7 +2287,7 @@ namespace Novacode
/// <param name="options">RegexOptions to use for this text replace.</param>
public void ReplaceText(string oldValue, string newValue, bool trackChanges, RegexOptions options)
{
ReplaceText(oldValue, newValue, false, false, trackChanges, options);
ReplaceText(oldValue, newValue, false, false, trackChanges, options, null, null, MatchFormattingOptions.SubsetMatch);
}
/// <summary>
@@ -2233,9 +2314,59 @@ namespace Novacode
/// <param name="trackChanges">Should this change be tracked?</param>
/// <param name="options">RegexOptions to use for this text replace.</param>
public void ReplaceText(string oldValue, string newValue, bool includeHeaders, bool includeFooters, bool trackChanges, RegexOptions options)
{
ReplaceText(oldValue, newValue, includeHeaders, includeFooters, trackChanges, options, null, null, MatchFormattingOptions.SubsetMatch);
}
/// <summary>
/// Replace text in this document, ignore case, include the headers and footers.
/// </summary>
/// <example>
/// Replace every instance of "old" in this document with "new".
/// <code>
/// // Load a document.
/// using (DocX document = DocX.Load(@"Test.docx"))
/// {
/// // The formatting to match.
/// Formatting matchFormatting = new Formatting();
/// matchFormatting.Size = 10;
/// matchFormatting.Italic = true;
/// matchFormatting.FontFamily = new FontFamily("Times New Roman");
///
/// // The formatting to apply to the inserted text.
/// Formatting newFormatting = new Formatting();
/// newFormatting.Size = 22;
/// newFormatting.UnderlineStyle = UnderlineStyle.dotted;
/// newFormatting.Bold = true;
///
/// /*
/// * Replace all instances of the string "old" with the string "new", include both the header and footer and ignore case.
/// * Each inserted instance of "new" should use the Formatting newFormatting.
/// * Only replace an instance of "old" if it is Size 10, Italic and Times New Roman.
/// * SubsetMatch means that the formatting must contain all elements of the match formatting,
/// * but it can also contain additional formatting for example Color, UnderlineStyle, etc.
/// * ExactMatch means it must not contain additional formatting.
/// */
/// document.ReplaceText("old", "new", true, true, false, RegexOptions.IgnoreCase, newFormatting, matchFormatting, MatchFormattingOptions.SubsetMatch);
///
/// // Save all changes made to this document.
/// document.Save();
/// }// Release this document from memory.
/// </code>
/// </example>
/// <param name="oldValue">The text to replace.</param>
/// <param name="newValue">The new text to insert.</param>
/// <param name="includeHeaders">Should ReplaceText include text in the headers?</param>
/// <param name="includeFooters">Should ReplaceText include text in the footers?</param>
/// <param name="trackChanges">Should this change be tracked?</param>
/// <param name="options">RegexOptions to use for this text replace.</param>
/// <param name="newFormatting">The formatting to apply to the text being inserted.</param>
/// <param name="matchFormatting">The formatting that the text must match in order to be replaced.</param>
/// <param name="fo">How should formatting be matched?</param>
public void ReplaceText(string oldValue, string newValue, bool includeHeaders, bool includeFooters, bool trackChanges, RegexOptions options, Formatting newFormatting, Formatting matchFormatting, MatchFormattingOptions fo)
{
foreach (Paragraph p in paragraphs)
p.ReplaceText(oldValue, newValue, trackChanges, options);
p.ReplaceText(oldValue, newValue, trackChanges, options, newFormatting, matchFormatting, fo);
#region Headers & Footers
List<PackagePart> headerAndFooters = new List<PackagePart>();
@@ -2258,13 +2389,13 @@ namespace Novacode
foreach (Paragraph p in paras)
{
p.ReplaceText(oldValue, newValue, trackChanges, options);
p.ReplaceText(oldValue, newValue, trackChanges, options, newFormatting, matchFormatting, fo);
}
}
using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create)))
d.Save(tw);
}
}
#endregion
}
@@ -2318,7 +2449,7 @@ namespace Novacode
/// <param name="trackChanges">Should this change be tracked?</param>
public void ReplaceText(string oldValue, string newValue, bool includeHeaders, bool includeFooters, bool trackChanges)
{
ReplaceText(oldValue, newValue, includeHeaders, includeFooters, trackChanges);
ReplaceText(oldValue, newValue, includeHeaders, includeFooters, trackChanges, RegexOptions.None, null, null, MatchFormattingOptions.SubsetMatch);
}
#region IDisposable Members

+ 1
- 0
DocX/Enumerations.cs Voir le fichier

@@ -5,6 +5,7 @@ using System.Text;
namespace Novacode
{
public enum MatchFormattingOptions { ExactMatch, SubsetMatch};
public enum Script { superscript, subscript, none }
public enum Highlight { yellow, green, cyan, magenta, blue, red, darkBlue, darkCyan, darkGreen, darkMagenta, darkRed, darkYellow, darkGray, lightGray, black, none };
public enum UnderlineStyle { none, singleLine, doubleLine, thick, dotted, dottedHeavy, dash, dashedHeavy, dashLong, dashLongHeavy, dotDash, dashDotHeavy, dotDotDash, dashDotDotHeavy, wave, wavyHeavy, wavyDouble, words };

+ 165
- 6
DocX/Paragraph.cs Voir le fichier

@@ -86,9 +86,10 @@ namespace Novacode
(
from d in styles_element.Descendants()
let styleId = d.Attribute(XName.Get("styleId", DocX.w.NamespaceName))
where styleId != null && styleId.Value == id
let type = d.Attribute(XName.Get("type", DocX.w.NamespaceName))
where type != null && type.Value == "paragraph" && styleId != null && styleId.Value == id
select d
).Single();
).First();
styles.Add(style);
}
@@ -1697,15 +1698,173 @@ namespace Novacode
/// <param name="options">A bitwise OR combination of RegexOption enumeration options.</param>
/// <param name="trackChanges">Track changes</param>
public void ReplaceText(string oldValue, string newValue, bool trackChanges, RegexOptions options)
{
ReplaceText(oldValue, newValue, trackChanges, options, null, null, MatchFormattingOptions.SubsetMatch);
}
/// <summary>
/// Replaces all occurrences of a specified System.String in this instance, with another specified System.String.
/// </summary>
/// <example>
/// <code>
/// // Create a document using a relative filename.
/// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
/// {
/// // The formatting to apply to the inserted text.
/// Formatting newFormatting = new Formatting();
/// newFormatting.Size = 22;
/// newFormatting.UnderlineStyle = UnderlineStyle.dotted;
/// newFormatting.Bold = true;
///
/// // Iterate through the paragraphs in this document.
/// foreach (Paragraph p in document.Paragraphs)
/// {
/// /*
/// * Replace all instances of the string "wrong" with the string "right" and ignore case.
/// * Each inserted instance of "wrong" should use the Formatting newFormatting.
/// */
/// p.ReplaceText("wrong", "right", false, RegexOptions.IgnoreCase, newFormatting);
/// }
///
/// // Save all changes made to this document.
/// document.Save();
/// }// Release this document from memory.
/// </code>
/// </example>
/// <seealso cref="Paragraph.RemoveText(int, int, bool)"/>
/// <seealso cref="Paragraph.RemoveText(int, bool)"/>
/// <seealso cref="Paragraph.InsertText(string, bool)"/>
/// <seealso cref="Paragraph.InsertText(int, string, bool)"/>
/// <seealso cref="Paragraph.InsertText(int, string, bool, Formatting)"/>
/// <seealso cref="Paragraph.InsertText(string, bool, Formatting)"/>
/// <param name="newValue">A System.String to replace all occurances of oldValue.</param>
/// <param name="oldValue">A System.String to be replaced.</param>
/// <param name="options">A bitwise OR combination of RegexOption enumeration options.</param>
/// <param name="trackChanges">Track changes</param>
/// <param name="newFormatting">The formatting to apply to the text being inserted.</param>
public void ReplaceText(string oldValue, string newValue, bool trackChanges, RegexOptions options, Formatting newFormatting)
{
ReplaceText(oldValue, newValue, trackChanges, options, null, null, MatchFormattingOptions.SubsetMatch);
}
/// <summary>
/// Replaces all occurrences of a specified System.String in this instance, with another specified System.String.
/// </summary>
/// <example>
/// <code>
/// // Load a document using a relative filename.
/// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
/// {
/// // The formatting to match.
/// Formatting matchFormatting = new Formatting();
/// matchFormatting.Size = 10;
/// matchFormatting.Italic = true;
/// matchFormatting.FontFamily = new FontFamily("Times New Roman");
///
/// // The formatting to apply to the inserted text.
/// Formatting newFormatting = new Formatting();
/// newFormatting.Size = 22;
/// newFormatting.UnderlineStyle = UnderlineStyle.dotted;
/// newFormatting.Bold = true;
///
/// // Iterate through the paragraphs in this document.
/// foreach (Paragraph p in document.Paragraphs)
/// {
/// /*
/// * Replace all instances of the string "wrong" with the string "right" and ignore case.
/// * Each inserted instance of "wrong" should use the Formatting newFormatting.
/// * Only replace an instance of "wrong" if it is Size 10, Italic and Times New Roman.
/// * SubsetMatch means that the formatting must contain all elements of the match formatting,
/// * but it can also contain additional formatting for example Color, UnderlineStyle, etc.
/// * ExactMatch means it must not contain additional formatting.
/// */
/// p.ReplaceText("wrong", "right", false, RegexOptions.IgnoreCase, newFormatting, matchFormatting, MatchFormattingOptions.SubsetMatch);
/// }
///
/// // Save all changes made to this document.
/// document.Save();
/// }// Release this document from memory.
/// </code>
/// </example>
/// <seealso cref="Paragraph.RemoveText(int, int, bool)"/>
/// <seealso cref="Paragraph.RemoveText(int, bool)"/>
/// <seealso cref="Paragraph.InsertText(string, bool)"/>
/// <seealso cref="Paragraph.InsertText(int, string, bool)"/>
/// <seealso cref="Paragraph.InsertText(int, string, bool, Formatting)"/>
/// <seealso cref="Paragraph.InsertText(string, bool, Formatting)"/>
/// <param name="newValue">A System.String to replace all occurances of oldValue.</param>
/// <param name="oldValue">A System.String to be replaced.</param>
/// <param name="options">A bitwise OR combination of RegexOption enumeration options.</param>
/// <param name="trackChanges">Track changes</param>
/// <param name="newFormatting">The formatting to apply to the text being inserted.</param>
/// <param name="matchFormatting">The formatting that the text must match in order to be replaced.</param>
/// <param name="fo">How should formatting be matched?</param>
public void ReplaceText(string oldValue, string newValue, bool trackChanges, RegexOptions options, Formatting newFormatting, Formatting matchFormatting, MatchFormattingOptions fo)
{
MatchCollection mc = Regex.Matches(this.Text, Regex.Escape(oldValue), options);
// Loop through the matches in reverse order
foreach (Match m in mc.Cast<Match>().Reverse())
{
InsertText(m.Index + oldValue.Length, newValue, trackChanges);
RemoveText(m.Index, m.Length, trackChanges);
// Assume the formatting matches until proven otherwise.
bool formattingMatch = true;
// Does the user want to match formatting?
if (matchFormatting != null)
{
// The number of characters processed so far
int processed = 0;
do
{
// 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));
if (rPr == null)
rPr = new Formatting().Xml;
/*
* Make sure that every formatting element in f.xml is also in this run,
* if this is not true, then their formatting does not match.
*/
if (!ContainsEveryChildOf(matchFormatting.Xml, rPr, fo))
{
formattingMatch = false;
break;
}
// We have processed some characters, so update the counter.
processed += run.Value.Length;
} while (processed < m.Length);
}
// If the formatting matches, do the replace.
if(formattingMatch)
{
InsertText(m.Index + oldValue.Length, newValue, trackChanges, newFormatting);
RemoveText(m.Index, m.Length, trackChanges);
}
}
}
internal bool ContainsEveryChildOf(XElement a, XElement b, MatchFormattingOptions fo)
{
foreach (XElement e in a.Elements())
{
// If a formatting property has the same name and value, its considered to be equivalent.
if (!b.Elements(e.Name).Where(bElement => bElement.Value == e.Value).Any())
return false;
}
// If the formatting has to be exact, no additionaly formatting must exist.
if (fo == MatchFormattingOptions.ExactMatch)
return a.Elements().Count() == b.Elements().Count();
return true;
}
/// <summary>
@@ -1826,7 +1985,7 @@ namespace Novacode
/// <param name="trackChanges">Track changes</param>
public void ReplaceText(string oldValue, string newValue, bool trackChanges)
{
ReplaceText(oldValue, newValue, trackChanges, RegexOptions.None);
ReplaceText(oldValue, newValue, trackChanges, RegexOptions.None, null, null, MatchFormattingOptions.SubsetMatch);
}
}
}

+ 1
- 1
DocX/Run.cs Voir le fichier

@@ -29,7 +29,7 @@ namespace Novacode
/// <summary>
/// The text value of this text element
/// </summary>
private string Value { set { value = text; } get { return text; } }
internal string Value { set { value = text; } get { return text; } }
internal Run(int startIndex, XElement xml)
{

+ 249
- 2
DocX/Table.cs Voir le fichier

@@ -13,7 +13,7 @@ namespace Novacode
/// <summary>
/// Designs\Styles that can be applied to a table.
/// </summary>
public enum TableDesign { TableNormal, TableGrid, LightShading, LightShadingAccent1, LightShadingAccent2, LightShadingAccent3, LightShadingAccent4, LightShadingAccent5, LightShadingAccent6, LightList, LightListAccent1, LightListAccent2, LightListAccent3, LightListAccent4, LightListAccent5, LightListAccent6, LightGrid, LightGridAccent1, LightGridAccent2, LightGridAccent3, LightGridAccent4, LightGridAccent5, LightGridAccent6, MediumShading1, MediumShading1Accent1, MediumShading1Accent2, MediumShading1Accent3, MediumShading1Accent4, MediumShading1Accent5, MediumShading1Accent6, MediumShading2, MediumShading2Accent1, MediumShading2Accent2, MediumShading2Accent3, MediumShading2Accent4, MediumShading2Accent5, MediumShading2Accent6, MediumList1, MediumList1Accent1, MediumList1Accent2, MediumList1Accent3, MediumList1Accent4, MediumList1Accent5, MediumList1Accent6, MediumList2, MediumList2Accent1, MediumList2Accent2, MediumList2Accent3, MediumList2Accent4, MediumList2Accent5, MediumList2Accent6, MediumGrid1, MediumGrid1Accent1, MediumGrid1Accent2, MediumGrid1Accent3, MediumGrid1Accent4, MediumGrid1Accent5, MediumGrid1Accent6, MediumGrid2, MediumGrid2Accent1, MediumGrid2Accent2, MediumGrid2Accent3, MediumGrid2Accent4, MediumGrid2Accent5, MediumGrid2Accent6, MediumGrid3, MediumGrid3Accent1, MediumGrid3Accent2, MediumGrid3Accent3, MediumGrid3Accent4, MediumGrid3Accent5, MediumGrid3Accent6, DarkList, DarkListAccent1, DarkListAccent2, DarkListAccent3, DarkListAccent4, DarkListAccent5, DarkListAccent6, ColorfulShading, ColorfulShadingAccent1, ColorfulShadingAccent2, ColorfulShadingAccent3, ColorfulShadingAccent4, ColorfulShadingAccent5, ColorfulShadingAccent6, ColorfulList, ColorfulListAccent1, ColorfulListAccent2, ColorfulListAccent3, ColorfulListAccent4, ColorfulListAccent5, ColorfulListAccent6, ColorfulGrid, ColorfulGridAccent1, ColorfulGridAccent2, ColorfulGridAccent3, ColorfulGridAccent4, ColorfulGridAccent5, ColorfulGridAccent6, None};
public enum TableDesign { Custom, TableNormal, TableGrid, LightShading, LightShadingAccent1, LightShadingAccent2, LightShadingAccent3, LightShadingAccent4, LightShadingAccent5, LightShadingAccent6, LightList, LightListAccent1, LightListAccent2, LightListAccent3, LightListAccent4, LightListAccent5, LightListAccent6, LightGrid, LightGridAccent1, LightGridAccent2, LightGridAccent3, LightGridAccent4, LightGridAccent5, LightGridAccent6, MediumShading1, MediumShading1Accent1, MediumShading1Accent2, MediumShading1Accent3, MediumShading1Accent4, MediumShading1Accent5, MediumShading1Accent6, MediumShading2, MediumShading2Accent1, MediumShading2Accent2, MediumShading2Accent3, MediumShading2Accent4, MediumShading2Accent5, MediumShading2Accent6, MediumList1, MediumList1Accent1, MediumList1Accent2, MediumList1Accent3, MediumList1Accent4, MediumList1Accent5, MediumList1Accent6, MediumList2, MediumList2Accent1, MediumList2Accent2, MediumList2Accent3, MediumList2Accent4, MediumList2Accent5, MediumList2Accent6, MediumGrid1, MediumGrid1Accent1, MediumGrid1Accent2, MediumGrid1Accent3, MediumGrid1Accent4, MediumGrid1Accent5, MediumGrid1Accent6, MediumGrid2, MediumGrid2Accent1, MediumGrid2Accent2, MediumGrid2Accent3, MediumGrid2Accent4, MediumGrid2Accent5, MediumGrid2Accent6, MediumGrid3, MediumGrid3Accent1, MediumGrid3Accent2, MediumGrid3Accent3, MediumGrid3Accent4, MediumGrid3Accent5, MediumGrid3Accent6, DarkList, DarkListAccent1, DarkListAccent2, DarkListAccent3, DarkListAccent4, DarkListAccent5, DarkListAccent6, ColorfulShading, ColorfulShadingAccent1, ColorfulShadingAccent2, ColorfulShadingAccent3, ColorfulShadingAccent4, ColorfulShadingAccent5, ColorfulShadingAccent6, ColorfulList, ColorfulListAccent1, ColorfulListAccent2, ColorfulListAccent3, ColorfulListAccent4, ColorfulListAccent5, ColorfulListAccent6, ColorfulGrid, ColorfulGridAccent1, ColorfulGridAccent2, ColorfulGridAccent3, ColorfulGridAccent4, ColorfulGridAccent5, ColorfulGridAccent6, None};
public enum AutoFit{Contents, Window, ColoumnWidth};
/// <summary>
@@ -67,7 +67,17 @@ namespace Novacode
XAttribute val = style.Attribute(XName.Get("val", DocX.w.NamespaceName));
if (val != null)
design = (TableDesign)Enum.Parse(typeof(TableDesign), val.Value.Replace("-", string.Empty));
{
try
{
design = (TableDesign)Enum.Parse(typeof(TableDesign), val.Value.Replace("-", string.Empty));
}
catch (Exception e)
{
design = TableDesign.Custom;
}
}
else
design = TableDesign.None;
}
@@ -1262,6 +1272,165 @@ namespace Novacode
cells = (from c in xml.Elements(XName.Get("tc", DocX.w.NamespaceName))
select new Cell(document, c)).ToList();
}
/// <summary>
/// Height in pixels. // Added by Joel, refactored by Cathal.
/// </summary>
public double Height
{
get
{
/*
* Get the trPr (table row properties) element for this Row,
* null will be return if no such element exists.
*/
XElement trPr = xml.Element(XName.Get("trPr", DocX.w.NamespaceName));
// If trPr is null, this row contains no height information.
if(trPr == null)
return double.NaN;
/*
* Get the trHeight element for this Row,
* null will be return if no such element exists.
*/
XElement trHeight = trPr.Element(XName.Get("trHeight", DocX.w.NamespaceName));
// If trHeight is null, this row contains no height information.
if (trHeight == null)
return double.NaN;
// Get the val attribute for this trHeight element.
XAttribute val = trHeight.Attribute(XName.Get("val", DocX.w.NamespaceName));
// If w is null, this cell contains no width information.
if (val == null)
return double.NaN;
// If val is not a double, something is wrong with this attributes value, so remove it and return double.NaN;
double heightInWordUnits;
if (!double.TryParse(val.Value, out heightInWordUnits))
{
val.Remove();
return double.NaN;
}
// 15 "word units" in one pixel
return (heightInWordUnits / 15);
}
set
{
/*
* Get the trPr (table row properties) element for this Row,
* null will be return if no such element exists.
*/
XElement trPr = xml.Element(XName.Get("trPr", DocX.w.NamespaceName));
if (trPr == null)
{
xml.SetElementValue(XName.Get("trPr", DocX.w.NamespaceName), string.Empty);
trPr = xml.Element(XName.Get("trPr", DocX.w.NamespaceName));
}
/*
* Get the trHeight element for this Row,
* null will be return if no such element exists.
*/
XElement trHeight = trPr.Element(XName.Get("trHeight", DocX.w.NamespaceName));
if (trHeight == null)
{
trPr.SetElementValue(XName.Get("trHeight", DocX.w.NamespaceName), string.Empty);
trHeight = trPr.Element(XName.Get("trHeight", DocX.w.NamespaceName));
}
// The hRule attribute needs to be set to exact.
trHeight.SetAttributeValue(XName.Get("hRule", DocX.w.NamespaceName), "exact");
// 15 "word units" is equal to one pixel.
trHeight.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), (value * 15).ToString());
}
}
/// <summary>
/// Merge cells starting with startIndex and ending with endIndex.
/// </summary>
public void MergeCells(int startIndex, int endIndex)
{
// Check for valid start and end indexes.
if (startIndex < 0 || endIndex <= startIndex || endIndex > Cells.Count + 1)
throw new IndexOutOfRangeException();
// The sum of all merged gridSpans.
int gridSpanSum = 0;
// Foreach each Cell between startIndex and endIndex inclusive.
foreach (Cell c in cells.Where((z, i) => i > startIndex && i <= endIndex))
{
XElement tcPr = c.xml.Element(XName.Get("tcPr", DocX.w.NamespaceName));
if (tcPr != null)
{
XElement gridSpan = tcPr.Element(XName.Get("gridSpan", DocX.w.NamespaceName));
if (gridSpan != null)
{
XAttribute val = gridSpan.Attribute(XName.Get("val", DocX.w.NamespaceName));
int value = 0;
if (val != null)
if (int.TryParse(val.Value, out value))
gridSpanSum += value - 1;
}
}
// Add this cells Pragraph to the merge start Cell.
cells[startIndex].xml.Add(c.xml.Elements(XName.Get("p", DocX.w.NamespaceName)));
// Remove this Cell.
c.xml.Remove();
}
/*
* Get the tcPr (table cell properties) element for the first cell in this merge,
* null will be returned if no such element exists.
*/
XElement start_tcPr = cells[startIndex].xml.Element(XName.Get("tcPr", DocX.w.NamespaceName));
if (start_tcPr == null)
{
cells[startIndex].xml.SetElementValue(XName.Get("tcPr", DocX.w.NamespaceName), string.Empty);
start_tcPr = cells[startIndex].xml.Element(XName.Get("tcPr", DocX.w.NamespaceName));
}
/*
* Get the gridSpan element of this row,
* null will be returned if no such element exists.
*/
XElement start_gridSpan = start_tcPr.Element(XName.Get("gridSpan", DocX.w.NamespaceName));
if (start_gridSpan == null)
{
start_tcPr.SetElementValue(XName.Get("gridSpan", DocX.w.NamespaceName), string.Empty);
start_gridSpan = start_tcPr.Element(XName.Get("gridSpan", DocX.w.NamespaceName));
}
/*
* Get the val attribute of this row,
* null will be returned if no such element exists.
*/
XAttribute start_val = start_gridSpan.Attribute(XName.Get("val", DocX.w.NamespaceName));
int start_value = 0;
if (start_val != null)
if (int.TryParse(start_val.Value, out start_value))
gridSpanSum += start_value - 1;
// Set the val attribute to the number of merged cells.
start_gridSpan.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), (gridSpanSum + (endIndex - startIndex + 1)).ToString());
// Rebuild the cells collection.
cells =
(
from c in xml.Elements(XName.Get("tc", DocX.w.NamespaceName))
select new Cell(document, c)
).ToList();
}
}
public class Cell
@@ -1285,5 +1454,83 @@ namespace Novacode
p = new Paragraph(document, 0, xml.Element(XName.Get("p", DocX.w.NamespaceName)));
}
/// <summary>
/// Width in pixels. // Added by Joel, refactored by Cathal
/// </summary>
public double Width
{
get
{
/*
* Get the tcPr (table cell properties) element for this Cell,
* null will be return if no such element exists.
*/
XElement tcPr = xml.Element(XName.Get("tcPr", DocX.w.NamespaceName));
// If tcPr is null, this cell contains no width information.
if (tcPr == null)
return double.NaN;
/*
* Get the tcW (table cell width) element for this Cell,
* null will be return if no such element exists.
*/
XElement tcW = tcPr.Element(XName.Get("tcW", DocX.w.NamespaceName));
// If tcW is null, this cell contains no width information.
if (tcW == null)
return double.NaN;
// Get the w attribute of the tcW element.
XAttribute w = tcW.Attribute(XName.Get("w", DocX.w.NamespaceName));
// If w is null, this cell contains no width information.
if (w == null)
return double.NaN;
// If w is not a double, something is wrong with this attributes value, so remove it and return double.NaN;
double widthInWordUnits;
if (!double.TryParse(w.Value, out widthInWordUnits))
{
w.Remove();
return double.NaN;
}
// 15 "word units" is equal to one pixel.
return (widthInWordUnits / 15);
}
set
{
/*
* Get the tcPr (table cell properties) element for this Cell,
* null will be return if no such element exists.
*/
XElement tcPr = xml.Element(XName.Get("tcPr", DocX.w.NamespaceName));
if (tcPr == null)
{
xml.SetElementValue(XName.Get("tcPr", DocX.w.NamespaceName), string.Empty);
tcPr = xml.Element(XName.Get("tcPr", DocX.w.NamespaceName));
}
/*
* Get the tcW (table cell width) element for this Cell,
* null will be return if no such element exists.
*/
XElement tcW = tcPr.Element(XName.Get("tcW", DocX.w.NamespaceName));
if (tcW == null)
{
tcPr.SetElementValue(XName.Get("tcW", DocX.w.NamespaceName), string.Empty);
tcW = tcPr.Element(XName.Get("tcW", DocX.w.NamespaceName));
}
// The type attribute needs to be set to dxa which represents "twips" or twentieths of a point. In other words, 1/1440th of an inch.
tcW.SetAttributeValue(XName.Get("type", DocX.w.NamespaceName), "dxa");
// 15 "word units" is equal to one pixel.
tcW.SetAttributeValue(XName.Get("w", DocX.w.NamespaceName), (value * 15).ToString());
}
}
}
}

Chargement…
Annuler
Enregistrer