| @@ -3,23 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 10.00 | |||
| # Visual Studio 2008 | |||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocX", "DocX\DocX.csproj", "{E863D072-AA8B-4108-B5F1-785241B37F67}" | |||
| EndProject | |||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{6E4A2A95-9A9A-4F8C-A68D-4950E3455700}" | |||
| ProjectSection(ProjectDependencies) = postProject | |||
| {E863D072-AA8B-4108-B5F1-785241B37F67} = {E863D072-AA8B-4108-B5F1-785241B37F67} | |||
| EndProjectSection | |||
| EndProject | |||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DF41F5CE-8BCB-40CC-835F-54A3DB7D802F}" | |||
| ProjectSection(SolutionItems) = preProject | |||
| DocX.vsmdi = DocX.vsmdi | |||
| LocalTestRun.testrunconfig = LocalTestRun.testrunconfig | |||
| ..\..\..\..\..\Desktop\DocX zipped\ReadMe.docx = ..\..\..\..\..\Desktop\DocX zipped\ReadMe.docx | |||
| EndProjectSection | |||
| EndProject | |||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StringReplaceTestApp", "StringReplaceTestApp\StringReplaceTestApp.csproj", "{EA960F96-7CA4-4AA1-BB43-0478E3407C5C}" | |||
| EndProject | |||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomPropertyTestApp", "CustomPropertyTestApp\CustomPropertyTestApp.csproj", "{9EABCAA8-175C-4FA2-9829-59E9D9E275D3}" | |||
| EndProject | |||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreateDocumentOnTheFly", "CreateDocumentOnTheFly\CreateDocumentOnTheFly.csproj", "{40E089B2-BFE4-4E47-83CC-36A4D43269C4}" | |||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples", "Examples\Examples.csproj", "{EF2E13CC-B36B-4B5A-AE73-78F5DDCA094E}" | |||
| EndProject | |||
| Global | |||
| GlobalSection(TeamFoundationVersionControl) = preSolution | |||
| @@ -52,22 +42,10 @@ Global | |||
| {E863D072-AA8B-4108-B5F1-785241B37F67}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {E863D072-AA8B-4108-B5F1-785241B37F67}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {E863D072-AA8B-4108-B5F1-785241B37F67}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {6E4A2A95-9A9A-4F8C-A68D-4950E3455700}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {6E4A2A95-9A9A-4F8C-A68D-4950E3455700}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {6E4A2A95-9A9A-4F8C-A68D-4950E3455700}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {6E4A2A95-9A9A-4F8C-A68D-4950E3455700}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {EA960F96-7CA4-4AA1-BB43-0478E3407C5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {EA960F96-7CA4-4AA1-BB43-0478E3407C5C}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {EA960F96-7CA4-4AA1-BB43-0478E3407C5C}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {EA960F96-7CA4-4AA1-BB43-0478E3407C5C}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| {9EABCAA8-175C-4FA2-9829-59E9D9E275D3}.Debug|Any CPU.ActiveCfg = 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.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 | |||
| {EF2E13CC-B36B-4B5A-AE73-78F5DDCA094E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
| {EF2E13CC-B36B-4B5A-AE73-78F5DDCA094E}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
| {EF2E13CC-B36B-4B5A-AE73-78F5DDCA094E}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {EF2E13CC-B36B-4B5A-AE73-78F5DDCA094E}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||
| @@ -17,12 +17,12 @@ namespace Novacode | |||
| { | |||
| static internal string editSessionID; | |||
| public static XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"; | |||
| static internal XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"; | |||
| /// <summary> | |||
| /// Default constructor | |||
| /// </summary> | |||
| public DocX() | |||
| internal DocX() | |||
| { | |||
| editSessionID = Guid.NewGuid().ToString().Substring(0, 8); | |||
| } | |||
| @@ -30,10 +30,12 @@ namespace Novacode | |||
| #region Private static variable declarations | |||
| // The URI of this .docx | |||
| private static string uri; | |||
| // This memory stream will hold the DocX file | |||
| private static MemoryStream document; | |||
| // Object representation of the .docx | |||
| private static WordprocessingDocument wdDoc; | |||
| // Object representation of the \word\document.xml part | |||
| private static MainDocumentPart mainDocumentPart; | |||
| internal static MainDocumentPart mainDocumentPart; | |||
| // Object representation of the \docProps\custom.xml part | |||
| private static CustomFilePropertiesPart customPropertiesPart = null; | |||
| // The mainDocument is loaded into a XDocument object for easy querying and editing | |||
| @@ -43,8 +45,8 @@ namespace Novacode | |||
| // The collection of Paragraphs <w:p></w:p> in this .docx | |||
| private static IEnumerable<Paragraph> paragraphs; | |||
| // The collection of custom properties in this .docx | |||
| private static IEnumerable<CustomProperty> customProperties = new List<CustomProperty>(); | |||
| private static IEnumerable<CustomProperty> customProperties; | |||
| private static IEnumerable<Image> images; | |||
| private static XNamespace customPropertiesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"; | |||
| private static XNamespace customVTypesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"; | |||
| @@ -97,14 +99,19 @@ namespace Novacode | |||
| get { return customProperties; } | |||
| } | |||
| static internal void RebuildParagraphs() | |||
| { | |||
| // 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); | |||
| } | |||
| 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); | |||
| RebuildParagraphs(); | |||
| return new Paragraph(newParagraph); | |||
| } | |||
| @@ -216,6 +223,9 @@ namespace Novacode | |||
| // 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); | |||
| DocX.images = from i in mainDocumentPart.ImageParts | |||
| select new Image(i); | |||
| #endregion | |||
| #region CustomFilePropertiesPart | |||
| @@ -242,6 +252,37 @@ namespace Novacode | |||
| return new DocX(); | |||
| } | |||
| public Image AddImage(string filename) | |||
| { | |||
| ImagePart ip = mainDocumentPart.AddImagePart(ImagePartType.Jpeg); | |||
| using (Stream stream = ip.GetStream(FileMode.Create, FileAccess.Write)) | |||
| { | |||
| using (Stream s = new FileStream(filename, FileMode.Open)) | |||
| { | |||
| byte[] bytes = new byte[s.Length]; | |||
| s.Read(bytes, 0, (int)s.Length); | |||
| stream.Write(bytes, 0, (int)s.Length); | |||
| } | |||
| } | |||
| return new Image(ip); | |||
| } | |||
| public Image AddImage(Stream s) | |||
| { | |||
| ImagePart ip = mainDocumentPart.AddImagePart(ImagePartType.Jpeg); | |||
| using (Stream stream = ip.GetStream(FileMode.Create, FileAccess.Write)) | |||
| { | |||
| byte[] bytes = new byte[s.Length]; | |||
| s.Read(bytes, 0, (int)s.Length); | |||
| stream.Write(bytes, 0, (int)s.Length); | |||
| } | |||
| return new Image(ip); | |||
| } | |||
| /// <summary> | |||
| /// Saves all changes made to the DocX object back to the .docx file it represents. | |||
| /// </summary> | |||
| @@ -259,17 +300,17 @@ namespace Novacode | |||
| public void Save() | |||
| { | |||
| // Save the main document part back to disk | |||
| using (TextWriter w = new StreamWriter(mainDocumentPart.GetStream(FileMode.Create, FileAccess.Write))) | |||
| using (TextWriter tw = new StreamWriter(mainDocumentPart.GetStream(FileMode.Create, FileAccess.Write))) | |||
| { | |||
| mainDoc.Save(w, SaveOptions.DisableFormatting); | |||
| mainDoc.Save(tw, SaveOptions.DisableFormatting); | |||
| } | |||
| if (customPropertiesPart != null) | |||
| { | |||
| // Save the custom properties part back to disk | |||
| using (TextWriter w = new StreamWriter(customPropertiesPart.GetStream(FileMode.Create, FileAccess.Write))) | |||
| using (TextWriter tw = new StreamWriter(customPropertiesPart.GetStream(FileMode.Create, FileAccess.Write))) | |||
| { | |||
| customPropDoc.Save(w, SaveOptions.DisableFormatting); | |||
| customPropDoc.Save(tw, SaveOptions.DisableFormatting); | |||
| } | |||
| } | |||
| @@ -39,7 +39,10 @@ | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <Reference Include="DocumentFormat.OpenXml, Version=2.0.3302.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" /> | |||
| <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> | |||
| <Reference Include="Microsoft.VisualStudio.TeamSystem.Data.UnitTesting, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> | |||
| <Reference Include="System" /> | |||
| <Reference Include="System.Configuration" /> | |||
| <Reference Include="System.Core"> | |||
| <RequiredTargetFramework>3.5</RequiredTargetFramework> | |||
| </Reference> | |||
| @@ -61,12 +64,17 @@ | |||
| <Compile Include="Enumerations.cs" /> | |||
| <Compile Include="Extensions.cs" /> | |||
| <Compile Include="Formatting.cs" /> | |||
| <Compile Include="Image.cs" /> | |||
| <Compile Include="Picture.cs" /> | |||
| <Compile Include="Paragraph.cs" /> | |||
| <Compile Include="DocX.cs" /> | |||
| <Compile Include="Properties\AssemblyInfo.cs" /> | |||
| <Compile Include="Run.cs" /> | |||
| <Compile Include="Text.cs" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <None Include="app.config" /> | |||
| </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. | |||
| @@ -5,6 +5,207 @@ using System.Text; | |||
| namespace Novacode | |||
| { | |||
| public enum RectangleShapes | |||
| { | |||
| rect, | |||
| roundRect, | |||
| snip1Rect, | |||
| snip2SameRect, | |||
| snip2DiagRect, | |||
| snipRoundRect, | |||
| round1Rect, | |||
| round2SameRect, | |||
| round2DiagRect | |||
| }; | |||
| public enum BasicShapes | |||
| { | |||
| ellipse, | |||
| triangle, | |||
| rtTriangle, | |||
| parallelogram, | |||
| trapezoid, | |||
| diamond, | |||
| pentagon, | |||
| hexagon, | |||
| heptagon, | |||
| octagon, | |||
| decagon, | |||
| dodecagon, | |||
| pie, | |||
| chord, | |||
| teardrop, | |||
| frame, | |||
| halfFrame, | |||
| corner, | |||
| diagStripe, | |||
| plus, | |||
| plaque, | |||
| can, | |||
| cube, | |||
| bevel, | |||
| donut, | |||
| noSmoking, | |||
| blockArc, | |||
| foldedCorner, | |||
| smileyFace, | |||
| heart, | |||
| lightningBolt, | |||
| sun, | |||
| moon, | |||
| cloud, | |||
| arc, | |||
| backetPair, | |||
| bracePair, | |||
| leftBracket, | |||
| rightBracket, | |||
| leftBrace, | |||
| rightBrace | |||
| }; | |||
| public enum BlockArrowShapes | |||
| { | |||
| rightArrow, | |||
| leftArrow, | |||
| upArrow, | |||
| downArrow, | |||
| leftRightArrow, | |||
| upDownArrow, | |||
| quadArrow, | |||
| leftRightUpArrow, | |||
| bentArrow, | |||
| uturnArrow, | |||
| leftUpArrow, | |||
| bentUpArrow, | |||
| curvedRightArrow, | |||
| curvedLeftArrow, | |||
| curvedUpArrow, | |||
| curvedDownArrow, | |||
| stripedRightArrow, | |||
| notchedRightArrow, | |||
| homePlate, | |||
| chevron, | |||
| rightArrowCallout, | |||
| downArrowCallout, | |||
| leftArrowCallout, | |||
| upArrowCallout, | |||
| leftRightArrowCallout, | |||
| quadArrowCallout, | |||
| circularArrow | |||
| }; | |||
| public enum EquationShapes | |||
| { | |||
| mathPlus, | |||
| mathMinus, | |||
| mathMultiply, | |||
| mathDivide, | |||
| mathEqual, | |||
| mathNotEqual | |||
| }; | |||
| public enum FlowchartShapes | |||
| { | |||
| flowChartProcess, | |||
| flowChartAlternateProcess, | |||
| flowChartDecision, | |||
| flowChartInputOutput, | |||
| flowChartPredefinedProcess, | |||
| flowChartInternalStorage, | |||
| flowChartDocument, | |||
| flowChartMultidocument, | |||
| flowChartTerminator, | |||
| flowChartPreparation, | |||
| flowChartManualInput, | |||
| flowChartManualOperation, | |||
| flowChartConnector, | |||
| flowChartOffpageConnector, | |||
| flowChartPunchedCard, | |||
| flowChartPunchedTape, | |||
| flowChartSummingJunction, | |||
| flowChartOr, | |||
| flowChartCollate, | |||
| flowChartSort, | |||
| flowChartExtract, | |||
| flowChartMerge, | |||
| flowChartOnlineStorage, | |||
| flowChartDelay, | |||
| flowChartMagneticTape, | |||
| flowChartMagneticDisk, | |||
| flowChartMagneticDrum, | |||
| flowChartDisplay | |||
| }; | |||
| public enum StarAndBannerShapes | |||
| { | |||
| irregularSeal1, | |||
| irregularSeal2, | |||
| star4, | |||
| star5, | |||
| star6, | |||
| star7, | |||
| star8, | |||
| star10, | |||
| star12, | |||
| star16, | |||
| star24, | |||
| star32, | |||
| ribbon, | |||
| ribbon2, | |||
| ellipseRibbon, | |||
| ellipseRibbon2, | |||
| verticalScroll, | |||
| horizontalScroll, | |||
| wave, | |||
| doubleWave | |||
| }; | |||
| public enum CalloutShapes | |||
| { | |||
| wedgeRectCallout, | |||
| wedgeRoundRectCallout, | |||
| wedgeEllipseCallout, | |||
| cloudCallout, | |||
| borderCallout1, | |||
| borderCallout2, | |||
| borderCallout3, | |||
| accentCallout1, | |||
| accentCallout2, | |||
| accentCallout3, | |||
| callout1, | |||
| callout2, | |||
| callout3, | |||
| accentBorderCallout1, | |||
| accentBorderCallout2, | |||
| accentBorderCallout3 | |||
| }; | |||
| /// <summary> | |||
| /// Text alignment of a paragraph | |||
| /// </summary> | |||
| public enum Alignment | |||
| { | |||
| /// <summary> | |||
| /// Align text to the left. | |||
| /// </summary> | |||
| left, | |||
| /// <summary> | |||
| /// Center text. | |||
| /// </summary> | |||
| center, | |||
| /// <summary> | |||
| /// Align text to the right. | |||
| /// </summary> | |||
| right, | |||
| /// <summary> | |||
| /// Align text to both the left and right margins, adding extra space between words as necessary. | |||
| /// </summary> | |||
| both | |||
| }; | |||
| /// <summary> | |||
| /// Paragraph edit types | |||
| /// </summary> | |||
| @@ -0,0 +1,23 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using DocumentFormat.OpenXml.Packaging; | |||
| namespace Novacode | |||
| { | |||
| public class Image | |||
| { | |||
| private string id; | |||
| public string Id | |||
| { | |||
| get {return id;} | |||
| } | |||
| internal Image(ImagePart ip) | |||
| { | |||
| id = DocX.mainDocumentPart.GetIdOfPart(ip); | |||
| } | |||
| } | |||
| } | |||
| @@ -15,21 +15,117 @@ namespace Novacode | |||
| /// </summary> | |||
| public class Paragraph | |||
| { | |||
| // This paragraphs text alignment | |||
| private Alignment alignment; | |||
| // A lookup for the runs in this paragraph | |||
| Dictionary<int, Run> runLookup = new Dictionary<int, Run>(); | |||
| // The underlying XElement which this Paragraph wraps | |||
| private XElement p; | |||
| // A collection of images in this paragraph | |||
| private IEnumerable<Picture> pictures; | |||
| public IEnumerable<Picture> Pictures { get { return pictures; } } | |||
| /// <summary> | |||
| /// Wraps a XElement as a Paragraph. | |||
| /// </summary> | |||
| /// <param name="p">The XElement to wrap.</param> | |||
| public Paragraph(XElement p) | |||
| internal Paragraph(XElement p) | |||
| { | |||
| this.p = p; | |||
| BuildRunLookup(p); | |||
| // Get all of the images in this document | |||
| pictures = from i in p.Descendants(XName.Get("drawing", DocX.w.NamespaceName)) | |||
| select new Picture(i); | |||
| } | |||
| /// <summary> | |||
| /// Gets or set this paragraphs text alignment | |||
| /// </summary> | |||
| public Alignment Alignment | |||
| { | |||
| get { return alignment; } | |||
| set | |||
| { | |||
| alignment = value; | |||
| XElement pPr = p.Element(XName.Get("pPr", DocX.w.NamespaceName)); | |||
| if (alignment != Novacode.Alignment.left) | |||
| { | |||
| if (pPr == null) | |||
| p.Add(new XElement(XName.Get("pPr", DocX.w.NamespaceName))); | |||
| pPr = p.Element(XName.Get("pPr", DocX.w.NamespaceName)); | |||
| XElement jc = pPr.Element(XName.Get("jc", DocX.w.NamespaceName)); | |||
| 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(); | |||
| } | |||
| else | |||
| { | |||
| if (pPr != null) | |||
| { | |||
| XElement jc = pPr.Element(XName.Get("jc", DocX.w.NamespaceName)); | |||
| if (jc != null) | |||
| jc.Remove(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| public void Delete(bool trackChanges) | |||
| { | |||
| if (trackChanges) | |||
| { | |||
| DateTime now = DateTime.Now.ToUniversalTime(); | |||
| List<XElement> elements = p.Elements().ToList(); | |||
| List<XElement> temp = new List<XElement>(); | |||
| for (int i = 0; i < elements.Count(); i++ ) | |||
| { | |||
| XElement e = elements[i]; | |||
| if (e.Name.LocalName != "del") | |||
| { | |||
| temp.Add(e); | |||
| e.Remove(); | |||
| } | |||
| else | |||
| { | |||
| if (temp.Count() > 0) | |||
| { | |||
| e.AddBeforeSelf(CreateEdit(EditType.del, now, temp.Elements())); | |||
| temp.Clear(); | |||
| } | |||
| } | |||
| } | |||
| if (temp.Count() > 0) | |||
| p.Add(CreateEdit(EditType.del, now, temp)); | |||
| } | |||
| else | |||
| { | |||
| // Remove this paragraph from the document | |||
| p.Remove(); | |||
| p = null; | |||
| runLookup.Clear(); | |||
| runLookup = null; | |||
| } | |||
| DocX.RebuildParagraphs(); | |||
| } | |||
| private void BuildRunLookup(XElement p) | |||
| @@ -90,6 +186,32 @@ namespace Novacode | |||
| } | |||
| } | |||
| public void InsertPicture(Picture picture, int index) | |||
| { | |||
| Run run = GetFirstRunEffectedByEdit(index); | |||
| if (run == null) | |||
| p.Add(picture.i); | |||
| else | |||
| { | |||
| // 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], | |||
| picture.i, | |||
| splitRun[1] | |||
| ); | |||
| } | |||
| // Rebuild the run lookup for this paragraph | |||
| runLookup.Clear(); | |||
| BuildRunLookup(p); | |||
| DocX.RenumberIDs(); | |||
| } | |||
| /// <summary> | |||
| /// Creates an Edit either a ins or a del with the specified content and date | |||
| /// </summary> | |||
| @@ -97,11 +219,11 @@ namespace Novacode | |||
| /// <param name="edit_time">The time stamp to use for this edit</param> | |||
| /// <param name="content">The initial content of this edit</param> | |||
| /// <returns></returns> | |||
| private XElement CreateEdit(EditType t, DateTime edit_time, params object[] content) | |||
| private XElement CreateEdit(EditType t, DateTime edit_time, object content) | |||
| { | |||
| if (t == EditType.del) | |||
| { | |||
| foreach (object o in content) | |||
| foreach (object o in (IEnumerable<XElement>)content) | |||
| { | |||
| if (o is XElement) | |||
| { | |||
| @@ -219,7 +341,7 @@ namespace Novacode | |||
| /// </summary> | |||
| /// <param name="run">An element</param> | |||
| /// <returns>The length of this elements text</returns> | |||
| public static int GetElementTextLength(XElement run) | |||
| static internal int GetElementTextLength(XElement run) | |||
| { | |||
| int count = 0; | |||
| @@ -480,7 +602,7 @@ namespace Novacode | |||
| XElement[] splitEditAfter = SplitEdit(parentElement, index + processed + min, EditType.del); | |||
| XElement temp = SplitEdit(splitEditBefore[1], index + processed + min, EditType.del)[0]; | |||
| object middle = CreateEdit(EditType.del, remove_datetime, temp.Elements().ToArray()); | |||
| object middle = CreateEdit(EditType.del, remove_datetime, temp.Elements()); | |||
| processed += GetElementTextLength(middle as XElement); | |||
| if (!trackChanges) | |||
| @@ -517,7 +639,7 @@ namespace Novacode | |||
| int min = Math.Min(index + processed + (count - processed), run.EndIndex); | |||
| XElement[] splitRunAfter = Run.SplitRun(run, min); | |||
| object middle = CreateEdit(EditType.del, remove_datetime, Run.SplitRun(new Run(run.StartIndex + GetElementTextLength(splitRunBefore[0]), splitRunBefore[1]), min)[0]); | |||
| object middle = CreateEdit(EditType.del, remove_datetime, new List<XElement>() { Run.SplitRun(new Run(run.StartIndex + GetElementTextLength(splitRunBefore[0]), splitRunBefore[1]), min)[0] }); | |||
| processed += GetElementTextLength(middle as XElement); | |||
| if (!trackChanges) | |||
| @@ -0,0 +1,343 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Xml.Linq; | |||
| using System.Drawing; | |||
| using DocumentFormat.OpenXml.Packaging; | |||
| namespace Novacode | |||
| { | |||
| public class Picture | |||
| { | |||
| private string id; | |||
| private string name; | |||
| private string descr; | |||
| private int cx, cy; | |||
| private uint rotation; | |||
| private bool hFlip, vFlip; | |||
| private object pictureShape; | |||
| // The underlying XElement which this Image wraps | |||
| internal XElement i; | |||
| private XElement xfrm; | |||
| private XElement prstGeom; | |||
| public Picture(string id, string name, string descr) | |||
| { | |||
| OpenXmlPart part = DocX.mainDocumentPart.GetPartById(id); | |||
| this.id = id; | |||
| this.name = name; | |||
| this.descr = descr; | |||
| using (System.Drawing.Image img = System.Drawing.Image.FromStream(part.GetStream())) | |||
| { | |||
| this.cx = img.Width * 4156; | |||
| this.cy = img.Height * 4156; | |||
| } | |||
| XElement e = new XElement(DocX.w + "drawing"); | |||
| i = 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""> | |||
| <wp:extent cx=""{0}"" cy=""{1}"" /> | |||
| <wp:effectExtent l=""0"" t=""0"" r=""0"" b=""0"" /> | |||
| <wp:docPr id=""1"" name=""{3}"" descr=""{4}"" /> | |||
| <wp:cNvGraphicFramePr> | |||
| <a:graphicFrameLocks xmlns:a=""http://schemas.openxmlformats.org/drawingml/2006/main"" noChangeAspect=""1"" /> | |||
| </wp:cNvGraphicFramePr> | |||
| <a:graphic xmlns:a=""http://schemas.openxmlformats.org/drawingml/2006/main""> | |||
| <a:graphicData uri=""http://schemas.openxmlformats.org/drawingml/2006/picture""> | |||
| <pic:pic xmlns:pic=""http://schemas.openxmlformats.org/drawingml/2006/picture""> | |||
| <pic:nvPicPr> | |||
| <pic:cNvPr id=""0"" name=""{3}"" /> | |||
| <pic:cNvPicPr /> | |||
| </pic:nvPicPr> | |||
| <pic:blipFill> | |||
| <a:blip r:embed=""{2}"" xmlns:r=""http://schemas.openxmlformats.org/officeDocument/2006/relationships""/> | |||
| <a:stretch> | |||
| <a:fillRect /> | |||
| </a:stretch> | |||
| </pic:blipFill> | |||
| <pic:spPr> | |||
| <a:xfrm> | |||
| <a:off x=""0"" y=""0"" /> | |||
| <a:ext cx=""{0}"" cy=""{1}"" /> | |||
| </a:xfrm> | |||
| <a:prstGeom prst=""rect""> | |||
| <a:avLst /> | |||
| </a:prstGeom> | |||
| </pic:spPr> | |||
| </pic:pic> | |||
| </a:graphicData> | |||
| </a:graphic> | |||
| </wp:inline> | |||
| </drawing> | |||
| ", cx, cy, id, name, descr)); | |||
| this.xfrm = | |||
| ( | |||
| from d in i.Descendants() | |||
| where d.Name.LocalName.Equals("xfrm") | |||
| select d | |||
| ).Single(); | |||
| this.prstGeom = | |||
| ( | |||
| from d in i.Descendants() | |||
| where d.Name.LocalName.Equals("prstGeom") | |||
| select d | |||
| ).Single(); | |||
| this.rotation = xfrm.Attribute(XName.Get("rot")) == null ? 0 : uint.Parse(xfrm.Attribute(XName.Get("rot")).Value); | |||
| } | |||
| /// <summary> | |||
| /// Wraps an XElement as an Image | |||
| /// </summary> | |||
| /// <param name="i">The XElement i to wrap</param> | |||
| internal Picture(XElement i) | |||
| { | |||
| this.i = i; | |||
| this.id = | |||
| ( | |||
| from e in i.Descendants() | |||
| where e.Name.LocalName.Equals("blip") | |||
| select e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")).Value | |||
| ).Single(); | |||
| this.name = | |||
| ( | |||
| from e in i.Descendants() | |||
| let a = e.Attribute(XName.Get("name")) | |||
| where (a != null) | |||
| select a.Value | |||
| ).First(); | |||
| this.descr = | |||
| ( | |||
| from e in i.Descendants() | |||
| let a = e.Attribute(XName.Get("descr")) | |||
| where (a != null) | |||
| select a.Value | |||
| ).First(); | |||
| this.cx = | |||
| ( | |||
| from e in i.Descendants() | |||
| let a = e.Attribute(XName.Get("cx")) | |||
| where (a != null) | |||
| select int.Parse(a.Value) | |||
| ).First(); | |||
| this.cy = | |||
| ( | |||
| from e in i.Descendants() | |||
| let a = e.Attribute(XName.Get("cy")) | |||
| where (a != null) | |||
| select int.Parse(a.Value) | |||
| ).First(); | |||
| this.xfrm = | |||
| ( | |||
| from d in i.Descendants() | |||
| where d.Name.LocalName.Equals("xfrm") | |||
| select d | |||
| ).Single(); | |||
| this.prstGeom = | |||
| ( | |||
| from d in i.Descendants() | |||
| where d.Name.LocalName.Equals("prstGeom") | |||
| select d | |||
| ).Single(); | |||
| this.rotation = xfrm.Attribute(XName.Get("rot")) == null ? 0 : uint.Parse(xfrm.Attribute(XName.Get("rot")).Value); | |||
| } | |||
| private void SetPictureShape(object shape) | |||
| { | |||
| this.pictureShape = shape; | |||
| XAttribute prst = prstGeom.Attribute(XName.Get("prst")); | |||
| if (prst == null) | |||
| prstGeom.Add(new XAttribute(XName.Get("prst"), "rectangle")); | |||
| prstGeom.Attribute(XName.Get("prst")).Value = shape.ToString(); | |||
| } | |||
| public void SetPictureShape(BasicShapes shape) | |||
| { | |||
| SetPictureShape((object)shape); | |||
| } | |||
| public void SetPictureShape(RectangleShapes shape) | |||
| { | |||
| SetPictureShape((object)shape); | |||
| } | |||
| public void SetPictureShape(BlockArrowShapes shape) | |||
| { | |||
| SetPictureShape((object)shape); | |||
| } | |||
| public void SetPictureShape(EquationShapes shape) | |||
| { | |||
| SetPictureShape((object)shape); | |||
| } | |||
| public void SetPictureShape(FlowchartShapes shape) | |||
| { | |||
| SetPictureShape((object)shape); | |||
| } | |||
| public void SetPictureShape(StarAndBannerShapes shape) | |||
| { | |||
| SetPictureShape((object)shape); | |||
| } | |||
| public void SetPictureShape(CalloutShapes shape) | |||
| { | |||
| SetPictureShape((object)shape); | |||
| } | |||
| public string Id | |||
| { | |||
| get { return id; } | |||
| } | |||
| public bool FlipHorizontal | |||
| { | |||
| get { return hFlip; } | |||
| set | |||
| { | |||
| hFlip = value; | |||
| XAttribute flipH = xfrm.Attribute(XName.Get("flipH")); | |||
| if (flipH == null) | |||
| xfrm.Add(new XAttribute(XName.Get("flipH"), "0")); | |||
| xfrm.Attribute(XName.Get("flipH")).Value = hFlip ? "1" : "0"; | |||
| } | |||
| } | |||
| public bool FlipVertical | |||
| { | |||
| get { return vFlip; } | |||
| set | |||
| { | |||
| vFlip = value; | |||
| XAttribute flipV = xfrm.Attribute(XName.Get("flipV")); | |||
| if (flipV == null) | |||
| xfrm.Add(new XAttribute(XName.Get("flipV"), "0")); | |||
| xfrm.Attribute(XName.Get("flipV")).Value = vFlip ? "1" : "0"; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// The rotation in degrees of this image, actual value = value % 360 | |||
| /// </summary> | |||
| public uint Rotation | |||
| { | |||
| get { return rotation / 60000; } | |||
| set | |||
| { | |||
| rotation = (value % 360) * 60000; | |||
| XElement xfrm = | |||
| (from d in i.Descendants() | |||
| where d.Name.LocalName.Equals("xfrm") | |||
| select d).Single(); | |||
| XAttribute rot = xfrm.Attribute(XName.Get("rot")); | |||
| if(rot == null) | |||
| xfrm.Add(new XAttribute(XName.Get("rot"), 0)); | |||
| xfrm.Attribute(XName.Get("rot")).Value = rotation.ToString(); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Gets or sets the name of this Image. | |||
| /// </summary> | |||
| public string Name | |||
| { | |||
| get { return name; } | |||
| set | |||
| { | |||
| name = value; | |||
| foreach (XAttribute a in i.Descendants().Attributes(XName.Get("name"))) | |||
| a.Value = name; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Gets or sets the description for this Image. | |||
| /// </summary> | |||
| public string Description | |||
| { | |||
| get { return descr; } | |||
| set | |||
| { | |||
| descr = value; | |||
| foreach (XAttribute a in i.Descendants().Attributes(XName.Get("descr"))) | |||
| a.Value = descr; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Get or sets the Width of this Image. | |||
| /// </summary> | |||
| public int Width | |||
| { | |||
| get { return cx / 4156; } | |||
| set | |||
| { | |||
| cx = value; | |||
| foreach (XAttribute a in i.Descendants().Attributes(XName.Get("cx"))) | |||
| a.Value = (cx * 4156).ToString(); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Get or sets the height of this Image. | |||
| /// </summary> | |||
| public int Height | |||
| { | |||
| get { return cy / 4156; } | |||
| set | |||
| { | |||
| cy = value; | |||
| foreach (XAttribute a in i.Descendants().Attributes(XName.Get("cy"))) | |||
| a.Value = (cy * 4156).ToString(); | |||
| } | |||
| } | |||
| //public void Delete() | |||
| //{ | |||
| // // Remove xml | |||
| // i.Remove(); | |||
| // // Rebuild the image collection for this paragraph | |||
| // // Requires that every Image have a link to its paragraph | |||
| //} | |||
| } | |||
| } | |||
| @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; | |||
| // 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")] | |||
| [assembly: AssemblyVersion("1.0.0.1")] | |||
| [assembly: AssemblyFileVersion("1.0.0.1")] | |||
| @@ -43,7 +43,7 @@ namespace Novacode | |||
| /// <param name="endIndex">The end index of this run (text length before this run, plus this runs text length)</param> | |||
| /// <param name="runText">The text value of this run</param> | |||
| /// <param name="e">The underlying XElement of this run</param> | |||
| public Run(int startIndex, XElement e) | |||
| internal Run(int startIndex, XElement e) | |||
| { | |||
| this.startIndex = startIndex; | |||
| this.e = e; | |||
| @@ -97,7 +97,7 @@ namespace Novacode | |||
| /// <param name="r">The run element to split</param> | |||
| /// <param name="index">The index to split at</param> | |||
| /// <returns>A two element array which contains both sides of the split</returns> | |||
| public static XElement[] SplitRun(Run r, int index) | |||
| static internal XElement[] SplitRun(Run r, int index) | |||
| { | |||
| Text t = r.GetFirstTextEffectedByEdit(index); | |||
| XElement[] splitText = Text.SplitText(t, index); | |||
| @@ -39,7 +39,7 @@ namespace Novacode | |||
| /// <param name="startIndex">The index this text starts at</param> | |||
| /// <param name="text">The index this text ends at</param> | |||
| /// <param name="e">The underlying xml element that this text wraps</param> | |||
| public Text(int startIndex, XElement e) | |||
| internal Text(int startIndex, XElement e) | |||
| { | |||
| this.startIndex = startIndex; | |||
| this.e = e; | |||
| @@ -0,0 +1,4 @@ | |||
| <?xml version="1.0" encoding="utf-8" ?> | |||
| <configuration> | |||
| </configuration> | |||