| <WarningLevel>4</WarningLevel> | <WarningLevel>4</WarningLevel> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <Reference Include="DocX, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
| <SpecificVersion>False</SpecificVersion> | |||||
| <HintPath>..\DocX\bin\Debug\DocX.dll</HintPath> | |||||
| </Reference> | |||||
| <Reference Include="System" /> | <Reference Include="System" /> | ||||
| <Reference Include="System.Core"> | <Reference Include="System.Core"> | ||||
| <RequiredTargetFramework>3.5</RequiredTargetFramework> | <RequiredTargetFramework>3.5</RequiredTargetFramework> | ||||
| <CopyToOutputDirectory>Always</CopyToOutputDirectory> | <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
| </None> | </None> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | |||||
| <ProjectReference Include="..\DocX\DocX.csproj"> | |||||
| <Project>{E863D072-AA8B-4108-B5F1-785241B37F67}</Project> | |||||
| <Name>DocX</Name> | |||||
| </ProjectReference> | |||||
| </ItemGroup> | |||||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||||
| <!-- To modify your build process, add your task inside one of the targets below and uncomment it. | <!-- 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. | Other similar extension points exist, see Microsoft.Common.targets. |
| EndProject | EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomPropertyTestApp", "CustomPropertyTestApp\CustomPropertyTestApp.csproj", "{9EABCAA8-175C-4FA2-9829-59E9D9E275D3}" | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomPropertyTestApp", "CustomPropertyTestApp\CustomPropertyTestApp.csproj", "{9EABCAA8-175C-4FA2-9829-59E9D9E275D3}" | ||||
| EndProject | EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreateDocumentOnTheFly", "CreateDocumentOnTheFly\CreateDocumentOnTheFly.csproj", "{40E089B2-BFE4-4E47-83CC-36A4D43269C4}" | |||||
| EndProject | |||||
| Global | Global | ||||
| GlobalSection(TeamFoundationVersionControl) = preSolution | GlobalSection(TeamFoundationVersionControl) = preSolution | ||||
| SccNumberOfProjects = 5 | SccNumberOfProjects = 5 | ||||
| {9EABCAA8-175C-4FA2-9829-59E9D9E275D3}.Debug|Any CPU.Build.0 = Debug|Any CPU | {9EABCAA8-175C-4FA2-9829-59E9D9E275D3}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {9EABCAA8-175C-4FA2-9829-59E9D9E275D3}.Release|Any CPU.ActiveCfg = Release|Any CPU | {9EABCAA8-175C-4FA2-9829-59E9D9E275D3}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {9EABCAA8-175C-4FA2-9829-59E9D9E275D3}.Release|Any CPU.Build.0 = Release|Any CPU | {9EABCAA8-175C-4FA2-9829-59E9D9E275D3}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {40E089B2-BFE4-4E47-83CC-36A4D43269C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {40E089B2-BFE4-4E47-83CC-36A4D43269C4}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {40E089B2-BFE4-4E47-83CC-36A4D43269C4}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {40E089B2-BFE4-4E47-83CC-36A4D43269C4}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| EndGlobalSection | EndGlobalSection | ||||
| GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
| HideSolutionNode = FALSE | HideSolutionNode = FALSE |
| get { return customProperties; } | get { return customProperties; } | ||||
| } | } | ||||
| public Paragraph AddParagraph() | |||||
| { | |||||
| XElement newParagraph = new XElement(w + "p"); | |||||
| mainDoc.Descendants(XName.Get("body", "http://schemas.openxmlformats.org/wordprocessingml/2006/main")).Single().Add(newParagraph); | |||||
| // Get all of the paragraphs in this document | |||||
| DocX.paragraphs = from p in mainDoc.Descendants(XName.Get("p", "http://schemas.openxmlformats.org/wordprocessingml/2006/main")) | |||||
| select new Paragraph(p); | |||||
| return new Paragraph(newParagraph); | |||||
| } | |||||
| public static DocX Create(string uri) | |||||
| { | |||||
| FileInfo fi = new FileInfo(uri); | |||||
| if (fi.Extension != ".docx") | |||||
| throw new Exception(string.Format("The input file {0} is not a .docx file", fi.FullName)); | |||||
| DocX.uri = uri; | |||||
| // Create the docx package | |||||
| wdDoc = WordprocessingDocument.Create(uri, DocumentFormat.OpenXml.WordprocessingDocumentType.Document); | |||||
| #region MainDocumentPart | |||||
| // Create the main document part for this package | |||||
| mainDocumentPart = wdDoc.AddMainDocumentPart(); | |||||
| // Load the document part into a XDocument object | |||||
| using (TextReader tr = new StreamReader(mainDocumentPart.GetStream(FileMode.Create, FileAccess.ReadWrite))) | |||||
| { | |||||
| mainDoc = XDocument.Parse | |||||
| (@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?> | |||||
| <w:document xmlns:ve=""http://schemas.openxmlformats.org/markup-compatibility/2006"" xmlns:o=""urn:schemas-microsoft-com:office:office"" xmlns:r=""http://schemas.openxmlformats.org/officeDocument/2006/relationships"" xmlns:m=""http://schemas.openxmlformats.org/officeDocument/2006/math"" xmlns:v=""urn:schemas-microsoft-com:vml"" xmlns:wp=""http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"" xmlns:w10=""urn:schemas-microsoft-com:office:word"" xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"" xmlns:wne=""http://schemas.microsoft.com/office/word/2006/wordml""> | |||||
| <w:body> | |||||
| <w:sectPr w:rsidR=""003E25F4"" w:rsidSect=""00FC3028""> | |||||
| <w:pgSz w:w=""11906"" w:h=""16838""/> | |||||
| <w:pgMar w:top=""1440"" w:right=""1440"" w:bottom=""1440"" w:left=""1440"" w:header=""708"" w:footer=""708"" w:gutter=""0""/> | |||||
| <w:cols w:space=""708""/> | |||||
| <w:docGrid w:linePitch=""360""/> | |||||
| </w:sectPr> | |||||
| </w:body> | |||||
| </w:document>" | |||||
| ); | |||||
| } | |||||
| // Get all of the paragraphs in this document | |||||
| DocX.paragraphs = from p in mainDoc.Descendants(XName.Get("p", "http://schemas.openxmlformats.org/wordprocessingml/2006/main")) | |||||
| select new Paragraph(p); | |||||
| #endregion | |||||
| #region CustomFilePropertiesPart | |||||
| // Get the custom file properties part from the package | |||||
| customPropertiesPart = wdDoc.CustomFilePropertiesPart; | |||||
| // This docx contains a customFilePropertyPart | |||||
| if (customPropertiesPart != null) | |||||
| { | |||||
| // Load the customFilePropertyPart | |||||
| using (TextReader tr = new StreamReader(customPropertiesPart.GetStream(FileMode.Open, FileAccess.Read))) | |||||
| { | |||||
| customPropDoc = XDocument.Load(tr, LoadOptions.PreserveWhitespace); | |||||
| } | |||||
| // Get all of the custom properties in this document | |||||
| DocX.customProperties = from cp in customPropDoc.Descendants(XName.Get("property", customPropertiesSchema.NamespaceName)) | |||||
| select new CustomProperty(cp); | |||||
| } | |||||
| #endregion | |||||
| // Save the new docx file to disk and return | |||||
| DocX created = new DocX(); | |||||
| created.Save(); | |||||
| return created; | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// Loads a .docx file into a DocX object. | /// Loads a .docx file into a DocX object. | ||||
| /// </summary> | /// </summary> | ||||
| /// <summary> | /// <summary> | ||||
| /// Renumber all ins and del ids in this .docx file. | /// Renumber all ins and del ids in this .docx file. | ||||
| /// </summary> | /// </summary> | ||||
| private static void RenumberIDs() | |||||
| internal static void RenumberIDs() | |||||
| { | { | ||||
| IEnumerable<XAttribute> trackerIDs = | IEnumerable<XAttribute> trackerIDs = | ||||
| (from d in mainDoc.Descendants() | (from d in mainDoc.Descendants() |
| <Reference Include="System.Core"> | <Reference Include="System.Core"> | ||||
| <RequiredTargetFramework>3.5</RequiredTargetFramework> | <RequiredTargetFramework>3.5</RequiredTargetFramework> | ||||
| </Reference> | </Reference> | ||||
| <Reference Include="System.Drawing" /> | |||||
| <Reference Include="System.XML" /> | <Reference Include="System.XML" /> | ||||
| <Reference Include="System.Xml.Linq"> | <Reference Include="System.Xml.Linq"> | ||||
| <RequiredTargetFramework>3.5</RequiredTargetFramework> | <RequiredTargetFramework>3.5</RequiredTargetFramework> | ||||
| <RequiredTargetFramework>3.5</RequiredTargetFramework> | <RequiredTargetFramework>3.5</RequiredTargetFramework> | ||||
| </Reference> | </Reference> | ||||
| <Reference Include="System.Data" /> | <Reference Include="System.Data" /> | ||||
| <Reference Include="WindowsBase"> | |||||
| <RequiredTargetFramework>3.0</RequiredTargetFramework> | |||||
| </Reference> | |||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <Compile Include="CustomProperty.cs" /> | <Compile Include="CustomProperty.cs" /> | ||||
| <Compile Include="Enumerations.cs" /> | <Compile Include="Enumerations.cs" /> | ||||
| <Compile Include="Extensions.cs" /> | |||||
| <Compile Include="Formatting.cs" /> | |||||
| <Compile Include="Paragraph.cs" /> | <Compile Include="Paragraph.cs" /> | ||||
| <Compile Include="DocX.cs" /> | <Compile Include="DocX.cs" /> | ||||
| <Compile Include="Properties\AssemblyInfo.cs" /> | <Compile Include="Properties\AssemblyInfo.cs" /> |
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using System.Drawing; | |||||
| namespace Novacode | |||||
| { | |||||
| public static class Extensions | |||||
| { | |||||
| public static string ToHex(this Color source) | |||||
| { | |||||
| byte red = source.R; | |||||
| byte green = source.G; | |||||
| byte blue = source.B; | |||||
| string redHex = red.ToString("X"); | |||||
| if (redHex.Length < 2) | |||||
| redHex = "0" + redHex; | |||||
| string blueHex = blue.ToString("X"); | |||||
| if (blueHex.Length < 2) | |||||
| blueHex = "0" + blueHex; | |||||
| string greenHex = green.ToString("X"); | |||||
| if (greenHex.Length < 2) | |||||
| greenHex = "0" + greenHex; | |||||
| return string.Format("{0}{1}{2}", redHex, greenHex, blueHex); | |||||
| } | |||||
| } | |||||
| } |
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using System.Xml.Linq; | |||||
| using System.Drawing; | |||||
| namespace Novacode | |||||
| { | |||||
| 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}; | |||||
| public enum StrickThrough { none, strike, doubleStrike }; | |||||
| public enum Misc { none, shadow, outline, outlineShadow, emboss, engrave}; | |||||
| public enum CapsStyle { none, caps, smallCaps }; | |||||
| public class Formatting | |||||
| { | |||||
| private XElement rPr; | |||||
| private bool hidden; | |||||
| private bool bold; | |||||
| private bool italic; | |||||
| private StrickThrough strikethrough; | |||||
| private Script script; | |||||
| private Highlight highlight; | |||||
| private double? size; | |||||
| private Color? fontColor; | |||||
| private Color? underlineColor; | |||||
| private UnderlineStyle underlineStyle; | |||||
| private Misc misc; | |||||
| private CapsStyle capsStyle; | |||||
| private FontFamily fontFamily; | |||||
| private int? percentageScale; | |||||
| private int? kerning; | |||||
| private int? position; | |||||
| private double? spacing; | |||||
| public Formatting() | |||||
| { | |||||
| capsStyle = CapsStyle.none; | |||||
| strikethrough = StrickThrough.none; | |||||
| script = Script.none; | |||||
| highlight = Highlight.none; | |||||
| underlineStyle = UnderlineStyle.none; | |||||
| misc = Misc.none; | |||||
| rPr = new XElement(XName.Get("rPr", DocX.w.NamespaceName)); | |||||
| } | |||||
| public XElement Xml | |||||
| { | |||||
| get | |||||
| { | |||||
| if(spacing.HasValue) | |||||
| rPr.Add(new XElement(XName.Get("spacing", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), spacing.Value * 20))); | |||||
| if(position.HasValue) | |||||
| rPr.Add(new XElement(XName.Get("position", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), position.Value * 2))); | |||||
| if (kerning.HasValue) | |||||
| rPr.Add(new XElement(XName.Get("kern", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), kerning.Value * 2))); | |||||
| if (percentageScale.HasValue) | |||||
| rPr.Add(new XElement(XName.Get("w", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), percentageScale))); | |||||
| if(fontFamily != null) | |||||
| rPr.Add(new XElement(XName.Get("rFonts", DocX.w.NamespaceName), new XAttribute(XName.Get("ascii", DocX.w.NamespaceName), fontFamily.Name))); | |||||
| if(hidden) | |||||
| rPr.Add(new XElement(XName.Get("vanish", DocX.w.NamespaceName))); | |||||
| if (bold) | |||||
| rPr.Add(new XElement(XName.Get("b", DocX.w.NamespaceName))); | |||||
| if (italic) | |||||
| rPr.Add(new XElement(XName.Get("i", DocX.w.NamespaceName))); | |||||
| switch (underlineStyle) | |||||
| { | |||||
| case UnderlineStyle.none: | |||||
| break; | |||||
| case UnderlineStyle.singleLine: | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "single"))); | |||||
| break; | |||||
| case UnderlineStyle.doubleLine: | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "double"))); | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), underlineStyle.ToString()))); | |||||
| break; | |||||
| } | |||||
| if(underlineColor.HasValue) | |||||
| { | |||||
| // If an underlineColor has been set but no underlineStyle has been set | |||||
| if (underlineStyle == UnderlineStyle.none) | |||||
| { | |||||
| // Set the underlineStyle to the default | |||||
| underlineStyle = UnderlineStyle.singleLine; | |||||
| rPr.Add(new XElement(XName.Get("u", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), "single"))); | |||||
| } | |||||
| rPr.Element(XName.Get("u", DocX.w.NamespaceName)).Add(new XAttribute(XName.Get("color", DocX.w.NamespaceName), underlineColor.Value.ToHex())); | |||||
| } | |||||
| switch (strikethrough) | |||||
| { | |||||
| case StrickThrough.none: | |||||
| break; | |||||
| case StrickThrough.strike: | |||||
| rPr.Add(new XElement(XName.Get("strike", DocX.w.NamespaceName))); | |||||
| break; | |||||
| case StrickThrough.doubleStrike: | |||||
| rPr.Add(new XElement(XName.Get("dstrike", DocX.w.NamespaceName))); | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| switch (script) | |||||
| { | |||||
| case Script.none: | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get("vertAlign", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), script.ToString()))); | |||||
| break; | |||||
| } | |||||
| if (size.HasValue) | |||||
| { | |||||
| rPr.Add(new XElement(XName.Get("sz", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), (size * 2).ToString()))); | |||||
| rPr.Add(new XElement(XName.Get("szCs", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), (size * 2).ToString()))); | |||||
| } | |||||
| if(fontColor.HasValue) | |||||
| rPr.Add(new XElement(XName.Get("color", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), fontColor.Value.ToHex()))); | |||||
| switch (highlight) | |||||
| { | |||||
| case Highlight.none: | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get("highlight", DocX.w.NamespaceName), new XAttribute(XName.Get("val", DocX.w.NamespaceName), highlight.ToString()))); | |||||
| break; | |||||
| } | |||||
| switch (capsStyle) | |||||
| { | |||||
| case CapsStyle.none: | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get(capsStyle.ToString(), DocX.w.NamespaceName))); | |||||
| break; | |||||
| } | |||||
| switch (misc) | |||||
| { | |||||
| case Misc.none: | |||||
| break; | |||||
| case Misc.outlineShadow: | |||||
| rPr.Add(new XElement(XName.Get("outline", DocX.w.NamespaceName))); | |||||
| rPr.Add(new XElement(XName.Get("shadow", DocX.w.NamespaceName))); | |||||
| break; | |||||
| case Misc.engrave: | |||||
| rPr.Add(new XElement(XName.Get("imprint", DocX.w.NamespaceName))); | |||||
| break; | |||||
| default: | |||||
| rPr.Add(new XElement(XName.Get(misc.ToString(), DocX.w.NamespaceName))); | |||||
| break; | |||||
| } | |||||
| return rPr; | |||||
| } | |||||
| } | |||||
| public bool Bold { get { return bold; } set { bold = value;} } | |||||
| public bool Italic { get { return Italic; } set { italic = value; } } | |||||
| public StrickThrough StrikeThrough { get { return strikethrough; } set { strikethrough = value; } } | |||||
| public Script Script { get { return script; } set { script = value; } } | |||||
| public double? Size | |||||
| { | |||||
| get { return size; } | |||||
| set | |||||
| { | |||||
| double? temp = value * 2; | |||||
| if (temp - (int)temp == 0) | |||||
| { | |||||
| if(value > 0 && value < 1639) | |||||
| size = value; | |||||
| else | |||||
| throw new ArgumentException("Size", "Value must be in the range 0 - 1638"); | |||||
| } | |||||
| else | |||||
| throw new ArgumentException("Size", "Value must be either a whole or half number, examples: 32, 32.5"); | |||||
| } | |||||
| } | |||||
| public int? PercentageScale | |||||
| { | |||||
| get { return percentageScale; } | |||||
| set | |||||
| { | |||||
| if ((new int?[] { 200, 150, 100, 90, 80, 66, 50, 33 }).Contains(value)) | |||||
| percentageScale = value; | |||||
| else | |||||
| throw new ArgumentOutOfRangeException("PercentageScale", "Value must be one of the following: 200, 150, 100, 90, 80, 66, 50 or 33"); | |||||
| } | |||||
| } | |||||
| public int? Kerning | |||||
| { | |||||
| get { return kerning; } | |||||
| set | |||||
| { | |||||
| if(new int?[] {8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72}.Contains(value)) | |||||
| kerning = value; | |||||
| else | |||||
| throw new ArgumentOutOfRangeException("Kerning", "Value must be one of the following: 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48 or 72"); | |||||
| } | |||||
| } | |||||
| public int? Position | |||||
| { | |||||
| get { return position; } | |||||
| set | |||||
| { | |||||
| if (value > -1585 && value < 1585) | |||||
| position = value; | |||||
| else | |||||
| throw new ArgumentOutOfRangeException("Position", "Value must be in the range -1585 - 1585"); | |||||
| } | |||||
| } | |||||
| public double? Spacing | |||||
| { | |||||
| get { return spacing; } | |||||
| set | |||||
| { | |||||
| double? temp = value * 20; | |||||
| if (temp - (int)temp == 0) | |||||
| { | |||||
| if (value > -1585 && value < 1585) | |||||
| spacing = value; | |||||
| else | |||||
| 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"); | |||||
| } | |||||
| } | |||||
| public Color? FontColor { get { return fontColor; } set { fontColor = value; } } | |||||
| public Highlight Highlight { get { return highlight; } set { highlight = value; } } | |||||
| public UnderlineStyle UnderlineStyle { get { return underlineStyle; } set { underlineStyle = value; } } | |||||
| public Color? UnderlineColor { get { return underlineColor; } set { underlineColor = value; } } | |||||
| public Misc Misc { get { return misc; } set { misc = value; } } | |||||
| public bool Hidden { get { return hidden; } set { hidden = value; } } | |||||
| public CapsStyle CapsStyle { get { return capsStyle; } set { capsStyle = value; } } | |||||
| public FontFamily FontFamily { get { return FontFamily; } set { fontFamily = value; } } | |||||
| } | |||||
| } |
| // Loop through each run in this paragraph | // Loop through each run in this paragraph | ||||
| foreach (XElement run in runs) | foreach (XElement run in runs) | ||||
| { | { | ||||
| Run r = new Run(startIndex, run); | |||||
| runLookup.Add(r.EndIndex, r); | |||||
| startIndex = r.EndIndex; | |||||
| // Only add runs which contain text | |||||
| if (GetElementTextLength(run) > 0) | |||||
| { | |||||
| Run r = new Run(startIndex, run); | |||||
| runLookup.Add(r.EndIndex, r); | |||||
| startIndex = r.EndIndex; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| /// <returns>The first Run that will be effected</returns> | /// <returns>The first Run that will be effected</returns> | ||||
| public Run GetFirstRunEffectedByInsert(int index) | public Run GetFirstRunEffectedByInsert(int index) | ||||
| { | { | ||||
| // This paragraph contains no Runs and insertion is at index 0 | |||||
| if (runLookup.Keys.Count() == 0 && index == 0) | |||||
| return null; | |||||
| foreach (int runEndIndex in runLookup.Keys) | foreach (int runEndIndex in runLookup.Keys) | ||||
| { | { | ||||
| if (runEndIndex >= index) | if (runEndIndex >= index) | ||||
| ); | ); | ||||
| } | } | ||||
| public void Insert(int index, string value, bool trackChanges) | |||||
| { | |||||
| Insert(index, value, null, trackChanges); | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// Inserts a specified instance of System.String into a Novacode.DocX.Paragraph at a specified index position. | /// Inserts a specified instance of System.String into a Novacode.DocX.Paragraph at a specified index position. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="index">The index position of the insertion.</param> | /// <param name="index">The index position of the insertion.</param> | ||||
| /// <param name="value">The System.String to insert.</param> | /// <param name="value">The System.String to insert.</param> | ||||
| /// <param name="trackChanges">Flag this insert as a change</param> | /// <param name="trackChanges">Flag this insert as a change</param> | ||||
| public void Insert(int index, string value, bool trackChanges) | |||||
| public void Insert(int index, string value, Formatting formatting, bool trackChanges) | |||||
| { | { | ||||
| // Timestamp to mark the start of insert | // Timestamp to mark the start of insert | ||||
| DateTime now = DateTime.Now; | DateTime now = DateTime.Now; | ||||
| // Get the first run effected by this Insert | // Get the first run effected by this Insert | ||||
| Run run = GetFirstRunEffectedByInsert(index); | Run run = GetFirstRunEffectedByInsert(index); | ||||
| // Convert value into a List of XElement's | |||||
| List<XElement> newRuns = formatInput(value, run.Xml.Element(XName.Get("rPr", DocX.w.NamespaceName))); | |||||
| if (run == null) | |||||
| { | |||||
| object insert; | |||||
| if (formatting != null) | |||||
| insert = formatInput(value, formatting.Xml); | |||||
| else | |||||
| insert = formatInput(value, null); | |||||
| if (trackChanges) | |||||
| insert = CreateEdit(EditType.ins, insert_datetime, insert); | |||||
| p.Add(insert); | |||||
| } | |||||
| // The parent of this Run | |||||
| XElement parentElement = run.Xml.Parent; | |||||
| switch (parentElement.Name.LocalName) | |||||
| else | |||||
| { | { | ||||
| case "ins": | |||||
| { | |||||
| // The datetime that this ins was created | |||||
| DateTime parent_ins_date = DateTime.Parse(parentElement.Attribute(XName.Get("date", DocX.w.NamespaceName)).Value); | |||||
| /* | |||||
| * Special case: You want to track changes, | |||||
| * and the first Run effected by this insert | |||||
| * has a datetime stamp equal to now. | |||||
| */ | |||||
| if (trackChanges && parent_ins_date.CompareTo(insert_datetime) == 0) | |||||
| object newRuns; | |||||
| if (formatting != null) | |||||
| newRuns = formatInput(value, formatting.Xml); | |||||
| else | |||||
| newRuns = formatInput(value, run.Xml.Element(XName.Get("rPr", DocX.w.NamespaceName))); | |||||
| // The parent of this Run | |||||
| XElement parentElement = run.Xml.Parent; | |||||
| switch (parentElement.Name.LocalName) | |||||
| { | |||||
| case "ins": | |||||
| { | { | ||||
| // The datetime that this ins was created | |||||
| DateTime parent_ins_date = DateTime.Parse(parentElement.Attribute(XName.Get("date", DocX.w.NamespaceName)).Value); | |||||
| /* | |||||
| * Special case: You want to track changes, | |||||
| * and the first Run effected by this insert | |||||
| * has a datetime stamp equal to now. | |||||
| */ | |||||
| if (trackChanges && parent_ins_date.CompareTo(insert_datetime) == 0) | |||||
| { | |||||
| /* | |||||
| * Inserting into a non edit and this special case, is the same procedure. | |||||
| */ | |||||
| goto default; | |||||
| } | |||||
| /* | /* | ||||
| * Inserting into a non edit and this special case, is the same procedure. | |||||
| * If not the special case above, | |||||
| * then inserting into an ins or a del, is the same procedure. | |||||
| */ | */ | ||||
| goto default; | |||||
| goto case "del"; | |||||
| } | } | ||||
| /* | |||||
| * If not the special case above, | |||||
| * then inserting into an ins or a del, is the same procedure. | |||||
| */ | |||||
| goto case "del"; | |||||
| } | |||||
| case "del": | |||||
| { | |||||
| object insert = newRuns; | |||||
| if (trackChanges) | |||||
| insert = CreateEdit(EditType.ins, insert_datetime, newRuns); | |||||
| case "del": | |||||
| { | |||||
| object insert = newRuns; | |||||
| if (trackChanges) | |||||
| insert = CreateEdit(EditType.ins, insert_datetime, newRuns); | |||||
| // Split this Edit at the point you want to insert | |||||
| XElement[] splitEdit = SplitEdit(parentElement, index, EditType.ins); | |||||
| // Replace the origional run | |||||
| parentElement.ReplaceWith | |||||
| ( | |||||
| splitEdit[0], | |||||
| insert, | |||||
| splitEdit[1] | |||||
| ); | |||||
| break; | |||||
| } | |||||
| // Split this Edit at the point you want to insert | |||||
| XElement[] splitEdit = SplitEdit(parentElement, index, EditType.ins); | |||||
| default: | |||||
| { | |||||
| object insert = newRuns; | |||||
| if (trackChanges && !parentElement.Name.LocalName.Equals("ins")) | |||||
| insert = CreateEdit(EditType.ins, insert_datetime, newRuns); | |||||
| // Split this run at the point you want to insert | |||||
| XElement[] splitRun = Run.SplitRun(run, index); | |||||
| // Replace the origional run | |||||
| run.Xml.ReplaceWith | |||||
| ( | |||||
| splitRun[0], | |||||
| insert, | |||||
| splitRun[1] | |||||
| ); | |||||
| break; | |||||
| } | |||||
| // Replace the origional run | |||||
| parentElement.ReplaceWith | |||||
| ( | |||||
| splitEdit[0], | |||||
| insert, | |||||
| splitEdit[1] | |||||
| ); | |||||
| break; | |||||
| } | |||||
| default: | |||||
| { | |||||
| object insert = newRuns; | |||||
| if (trackChanges && !parentElement.Name.LocalName.Equals("ins")) | |||||
| insert = CreateEdit(EditType.ins, insert_datetime, newRuns); | |||||
| // Split this run at the point you want to insert | |||||
| XElement[] splitRun = Run.SplitRun(run, index); | |||||
| // Replace the origional run | |||||
| run.Xml.ReplaceWith | |||||
| ( | |||||
| splitRun[0], | |||||
| insert, | |||||
| splitRun[1] | |||||
| ); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| // Rebuild the run lookup for this paragraph | // Rebuild the run lookup for this paragraph | ||||
| runLookup.Clear(); | runLookup.Clear(); | ||||
| BuildRunLookup(p); | BuildRunLookup(p); | ||||
| DocX.RenumberIDs(); | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| int min = Math.Min(count - processed, run.Xml.ElementsAfterSelf().Sum(e => GetElementTextLength(e))); | int min = Math.Min(count - processed, run.Xml.ElementsAfterSelf().Sum(e => GetElementTextLength(e))); | ||||
| XElement[] splitEditAfter = SplitEdit(parentElement, index + processed + min, EditType.del); | XElement[] splitEditAfter = SplitEdit(parentElement, index + processed + min, EditType.del); | ||||
| object middle = CreateEdit(EditType.del, remove_datetime, SplitEdit(splitEditBefore[1], min, EditType.del)[0].Descendants()); | |||||
| XElement temp = SplitEdit(splitEditBefore[1], index + processed + min, EditType.del)[0]; | |||||
| object middle = CreateEdit(EditType.del, remove_datetime, temp.Elements().ToArray()); | |||||
| processed += GetElementTextLength(middle as XElement); | processed += GetElementTextLength(middle as XElement); | ||||
| if (!trackChanges) | if (!trackChanges) | ||||
| // Rebuild the run lookup | // Rebuild the run lookup | ||||
| runLookup.Clear(); | runLookup.Clear(); | ||||
| BuildRunLookup(p); | BuildRunLookup(p); | ||||
| DocX.RenumberIDs(); | |||||
| } | } | ||||
| /// <summary> | /// <summary> |
| case "t": goto case "delText"; | case "t": goto case "delText"; | ||||
| case "delText": | case "delText": | ||||
| { | { | ||||
| textLookup.Add(start + text.Value.Length, new Text(start, text)); | |||||
| Value += text.Value; | |||||
| start += text.Value.Length; | |||||
| // Only add strings which are not empty | |||||
| if (text.Value.Length > 0) | |||||
| { | |||||
| textLookup.Add(start + text.Value.Length, new Text(start, text)); | |||||
| Value += text.Value; | |||||
| start += text.Value.Length; | |||||
| } | |||||
| break; | break; | ||||
| } | } | ||||
| default: break; | default: break; |
| using Novacode; | using Novacode; | ||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||
| using System.IO; | using System.IO; | ||||
| using System.Xml.Linq; | |||||
| namespace StringReplaceTestApp | namespace StringReplaceTestApp | ||||
| { | { |
| <WarningLevel>4</WarningLevel> | <WarningLevel>4</WarningLevel> | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <Reference Include="DocX, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
| <SpecificVersion>False</SpecificVersion> | |||||
| <HintPath>..\DocX\bin\Debug\DocX.dll</HintPath> | |||||
| </Reference> | |||||
| <Reference Include="System" /> | <Reference Include="System" /> | ||||
| <Reference Include="System.Core"> | <Reference Include="System.Core"> | ||||
| <RequiredTargetFramework>3.5</RequiredTargetFramework> | <RequiredTargetFramework>3.5</RequiredTargetFramework> | ||||
| <CopyToOutputDirectory>Always</CopyToOutputDirectory> | <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
| </None> | </None> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | |||||
| <ProjectReference Include="..\DocX\DocX.csproj"> | |||||
| <Project>{E863D072-AA8B-4108-B5F1-785241B37F67}</Project> | |||||
| <Name>DocX</Name> | |||||
| </ProjectReference> | |||||
| </ItemGroup> | |||||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||||
| <!-- To modify your build process, add your task inside one of the targets below and uncomment it. | <!-- 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. | Other similar extension points exist, see Microsoft.Common.targets. |