Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Xml.Linq;
  6. using System.Xml;
  7. using System.IO;
  8. using System.Text.RegularExpressions;
  9. using System.IO.Packaging;
  10. using System.Security.Principal;
  11. using System.Reflection;
  12. using System.IO.Compression;
  13. namespace Novacode
  14. {
  15. /// <summary>
  16. /// Represents a document.
  17. /// </summary>
  18. public class DocX : Container, IDisposable
  19. {
  20. #region Namespaces
  21. static internal XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
  22. static internal XNamespace rel = "http://schemas.openxmlformats.org/package/2006/relationships";
  23. static internal XNamespace r = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
  24. static internal XNamespace m = "http://schemas.openxmlformats.org/officeDocument/2006/math";
  25. static internal XNamespace customPropertiesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
  26. static internal XNamespace customVTypesSchema = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes";
  27. static internal XNamespace wp = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing";
  28. static internal XNamespace a = "http://schemas.openxmlformats.org/drawingml/2006/main";
  29. static internal XNamespace c = "http://schemas.openxmlformats.org/drawingml/2006/chart";
  30. #endregion
  31. public float PageWidth
  32. {
  33. get
  34. {
  35. XElement body = mainDoc.Root.Element(XName.Get("body", DocX.w.NamespaceName));
  36. XElement sectPr = body.Element(XName.Get("sectPr", DocX.w.NamespaceName));
  37. if (sectPr != null)
  38. {
  39. XElement pgSz = sectPr.Element(XName.Get("pgSz", DocX.w.NamespaceName));
  40. if(pgSz != null)
  41. {
  42. XAttribute w = pgSz.Attribute(XName.Get("w", DocX.w.NamespaceName));
  43. if(w != null)
  44. {
  45. float f;
  46. if(float.TryParse(w.Value,out f))
  47. return (int)(f / 15.0f);
  48. }
  49. }
  50. }
  51. return (int)(11906.0f / 15.0f);
  52. }
  53. set
  54. {
  55. XElement body = mainDoc.Root.Element(XName.Get("body", DocX.w.NamespaceName));
  56. if (body != null)
  57. {
  58. XElement sectPr = body.Element(XName.Get("sectPr", DocX.w.NamespaceName));
  59. if (sectPr != null)
  60. {
  61. XElement pgSz = sectPr.Element(XName.Get("pgSz", DocX.w.NamespaceName));
  62. if (pgSz != null)
  63. {
  64. pgSz.SetAttributeValue(XName.Get("w", DocX.w.NamespaceName), value);
  65. }
  66. }
  67. }
  68. }
  69. }
  70. public float PageHeight
  71. {
  72. get
  73. {
  74. XElement body = mainDoc.Root.Element(XName.Get("body", DocX.w.NamespaceName));
  75. XElement sectPr = body.Element(XName.Get("sectPr", DocX.w.NamespaceName));
  76. if (sectPr != null)
  77. {
  78. XElement pgSz = sectPr.Element(XName.Get("pgSz", DocX.w.NamespaceName));
  79. if (pgSz != null)
  80. {
  81. XAttribute w = pgSz.Attribute(XName.Get("h", DocX.w.NamespaceName));
  82. if (w != null)
  83. {
  84. float f;
  85. if (float.TryParse(w.Value, out f))
  86. return (int)(f / 15.0f);
  87. }
  88. }
  89. }
  90. return (int)(16838.0f / 15.0f);
  91. }
  92. set
  93. {
  94. XElement body = mainDoc.Root.Element(XName.Get("body", DocX.w.NamespaceName));
  95. if (body != null)
  96. {
  97. XElement sectPr = body.Element(XName.Get("sectPr", DocX.w.NamespaceName));
  98. if (sectPr != null)
  99. {
  100. XElement pgSz = sectPr.Element(XName.Get("pgSz", DocX.w.NamespaceName));
  101. if (pgSz != null)
  102. {
  103. pgSz.SetAttributeValue(XName.Get("h", DocX.w.NamespaceName), value);
  104. }
  105. }
  106. }
  107. }
  108. }
  109. /// <summary>
  110. /// Returns true if any editing restrictions are imposed on this document.
  111. /// </summary>
  112. /// <example>
  113. /// <code>
  114. /// // Create a new document.
  115. /// using (DocX document = DocX.Create(@"Test.docx"))
  116. /// {
  117. /// if(document.isProtected)
  118. /// Console.WriteLine("Protected");
  119. /// else
  120. /// Console.WriteLine("Not protected");
  121. ///
  122. /// // Save the document.
  123. /// document.Save();
  124. /// }
  125. /// </code>
  126. /// </example>
  127. /// <seealso cref="AddProtection"/>
  128. /// <seealso cref="RemoveProtection"/>
  129. /// <seealso cref="GetProtectionType"/>
  130. public bool isProtected
  131. {
  132. get
  133. {
  134. return settings.Descendants(XName.Get("documentProtection", DocX.w.NamespaceName)).Count() > 0;
  135. }
  136. }
  137. /// <summary>
  138. /// Returns the type of editing protection imposed on this document.
  139. /// </summary>
  140. /// <returns>The type of editing protection imposed on this document.</returns>
  141. /// <example>
  142. /// <code>
  143. /// Create a new document.
  144. /// using (DocX document = DocX.Create(@"Test.docx"))
  145. /// {
  146. /// // Make sure the document is protected before checking the protection type.
  147. /// if (document.isProtected)
  148. /// {
  149. /// EditRestrictions protection = document.GetProtectionType();
  150. /// Console.WriteLine("Document is protected using " + protection.ToString());
  151. /// }
  152. ///
  153. /// else
  154. /// Console.WriteLine("Document is not protected.");
  155. ///
  156. /// // Save the document.
  157. /// document.Save();
  158. /// }
  159. /// </code>
  160. /// </example>
  161. /// <seealso cref="AddProtection"/>
  162. /// <seealso cref="RemoveProtection"/>
  163. /// <seealso cref="isProtected"/>
  164. public EditRestrictions GetProtectionType()
  165. {
  166. if (isProtected)
  167. {
  168. XElement documentProtection = settings.Descendants(XName.Get("documentProtection", DocX.w.NamespaceName)).FirstOrDefault();
  169. string edit_type = documentProtection.Attribute(XName.Get("edit", DocX.w.NamespaceName)).Value;
  170. return (EditRestrictions)Enum.Parse(typeof(EditRestrictions), edit_type);
  171. }
  172. return EditRestrictions.none;
  173. }
  174. /// <summary>
  175. /// Add editing protection to this document.
  176. /// </summary>
  177. /// <param name="er">The type of protection to add to this document.</param>
  178. /// <example>
  179. /// <code>
  180. /// // Create a new document.
  181. /// using (DocX document = DocX.Create(@"Test.docx"))
  182. /// {
  183. /// // Allow no editing, only the adding of comment.
  184. /// document.AddProtection(EditRestrictions.comments);
  185. ///
  186. /// // Save the document.
  187. /// document.Save();
  188. /// }
  189. /// </code>
  190. /// </example>
  191. /// <seealso cref="RemoveProtection"/>
  192. /// <seealso cref="GetProtectionType"/>
  193. /// <seealso cref="isProtected"/>
  194. public void AddProtection(EditRestrictions er)
  195. {
  196. // Call remove protection before adding a new protection element.
  197. RemoveProtection();
  198. if (er == EditRestrictions.none)
  199. return;
  200. XElement documentProtection = new XElement(XName.Get("documentProtection", DocX.w.NamespaceName));
  201. documentProtection.Add(new XAttribute(XName.Get("edit", DocX.w.NamespaceName), er.ToString()));
  202. documentProtection.Add(new XAttribute(XName.Get("enforcement", DocX.w.NamespaceName), "1"));
  203. settings.Root.AddFirst(documentProtection);
  204. }
  205. /// <summary>
  206. /// Remove editing protection from this document.
  207. /// </summary>
  208. /// <example>
  209. /// <code>
  210. /// // Create a new document.
  211. /// using (DocX document = DocX.Create(@"Test.docx"))
  212. /// {
  213. /// // Remove any editing restrictions that are imposed on this document.
  214. /// document.RemoveProtection();
  215. ///
  216. /// // Save the document.
  217. /// document.Save();
  218. /// }
  219. /// </code>
  220. /// </example>
  221. /// <seealso cref="AddProtection"/>
  222. /// <seealso cref="GetProtectionType"/>
  223. /// <seealso cref="isProtected"/>
  224. public void RemoveProtection()
  225. {
  226. // Remove every node of type documentProtection.
  227. settings.Descendants(XName.Get("documentProtection", DocX.w.NamespaceName)).Remove();
  228. }
  229. public PageLayout PageLayout
  230. {
  231. get
  232. {
  233. XElement sectPr = Xml.Element(XName.Get("sectPr", DocX.w.NamespaceName));
  234. if (sectPr == null)
  235. {
  236. Xml.SetElementValue(XName.Get("sectPr", DocX.w.NamespaceName), string.Empty);
  237. sectPr = Xml.Element(XName.Get("sectPr", DocX.w.NamespaceName));
  238. }
  239. return new PageLayout(this, sectPr);
  240. }
  241. }
  242. /// <summary>
  243. /// Returns a collection of Headers in this Document.
  244. /// A document typically contains three Headers.
  245. /// A default one (odd), one for the first page and one for even pages.
  246. /// </summary>
  247. /// <example>
  248. /// <code>
  249. /// // Create a document.
  250. /// using (DocX document = DocX.Create(@"Test.docx"))
  251. /// {
  252. /// // Add header support to this document.
  253. /// document.AddHeaders();
  254. ///
  255. /// // Get a collection of all headers in this document.
  256. /// Headers headers = document.Headers;
  257. ///
  258. /// // The header used for the first page of this document.
  259. /// Header first = headers.first;
  260. ///
  261. /// // The header used for odd pages of this document.
  262. /// Header odd = headers.odd;
  263. ///
  264. /// // The header used for even pages of this document.
  265. /// Header even = headers.even;
  266. /// }
  267. /// </code>
  268. /// </example>
  269. public Headers Headers
  270. {
  271. get
  272. {
  273. return headers;
  274. }
  275. }
  276. private Headers headers;
  277. /// <summary>
  278. /// Returns a collection of Footers in this Document.
  279. /// A document typically contains three Footers.
  280. /// A default one (odd), one for the first page and one for even pages.
  281. /// </summary>
  282. /// <example>
  283. /// <code>
  284. /// // Create a document.
  285. /// using (DocX document = DocX.Create(@"Test.docx"))
  286. /// {
  287. /// // Add footer support to this document.
  288. /// document.AddFooters();
  289. ///
  290. /// // Get a collection of all footers in this document.
  291. /// Footers footers = document.Footers;
  292. ///
  293. /// // The footer used for the first page of this document.
  294. /// Footer first = footers.first;
  295. ///
  296. /// // The footer used for odd pages of this document.
  297. /// Footer odd = footers.odd;
  298. ///
  299. /// // The footer used for even pages of this document.
  300. /// Footer even = footers.even;
  301. /// }
  302. /// </code>
  303. /// </example>
  304. public Footers Footers
  305. {
  306. get
  307. {
  308. return footers;
  309. }
  310. }
  311. private Footers footers;
  312. /// <summary>
  313. /// Should the Document use different Headers and Footers for odd and even pages?
  314. /// </summary>
  315. /// // Create a document.
  316. /// using (DocX document = DocX.Create(@"Test.docx"))
  317. /// {
  318. /// // Add header support to this document.
  319. /// document.AddHeaders();
  320. ///
  321. /// // Get a collection of all headers in this document.
  322. /// Headers headers = document.Headers;
  323. ///
  324. /// // The header used for odd pages of this document.
  325. /// Header odd = headers.odd;
  326. ///
  327. /// // The header used for even pages of this document.
  328. /// Header even = headers.even;
  329. ///
  330. /// // Force the document to use a different header for odd and even pages.
  331. /// document.DifferentOddAndEvenPages = true;
  332. ///
  333. /// // Content can be added to the Headers in the same manor that it would be added to the main document.
  334. /// Paragraph p1 = odd.InsertParagraph();
  335. /// p1.Append("This is the odd pages header.");
  336. ///
  337. /// Paragraph p2 = even.InsertParagraph();
  338. /// p2.Append("This is the even pages header.");
  339. ///
  340. /// // Save all changes to this document.
  341. /// document.Save();
  342. /// }// Release this document from memory.
  343. /// </example>
  344. public bool DifferentOddAndEvenPages
  345. {
  346. get
  347. {
  348. XDocument settings;
  349. using (TextReader tr = new StreamReader(settingsPart.GetStream()))
  350. settings = XDocument.Load(tr);
  351. XElement evenAndOddHeaders = settings.Root.Element(w + "evenAndOddHeaders");
  352. return evenAndOddHeaders != null;
  353. }
  354. set
  355. {
  356. XDocument settings;
  357. using (TextReader tr = new StreamReader(settingsPart.GetStream()))
  358. settings = XDocument.Load(tr);
  359. XElement evenAndOddHeaders = settings.Root.Element(w + "evenAndOddHeaders");
  360. if (evenAndOddHeaders == null)
  361. {
  362. if (value)
  363. settings.Root.AddFirst(new XElement(w + "evenAndOddHeaders"));
  364. }
  365. else
  366. {
  367. if (!value)
  368. evenAndOddHeaders.Remove();
  369. }
  370. using (TextWriter tw = new StreamWriter(settingsPart.GetStream()))
  371. settings.Save(tw);
  372. }
  373. }
  374. /// <summary>
  375. /// Should the Document use an independent Header and Footer for the first page?
  376. /// </summary>
  377. /// <example>
  378. /// // Create a document.
  379. /// using (DocX document = DocX.Create(@"Test.docx"))
  380. /// {
  381. /// // Add header support to this document.
  382. /// document.AddHeaders();
  383. ///
  384. /// // The header used for the first page of this document.
  385. /// Header first = document.Headers.first;
  386. ///
  387. /// // Force the document to use a different header for first page.
  388. /// document.DifferentFirstPage = true;
  389. ///
  390. /// // Content can be added to the Headers in the same manor that it would be added to the main document.
  391. /// Paragraph p = first.InsertParagraph();
  392. /// p.Append("This is the first pages header.");
  393. ///
  394. /// // Save all changes to this document.
  395. /// document.Save();
  396. /// }// Release this document from memory.
  397. /// </example>
  398. public bool DifferentFirstPage
  399. {
  400. get
  401. {
  402. XElement body = mainDoc.Root.Element(w + "body");
  403. XElement sectPr = body.Element(w + "sectPr");
  404. if (sectPr != null)
  405. {
  406. XElement titlePg = sectPr.Element(w + "titlePg");
  407. if (titlePg != null)
  408. return true;
  409. }
  410. return false;
  411. }
  412. set
  413. {
  414. XElement body = mainDoc.Root.Element(w + "body");
  415. XElement sectPr = null;
  416. XElement titlePg = null;
  417. if (sectPr == null)
  418. body.Add(new XElement(w + "sectPr", string.Empty));
  419. sectPr = body.Element(w + "sectPr");
  420. titlePg = sectPr.Element(w + "titlePg");
  421. if (titlePg == null)
  422. {
  423. if (value)
  424. sectPr.Add(new XElement(w + "titlePg", string.Empty));
  425. }
  426. else
  427. {
  428. if (!value)
  429. titlePg.Remove();
  430. }
  431. }
  432. }
  433. private Header GetHeaderByType(string type)
  434. {
  435. return (Header)GetHeaderOrFooterByType(type, true);
  436. }
  437. private Footer GetFooterByType(string type)
  438. {
  439. return (Footer)GetHeaderOrFooterByType(type, false);
  440. }
  441. private object GetHeaderOrFooterByType(string type, bool isHeader)
  442. {
  443. // Switch which handles either case Header\Footer, this just cuts down on code duplication.
  444. string reference = "footerReference";
  445. if (isHeader)
  446. reference = "headerReference";
  447. // Get the Id of the [default, even or first] [Header or Footer]
  448. string Id =
  449. (
  450. from e in mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).Descendants()
  451. where (e.Name.LocalName == reference) && (e.Attribute(w + "type").Value == type)
  452. select e.Attribute(r + "id").Value
  453. ).LastOrDefault();
  454. if (Id != null)
  455. {
  456. // Get the Xml file for this Header or Footer.
  457. Uri partUri = mainPart.GetRelationship(Id).TargetUri;
  458. // Weird problem with PackaePart API.
  459. if (!partUri.OriginalString.StartsWith("/word/"))
  460. partUri = new Uri("/word/" + partUri.OriginalString, UriKind.Relative);
  461. // Get the Part and open a stream to get the Xml file.
  462. PackagePart part = package.GetPart(partUri);
  463. XDocument doc;
  464. using (TextReader tr = new StreamReader(part.GetStream()))
  465. {
  466. doc = XDocument.Load(tr);
  467. // Header and Footer extend Container.
  468. Container c;
  469. if (isHeader)
  470. c = new Header(this, doc.Element(w + "hdr"), part);
  471. else
  472. c = new Footer(this, doc.Element(w + "ftr"), part);
  473. return c;
  474. }
  475. }
  476. // If we got this far something went wrong.
  477. return null;
  478. }
  479. // Get the word\document.xml part
  480. internal PackagePart mainPart;
  481. // Get the word\settings.xml part
  482. internal PackagePart settingsPart;
  483. #region Internal variables defined foreach DocX object
  484. // Object representation of the .docx
  485. internal Package package;
  486. // The mainDocument is loaded into a XDocument object for easy querying and editing
  487. internal XDocument mainDoc;
  488. internal XDocument settings;
  489. internal XDocument header1;
  490. internal XDocument header2;
  491. internal XDocument header3;
  492. // A lookup for the Paragraphs in this document.
  493. internal Dictionary<int, Paragraph> paragraphLookup = new Dictionary<int, Paragraph>();
  494. // Every document is stored in a MemoryStream, all edits made to a document are done in memory.
  495. internal MemoryStream memoryStream;
  496. // The filename that this document was loaded from
  497. internal string filename;
  498. // The stream that this document was loaded from
  499. internal Stream stream;
  500. #endregion
  501. internal DocX(DocX document, XElement xml)
  502. : base(document, xml)
  503. {
  504. }
  505. /// <summary>
  506. /// Returns a list of Images in this document.
  507. /// </summary>
  508. /// <example>
  509. /// Get the unique Id of every Image in this document.
  510. /// <code>
  511. /// // Load a document.
  512. /// DocX document = DocX.Load(@"C:\Example\Test.docx");
  513. ///
  514. /// // Loop through each Image in this document.
  515. /// foreach (Novacode.Image i in document.Images)
  516. /// {
  517. /// // Get the unique Id which identifies this Image.
  518. /// string uniqueId = i.Id;
  519. /// }
  520. ///
  521. /// </code>
  522. /// </example>
  523. /// <seealso cref="AddImage(string)"/>
  524. /// <seealso cref="AddImage(Stream)"/>
  525. /// <seealso cref="Paragraph.Pictures"/>
  526. /// <seealso cref="Paragraph.InsertPicture"/>
  527. public List<Image> Images
  528. {
  529. get
  530. {
  531. PackageRelationshipCollection imageRelationships = mainPart.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
  532. if (imageRelationships.Count() > 0)
  533. {
  534. return
  535. (
  536. from i in imageRelationships
  537. select new Image(this, i)
  538. ).ToList();
  539. }
  540. return new List<Image>();
  541. }
  542. }
  543. /// <summary>
  544. /// Returns a list of custom properties in this document.
  545. /// </summary>
  546. /// <example>
  547. /// Method 1: Get the name, type and value of each CustomProperty in this document.
  548. /// <code>
  549. /// // Load Example.docx
  550. /// DocX document = DocX.Load(@"C:\Example\Test.docx");
  551. ///
  552. /// /*
  553. /// * No two custom properties can have the same name,
  554. /// * so a Dictionary is the perfect data structure to store them in.
  555. /// * Each custom property can be accessed using its name.
  556. /// */
  557. /// foreach (string name in document.CustomProperties.Keys)
  558. /// {
  559. /// // Grab a custom property using its name.
  560. /// CustomProperty cp = document.CustomProperties[name];
  561. ///
  562. /// // Write this custom properties details to Console.
  563. /// Console.WriteLine(string.Format("Name: '{0}', Value: {1}", cp.Name, cp.Value));
  564. /// }
  565. ///
  566. /// Console.WriteLine("Press any key...");
  567. ///
  568. /// // Wait for the user to press a key before closing the Console.
  569. /// Console.ReadKey();
  570. /// </code>
  571. /// </example>
  572. /// <example>
  573. /// Method 2: Get the name, type and value of each CustomProperty in this document.
  574. /// <code>
  575. /// // Load Example.docx
  576. /// DocX document = DocX.Load(@"C:\Example\Test.docx");
  577. ///
  578. /// /*
  579. /// * No two custom properties can have the same name,
  580. /// * so a Dictionary is the perfect data structure to store them in.
  581. /// * The values of this Dictionary are CustomProperties.
  582. /// */
  583. /// foreach (CustomProperty cp in document.CustomProperties.Values)
  584. /// {
  585. /// // Write this custom properties details to Console.
  586. /// Console.WriteLine(string.Format("Name: '{0}', Value: {1}", cp.Name, cp.Value));
  587. /// }
  588. ///
  589. /// Console.WriteLine("Press any key...");
  590. ///
  591. /// // Wait for the user to press a key before closing the Console.
  592. /// Console.ReadKey();
  593. /// </code>
  594. /// </example>
  595. /// <seealso cref="AddCustomProperty"/>
  596. public Dictionary<string, CustomProperty> CustomProperties
  597. {
  598. get
  599. {
  600. if (package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
  601. {
  602. PackagePart docProps_custom = package.GetPart(new Uri("/docProps/custom.xml", UriKind.Relative));
  603. XDocument customPropDoc;
  604. using (TextReader tr = new StreamReader(docProps_custom.GetStream(FileMode.Open, FileAccess.Read)))
  605. customPropDoc = XDocument.Load(tr, LoadOptions.PreserveWhitespace);
  606. // Get all of the custom properties in this document
  607. return
  608. (
  609. from p in customPropDoc.Descendants(XName.Get("property", customPropertiesSchema.NamespaceName))
  610. let Name = p.Attribute(XName.Get("name")).Value
  611. let Type = p.Descendants().Single().Name.LocalName
  612. let Value = p.Descendants().Single().Value
  613. select new CustomProperty(Name, Type, Value)
  614. ).ToDictionary(p => p.Name, StringComparer.CurrentCultureIgnoreCase);
  615. }
  616. return new Dictionary<string, CustomProperty>();
  617. }
  618. }
  619. ///<summary>
  620. /// Returns the list of document core properties with corresponding values.
  621. ///</summary>
  622. public Dictionary<string, string> CoreProperties
  623. {
  624. get
  625. {
  626. if (package.PartExists(new Uri("/docProps/core.xml", UriKind.Relative)))
  627. {
  628. PackagePart docProps_Core = package.GetPart(new Uri("/docProps/core.xml", UriKind.Relative));
  629. XDocument corePropDoc;
  630. using (TextReader tr = new StreamReader(docProps_Core.GetStream(FileMode.Open, FileAccess.Read)))
  631. corePropDoc = XDocument.Load(tr, LoadOptions.PreserveWhitespace);
  632. // Get all of the core properties in this document
  633. return (from docProperty in corePropDoc.Root.Elements()
  634. select
  635. new KeyValuePair<string, string>(
  636. string.Format(
  637. "{0}:{1}",
  638. corePropDoc.Root.GetPrefixOfNamespace(docProperty.Name.Namespace),
  639. docProperty.Name.LocalName),
  640. docProperty.Value)).ToDictionary(p => p.Key, v => v.Value);
  641. }
  642. return new Dictionary<string, string>();
  643. }
  644. }
  645. /// <summary>
  646. /// Get the Text of this document.
  647. /// </summary>
  648. /// <example>
  649. /// Write to Console the Text from this document.
  650. /// <code>
  651. /// // Load a document
  652. /// DocX document = DocX.Load(@"C:\Example\Test.docx");
  653. ///
  654. /// // Get the text of this document.
  655. /// string text = document.Text;
  656. ///
  657. /// // Write the text of this document to Console.
  658. /// Console.Write(text);
  659. ///
  660. /// // Wait for the user to press a key before closing the console window.
  661. /// Console.ReadKey();
  662. /// </code>
  663. /// </example>
  664. public string Text
  665. {
  666. get
  667. {
  668. return HelperFunctions.GetText(Xml);
  669. }
  670. }
  671. internal string GetCollectiveText(List<PackagePart> list)
  672. {
  673. string text = string.Empty;
  674. foreach (var hp in list)
  675. {
  676. using (TextReader tr = new StreamReader(hp.GetStream()))
  677. {
  678. XDocument d = XDocument.Load(tr);
  679. StringBuilder sb = new StringBuilder();
  680. // Loop through each text item in this run
  681. foreach (XElement descendant in d.Descendants())
  682. {
  683. switch (descendant.Name.LocalName)
  684. {
  685. case "tab":
  686. sb.Append("\t");
  687. break;
  688. case "br":
  689. sb.Append("\n");
  690. break;
  691. case "t":
  692. goto case "delText";
  693. case "delText":
  694. sb.Append(descendant.Value);
  695. break;
  696. default: break;
  697. }
  698. }
  699. text += "\n" + sb.ToString();
  700. }
  701. }
  702. return text;
  703. }
  704. /// <summary>
  705. /// Insert the contents of another document at the end of this document.
  706. /// </summary>
  707. /// <param name="document">The document to insert at the end of this document.</param>
  708. /// <example>
  709. /// Create a new document and insert an old document into it.
  710. /// <code>
  711. /// // Create a new document.
  712. /// using (DocX newDocument = DocX.Create(@"NewDocument.docx"))
  713. /// {
  714. /// // Load an old document.
  715. /// using (DocX oldDocument = DocX.Load(@"OldDocument.docx"))
  716. /// {
  717. /// // Insert the old document into the new document.
  718. /// newDocument.InsertDocument(oldDocument);
  719. ///
  720. /// // Save the new document.
  721. /// newDocument.Save();
  722. /// }// Release the old document from memory.
  723. /// }// Release the new document from memory.
  724. /// </code>
  725. /// <remarks>
  726. /// If the document being inserted contains Images, CustomProperties and or custom styles, these will be correctly inserted into the new document. In the case of Images, new ID's are generated for the Images being inserted to avoid ID conflicts. CustomProperties with the same name will be ignored not replaced.
  727. /// </remarks>
  728. /// </example>
  729. public void InsertDocument(DocX document)
  730. {
  731. #region /word/document.xml
  732. // Get the external elements that are going to be inserted.
  733. IEnumerable<XElement> external_elements = document.mainDoc.Root.Element(XName.Get("body", DocX.w.NamespaceName)).Elements();
  734. // Get the body element of the internal document.
  735. XElement internal_body = mainDoc.Root.Element(XName.Get("body", DocX.w.NamespaceName));
  736. // Insert the elements
  737. internal_body.Add(external_elements);
  738. // A moment of genius
  739. int count = external_elements.Count();
  740. external_elements = internal_body.Elements().Reverse().TakeWhile((i, j) => j < count);
  741. #endregion
  742. #region /word/styles.xml
  743. Uri word_styles_Uri = new Uri("/word/styles.xml", UriKind.Relative);
  744. // If the external document has a styles.xml, we need to insert its elements into the internal documents styles.xml.
  745. if (document.package.PartExists(word_styles_Uri))
  746. {
  747. // Load the external documents styles.xml into memory.
  748. XDocument external_word_styles;
  749. using (TextReader tr = new StreamReader(document.package.GetPart(word_styles_Uri).GetStream()))
  750. external_word_styles = XDocument.Load(tr);
  751. // If the internal document contains no /word/styles.xml create one.
  752. if (!package.PartExists(word_styles_Uri))
  753. HelperFunctions.AddDefaultStylesXml(package);
  754. // Load the internal documents styles.xml into memory.
  755. XDocument internal_word_styles;
  756. using (TextReader tr = new StreamReader(package.GetPart(word_styles_Uri).GetStream()))
  757. internal_word_styles = XDocument.Load(tr);
  758. // Create a list of internal and external style elements for easy iteration.
  759. var internal_style_list = internal_word_styles.Root.Elements(XName.Get("style", DocX.w.NamespaceName));
  760. var external_style_list = external_word_styles.Root.Elements(XName.Get("style", DocX.w.NamespaceName));
  761. // Loop through the external style elements
  762. foreach (XElement style in external_style_list)
  763. {
  764. // If the internal styles document does not contain this element, add it.
  765. if (!internal_style_list.Contains(style))
  766. internal_word_styles.Root.Add(style);
  767. }
  768. // Save the internal styles document.
  769. using (TextWriter tw = new StreamWriter(package.GetPart(word_styles_Uri).GetStream()))
  770. internal_word_styles.Save(tw);
  771. }
  772. #endregion
  773. #region Images
  774. PackagePart internal_word_document = mainPart;
  775. PackagePart external_word_document = document.mainPart;
  776. // Get all Image relationships in the external document.
  777. var external_image_rels = external_word_document.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
  778. // Get all Image relationships in the internal document.
  779. var internal_image_rels = internal_word_document.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
  780. var internal_image_parts = internal_image_rels.Select(ir => package.GetParts().Where(p => p.Uri.ToString().EndsWith(ir.TargetUri.ToString())).First());
  781. int max = 0;
  782. var values =
  783. (
  784. from ip in internal_image_parts
  785. let Name = Path.GetFileNameWithoutExtension(ip.Uri.ToString())
  786. let Number = Regex.Match(Name, @"\d+$").Value
  787. select Number != string.Empty ? int.Parse(Number) : 0
  788. );
  789. if (values.Count() > 0)
  790. max = Math.Max(max, values.Max());
  791. // Foreach external image relationship
  792. foreach (var rel in external_image_rels)
  793. {
  794. string uri_string = rel.TargetUri.ToString();
  795. if (!uri_string.StartsWith("/"))
  796. uri_string = "/" + uri_string;
  797. PackagePart external_image_part = rel.Package.GetPart(new Uri("/word" + uri_string, UriKind.RelativeOrAbsolute));
  798. PackagePart internal_image_part = package.CreatePart(new Uri(string.Format("/word/media/image{0}.jpeg", max + 1), UriKind.RelativeOrAbsolute), System.Net.Mime.MediaTypeNames.Image.Jpeg);
  799. PackageRelationship pr = internal_word_document.CreateRelationship(internal_image_part.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
  800. var query = from e in external_elements.DescendantsAndSelf()
  801. let embed = e.Attribute(XName.Get("embed", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"))
  802. where embed != null && embed.Value == rel.Id
  803. select embed;
  804. foreach (XAttribute a in query)
  805. a.Value = pr.Id;
  806. using (Stream stream = internal_image_part.GetStream(FileMode.Create, FileAccess.Write))
  807. {
  808. using (Stream s = external_image_part.GetStream())
  809. {
  810. byte[] bytes = new byte[s.Length];
  811. s.Read(bytes, 0, (int)s.Length);
  812. stream.Write(bytes, 0, (int)s.Length);
  813. }
  814. }
  815. max++;
  816. }
  817. #endregion
  818. #region CustomProperties
  819. // Check if the external document contains custom properties.
  820. if (document.package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
  821. {
  822. PackagePart external_docProps_custom = document.package.GetPart(new Uri("/docProps/custom.xml", UriKind.Relative));
  823. XDocument external_customPropDoc;
  824. using (TextReader tr = new StreamReader(external_docProps_custom.GetStream(FileMode.Open, FileAccess.Read)))
  825. external_customPropDoc = XDocument.Load(tr, LoadOptions.PreserveWhitespace);
  826. // Get all of the custom properties in this document.
  827. IEnumerable<XElement> external_customProperties =
  828. (
  829. from cp in external_customPropDoc.Descendants(XName.Get("property", customPropertiesSchema.NamespaceName))
  830. select cp
  831. );
  832. // If the internal document does not contain a customFilePropertyPart, create one.
  833. if (!package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
  834. HelperFunctions.CreateCustomPropertiesPart(this);
  835. PackagePart internal_docProps_custom = package.GetPart(new Uri("/docProps/custom.xml", UriKind.Relative));
  836. XDocument internal_customPropDoc;
  837. using (TextReader tr = new StreamReader(internal_docProps_custom.GetStream(FileMode.Open, FileAccess.Read)))
  838. internal_customPropDoc = XDocument.Load(tr, LoadOptions.PreserveWhitespace);
  839. foreach (XElement cp in external_customProperties)
  840. {
  841. // Does the internal document already have a custom property with this name?
  842. XElement conflict =
  843. (
  844. from d in internal_customPropDoc.Descendants(XName.Get("property", customPropertiesSchema.NamespaceName))
  845. let ExternalName = d.Attribute(XName.Get("name", customPropertiesSchema.NamespaceName))
  846. let InternalName = cp.Attribute(XName.Get("name", customPropertiesSchema.NamespaceName))
  847. where ExternalName != null && InternalName != null && ExternalName == InternalName
  848. select d
  849. ).FirstOrDefault();
  850. // Same name
  851. if (conflict != null)
  852. {
  853. }
  854. // There is no conflict, just add the Custom Property.
  855. else
  856. internal_customPropDoc.Root.Add(cp);
  857. }
  858. using (TextWriter tw = new StreamWriter(internal_docProps_custom.GetStream(FileMode.Open, FileAccess.Write)))
  859. internal_customPropDoc.Save(tw);
  860. }
  861. #endregion
  862. // A document can only have one header and one footer.
  863. #region Remove external (header & footer) references
  864. var externalHeaderAndFooterReferences =
  865. (
  866. from d in external_elements.Descendants()
  867. where d.Name.LocalName == "headerReference" || d.Name.LocalName == "footerReference"
  868. select d
  869. );
  870. foreach (var r in externalHeaderAndFooterReferences.ToList())
  871. r.Remove();
  872. #endregion
  873. }
  874. /// <summary>
  875. /// Insert a new Table at the end of this document.
  876. /// </summary>
  877. /// <param name="coloumnCount">The number of coloumns to create.</param>
  878. /// <param name="rowCount">The number of rows to create.</param>
  879. /// <returns>A new Table.</returns>
  880. /// <example>
  881. /// Insert a new Table with 2 coloumns and 3 rows, at the end of a document.
  882. /// <code>
  883. /// // Create a document.
  884. /// using (DocX document = DocX.Create(@"C:\Example\Test.docx"))
  885. /// {
  886. /// // Create a new Table with 2 coloumns and 3 rows.
  887. /// Table newTable = document.InsertTable(2, 3);
  888. ///
  889. /// // Set the design of this Table.
  890. /// newTable.Design = TableDesign.LightShadingAccent2;
  891. ///
  892. /// // Set the coloumn names.
  893. /// newTable.Rows[0].Cells[0].Paragraph.InsertText("Ice Cream", false);
  894. /// newTable.Rows[0].Cells[1].Paragraph.InsertText("Price", false);
  895. ///
  896. /// // Fill row 1
  897. /// newTable.Rows[1].Cells[0].Paragraph.InsertText("Chocolate", false);
  898. /// newTable.Rows[1].Cells[1].Paragraph.InsertText("€3:50", false);
  899. ///
  900. /// // Fill row 2
  901. /// newTable.Rows[2].Cells[0].Paragraph.InsertText("Vanilla", false);
  902. /// newTable.Rows[2].Cells[1].Paragraph.InsertText("€3:00", false);
  903. ///
  904. /// // Save all changes made to document b.
  905. /// document.Save();
  906. /// }// Release this document from memory.
  907. /// </code>
  908. /// </example>
  909. public new Table InsertTable(int rowCount, int coloumnCount)
  910. {
  911. if (rowCount < 1 || coloumnCount < 1)
  912. throw new ArgumentOutOfRangeException("Row and Coloumn count must be greater than zero.");
  913. Table t = base.InsertTable(rowCount, coloumnCount);
  914. t.mainPart = mainPart;
  915. return t;
  916. }
  917. public Table AddTable(int rowCount, int coloumnCount)
  918. {
  919. if (rowCount < 1 || coloumnCount < 1)
  920. throw new ArgumentOutOfRangeException("Row and Coloumn count must be greater than zero.");
  921. Table t = new Table(this, HelperFunctions.CreateTable(rowCount, coloumnCount));
  922. t.mainPart = mainPart;
  923. return t;
  924. }
  925. /// <summary>
  926. /// Insert a Table into this document. The Table's source can be a completely different document.
  927. /// </summary>
  928. /// <param name="t">The Table to insert.</param>
  929. /// <param name="index">The index to insert this Table at.</param>
  930. /// <returns>The Table now associated with this document.</returns>
  931. /// <example>
  932. /// Extract a Table from document a and insert it into document b, at index 10.
  933. /// <code>
  934. /// // Place holder for a Table.
  935. /// Table t;
  936. ///
  937. /// // Load document a.
  938. /// using (DocX documentA = DocX.Load(@"C:\Example\a.docx"))
  939. /// {
  940. /// // Get the first Table from this document.
  941. /// t = documentA.Tables[0];
  942. /// }
  943. ///
  944. /// // Load document b.
  945. /// using (DocX documentB = DocX.Load(@"C:\Example\b.docx"))
  946. /// {
  947. /// /*
  948. /// * Insert the Table that was extracted from document a, into document b.
  949. /// * This creates a new Table that is now associated with document b.
  950. /// */
  951. /// Table newTable = documentB.InsertTable(10, t);
  952. ///
  953. /// // Save all changes made to document b.
  954. /// documentB.Save();
  955. /// }// Release this document from memory.
  956. /// </code>
  957. /// </example>
  958. public new Table InsertTable(int index, Table t)
  959. {
  960. Table t2 = base.InsertTable(index, t);
  961. t2.mainPart = mainPart;
  962. return t2;
  963. }
  964. /// <summary>
  965. /// Insert a Table into this document. The Table's source can be a completely different document.
  966. /// </summary>
  967. /// <param name="t">The Table to insert.</param>
  968. /// <returns>The Table now associated with this document.</returns>
  969. /// <example>
  970. /// Extract a Table from document a and insert it at the end of document b.
  971. /// <code>
  972. /// // Place holder for a Table.
  973. /// Table t;
  974. ///
  975. /// // Load document a.
  976. /// using (DocX documentA = DocX.Load(@"C:\Example\a.docx"))
  977. /// {
  978. /// // Get the first Table from this document.
  979. /// t = documentA.Tables[0];
  980. /// }
  981. ///
  982. /// // Load document b.
  983. /// using (DocX documentB = DocX.Load(@"C:\Example\b.docx"))
  984. /// {
  985. /// /*
  986. /// * Insert the Table that was extracted from document a, into document b.
  987. /// * This creates a new Table that is now associated with document b.
  988. /// */
  989. /// Table newTable = documentB.InsertTable(t);
  990. ///
  991. /// // Save all changes made to document b.
  992. /// documentB.Save();
  993. /// }// Release this document from memory.
  994. /// </code>
  995. /// </example>
  996. public new Table InsertTable(Table t)
  997. {
  998. t = base.InsertTable(t);
  999. t.mainPart = mainPart;
  1000. return t;
  1001. }
  1002. /// <summary>
  1003. /// Insert a new Table at the end of this document.
  1004. /// </summary>
  1005. /// <param name="coloumnCount">The number of coloumns to create.</param>
  1006. /// <param name="rowCount">The number of rows to create.</param>
  1007. /// <param name="index">The index to insert this Table at.</param>
  1008. /// <returns>A new Table.</returns>
  1009. /// <example>
  1010. /// Insert a new Table with 2 coloumns and 3 rows, at index 37 in this document.
  1011. /// <code>
  1012. /// // Create a document.
  1013. /// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
  1014. /// {
  1015. /// // Create a new Table with 3 rows and 2 coloumns. Insert this Table at index 37.
  1016. /// Table newTable = document.InsertTable(37, 3, 2);
  1017. ///
  1018. /// // Set the design of this Table.
  1019. /// newTable.Design = TableDesign.LightShadingAccent3;
  1020. ///
  1021. /// // Set the coloumn names.
  1022. /// newTable.Rows[0].Cells[0].Paragraph.InsertText("Ice Cream", false);
  1023. /// newTable.Rows[0].Cells[1].Paragraph.InsertText("Price", false);
  1024. ///
  1025. /// // Fill row 1
  1026. /// newTable.Rows[1].Cells[0].Paragraph.InsertText("Chocolate", false);
  1027. /// newTable.Rows[1].Cells[1].Paragraph.InsertText("€3:50", false);
  1028. ///
  1029. /// // Fill row 2
  1030. /// newTable.Rows[2].Cells[0].Paragraph.InsertText("Vanilla", false);
  1031. /// newTable.Rows[2].Cells[1].Paragraph.InsertText("€3:00", false);
  1032. ///
  1033. /// // Save all changes made to document b.
  1034. /// document.Save();
  1035. /// }// Release this document from memory.
  1036. /// </code>
  1037. /// </example>
  1038. public new Table InsertTable(int index, int rowCount, int coloumnCount)
  1039. {
  1040. if (rowCount < 1 || coloumnCount < 1)
  1041. throw new ArgumentOutOfRangeException("Row and Column count must be greater than zero.");
  1042. Table t = InsertTable(index, rowCount, coloumnCount);
  1043. t.mainPart = mainPart;
  1044. return t;
  1045. }
  1046. /// <summary>
  1047. /// Creates a document using a Stream.
  1048. /// </summary>
  1049. /// <param name="stream">The Stream to create the document from.</param>
  1050. /// <returns>Returns a DocX object which represents the document.</returns>
  1051. /// <example>
  1052. /// Creating a document from a FileStream.
  1053. /// <code>
  1054. /// // Use a FileStream fs to create a new document.
  1055. /// using(FileStream fs = new FileStream(@"C:\Example\Test.docx", FileMode.Create))
  1056. /// {
  1057. /// // Load the document using fs
  1058. /// using (DocX document = DocX.Create(fs))
  1059. /// {
  1060. /// // Do something with the document here.
  1061. ///
  1062. /// // Save all changes made to this document.
  1063. /// document.Save();
  1064. /// }// Release this document from memory.
  1065. /// }
  1066. /// </code>
  1067. /// </example>
  1068. /// <example>
  1069. /// Creating a document in a SharePoint site.
  1070. /// <code>
  1071. /// using(SPSite mySite = new SPSite("http://server/sites/site"))
  1072. /// {
  1073. /// // Open a connection to the SharePoint site
  1074. /// using(SPWeb myWeb = mySite.OpenWeb())
  1075. /// {
  1076. /// // Create a MemoryStream ms.
  1077. /// using (MemoryStream ms = new MemoryStream())
  1078. /// {
  1079. /// // Create a document using ms.
  1080. /// using (DocX document = DocX.Create(ms))
  1081. /// {
  1082. /// // Do something with the document here.
  1083. ///
  1084. /// // Save all changes made to this document.
  1085. /// document.Save();
  1086. /// }// Release this document from memory
  1087. ///
  1088. /// // Add the document to the SharePoint site
  1089. /// web.Files.Add("filename", ms.ToArray(), true);
  1090. /// }
  1091. /// }
  1092. /// }
  1093. /// </code>
  1094. /// </example>
  1095. /// <seealso cref="DocX.Create(string)"/>
  1096. /// <seealso cref="DocX.Load(System.IO.Stream)"/>
  1097. /// <seealso cref="DocX.Load(string)"/>
  1098. /// <seealso cref="DocX.Save()"/>
  1099. public static DocX Create(Stream stream)
  1100. {
  1101. // Store this document in memory
  1102. MemoryStream ms = new MemoryStream();
  1103. // Create the docx package
  1104. Package package = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
  1105. PostCreation(ref package);
  1106. DocX document = DocX.Load(ms);
  1107. document.stream = stream;
  1108. return document;
  1109. }
  1110. /// <summary>
  1111. /// Creates a document using a fully qualified or relative filename.
  1112. /// </summary>
  1113. /// <param name="filename">The fully qualified or relative filename.</param>
  1114. /// <returns>Returns a DocX object which represents the document.</returns>
  1115. /// <example>
  1116. /// <code>
  1117. /// // Create a document using a relative filename.
  1118. /// using (DocX document = DocX.Create(@"..\Test.docx"))
  1119. /// {
  1120. /// // Do something with the document here.
  1121. ///
  1122. /// // Save all changes made to this document.
  1123. /// document.Save();
  1124. /// }// Release this document from memory
  1125. /// </code>
  1126. /// <code>
  1127. /// // Create a document using a relative filename.
  1128. /// using (DocX document = DocX.Create(@"..\Test.docx"))
  1129. /// {
  1130. /// // Do something with the document here.
  1131. ///
  1132. /// // Save all changes made to this document.
  1133. /// document.Save();
  1134. /// }// Release this document from memory
  1135. /// </code>
  1136. /// <seealso cref="DocX.Create(System.IO.Stream)"/>
  1137. /// <seealso cref="DocX.Load(System.IO.Stream)"/>
  1138. /// <seealso cref="DocX.Load(string)"/>
  1139. /// <seealso cref="DocX.Save()"/>
  1140. /// </example>
  1141. public static DocX Create(string filename)
  1142. {
  1143. // Store this document in memory
  1144. MemoryStream ms = new MemoryStream();
  1145. // Create the docx package
  1146. //WordprocessingDocument wdDoc = WordprocessingDocument.Create(ms, DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
  1147. Package package = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
  1148. PostCreation(ref package);
  1149. DocX document = DocX.Load(ms);
  1150. document.filename = filename;
  1151. return document;
  1152. }
  1153. internal static void PostCreation(ref Package package)
  1154. {
  1155. XDocument mainDoc, stylesDoc;
  1156. #region MainDocumentPart
  1157. // Create the main document part for this package
  1158. PackagePart mainDocumentPart = package.CreatePart(new Uri("/word/document.xml", UriKind.Relative), "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml");
  1159. package.CreateRelationship(mainDocumentPart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument");
  1160. // Load the document part into a XDocument object
  1161. using (TextReader tr = new StreamReader(mainDocumentPart.GetStream(FileMode.Create, FileAccess.ReadWrite)))
  1162. {
  1163. mainDoc = XDocument.Parse
  1164. (@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
  1165. <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"" xmlns:a=""http://schemas.openxmlformats.org/drawingml/2006/main"" xmlns:c=""http://schemas.openxmlformats.org/drawingml/2006/chart"">
  1166. <w:body>
  1167. <w:sectPr w:rsidR=""003E25F4"" w:rsidSect=""00FC3028"">
  1168. <w:pgSz w:w=""11906"" w:h=""16838""/>
  1169. <w:pgMar w:top=""1440"" w:right=""1440"" w:bottom=""1440"" w:left=""1440"" w:header=""708"" w:footer=""708"" w:gutter=""0""/>
  1170. <w:cols w:space=""708""/>
  1171. <w:docGrid w:linePitch=""360""/>
  1172. </w:sectPr>
  1173. </w:body>
  1174. </w:document>"
  1175. );
  1176. }
  1177. // Save the main document
  1178. using (TextWriter tw = new StreamWriter(mainDocumentPart.GetStream(FileMode.Create, FileAccess.Write)))
  1179. mainDoc.Save(tw, SaveOptions.DisableFormatting);
  1180. #endregion
  1181. #region StylePart
  1182. stylesDoc = HelperFunctions.AddDefaultStylesXml(package);
  1183. #endregion
  1184. package.Close();
  1185. }
  1186. internal static DocX PostLoad(ref Package package)
  1187. {
  1188. DocX document = new DocX(null, null);
  1189. document.package = package;
  1190. document.Document = document;
  1191. #region MainDocumentPart
  1192. document.mainPart = package.GetParts().Where
  1193. (
  1194. p => p.ContentType.Equals
  1195. (
  1196. "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
  1197. StringComparison.CurrentCultureIgnoreCase
  1198. )
  1199. ).Single();
  1200. using (TextReader tr = new StreamReader(document.mainPart.GetStream(FileMode.Open, FileAccess.Read)))
  1201. document.mainDoc = XDocument.Load(tr, LoadOptions.PreserveWhitespace);
  1202. #endregion
  1203. PopulateDocument(document, package);
  1204. using (TextReader tr = new StreamReader(document.settingsPart.GetStream()))
  1205. document.settings = XDocument.Load(tr);
  1206. return document;
  1207. }
  1208. private static void PopulateDocument(DocX document, Package package)
  1209. {
  1210. Headers headers = new Headers();
  1211. headers.odd = document.GetHeaderByType("default");
  1212. headers.even = document.GetHeaderByType("even");
  1213. headers.first = document.GetHeaderByType("first");
  1214. Footers footers = new Footers();
  1215. footers.odd = document.GetFooterByType("default");
  1216. footers.even = document.GetFooterByType("even");
  1217. footers.first = document.GetFooterByType("first");
  1218. //// Get the sectPr for this document.
  1219. //XElement sectPr = document.mainDoc.Descendants(XName.Get("sectPr", DocX.w.NamespaceName)).Single();
  1220. //if (sectPr != null)
  1221. //{
  1222. // // Extract the even header reference
  1223. // var header_even_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "headerReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "even");
  1224. // string id = header_even_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value;
  1225. // var res = document.mainPart.GetRelationship(id);
  1226. // string ans = res.SourceUri.OriginalString;
  1227. // headers.even.xml_filename = ans;
  1228. // // Extract the odd header reference
  1229. // var header_odd_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "headerReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "default");
  1230. // string id2 = header_odd_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value;
  1231. // var res2 = document.mainPart.GetRelationship(id2);
  1232. // string ans2 = res2.SourceUri.OriginalString;
  1233. // headers.odd.xml_filename = ans2;
  1234. // // Extract the first header reference
  1235. // var header_first_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "h
  1236. //eaderReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "first");
  1237. // string id3 = header_first_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value;
  1238. // var res3 = document.mainPart.GetRelationship(id3);
  1239. // string ans3 = res3.SourceUri.OriginalString;
  1240. // headers.first.xml_filename = ans3;
  1241. // // Extract the even footer reference
  1242. // var footer_even_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "footerReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "even");
  1243. // string id4 = footer_even_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value;
  1244. // var res4 = document.mainPart.GetRelationship(id4);
  1245. // string ans4 = res4.SourceUri.OriginalString;
  1246. // footers.even.xml_filename = ans4;
  1247. // // Extract the odd footer reference
  1248. // var footer_odd_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "footerReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "default");
  1249. // string id5 = footer_odd_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value;
  1250. // var res5 = document.mainPart.GetRelationship(id5);
  1251. // string ans5 = res5.SourceUri.OriginalString;
  1252. // footers.odd.xml_filename = ans5;
  1253. // // Extract the first footer reference
  1254. // var footer_first_ref = sectPr.Elements().SingleOrDefault(x => x.Name.LocalName == "footerReference" && x.Attribute(XName.Get("type", DocX.w.NamespaceName)) != null && x.Attribute(XName.Get("type", DocX.w.NamespaceName)).Value == "first");
  1255. // string id6 = footer_first_ref.Attribute(XName.Get("id", DocX.r.NamespaceName)).Value;
  1256. // var res6 = document.mainPart.GetRelationship(id6);
  1257. // string ans6 = res6.SourceUri.OriginalString;
  1258. // footers.first.xml_filename = ans6;
  1259. //}
  1260. document.Xml = document.mainDoc.Root.Element(w + "body");
  1261. document.headers = headers;
  1262. document.footers = footers;
  1263. document.settingsPart = HelperFunctions.CreateOrGetSettingsPart(package);
  1264. }
  1265. /// <summary>
  1266. /// Loads a document into a DocX object using a Stream.
  1267. /// </summary>
  1268. /// <param name="stream">The Stream to load the document from.</param>
  1269. /// <returns>
  1270. /// Returns a DocX object which represents the document.
  1271. /// </returns>
  1272. /// <example>
  1273. /// Loading a document from a FileStream.
  1274. /// <code>
  1275. /// // Open a FileStream fs to a document.
  1276. /// using (FileStream fs = new FileStream(@"C:\Example\Test.docx", FileMode.Open))
  1277. /// {
  1278. /// // Load the document using fs.
  1279. /// using (DocX document = DocX.Load(fs))
  1280. /// {
  1281. /// // Do something with the document here.
  1282. ///
  1283. /// // Save all changes made to the document.
  1284. /// document.Save();
  1285. /// }// Release this document from memory.
  1286. /// }
  1287. /// </code>
  1288. /// </example>
  1289. /// <example>
  1290. /// Loading a document from a SharePoint site.
  1291. /// <code>
  1292. /// // Get the SharePoint site that you want to access.
  1293. /// using (SPSite mySite = new SPSite("http://server/sites/site"))
  1294. /// {
  1295. /// // Open a connection to the SharePoint site
  1296. /// using (SPWeb myWeb = mySite.OpenWeb())
  1297. /// {
  1298. /// // Grab a document stored on this site.
  1299. /// SPFile file = web.GetFile("Source_Folder_Name/Source_File");
  1300. ///
  1301. /// // DocX.Load requires a Stream, so open a Stream to this document.
  1302. /// Stream str = new MemoryStream(file.OpenBinary());
  1303. ///
  1304. /// // Load the file using the Stream str.
  1305. /// using (DocX document = DocX.Load(str))
  1306. /// {
  1307. /// // Do something with the document here.
  1308. ///
  1309. /// // Save all changes made to the document.
  1310. /// document.Save();
  1311. /// }// Release this document from memory.
  1312. /// }
  1313. /// }
  1314. /// </code>
  1315. /// </example>
  1316. /// <seealso cref="DocX.Load(string)"/>
  1317. /// <seealso cref="DocX.Create(System.IO.Stream)"/>
  1318. /// <seealso cref="DocX.Create(string)"/>
  1319. /// <seealso cref="DocX.Save()"/>
  1320. public static DocX Load(Stream stream)
  1321. {
  1322. MemoryStream ms = new MemoryStream();
  1323. stream.Position = 0;
  1324. byte[] data = new byte[stream.Length];
  1325. stream.Read(data, 0, (int)stream.Length);
  1326. ms.Write(data, 0, (int)stream.Length);
  1327. // Open the docx package
  1328. Package package = Package.Open(ms, FileMode.Open, FileAccess.ReadWrite);
  1329. DocX document = PostLoad(ref package);
  1330. document.package = package;
  1331. document.memoryStream = ms;
  1332. document.stream = stream;
  1333. return document;
  1334. }
  1335. /// <summary>
  1336. /// Loads a document into a DocX object using a fully qualified or relative filename.
  1337. /// </summary>
  1338. /// <param name="filename">The fully qualified or relative filename.</param>
  1339. /// <returns>
  1340. /// Returns a DocX object which represents the document.
  1341. /// </returns>
  1342. /// <example>
  1343. /// <code>
  1344. /// // Load a document using its fully qualified filename
  1345. /// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
  1346. /// {
  1347. /// // Do something with the document here
  1348. ///
  1349. /// // Save all changes made to document.
  1350. /// document.Save();
  1351. /// }// Release this document from memory.
  1352. /// </code>
  1353. /// <code>
  1354. /// // Load a document using its relative filename.
  1355. /// using(DocX document = DocX.Load(@"..\..\Test.docx"))
  1356. /// {
  1357. /// // Do something with the document here.
  1358. ///
  1359. /// // Save all changes made to document.
  1360. /// document.Save();
  1361. /// }// Release this document from memory.
  1362. /// </code>
  1363. /// <seealso cref="DocX.Load(System.IO.Stream)"/>
  1364. /// <seealso cref="DocX.Create(System.IO.Stream)"/>
  1365. /// <seealso cref="DocX.Create(string)"/>
  1366. /// <seealso cref="DocX.Save()"/>
  1367. /// </example>
  1368. public static DocX Load(string filename)
  1369. {
  1370. if (!File.Exists(filename))
  1371. throw new FileNotFoundException(string.Format("File could not be found {0}", filename));
  1372. MemoryStream ms = new MemoryStream();
  1373. using (FileStream fs = new FileStream(filename, FileMode.Open))
  1374. {
  1375. byte[] data = new byte[fs.Length];
  1376. fs.Read(data, 0, (int)fs.Length);
  1377. ms.Write(data, 0, (int)fs.Length);
  1378. }
  1379. // Open the docx package
  1380. Package package = Package.Open(ms, FileMode.Open, FileAccess.ReadWrite);
  1381. DocX document = PostLoad(ref package);
  1382. document.package = package;
  1383. document.filename = filename;
  1384. document.memoryStream = ms;
  1385. return document;
  1386. }
  1387. ///<summary>
  1388. /// Applies document template to the document. Document template may include styles, headers, footers, properties, etc. as well as text content.
  1389. ///</summary>
  1390. ///<param name="templateFilePath">The path to the document template file.</param>
  1391. ///<exception cref="FileNotFoundException">The document template file not found.</exception>
  1392. public void ApplyTemplate(string templateFilePath)
  1393. {
  1394. ApplyTemplate(templateFilePath, true);
  1395. }
  1396. ///<summary>
  1397. /// Applies document template to the document. Document template may include styles, headers, footers, properties, etc. as well as text content.
  1398. ///</summary>
  1399. ///<param name="templateFilePath">The path to the document template file.</param>
  1400. ///<param name="includeContent">Whether to copy the document template text content to document.</param>
  1401. ///<exception cref="FileNotFoundException">The document template file not found.</exception>
  1402. public void ApplyTemplate(string templateFilePath, bool includeContent)
  1403. {
  1404. if (!File.Exists(templateFilePath))
  1405. {
  1406. throw new FileNotFoundException(string.Format("File could not be found {0}", templateFilePath));
  1407. }
  1408. using (FileStream packageStream = new FileStream(templateFilePath, FileMode.Open, FileAccess.Read))
  1409. {
  1410. ApplyTemplate(packageStream, includeContent);
  1411. }
  1412. }
  1413. ///<summary>
  1414. /// Applies document template to the document. Document template may include styles, headers, footers, properties, etc. as well as text content.
  1415. ///</summary>
  1416. ///<param name="templateStream">The stream of the document template file.</param>
  1417. public void ApplyTemplate(Stream templateStream)
  1418. {
  1419. ApplyTemplate(templateStream, true);
  1420. }
  1421. ///<summary>
  1422. /// Applies document template to the document. Document template may include styles, headers, footers, properties, etc. as well as text content.
  1423. ///</summary>
  1424. ///<param name="templateStream">The stream of the document template file.</param>
  1425. ///<param name="includeContent">Whether to copy the document template text content to document.</param>
  1426. public void ApplyTemplate(Stream templateStream, bool includeContent)
  1427. {
  1428. Package templatePackage = Package.Open(templateStream);
  1429. try
  1430. {
  1431. PackagePart documentPart = null;
  1432. XDocument documentDoc = null;
  1433. foreach (PackagePart packagePart in templatePackage.GetParts())
  1434. {
  1435. switch (packagePart.Uri.ToString())
  1436. {
  1437. case "/word/document.xml":
  1438. documentPart = packagePart;
  1439. using (XmlReader xr = XmlReader.Create(packagePart.GetStream(FileMode.Open, FileAccess.Read)))
  1440. {
  1441. documentDoc = XDocument.Load(xr);
  1442. }
  1443. break;
  1444. case "/_rels/.rels":
  1445. if (!this.package.PartExists(packagePart.Uri))
  1446. {
  1447. this.package.CreatePart(packagePart.Uri, packagePart.ContentType, packagePart.CompressionOption);
  1448. }
  1449. PackagePart globalRelsPart = this.package.GetPart(packagePart.Uri);
  1450. using (
  1451. StreamReader tr = new StreamReader(
  1452. packagePart.GetStream(FileMode.Open, FileAccess.Read), Encoding.UTF8))
  1453. {
  1454. using (
  1455. StreamWriter tw = new StreamWriter(
  1456. globalRelsPart.GetStream(FileMode.Create, FileAccess.Write), Encoding.UTF8))
  1457. {
  1458. tw.Write(tr.ReadToEnd());
  1459. }
  1460. }
  1461. break;
  1462. case "/word/_rels/document.xml.rels":
  1463. break;
  1464. default:
  1465. if (!this.package.PartExists(packagePart.Uri))
  1466. {
  1467. this.package.CreatePart(packagePart.Uri, packagePart.ContentType, packagePart.CompressionOption);
  1468. }
  1469. Encoding packagePartEncoding = Encoding.Default;
  1470. if (packagePart.Uri.ToString().EndsWith(".xml") || packagePart.Uri.ToString().EndsWith(".rels"))
  1471. {
  1472. packagePartEncoding = Encoding.UTF8;
  1473. }
  1474. PackagePart nativePart = this.package.GetPart(packagePart.Uri);
  1475. using (
  1476. StreamReader tr = new StreamReader(
  1477. packagePart.GetStream(FileMode.Open, FileAccess.Read), packagePartEncoding))
  1478. {
  1479. using (
  1480. StreamWriter tw = new StreamWriter(
  1481. nativePart.GetStream(FileMode.Create, FileAccess.Write), tr.CurrentEncoding))
  1482. {
  1483. tw.Write(tr.ReadToEnd());
  1484. }
  1485. }
  1486. break;
  1487. }
  1488. }
  1489. if (documentPart != null)
  1490. {
  1491. string mainContentType = documentPart.ContentType.Replace("template.main", "document.main");
  1492. if (this.package.PartExists(documentPart.Uri))
  1493. {
  1494. this.package.DeletePart(documentPart.Uri);
  1495. }
  1496. PackagePart documentNewPart = this.package.CreatePart(
  1497. documentPart.Uri, mainContentType, documentPart.CompressionOption);
  1498. using (XmlWriter xw = XmlWriter.Create(documentNewPart.GetStream(FileMode.Create, FileAccess.Write)))
  1499. {
  1500. documentDoc.WriteTo(xw);
  1501. }
  1502. foreach (PackageRelationship documentPartRel in documentPart.GetRelationships())
  1503. {
  1504. documentNewPart.CreateRelationship(
  1505. documentPartRel.TargetUri,
  1506. documentPartRel.TargetMode,
  1507. documentPartRel.RelationshipType,
  1508. documentPartRel.Id);
  1509. }
  1510. this.mainPart = documentNewPart;
  1511. this.mainDoc = documentDoc;
  1512. PopulateDocument(this, templatePackage);
  1513. // DragonFire: I added next line and recovered ApplyTemplate method.
  1514. // I do it, becouse PopulateDocument(...) writes into field "settingsPart" the part of Template's package
  1515. // and after line "templatePackage.Close();" in finally, field "settingsPart" becomes not available and method "Save" throw an exception...
  1516. // That's why I recreated settingsParts and unlinked it from Template's package =)
  1517. settingsPart = HelperFunctions.CreateOrGetSettingsPart(package);
  1518. }
  1519. if (!includeContent)
  1520. {
  1521. foreach (Paragraph paragraph in this.Paragraphs)
  1522. {
  1523. paragraph.Remove(false);
  1524. }
  1525. }
  1526. }
  1527. finally
  1528. {
  1529. this.package.Flush();
  1530. var documentRelsPart = this.package.GetPart(new Uri("/word/_rels/document.xml.rels", UriKind.Relative));
  1531. using (TextReader tr = new StreamReader(documentRelsPart.GetStream(FileMode.Open, FileAccess.Read)))
  1532. {
  1533. tr.Read();
  1534. }
  1535. templatePackage.Close();
  1536. }
  1537. }
  1538. /// <summary>
  1539. /// Add an Image into this document from a fully qualified or relative filename.
  1540. /// </summary>
  1541. /// <param name="filename">The fully qualified or relative filename.</param>
  1542. /// <returns>An Image file.</returns>
  1543. /// <example>
  1544. /// Add an Image into this document from a fully qualified filename.
  1545. /// <code>
  1546. /// // Load a document.
  1547. /// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
  1548. /// {
  1549. /// // Add an Image from a file.
  1550. /// document.AddImage(@"C:\Example\Image.png");
  1551. ///
  1552. /// // Save all changes made to this document.
  1553. /// document.Save();
  1554. /// }// Release this document from memory.
  1555. /// </code>
  1556. /// </example>
  1557. /// <seealso cref="AddImage(System.IO.Stream)"/>
  1558. /// <seealso cref="Paragraph.InsertPicture"/>
  1559. public Image AddImage(string filename)
  1560. {
  1561. string contentType = "";
  1562. // The extension this file has will be taken to be its format.
  1563. switch (Path.GetExtension(filename))
  1564. {
  1565. case ".tiff": contentType = "image/tif"; break;
  1566. case ".tif": contentType = "image/tif"; break;
  1567. case ".png": contentType = "image/png"; break;
  1568. case ".bmp": contentType = "image/png"; break;
  1569. case ".gif": contentType = "image/gif"; break;
  1570. case ".jpg": contentType = "image/jpg"; break;
  1571. case ".jpeg": contentType = "image/jpeg"; break;
  1572. default: contentType = "image/jpg"; break;
  1573. }
  1574. return AddImage(filename as object, contentType);
  1575. }
  1576. /// <summary>
  1577. /// Add an Image into this document from a Stream.
  1578. /// </summary>
  1579. /// <param name="stream">A Stream stream.</param>
  1580. /// <returns>An Image file.</returns>
  1581. /// <example>
  1582. /// Add an Image into a document using a Stream.
  1583. /// <code>
  1584. /// // Open a FileStream fs to an Image.
  1585. /// using (FileStream fs = new FileStream(@"C:\Example\Image.jpg", FileMode.Open))
  1586. /// {
  1587. /// // Load a document.
  1588. /// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
  1589. /// {
  1590. /// // Add an Image from a filestream fs.
  1591. /// document.AddImage(fs);
  1592. ///
  1593. /// // Save all changes made to this document.
  1594. /// document.Save();
  1595. /// }// Release this document from memory.
  1596. /// }
  1597. /// </code>
  1598. /// </example>
  1599. /// <seealso cref="AddImage(string)"/>
  1600. /// <seealso cref="Paragraph.InsertPicture"/>
  1601. public Image AddImage(Stream stream)
  1602. {
  1603. return AddImage(stream as object);
  1604. }
  1605. /// <summary>
  1606. /// Adds a hyperlink to a document and creates a Paragraph which uses it.
  1607. /// </summary>
  1608. /// <param name="text">The text as displayed by the hyperlink.</param>
  1609. /// <param name="uri">The hyperlink itself.</param>
  1610. /// <returns>Returns a hyperlink that can be inserted into a Paragraph.</returns>
  1611. /// <example>
  1612. /// Adds a hyperlink to a document and creates a Paragraph which uses it.
  1613. /// <code>
  1614. /// // Create a document.
  1615. /// using (DocX document = DocX.Create(@"Test.docx"))
  1616. /// {
  1617. /// // Add a hyperlink to this document.
  1618. /// Hyperlink h = document.AddHyperlink("Google", new Uri("http://www.google.com"));
  1619. ///
  1620. /// // Add a new Paragraph to this document.
  1621. /// Paragraph p = document.InsertParagraph();
  1622. /// p.Append("My favourite search engine is ");
  1623. /// p.AppendHyperlink(h);
  1624. /// p.Append(", I think it's great.");
  1625. ///
  1626. /// // Save all changes made to this document.
  1627. /// document.Save();
  1628. /// }
  1629. /// </code>
  1630. /// </example>
  1631. public Hyperlink AddHyperlink(string text, Uri uri)
  1632. {
  1633. XElement i = new XElement
  1634. (
  1635. XName.Get("hyperlink", DocX.w.NamespaceName),
  1636. new XAttribute(r + "id", string.Empty),
  1637. new XAttribute(w + "history", "1"),
  1638. new XElement(XName.Get("r", DocX.w.NamespaceName),
  1639. new XElement(XName.Get("rPr", DocX.w.NamespaceName),
  1640. new XElement(XName.Get("rStyle", DocX.w.NamespaceName),
  1641. new XAttribute(w + "val", "Hyperlink"))),
  1642. new XElement(XName.Get("t", DocX.w.NamespaceName), text))
  1643. );
  1644. Hyperlink h = new Hyperlink(this, i);
  1645. h.Text = text;
  1646. h.Uri = uri;
  1647. AddHyperlinkStyleIfNotPresent();
  1648. return h;
  1649. }
  1650. internal void AddHyperlinkStyleIfNotPresent()
  1651. {
  1652. Uri word_styles_Uri = new Uri("/word/styles.xml", UriKind.Relative);
  1653. // If the internal document contains no /word/styles.xml create one.
  1654. if (!package.PartExists(word_styles_Uri))
  1655. HelperFunctions.AddDefaultStylesXml(package);
  1656. // Load the styles.xml into memory.
  1657. XDocument word_styles;
  1658. using (TextReader tr = new StreamReader(package.GetPart(word_styles_Uri).GetStream()))
  1659. word_styles = XDocument.Load(tr);
  1660. bool hyperlinkStyleExists =
  1661. (
  1662. from s in word_styles.Element(w + "styles").Elements()
  1663. let styleId = s.Attribute(XName.Get("styleId", w.NamespaceName))
  1664. where (styleId != null && styleId.Value == "Hyperlink")
  1665. select s
  1666. ).Count() > 0;
  1667. if (!hyperlinkStyleExists)
  1668. {
  1669. XElement style = new XElement
  1670. (
  1671. w + "style",
  1672. new XAttribute(w + "type", "character"),
  1673. new XAttribute(w + "styleId", "Hyperlink"),
  1674. new XElement(w + "name", new XAttribute(w + "val", "Hyperlink")),
  1675. new XElement(w + "basedOn", new XAttribute(w + "val", "DefaultParagraphFont")),
  1676. new XElement(w + "uiPriority", new XAttribute(w + "val", "99")),
  1677. new XElement(w + "unhideWhenUsed"),
  1678. new XElement(w + "rsid", new XAttribute(w + "val", "0005416C")),
  1679. new XElement
  1680. (
  1681. w + "rPr",
  1682. new XElement(w + "color", new XAttribute(w + "val", "0000FF"), new XAttribute(w + "themeColor", "hyperlink")),
  1683. new XElement
  1684. (
  1685. w + "u",
  1686. new XAttribute(w + "val", "single")
  1687. )
  1688. )
  1689. );
  1690. word_styles.Element(w + "styles").Add(style);
  1691. // Save the styles document.
  1692. using (TextWriter tw = new StreamWriter(package.GetPart(word_styles_Uri).GetStream()))
  1693. word_styles.Save(tw);
  1694. }
  1695. }
  1696. private string GetNextFreeRelationshipID()
  1697. {
  1698. string id =
  1699. (
  1700. from r in mainPart.GetRelationships()
  1701. select r.Id
  1702. ).Max();
  1703. // The convension for ids is rid01, rid02, etc
  1704. string newId = id.Replace("rId", "");
  1705. int result;
  1706. if (int.TryParse(newId, out result))
  1707. return ("rId" + (result + 1));
  1708. else
  1709. {
  1710. String guid = String.Empty;
  1711. do
  1712. {
  1713. guid = Guid.NewGuid().ToString();
  1714. } while (Char.IsDigit(guid[0]));
  1715. return guid;
  1716. }
  1717. }
  1718. /// <summary>
  1719. /// Adds three new Headers to this document. One for the first page, one for odd pages and one for even pages.
  1720. /// </summary>
  1721. /// <example>
  1722. /// // Create a document.
  1723. /// using (DocX document = DocX.Create(@"Test.docx"))
  1724. /// {
  1725. /// // Add header support to this document.
  1726. /// document.AddHeaders();
  1727. ///
  1728. /// // Get a collection of all headers in this document.
  1729. /// Headers headers = document.Headers;
  1730. ///
  1731. /// // The header used for the first page of this document.
  1732. /// Header first = headers.first;
  1733. ///
  1734. /// // The header used for odd pages of this document.
  1735. /// Header odd = headers.odd;
  1736. ///
  1737. /// // The header used for even pages of this document.
  1738. /// Header even = headers.even;
  1739. ///
  1740. /// // Force the document to use a different header for first, odd and even pages.
  1741. /// document.DifferentFirstPage = true;
  1742. /// document.DifferentOddAndEvenPages = true;
  1743. ///
  1744. /// // Content can be added to the Headers in the same manor that it would be added to the main document.
  1745. /// Paragraph p = first.InsertParagraph();
  1746. /// p.Append("This is the first pages header.");
  1747. ///
  1748. /// // Save all changes to this document.
  1749. /// document.Save();
  1750. /// }// Release this document from memory.
  1751. /// </example>
  1752. public void AddHeaders()
  1753. {
  1754. AddHeadersOrFooters(true);
  1755. headers.odd = Document.GetHeaderByType("default");
  1756. headers.even = Document.GetHeaderByType("even");
  1757. headers.first = Document.GetHeaderByType("first");
  1758. }
  1759. /// <summary>
  1760. /// Adds three new Footers to this document. One for the first page, one for odd pages and one for even pages.
  1761. /// </summary>
  1762. /// <example>
  1763. /// // Create a document.
  1764. /// using (DocX document = DocX.Create(@"Test.docx"))
  1765. /// {
  1766. /// // Add footer support to this document.
  1767. /// document.AddFooters();
  1768. ///
  1769. /// // Get a collection of all footers in this document.
  1770. /// Footers footers = document.Footers;
  1771. ///
  1772. /// // The footer used for the first page of this document.
  1773. /// Footer first = footers.first;
  1774. ///
  1775. /// // The footer used for odd pages of this document.
  1776. /// Footer odd = footers.odd;
  1777. ///
  1778. /// // The footer used for even pages of this document.
  1779. /// Footer even = footers.even;
  1780. ///
  1781. /// // Force the document to use a different footer for first, odd and even pages.
  1782. /// document.DifferentFirstPage = true;
  1783. /// document.DifferentOddAndEvenPages = true;
  1784. ///
  1785. /// // Content can be added to the Footers in the same manor that it would be added to the main document.
  1786. /// Paragraph p = first.InsertParagraph();
  1787. /// p.Append("This is the first pages footer.");
  1788. ///
  1789. /// // Save all changes to this document.
  1790. /// document.Save();
  1791. /// }// Release this document from memory.
  1792. /// </example>
  1793. public void AddFooters()
  1794. {
  1795. AddHeadersOrFooters(false);
  1796. footers.odd = Document.GetFooterByType("default");
  1797. footers.even = Document.GetFooterByType("even");
  1798. footers.first = Document.GetFooterByType("first");
  1799. }
  1800. /// <summary>
  1801. /// Adds a Header to a document.
  1802. /// If the document already contains a Header it will be replaced.
  1803. /// </summary>
  1804. /// <returns>The Header that was added to the document.</returns>
  1805. internal void AddHeadersOrFooters(bool b)
  1806. {
  1807. string element = "ftr";
  1808. string reference = "footer";
  1809. if (b)
  1810. {
  1811. element = "hdr";
  1812. reference = "header";
  1813. }
  1814. DeleteHeadersOrFooters(b);
  1815. XElement sectPr = mainDoc.Root.Element(w + "body").Element(w + "sectPr");
  1816. for (int i = 1; i < 4; i++)
  1817. {
  1818. string header_uri = string.Format("/word/{0}{1}.xml", reference, i);
  1819. PackagePart headerPart = package.CreatePart(new Uri(header_uri, UriKind.Relative), string.Format("application/vnd.openxmlformats-officedocument.wordprocessingml.{0}+xml", reference));
  1820. PackageRelationship headerRelationship = mainPart.CreateRelationship(headerPart.Uri, TargetMode.Internal, string.Format("http://schemas.openxmlformats.org/officeDocument/2006/relationships/{0}", reference));
  1821. XDocument header;
  1822. // Load the document part into a XDocument object
  1823. using (TextReader tr = new StreamReader(headerPart.GetStream(FileMode.Create, FileAccess.ReadWrite)))
  1824. {
  1825. header = XDocument.Parse
  1826. (string.Format(@"<?xml version=""1.0"" encoding=""utf-16"" standalone=""yes""?>
  1827. <w:{0} 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"">
  1828. <w:p w:rsidR=""009D472B"" w:rsidRDefault=""009D472B"">
  1829. <w:pPr>
  1830. <w:pStyle w:val=""{1}"" />
  1831. </w:pPr>
  1832. </w:p>
  1833. </w:{0}>", element, reference)
  1834. );
  1835. }
  1836. // Save the main document
  1837. using (TextWriter tw = new StreamWriter(headerPart.GetStream(FileMode.Create, FileAccess.Write)))
  1838. header.Save(tw, SaveOptions.DisableFormatting);
  1839. string type;
  1840. switch (i)
  1841. {
  1842. case 1: type = "default"; break;
  1843. case 2: type = "even"; break;
  1844. case 3: type = "first"; break;
  1845. default: throw new ArgumentOutOfRangeException();
  1846. }
  1847. sectPr.Add
  1848. (
  1849. new XElement
  1850. (
  1851. w + string.Format("{0}Reference", reference),
  1852. new XAttribute(w + "type", type),
  1853. new XAttribute(r + "id", headerRelationship.Id)
  1854. )
  1855. );
  1856. }
  1857. }
  1858. internal void DeleteHeadersOrFooters(bool b)
  1859. {
  1860. string reference = "footer";
  1861. if (b)
  1862. reference = "header";
  1863. // Get all header Relationships in this document.
  1864. var header_relationships = mainPart.GetRelationshipsByType(string.Format("http://schemas.openxmlformats.org/officeDocument/2006/relationships/{0}", reference));
  1865. foreach (PackageRelationship header_relationship in header_relationships)
  1866. {
  1867. // Get the TargetUri for this Part.
  1868. Uri header_uri = header_relationship.TargetUri;
  1869. // Check to see if the document actually contains the Part.
  1870. if (!header_uri.OriginalString.StartsWith("/word/"))
  1871. header_uri = new Uri("/word/" + header_uri.OriginalString, UriKind.Relative);
  1872. if (package.PartExists(header_uri))
  1873. {
  1874. // Delete the Part
  1875. package.DeletePart(header_uri);
  1876. // Get all references to this Relationship in the document.
  1877. var query =
  1878. (
  1879. from e in mainDoc.Descendants(XName.Get("body", DocX.w.NamespaceName)).Descendants()
  1880. where (e.Name.LocalName == string.Format("{0}Reference", reference)) && (e.Attribute(r + "id").Value == header_relationship.Id)
  1881. select e
  1882. );
  1883. // Remove all references to this Relationship in the document.
  1884. for (int i = 0; i < query.Count(); i++)
  1885. query.ElementAt(i).Remove();
  1886. // Delete the Relationship.
  1887. package.DeleteRelationship(header_relationship.Id);
  1888. }
  1889. }
  1890. }
  1891. internal Image AddImage(object o, string contentType = "image/jpeg")
  1892. {
  1893. // Open a Stream to the new image being added.
  1894. Stream newImageStream;
  1895. if (o is string)
  1896. newImageStream = new FileStream(o as string, FileMode.Open, FileAccess.Read);
  1897. else
  1898. newImageStream = o as Stream;
  1899. // Get all image parts in word\document.xml
  1900. List<PackagePart> imageParts = mainPart.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image").Select(ir => package.GetParts().Where(p => p.Uri.ToString().EndsWith(ir.TargetUri.ToString())).First()).ToList();
  1901. foreach (PackagePart relsPart in package.GetParts().Where(part => part.Uri.ToString().Contains("/word/")).Where(part => part.ContentType.Equals("application/vnd.openxmlformats-package.relationships+xml")))
  1902. {
  1903. XDocument relsPartContent;
  1904. using (TextReader tr = new StreamReader(relsPart.GetStream(FileMode.Open, FileAccess.Read)))
  1905. relsPartContent = XDocument.Load(tr);
  1906. IEnumerable<XElement> imageRelationships =
  1907. relsPartContent.Root.Elements().Where
  1908. (
  1909. imageRel =>
  1910. imageRel.Attribute(XName.Get("Type")).Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image")
  1911. );
  1912. foreach (XElement imageRelationship in imageRelationships)
  1913. {
  1914. if (imageRelationship.Attribute(XName.Get("Target")) != null)
  1915. {
  1916. string imagePartUri = Path.Combine(Path.GetDirectoryName(relsPart.Uri.ToString()), imageRelationship.Attribute(XName.Get("Target")).Value);
  1917. imagePartUri = Path.GetFullPath(imagePartUri.Replace("\\_rels", string.Empty));
  1918. imagePartUri = imagePartUri.Replace(Path.GetFullPath("\\"), string.Empty).Replace("\\", "/");
  1919. if (!imagePartUri.StartsWith("/"))
  1920. imagePartUri = "/" + imagePartUri;
  1921. PackagePart imagePart = package.GetPart(new Uri(imagePartUri, UriKind.Relative));
  1922. imageParts.Add(imagePart);
  1923. }
  1924. }
  1925. }
  1926. // Loop through each image part in this document.
  1927. foreach (PackagePart pp in imageParts)
  1928. {
  1929. // Open a tempory Stream to this image part.
  1930. using (Stream tempStream = pp.GetStream(FileMode.Open, FileAccess.Read))
  1931. {
  1932. // Compare this image to the new image being added.
  1933. if (HelperFunctions.IsSameFile(tempStream, newImageStream))
  1934. {
  1935. // Get the image object for this image part
  1936. string id = mainPart.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image")
  1937. .Where(r => r.TargetUri == pp.Uri)
  1938. .Select(r => r.Id).First();
  1939. // Return the Image object
  1940. return Images.Where(i => i.Id == id).First();
  1941. }
  1942. }
  1943. }
  1944. string imgPartUriPath = string.Empty;
  1945. string extension = contentType.Substring(contentType.LastIndexOf("/") + 1);
  1946. do
  1947. {
  1948. // Create a new image part.
  1949. imgPartUriPath = string.Format
  1950. (
  1951. "/word/media/{0}.{1}",
  1952. Guid.NewGuid().ToString(), // The unique part.
  1953. extension
  1954. );
  1955. } while (package.PartExists(new Uri(imgPartUriPath, UriKind.Relative)));
  1956. // We are now guareenteed that imgPartUriPath is unique.
  1957. PackagePart img = package.CreatePart(new Uri(imgPartUriPath, UriKind.Relative), contentType);
  1958. // Create a new image relationship
  1959. PackageRelationship rel = mainPart.CreateRelationship(img.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
  1960. // Open a Stream to the newly created Image part.
  1961. using (Stream stream = img.GetStream(FileMode.Create, FileAccess.Write))
  1962. {
  1963. // Using the Stream to the real image, copy this streams data into the newly create Image part.
  1964. using (newImageStream)
  1965. {
  1966. byte[] bytes = new byte[newImageStream.Length];
  1967. newImageStream.Read(bytes, 0, (int)newImageStream.Length);
  1968. stream.Write(bytes, 0, (int)newImageStream.Length);
  1969. }// Close the Stream to the new image.
  1970. }// Close the Stream to the new image part.
  1971. return new Image(this, rel);
  1972. }
  1973. /// <summary>
  1974. /// Save this document back to the location it was loaded from.
  1975. /// </summary>
  1976. /// <example>
  1977. /// <code>
  1978. /// // Load a document.
  1979. /// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
  1980. /// {
  1981. /// // Add an Image from a file.
  1982. /// document.AddImage(@"C:\Example\Image.jpg");
  1983. ///
  1984. /// // Save all changes made to this document.
  1985. /// document.Save();
  1986. /// }// Release this document from memory.
  1987. /// </code>
  1988. /// </example>
  1989. /// <seealso cref="DocX.SaveAs(string)"/>
  1990. /// <seealso cref="DocX.Create(System.IO.Stream)"/>
  1991. /// <seealso cref="DocX.Create(string)"/>
  1992. /// <seealso cref="DocX.Load(System.IO.Stream)"/>
  1993. /// <seealso cref="DocX.Load(string)"/>
  1994. /// <!--
  1995. /// Bug found and fixed by krugs525 on August 12 2009.
  1996. /// Use TFS compare to see exact code change.
  1997. /// -->
  1998. public void Save()
  1999. {
  2000. Headers headers = Headers;
  2001. // Save the main document
  2002. using (TextWriter tw = new StreamWriter(mainPart.GetStream(FileMode.Create, FileAccess.Write)))
  2003. mainDoc.Save(tw, SaveOptions.DisableFormatting);
  2004. XElement body = mainDoc.Root.Element(w + "body");
  2005. XElement sectPr = body.Descendants(w + "sectPr").FirstOrDefault();
  2006. if (sectPr != null)
  2007. {
  2008. var evenHeaderRef =
  2009. (
  2010. from e in mainDoc.Descendants(w + "headerReference")
  2011. let type = e.Attribute(w + "type")
  2012. where type != null && type.Value.Equals("even", StringComparison.CurrentCultureIgnoreCase)
  2013. select e.Attribute(r + "id").Value
  2014. ).LastOrDefault();
  2015. if (evenHeaderRef != null)
  2016. {
  2017. XElement even = headers.even.Xml;
  2018. Uri target = PackUriHelper.ResolvePartUri
  2019. (
  2020. mainPart.Uri,
  2021. mainPart.GetRelationship(evenHeaderRef).TargetUri
  2022. );
  2023. using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
  2024. {
  2025. new XDocument
  2026. (
  2027. new XDeclaration("1.0", "UTF-8", "yes"),
  2028. even
  2029. ).Save(tw, SaveOptions.DisableFormatting);
  2030. }
  2031. }
  2032. var oddHeaderRef =
  2033. (
  2034. from e in mainDoc.Descendants(w + "headerReference")
  2035. let type = e.Attribute(w + "type")
  2036. where type != null && type.Value.Equals("default", StringComparison.CurrentCultureIgnoreCase)
  2037. select e.Attribute(r + "id").Value
  2038. ).LastOrDefault();
  2039. if (oddHeaderRef != null)
  2040. {
  2041. XElement odd = headers.odd.Xml;
  2042. Uri target = PackUriHelper.ResolvePartUri
  2043. (
  2044. mainPart.Uri,
  2045. mainPart.GetRelationship(oddHeaderRef).TargetUri
  2046. );
  2047. // Save header1
  2048. using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
  2049. {
  2050. new XDocument
  2051. (
  2052. new XDeclaration("1.0", "UTF-8", "yes"),
  2053. odd
  2054. ).Save(tw, SaveOptions.DisableFormatting);
  2055. }
  2056. }
  2057. var firstHeaderRef =
  2058. (
  2059. from e in mainDoc.Descendants(w + "headerReference")
  2060. let type = e.Attribute(w + "type")
  2061. where type != null && type.Value.Equals("first", StringComparison.CurrentCultureIgnoreCase)
  2062. select e.Attribute(r + "id").Value
  2063. ).LastOrDefault();
  2064. if (firstHeaderRef != null)
  2065. {
  2066. XElement first = headers.first.Xml;
  2067. Uri target = PackUriHelper.ResolvePartUri
  2068. (
  2069. mainPart.Uri,
  2070. mainPart.GetRelationship(firstHeaderRef).TargetUri
  2071. );
  2072. // Save header3
  2073. using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
  2074. {
  2075. new XDocument
  2076. (
  2077. new XDeclaration("1.0", "UTF-8", "yes"),
  2078. first
  2079. ).Save(tw, SaveOptions.DisableFormatting);
  2080. }
  2081. }
  2082. var oddFooterRef =
  2083. (
  2084. from e in mainDoc.Descendants(w + "footerReference")
  2085. let type = e.Attribute(w + "type")
  2086. where type != null && type.Value.Equals("default", StringComparison.CurrentCultureIgnoreCase)
  2087. select e.Attribute(r + "id").Value
  2088. ).LastOrDefault();
  2089. if (oddFooterRef != null)
  2090. {
  2091. XElement odd = footers.odd.Xml;
  2092. Uri target = PackUriHelper.ResolvePartUri
  2093. (
  2094. mainPart.Uri,
  2095. mainPart.GetRelationship(oddFooterRef).TargetUri
  2096. );
  2097. // Save header1
  2098. using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
  2099. {
  2100. new XDocument
  2101. (
  2102. new XDeclaration("1.0", "UTF-8", "yes"),
  2103. odd
  2104. ).Save(tw, SaveOptions.DisableFormatting);
  2105. }
  2106. }
  2107. var evenFooterRef =
  2108. (
  2109. from e in mainDoc.Descendants(w + "footerReference")
  2110. let type = e.Attribute(w + "type")
  2111. where type != null && type.Value.Equals("even", StringComparison.CurrentCultureIgnoreCase)
  2112. select e.Attribute(r + "id").Value
  2113. ).LastOrDefault();
  2114. if (evenFooterRef != null)
  2115. {
  2116. XElement even = footers.even.Xml;
  2117. Uri target = PackUriHelper.ResolvePartUri
  2118. (
  2119. mainPart.Uri,
  2120. mainPart.GetRelationship(evenFooterRef).TargetUri
  2121. );
  2122. // Save header2
  2123. using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
  2124. {
  2125. new XDocument
  2126. (
  2127. new XDeclaration("1.0", "UTF-8", "yes"),
  2128. even
  2129. ).Save(tw, SaveOptions.DisableFormatting);
  2130. }
  2131. }
  2132. var firstFooterRef =
  2133. (
  2134. from e in mainDoc.Descendants(w + "footerReference")
  2135. let type = e.Attribute(w + "type")
  2136. where type != null && type.Value.Equals("first", StringComparison.CurrentCultureIgnoreCase)
  2137. select e.Attribute(r + "id").Value
  2138. ).LastOrDefault();
  2139. if (firstFooterRef != null)
  2140. {
  2141. XElement first = footers.first.Xml;
  2142. Uri target = PackUriHelper.ResolvePartUri
  2143. (
  2144. mainPart.Uri,
  2145. mainPart.GetRelationship(firstFooterRef).TargetUri
  2146. );
  2147. // Save header3
  2148. using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
  2149. {
  2150. new XDocument
  2151. (
  2152. new XDeclaration("1.0", "UTF-8", "yes"),
  2153. first
  2154. ).Save(tw, SaveOptions.DisableFormatting);
  2155. }
  2156. }
  2157. // Save the settings document.
  2158. using (TextWriter tw = new StreamWriter(settingsPart.GetStream(FileMode.Create, FileAccess.Write)))
  2159. settings.Save(tw, SaveOptions.DisableFormatting);
  2160. }
  2161. // Close the document so that it can be saved.
  2162. package.Flush();
  2163. #region Save this document back to a file or stream, that was specified by the user at save time.
  2164. if (filename != null)
  2165. {
  2166. using (FileStream fs = new FileStream(filename, FileMode.Create))
  2167. fs.Write(memoryStream.ToArray(), 0, (int)memoryStream.Length);
  2168. }
  2169. else
  2170. {
  2171. // Set the length of this stream to 0
  2172. stream.SetLength(0);
  2173. // Write to the beginning of the stream
  2174. stream.Position = 0;
  2175. memoryStream.WriteTo(stream);
  2176. }
  2177. #endregion
  2178. }
  2179. /// <summary>
  2180. /// Save this document to a file.
  2181. /// </summary>
  2182. /// <param name="filename">The filename to save this document as.</param>
  2183. /// <example>
  2184. /// Load a document from one file and save it to another.
  2185. /// <code>
  2186. /// // Load a document using its fully qualified filename.
  2187. /// DocX document = DocX.Load(@"C:\Example\Test1.docx");
  2188. ///
  2189. /// // Insert a new Paragraph
  2190. /// document.InsertParagraph("Hello world!", false);
  2191. ///
  2192. /// // Save the document to a new location.
  2193. /// document.SaveAs(@"C:\Example\Test2.docx");
  2194. /// </code>
  2195. /// </example>
  2196. /// <example>
  2197. /// Load a document from a Stream and save it to a file.
  2198. /// <code>
  2199. /// DocX document;
  2200. /// using (FileStream fs1 = new FileStream(@"C:\Example\Test1.docx", FileMode.Open))
  2201. /// {
  2202. /// // Load a document using a stream.
  2203. /// document = DocX.Load(fs1);
  2204. ///
  2205. /// // Insert a new Paragraph
  2206. /// document.InsertParagraph("Hello world again!", false);
  2207. /// }
  2208. ///
  2209. /// // Save the document to a new location.
  2210. /// document.SaveAs(@"C:\Example\Test2.docx");
  2211. /// </code>
  2212. /// </example>
  2213. /// <seealso cref="DocX.Save()"/>
  2214. /// <seealso cref="DocX.Create(System.IO.Stream)"/>
  2215. /// <seealso cref="DocX.Create(string)"/>
  2216. /// <seealso cref="DocX.Load(System.IO.Stream)"/>
  2217. /// <seealso cref="DocX.Load(string)"/>
  2218. public void SaveAs(string filename)
  2219. {
  2220. this.filename = filename;
  2221. this.stream = null;
  2222. Save();
  2223. }
  2224. /// <summary>
  2225. /// Save this document to a Stream.
  2226. /// </summary>
  2227. /// <param name="stream">The Stream to save this document to.</param>
  2228. /// <example>
  2229. /// Load a document from a file and save it to a Stream.
  2230. /// <code>
  2231. /// // Place holder for a document.
  2232. /// DocX document;
  2233. ///
  2234. /// using (FileStream fs1 = new FileStream(@"C:\Example\Test1.docx", FileMode.Open))
  2235. /// {
  2236. /// // Load a document using a stream.
  2237. /// document = DocX.Load(fs1);
  2238. ///
  2239. /// // Insert a new Paragraph
  2240. /// document.InsertParagraph("Hello world again!", false);
  2241. /// }
  2242. ///
  2243. /// using (FileStream fs2 = new FileStream(@"C:\Example\Test2.docx", FileMode.Create))
  2244. /// {
  2245. /// // Save the document to a different stream.
  2246. /// document.SaveAs(fs2);
  2247. /// }
  2248. ///
  2249. /// // Release this document from memory.
  2250. /// document.Dispose();
  2251. /// </code>
  2252. /// </example>
  2253. /// <example>
  2254. /// Load a document from one Stream and save it to another.
  2255. /// <code>
  2256. /// DocX document;
  2257. /// using (FileStream fs1 = new FileStream(@"C:\Example\Test1.docx", FileMode.Open))
  2258. /// {
  2259. /// // Load a document using a stream.
  2260. /// document = DocX.Load(fs1);
  2261. ///
  2262. /// // Insert a new Paragraph
  2263. /// document.InsertParagraph("Hello world again!", false);
  2264. /// }
  2265. ///
  2266. /// using (FileStream fs2 = new FileStream(@"C:\Example\Test2.docx", FileMode.Create))
  2267. /// {
  2268. /// // Save the document to a different stream.
  2269. /// document.SaveAs(fs2);
  2270. /// }
  2271. /// </code>
  2272. /// </example>
  2273. /// <seealso cref="DocX.Save()"/>
  2274. /// <seealso cref="DocX.Create(System.IO.Stream)"/>
  2275. /// <seealso cref="DocX.Create(string)"/>
  2276. /// <seealso cref="DocX.Load(System.IO.Stream)"/>
  2277. /// <seealso cref="DocX.Load(string)"/>
  2278. public void SaveAs(Stream stream)
  2279. {
  2280. this.filename = null;
  2281. this.stream = stream;
  2282. Save();
  2283. }
  2284. /// <summary>
  2285. /// Add a core property to this document. If a core property already exists with the same name it will be replaced. Core property names are case insensitive.
  2286. /// </summary>
  2287. ///<param name="propertyName">The property name.</param>
  2288. ///<param name="propertyValue">The property value.</param>
  2289. ///<example>
  2290. /// Add a core properties of each type to a document.
  2291. /// <code>
  2292. /// // Load Example.docx
  2293. /// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
  2294. /// {
  2295. /// // If this document does not contain a core property called 'forename', create one.
  2296. /// if (!document.CoreProperties.ContainsKey("forename"))
  2297. /// {
  2298. /// // Create a new core property called 'forename' and set its value.
  2299. /// document.AddCoreProperty("forename", "Cathal");
  2300. /// }
  2301. ///
  2302. /// // Get this documents core property called 'forename'.
  2303. /// string forenameValue = document.CoreProperties["forename"];
  2304. ///
  2305. /// // Print all of the information about this core property to Console.
  2306. /// Console.WriteLine(string.Format("Name: '{0}', Value: '{1}'\nPress any key...", "forename", forenameValue));
  2307. ///
  2308. /// // Save all changes made to this document.
  2309. /// document.Save();
  2310. /// } // Release this document from memory.
  2311. ///
  2312. /// // Wait for the user to press a key before exiting.
  2313. /// Console.ReadKey();
  2314. /// </code>
  2315. /// </example>
  2316. /// <seealso cref="CoreProperties"/>
  2317. /// <seealso cref="CustomProperty"/>
  2318. /// <seealso cref="CustomProperties"/>
  2319. public void AddCoreProperty(string propertyName, string propertyValue)
  2320. {
  2321. string propertyNamespacePrefix = propertyName.Contains(":") ? propertyName.Split(new[] { ':' })[0] : "cp";
  2322. string propertyLocalName = propertyName.Contains(":") ? propertyName.Split(new[] { ':' })[1] : propertyName;
  2323. // If this document does not contain a coreFilePropertyPart create one.)
  2324. if (!package.PartExists(new Uri("/docProps/core.xml", UriKind.Relative)))
  2325. throw new Exception("Core properties part doesn't exist.");
  2326. XDocument corePropDoc;
  2327. PackagePart corePropPart = package.GetPart(new Uri("/docProps/core.xml", UriKind.Relative));
  2328. using (TextReader tr = new StreamReader(corePropPart.GetStream(FileMode.Open, FileAccess.Read)))
  2329. {
  2330. corePropDoc = XDocument.Load(tr);
  2331. }
  2332. XElement corePropElement =
  2333. (from propElement in corePropDoc.Root.Elements()
  2334. where (propElement.Name.LocalName.Equals(propertyLocalName))
  2335. select propElement).SingleOrDefault();
  2336. if (corePropElement != null)
  2337. {
  2338. corePropElement.SetValue(propertyValue);
  2339. }
  2340. else
  2341. {
  2342. var propertyNamespace = corePropDoc.Root.GetNamespaceOfPrefix(propertyNamespacePrefix);
  2343. corePropDoc.Root.Add(new XElement(XName.Get(propertyLocalName, propertyNamespace.NamespaceName), propertyValue));
  2344. }
  2345. using (TextWriter tw = new StreamWriter(corePropPart.GetStream(FileMode.Create, FileAccess.Write)))
  2346. {
  2347. corePropDoc.Save(tw);
  2348. }
  2349. UpdateCorePropertyValue(this, propertyLocalName, propertyValue);
  2350. }
  2351. internal static void UpdateCorePropertyValue(DocX document, string corePropertyName, string corePropertyValue)
  2352. {
  2353. string matchPattern = string.Format(@"(DOCPROPERTY)?{0}\\\*MERGEFORMAT", corePropertyName).ToLower();
  2354. foreach (XElement e in document.mainDoc.Descendants(XName.Get("fldSimple", w.NamespaceName)))
  2355. {
  2356. string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim().ToLower();
  2357. if (Regex.IsMatch(attr_value, matchPattern))
  2358. {
  2359. XElement firstRun = e.Element(w + "r");
  2360. XElement firstText = firstRun.Element(w + "t");
  2361. XElement rPr = firstText.Element(w + "rPr");
  2362. // Delete everything and insert updated text value
  2363. e.RemoveNodes();
  2364. XElement t = new XElement(w + "t", rPr, corePropertyValue);
  2365. Novacode.Text.PreserveSpace(t);
  2366. e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
  2367. }
  2368. }
  2369. #region Headers
  2370. IEnumerable<PackagePart> headerParts = from headerPart in document.package.GetParts()
  2371. where (Regex.IsMatch(headerPart.Uri.ToString(), @"/word/header\d?.xml"))
  2372. select headerPart;
  2373. foreach (PackagePart pp in headerParts)
  2374. {
  2375. XDocument header = XDocument.Load(new StreamReader(pp.GetStream()));
  2376. foreach (XElement e in header.Descendants(XName.Get("fldSimple", w.NamespaceName)))
  2377. {
  2378. string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim().ToLower();
  2379. if (Regex.IsMatch(attr_value, matchPattern))
  2380. {
  2381. XElement firstRun = e.Element(w + "r");
  2382. // Delete everything and insert updated text value
  2383. e.RemoveNodes();
  2384. XElement t = new XElement(w + "t", corePropertyValue);
  2385. Novacode.Text.PreserveSpace(t);
  2386. e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
  2387. }
  2388. }
  2389. using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create, FileAccess.Write)))
  2390. header.Save(tw);
  2391. }
  2392. #endregion
  2393. #region Footers
  2394. IEnumerable<PackagePart> footerParts = from footerPart in document.package.GetParts()
  2395. where (Regex.IsMatch(footerPart.Uri.ToString(), @"/word/footer\d?.xml"))
  2396. select footerPart;
  2397. foreach (PackagePart pp in footerParts)
  2398. {
  2399. XDocument footer = XDocument.Load(new StreamReader(pp.GetStream()));
  2400. foreach (XElement e in footer.Descendants(XName.Get("fldSimple", w.NamespaceName)))
  2401. {
  2402. string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim().ToLower();
  2403. if (Regex.IsMatch(attr_value, matchPattern))
  2404. {
  2405. XElement firstRun = e.Element(w + "r");
  2406. // Delete everything and insert updated text value
  2407. e.RemoveNodes();
  2408. XElement t = new XElement(w + "t", corePropertyValue);
  2409. Novacode.Text.PreserveSpace(t);
  2410. e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
  2411. }
  2412. }
  2413. using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create, FileAccess.Write)))
  2414. footer.Save(tw);
  2415. }
  2416. #endregion
  2417. PopulateDocument(document, document.package);
  2418. }
  2419. /// <summary>
  2420. /// Add a custom property to this document. If a custom property already exists with the same name it will be replace. CustomProperty names are case insensitive.
  2421. /// </summary>
  2422. /// <param name="cp">The CustomProperty to add to this document.</param>
  2423. /// <example>
  2424. /// Add a custom properties of each type to a document.
  2425. /// <code>
  2426. /// // Load Example.docx
  2427. /// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
  2428. /// {
  2429. /// // A CustomProperty called forename which stores a string.
  2430. /// CustomProperty forename;
  2431. ///
  2432. /// // If this document does not contain a custom property called 'forename', create one.
  2433. /// if (!document.CustomProperties.ContainsKey("forename"))
  2434. /// {
  2435. /// // Create a new custom property called 'forename' and set its value.
  2436. /// document.AddCustomProperty(new CustomProperty("forename", "Cathal"));
  2437. /// }
  2438. ///
  2439. /// // Get this documents custom property called 'forename'.
  2440. /// forename = document.CustomProperties["forename"];
  2441. ///
  2442. /// // Print all of the information about this CustomProperty to Console.
  2443. /// Console.WriteLine(string.Format("Name: '{0}', Value: '{1}'\nPress any key...", forename.Name, forename.Value));
  2444. ///
  2445. /// // Save all changes made to this document.
  2446. /// document.Save();
  2447. /// } // Release this document from memory.
  2448. ///
  2449. /// // Wait for the user to press a key before exiting.
  2450. /// Console.ReadKey();
  2451. /// </code>
  2452. /// </example>
  2453. /// <seealso cref="CustomProperty"/>
  2454. /// <seealso cref="CustomProperties"/>
  2455. public void AddCustomProperty(CustomProperty cp)
  2456. {
  2457. // If this document does not contain a customFilePropertyPart create one.
  2458. if (!package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
  2459. HelperFunctions.CreateCustomPropertiesPart(this);
  2460. XDocument customPropDoc;
  2461. PackagePart customPropPart = package.GetPart(new Uri("/docProps/custom.xml", UriKind.Relative));
  2462. using (TextReader tr = new StreamReader(customPropPart.GetStream(FileMode.Open, FileAccess.Read)))
  2463. customPropDoc = XDocument.Load(tr, LoadOptions.PreserveWhitespace);
  2464. // Each custom property has a PID, get the highest PID in this document.
  2465. IEnumerable<int> pids =
  2466. (
  2467. from d in customPropDoc.Descendants()
  2468. where d.Name.LocalName == "property"
  2469. select int.Parse(d.Attribute(XName.Get("pid")).Value)
  2470. );
  2471. int pid = 1;
  2472. if (pids.Count() > 0)
  2473. pid = pids.Max();
  2474. // Check if a custom property already exists with this name
  2475. var customProperty =
  2476. (
  2477. from d in customPropDoc.Descendants()
  2478. where (d.Name.LocalName == "property") && (d.Attribute(XName.Get("name")).Value == cp.Name)
  2479. select d
  2480. ).SingleOrDefault();
  2481. // If a custom property with this name already exists remove it.
  2482. if (customProperty != null)
  2483. customProperty.Remove();
  2484. XElement propertiesElement = customPropDoc.Element(XName.Get("Properties", customPropertiesSchema.NamespaceName));
  2485. propertiesElement.Add
  2486. (
  2487. new XElement
  2488. (
  2489. XName.Get("property", customPropertiesSchema.NamespaceName),
  2490. new XAttribute("fmtid", "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"),
  2491. new XAttribute("pid", pid + 1),
  2492. new XAttribute("name", cp.Name),
  2493. new XElement(customVTypesSchema + cp.Type, cp.Value)
  2494. )
  2495. );
  2496. // Save the custom properties
  2497. using (TextWriter tw = new StreamWriter(customPropPart.GetStream(FileMode.Create, FileAccess.Write)))
  2498. customPropDoc.Save(tw, SaveOptions.DisableFormatting);
  2499. // Refresh all fields in this document which display this custom property.
  2500. UpdateCustomPropertyValue(this, cp.Name, cp.Value.ToString());
  2501. }
  2502. internal static void UpdateCustomPropertyValue(DocX document, string customPropertyName, string customPropertyValue)
  2503. {
  2504. foreach (XElement e in document.mainDoc.Descendants(XName.Get("fldSimple", w.NamespaceName)))
  2505. {
  2506. string attr_value = e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Replace(" ", string.Empty).Trim();
  2507. string match_value = string.Format(@"DOCPROPERTY {0} \* MERGEFORMAT", customPropertyName).Replace(" ", string.Empty);
  2508. if (attr_value.Equals(match_value, StringComparison.CurrentCultureIgnoreCase))
  2509. {
  2510. XElement firstRun = e.Element(w + "r");
  2511. XElement firstText = firstRun.Element(w + "t");
  2512. XElement rPr = firstText.Element(w + "rPr");
  2513. // Delete everything and insert updated text value
  2514. e.RemoveNodes();
  2515. XElement t = new XElement(w + "t", rPr, customPropertyValue);
  2516. Novacode.Text.PreserveSpace(t);
  2517. e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
  2518. }
  2519. }
  2520. //#region Headers
  2521. //foreach(PackagePart pp in document.headers)
  2522. //{
  2523. // XDocument header = XDocument.Load(new StreamReader(pp.GetStream()));
  2524. // foreach (XElement e in header.Descendants(XName.Get("fldSimple", w.NamespaceName)))
  2525. // {
  2526. // if (e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Trim().Equals(string.Format(@"DOCPROPERTY {0} \* MERGEFORMAT", customPropertyName), StringComparison.CurrentCultureIgnoreCase))
  2527. // {
  2528. // XElement firstRun = e.Element(w + "r");
  2529. // // Delete everything and insert updated text value
  2530. // e.RemoveNodes();
  2531. // XElement t = new XElement(w + "t", customPropertyValue);
  2532. // Novacode.Text.PreserveSpace(t);
  2533. // e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
  2534. // }
  2535. // }
  2536. // using (TextWriter tw = new StreamWriter(pp.GetStream()))
  2537. // header.Save(tw);
  2538. //}
  2539. //#endregion
  2540. //#region Footers
  2541. //foreach (PackagePart pp in document.footers)
  2542. //{
  2543. // XDocument footer = XDocument.Load(new StreamReader(pp.GetStream()));
  2544. // foreach (XElement e in footer.Descendants(XName.Get("fldSimple", w.NamespaceName)))
  2545. // {
  2546. // if (e.Attribute(XName.Get("instr", w.NamespaceName)).Value.Trim().Equals(string.Format(@"DOCPROPERTY {0} \* MERGEFORMAT", customPropertyName), StringComparison.CurrentCultureIgnoreCase))
  2547. // {
  2548. // XElement firstRun = e.Element(w + "r");
  2549. // // Delete everything and insert updated text value
  2550. // e.RemoveNodes();
  2551. // XElement t = new XElement(w + "t", customPropertyValue);
  2552. // Novacode.Text.PreserveSpace(t);
  2553. // e.Add(new XElement(firstRun.Name, firstRun.Attributes(), firstRun.Element(XName.Get("rPr", w.NamespaceName)), t));
  2554. // }
  2555. // }
  2556. // using (TextWriter tw = new StreamWriter(pp.GetStream()))
  2557. // footer.Save(tw);
  2558. //}
  2559. //#endregion
  2560. }
  2561. public override Paragraph InsertParagraph()
  2562. {
  2563. Paragraph p = base.InsertParagraph();
  2564. p.PackagePart = mainPart;
  2565. return p;
  2566. }
  2567. public override Paragraph InsertParagraph(int index, string text, bool trackChanges)
  2568. {
  2569. Paragraph p = base.InsertParagraph(index, text, trackChanges);
  2570. p.PackagePart = mainPart;
  2571. return p;
  2572. }
  2573. public override Paragraph InsertParagraph(Paragraph p)
  2574. {
  2575. p.PackagePart = mainPart;
  2576. return base.InsertParagraph(p);
  2577. }
  2578. public override Paragraph InsertParagraph(int index, Paragraph p)
  2579. {
  2580. p.PackagePart = mainPart;
  2581. return base.InsertParagraph(index, p);
  2582. }
  2583. public override Paragraph InsertParagraph(int index, string text, bool trackChanges, Formatting formatting)
  2584. {
  2585. Paragraph p = base.InsertParagraph(index, text, trackChanges, formatting);
  2586. p.PackagePart = mainPart;
  2587. return p;
  2588. }
  2589. public override Paragraph InsertParagraph(string text)
  2590. {
  2591. Paragraph p = base.InsertParagraph(text);
  2592. p.PackagePart = mainPart;
  2593. return p;
  2594. }
  2595. public override Paragraph InsertParagraph(string text, bool trackChanges)
  2596. {
  2597. Paragraph p = base.InsertParagraph(text, trackChanges);
  2598. p.PackagePart = mainPart;
  2599. return p;
  2600. }
  2601. public override Paragraph InsertParagraph(string text, bool trackChanges, Formatting formatting)
  2602. {
  2603. Paragraph p = base.InsertParagraph(text, trackChanges, formatting);
  2604. p.PackagePart = mainPart;
  2605. return p;
  2606. }
  2607. public override List<Paragraph> Paragraphs
  2608. {
  2609. get
  2610. {
  2611. List<Paragraph> l = base.Paragraphs;
  2612. l.ForEach(x => x.PackagePart = mainPart);
  2613. return l;
  2614. }
  2615. }
  2616. public override List<Table> Tables
  2617. {
  2618. get
  2619. {
  2620. List<Table> l = base.Tables;
  2621. l.ForEach(x => x.mainPart = mainPart);
  2622. return l;
  2623. }
  2624. }
  2625. /// <summary>
  2626. /// Create an equation and insert it in the new paragraph
  2627. /// </summary>
  2628. public override Paragraph InsertEquation(String equation)
  2629. {
  2630. Paragraph p = base.InsertEquation(equation);
  2631. p.PackagePart = mainPart;
  2632. return p;
  2633. }
  2634. /// <summary>
  2635. /// Insert a chart in document
  2636. /// </summary>
  2637. public void InsertChart(Chart chart)
  2638. {
  2639. // Create a new chart part uri.
  2640. String chartPartUriPath = String.Empty;
  2641. Int32 chartIndex = 1;
  2642. do
  2643. {
  2644. chartPartUriPath = String.Format
  2645. (
  2646. "/word/charts/chart{0}.xml",
  2647. chartIndex
  2648. );
  2649. chartIndex++;
  2650. } while (package.PartExists(new Uri(chartPartUriPath, UriKind.Relative)));
  2651. // Create chart part.
  2652. PackagePart chartPackagePart = package.CreatePart(new Uri(chartPartUriPath, UriKind.Relative), "application/vnd.openxmlformats-officedocument.drawingml.chart+xml");
  2653. // Create a new chart relationship
  2654. String relID = GetNextFreeRelationshipID();
  2655. PackageRelationship rel = mainPart.CreateRelationship(chartPackagePart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", relID);
  2656. // Save a chart info the chartPackagePart
  2657. chart.Xml.Save(chartPackagePart.GetStream(FileMode.Create, FileAccess.Write));
  2658. // Insert a new chart into a paragraph.
  2659. Paragraph p = InsertParagraph();
  2660. XElement chartElement = new XElement(
  2661. XName.Get("r", DocX.w.NamespaceName),
  2662. new XElement(
  2663. XName.Get("drawing", DocX.w.NamespaceName),
  2664. new XElement(
  2665. XName.Get("inline", DocX.wp.NamespaceName),
  2666. new XElement(XName.Get("extent", DocX.wp.NamespaceName), new XAttribute("cx", "5486400"), new XAttribute("cy", "3200400")),
  2667. new XElement(XName.Get("effectExtent", DocX.wp.NamespaceName), new XAttribute("l", "0"), new XAttribute("t", "0"), new XAttribute("r", "19050"), new XAttribute("b", "19050")),
  2668. new XElement(XName.Get("docPr", DocX.wp.NamespaceName), new XAttribute("id", "1"), new XAttribute("name", "chart")),
  2669. new XElement(
  2670. XName.Get("graphic", DocX.a.NamespaceName),
  2671. new XElement(
  2672. XName.Get("graphicData", DocX.a.NamespaceName),
  2673. new XAttribute("uri", DocX.c.NamespaceName),
  2674. new XElement(
  2675. XName.Get("chart", DocX.c.NamespaceName),
  2676. new XAttribute(XName.Get("id", DocX.r.NamespaceName), relID)
  2677. )
  2678. )
  2679. )
  2680. )
  2681. ));
  2682. p.Xml.Add(chartElement);
  2683. }
  2684. #region IDisposable Members
  2685. /// <summary>
  2686. /// Releases all resources used by this document.
  2687. /// </summary>
  2688. /// <example>
  2689. /// If you take advantage of the using keyword, Dispose() is automatically called for you.
  2690. /// <code>
  2691. /// // Load document.
  2692. /// using (DocX document = DocX.Load(@"C:\Example\Test.docx"))
  2693. /// {
  2694. /// // The document is only in memory while in this scope.
  2695. ///
  2696. /// }// Dispose() is automatically called at this point.
  2697. /// </code>
  2698. /// </example>
  2699. /// <example>
  2700. /// This example is equilivant to the one above example.
  2701. /// <code>
  2702. /// // Load document.
  2703. /// DocX document = DocX.Load(@"C:\Example\Test.docx");
  2704. ///
  2705. /// // Do something with the document here.
  2706. ///
  2707. /// // Dispose of the document.
  2708. /// document.Dispose();
  2709. /// </code>
  2710. /// </example>
  2711. public void Dispose()
  2712. {
  2713. package.Close();
  2714. }
  2715. #endregion
  2716. }
  2717. }