| # Visual Studio 2008 | # Visual Studio 2008 | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocX", "DocX\DocX.csproj", "{E863D072-AA8B-4108-B5F1-785241B37F67}" | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocX", "DocX\DocX.csproj", "{E863D072-AA8B-4108-B5F1-785241B37F67}" | ||||
| EndProject | 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}" | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DF41F5CE-8BCB-40CC-835F-54A3DB7D802F}" | ||||
| ProjectSection(SolutionItems) = preProject | ProjectSection(SolutionItems) = preProject | ||||
| DocX.vsmdi = DocX.vsmdi | DocX.vsmdi = DocX.vsmdi | ||||
| LocalTestRun.testrunconfig = LocalTestRun.testrunconfig | LocalTestRun.testrunconfig = LocalTestRun.testrunconfig | ||||
| ..\..\..\..\..\Desktop\DocX zipped\ReadMe.docx = ..\..\..\..\..\Desktop\DocX zipped\ReadMe.docx | |||||
| EndProjectSection | EndProjectSection | ||||
| EndProject | 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 | EndProject | ||||
| Global | Global | ||||
| GlobalSection(TeamFoundationVersionControl) = preSolution | GlobalSection(TeamFoundationVersionControl) = preSolution | ||||
| {E863D072-AA8B-4108-B5F1-785241B37F67}.Debug|Any CPU.Build.0 = Debug|Any CPU | {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.ActiveCfg = Release|Any CPU | ||||
| {E863D072-AA8B-4108-B5F1-785241B37F67}.Release|Any CPU.Build.0 = 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 | EndGlobalSection | ||||
| GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
| HideSolutionNode = FALSE | HideSolutionNode = FALSE |
| { | { | ||||
| static internal string editSessionID; | 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> | /// <summary> | ||||
| /// Default constructor | /// Default constructor | ||||
| /// </summary> | /// </summary> | ||||
| public DocX() | |||||
| internal DocX() | |||||
| { | { | ||||
| editSessionID = Guid.NewGuid().ToString().Substring(0, 8); | editSessionID = Guid.NewGuid().ToString().Substring(0, 8); | ||||
| } | } | ||||
| #region Private static variable declarations | #region Private static variable declarations | ||||
| // The URI of this .docx | // The URI of this .docx | ||||
| private static string uri; | private static string uri; | ||||
| // This memory stream will hold the DocX file | |||||
| private static MemoryStream document; | |||||
| // Object representation of the .docx | // Object representation of the .docx | ||||
| private static WordprocessingDocument wdDoc; | private static WordprocessingDocument wdDoc; | ||||
| // Object representation of the \word\document.xml part | // Object representation of the \word\document.xml part | ||||
| private static MainDocumentPart mainDocumentPart; | |||||
| internal static MainDocumentPart mainDocumentPart; | |||||
| // Object representation of the \docProps\custom.xml part | // Object representation of the \docProps\custom.xml part | ||||
| private static CustomFilePropertiesPart customPropertiesPart = null; | private static CustomFilePropertiesPart customPropertiesPart = null; | ||||
| // The mainDocument is loaded into a XDocument object for easy querying and editing | // The mainDocument is loaded into a XDocument object for easy querying and editing | ||||
| // The collection of Paragraphs <w:p></w:p> in this .docx | // The collection of Paragraphs <w:p></w:p> in this .docx | ||||
| private static IEnumerable<Paragraph> paragraphs; | private static IEnumerable<Paragraph> paragraphs; | ||||
| // The collection of custom properties in this .docx | // 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 customPropertiesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"; | ||||
| private static XNamespace customVTypesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"; | private static XNamespace customVTypesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"; | ||||
| get { return customProperties; } | 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() | public Paragraph AddParagraph() | ||||
| { | { | ||||
| XElement newParagraph = new XElement(w + "p"); | XElement newParagraph = new XElement(w + "p"); | ||||
| mainDoc.Descendants(XName.Get("body", "http://schemas.openxmlformats.org/wordprocessingml/2006/main")).Single().Add(newParagraph); | 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); | return new Paragraph(newParagraph); | ||||
| } | } | ||||
| // Get all of the paragraphs in this 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")) | DocX.paragraphs = from p in mainDoc.Descendants(XName.Get("p", "http://schemas.openxmlformats.org/wordprocessingml/2006/main")) | ||||
| select new Paragraph(p); | select new Paragraph(p); | ||||
| DocX.images = from i in mainDocumentPart.ImageParts | |||||
| select new Image(i); | |||||
| #endregion | #endregion | ||||
| #region CustomFilePropertiesPart | #region CustomFilePropertiesPart | ||||
| return new DocX(); | 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> | /// <summary> | ||||
| /// Saves all changes made to the DocX object back to the .docx file it represents. | /// Saves all changes made to the DocX object back to the .docx file it represents. | ||||
| /// </summary> | /// </summary> | ||||
| public void Save() | public void Save() | ||||
| { | { | ||||
| // Save the main document part back to disk | // 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) | if (customPropertiesPart != null) | ||||
| { | { | ||||
| // Save the custom properties part back to disk | // 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); | |||||
| } | } | ||||
| } | } | ||||
| </PropertyGroup> | </PropertyGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <Reference Include="DocumentFormat.OpenXml, Version=2.0.3302.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" /> | <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" /> | ||||
| <Reference Include="System.Configuration" /> | |||||
| <Reference Include="System.Core"> | <Reference Include="System.Core"> | ||||
| <RequiredTargetFramework>3.5</RequiredTargetFramework> | <RequiredTargetFramework>3.5</RequiredTargetFramework> | ||||
| </Reference> | </Reference> | ||||
| <Compile Include="Enumerations.cs" /> | <Compile Include="Enumerations.cs" /> | ||||
| <Compile Include="Extensions.cs" /> | <Compile Include="Extensions.cs" /> | ||||
| <Compile Include="Formatting.cs" /> | <Compile Include="Formatting.cs" /> | ||||
| <Compile Include="Image.cs" /> | |||||
| <Compile Include="Picture.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" /> | ||||
| <Compile Include="Run.cs" /> | <Compile Include="Run.cs" /> | ||||
| <Compile Include="Text.cs" /> | <Compile Include="Text.cs" /> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | |||||
| <None Include="app.config" /> | |||||
| </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. |
| namespace Novacode | 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> | /// <summary> | ||||
| /// Paragraph edit types | /// Paragraph edit types | ||||
| /// </summary> | /// </summary> |
| 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); | |||||
| } | |||||
| } | |||||
| } |
| /// </summary> | /// </summary> | ||||
| public class Paragraph | public class Paragraph | ||||
| { | { | ||||
| // This paragraphs text alignment | |||||
| private Alignment alignment; | |||||
| // A lookup for the runs in this paragraph | // A lookup for the runs in this paragraph | ||||
| Dictionary<int, Run> runLookup = new Dictionary<int, Run>(); | Dictionary<int, Run> runLookup = new Dictionary<int, Run>(); | ||||
| // The underlying XElement which this Paragraph wraps | // The underlying XElement which this Paragraph wraps | ||||
| private XElement p; | private XElement p; | ||||
| // A collection of images in this paragraph | |||||
| private IEnumerable<Picture> pictures; | |||||
| public IEnumerable<Picture> Pictures { get { return pictures; } } | |||||
| /// <summary> | /// <summary> | ||||
| /// Wraps a XElement as a Paragraph. | /// Wraps a XElement as a Paragraph. | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="p">The XElement to wrap.</param> | /// <param name="p">The XElement to wrap.</param> | ||||
| public Paragraph(XElement p) | |||||
| internal Paragraph(XElement p) | |||||
| { | { | ||||
| this.p = p; | this.p = p; | ||||
| BuildRunLookup(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) | private void BuildRunLookup(XElement p) | ||||
| } | } | ||||
| } | } | ||||
| 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> | /// <summary> | ||||
| /// Creates an Edit either a ins or a del with the specified content and date | /// Creates an Edit either a ins or a del with the specified content and date | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="edit_time">The time stamp to use for this edit</param> | /// <param name="edit_time">The time stamp to use for this edit</param> | ||||
| /// <param name="content">The initial content of this edit</param> | /// <param name="content">The initial content of this edit</param> | ||||
| /// <returns></returns> | /// <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) | if (t == EditType.del) | ||||
| { | { | ||||
| foreach (object o in content) | |||||
| foreach (object o in (IEnumerable<XElement>)content) | |||||
| { | { | ||||
| if (o is XElement) | if (o is XElement) | ||||
| { | { | ||||
| /// </summary> | /// </summary> | ||||
| /// <param name="run">An element</param> | /// <param name="run">An element</param> | ||||
| /// <returns>The length of this elements text</returns> | /// <returns>The length of this elements text</returns> | ||||
| public static int GetElementTextLength(XElement run) | |||||
| static internal int GetElementTextLength(XElement run) | |||||
| { | { | ||||
| int count = 0; | int count = 0; | ||||
| XElement[] splitEditAfter = SplitEdit(parentElement, index + processed + min, EditType.del); | XElement[] splitEditAfter = SplitEdit(parentElement, index + processed + min, EditType.del); | ||||
| XElement temp = SplitEdit(splitEditBefore[1], index + processed + min, EditType.del)[0]; | 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); | processed += GetElementTextLength(middle as XElement); | ||||
| if (!trackChanges) | if (!trackChanges) | ||||
| int min = Math.Min(index + processed + (count - processed), run.EndIndex); | int min = Math.Min(index + processed + (count - processed), run.EndIndex); | ||||
| XElement[] splitRunAfter = Run.SplitRun(run, min); | 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); | processed += GetElementTextLength(middle as XElement); | ||||
| if (!trackChanges) | if (!trackChanges) |
| 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 | |||||
| //} | |||||
| } | |||||
| } |
| // You can specify all the values or you can default the Build and Revision Numbers | // You can specify all the values or you can default the Build and Revision Numbers | ||||
| // by using the '*' as shown below: | // by using the '*' as shown below: | ||||
| // [assembly: AssemblyVersion("1.0.*")] | // [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")] |
| /// <param name="endIndex">The end index of this run (text length before this run, plus this runs text length)</param> | /// <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="runText">The text value of this run</param> | ||||
| /// <param name="e">The underlying XElement 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.startIndex = startIndex; | ||||
| this.e = e; | this.e = e; | ||||
| /// <param name="r">The run element to split</param> | /// <param name="r">The run element to split</param> | ||||
| /// <param name="index">The index to split at</param> | /// <param name="index">The index to split at</param> | ||||
| /// <returns>A two element array which contains both sides of the split</returns> | /// <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); | Text t = r.GetFirstTextEffectedByEdit(index); | ||||
| XElement[] splitText = Text.SplitText(t, index); | XElement[] splitText = Text.SplitText(t, index); |
| /// <param name="startIndex">The index this text starts at</param> | /// <param name="startIndex">The index this text starts at</param> | ||||
| /// <param name="text">The index this text ends at</param> | /// <param name="text">The index this text ends at</param> | ||||
| /// <param name="e">The underlying xml element that this text wraps</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.startIndex = startIndex; | ||||
| this.e = e; | this.e = e; |
| <?xml version="1.0" encoding="utf-8" ?> | |||||
| <configuration> | |||||
| </configuration> |