CopyParagraphs.cs
  1. //
  2. // This code is part of Document Solutions for Word demos.
  3. // Copyright (c) MESCIUS inc. All rights reserved.
  4. //
  5. using System;
  6. using System.IO;
  7. using System.Drawing;
  8. using System.Linq;
  9. using GrapeCity.Documents.Word;
  10. using GcFont = GrapeCity.Documents.Word.Font;
  11.  
  12. namespace DsWordWeb.Demos
  13. {
  14. // Starting with the v3 release (fall of 2019), DsWord provides built-in
  15. // support for copying and moving of content using the RangeBase.CopyTo()
  16. // and RangeBase.MoveTo() methods, so this sample is now obsolete.
  17. //
  18. // The original SampleParagraphs.docx used in this sample can be
  19. // seen by running the SampleParagraphs sample.
  20. public class CopyParagraphs
  21. {
  22. public GcWordDocument CreateDocx()
  23. {
  24. const string p1start = "This is the first paragraph of the original document";
  25. const string p2start = "This is the second paragraph of the original document";
  26. const string p3start = "This is the third paragraph of the original document";
  27. const string p4start = "This is the fourth paragraph of the original document";
  28.  
  29. var doc = new GcWordDocument();
  30.  
  31. // Load an existing DOCX file:
  32. var path = Path.Combine("Resources", "WordDocs", "SampleParagraphs.docx");
  33. doc.Load(path);
  34.  
  35. Paragraph p1 = null, p2 = null, p3 = null, p4 = null;
  36. foreach (var p in doc.Body.Paragraphs)
  37. {
  38. var t = p.GetRange().Text;
  39. if (t.StartsWith(p1start))
  40. p1 = p;
  41. else if (t.StartsWith(p2start))
  42. p2 = p;
  43. else if (t.StartsWith(p3start))
  44. p3 = p;
  45. else if (t.StartsWith(p4start))
  46. p4 = p;
  47. }
  48. if (p1 == null || p2 == null || p3 == null || p4 == null)
  49. throw new Exception("Unexpected: could not find paragraphs.");
  50.  
  51. var swapResult = Helper.SwapParagraphs(p1, p3);
  52.  
  53. swapResult.Item1.GetRange().Runs.Insert("Second swapped paragraph (paragraph 3): ", InsertLocation.Start);
  54. swapResult.Item2.GetRange().Runs.Insert("First swapped paragraph (paragraph 1): ", InsertLocation.Start);
  55.  
  56. var joinResult = Helper.JoinParagraphs(doc.Body.Paragraphs.Add(), swapResult.Item1, swapResult.Item2);
  57. joinResult.GetRange().Runs.Insert("Jointed first and 3rd paragraphs: ", InsertLocation.Start);
  58.  
  59. // Add a note at the end of the document:
  60. doc.Body.Paragraphs.Add($"Created by DsWord on {Util.TimeNow():R}.");
  61.  
  62. // Done:
  63. return doc;
  64. }
  65.  
  66. // A static helper class that provides methods to copy or move
  67. // DsWord content objects such as paragraphs and runs.
  68. //
  69. // AddRun, AddPicture, AddField, AddText, AddParagraph methods accept parameter
  70. // "withFormatting" which determines whether to copy just the content,
  71. // or content and formatting. Note that if this parameter is true,
  72. // direct formatting is applied to the newly created objects,
  73. // so the connection to the original document style is broken
  74. // (updating the style will not affect the new objects).
  75. static public class Helper
  76. {
  77. // Swaps two paragraphs by inserting a new paragraph before each one,
  78. // copying the content (and optionally formatting) from the other paragraph,
  79. // and the removing the old paragraphs.
  80. static public (Paragraph, Paragraph) SwapParagraphs(Paragraph p1, Paragraph p2, bool withFormatting = true)
  81. {
  82. if (p1.ParentBody != p2.ParentBody)
  83. throw new Exception("Both paragraphs must belong the same parent body.");
  84.  
  85. var newP2 = p1.GetRange().Paragraphs.Insert(InsertLocation.Before);
  86. CopyParagraph(newP2, p2, withFormatting);
  87. var newP1 = p2.GetRange().Paragraphs.Insert(InsertLocation.Before);
  88. CopyParagraph(newP1, p1, withFormatting);
  89. p1.Delete();
  90. p2.Delete();
  91. return (newP1, newP2);
  92. }
  93.  
  94. // Copies the contents (and optionally formatting) of two paragraphs into a third one.
  95. static public Paragraph JoinParagraphs(Paragraph target, Paragraph p1, Paragraph p2, bool withFormatting = true)
  96. {
  97. if (p1.ParentBody != p2.ParentBody)
  98. throw new Exception("Both paragraphs must belong the same parent body.");
  99.  
  100. CopyParagraph(target, p1, withFormatting);
  101. CopyParagraph(target, p2, withFormatting);
  102.  
  103. return target;
  104. }
  105.  
  106. // Copy child objects from one content object to another.
  107. static private void CopyChildren(ContentObject target, ContentObject source, bool withFormatting)
  108. {
  109. foreach (ContentObject child in source.Children)
  110. {
  111. switch (child)
  112. {
  113. case Run run:
  114. AddRun(target, run, withFormatting);
  115. break;
  116. case SimpleField field:
  117. AddField(target, field, withFormatting);
  118. break;
  119. case Picture picture:
  120. AddPicture(target, picture, withFormatting);
  121. break;
  122. case Paragraph paragraph:
  123. AddParagraph(target, paragraph, withFormatting);
  124. break;
  125. case Text text:
  126. AddText(target, text, withFormatting);
  127. break;
  128. default:
  129. System.Diagnostics.Debug.Assert(false, "Unexpected: unknown content object type.");
  130. break;
  131. }
  132. }
  133. }
  134.  
  135. // Joins two paragraphs.
  136. static private Paragraph JoinParagraphs(Paragraph first, Paragraph second, bool withFormatting = false)
  137. {
  138. if (first.ParentBody != second.ParentBody)
  139. throw new Exception("Left and right paragraphs must belong the same parent body.");
  140.  
  141. var newParagraph = first.ParentBody.Paragraphs.Add();
  142. CopyParagraph(newParagraph, first, withFormatting);
  143. // Note that second paragraph formatting overrides first paragraph formatting:
  144. CopyParagraph(newParagraph, second, withFormatting);
  145.  
  146. return newParagraph;
  147. }
  148.  
  149. // Adds a copy of a paragraph to a body.
  150. static private void AddParagraph(Body body, Paragraph source, bool withFormatting = false)
  151. {
  152. var newParagraph = body.Paragraphs.Add();
  153. CopyParagraph(newParagraph, source, withFormatting);
  154. }
  155.  
  156. // Adds a copy of a paragraph to a content object.
  157. static private void AddParagraph(ContentObject target, Paragraph source, bool withFormatting = false)
  158. {
  159. var newParagraph = target.GetRange().Paragraphs.Add();
  160. CopyParagraph(newParagraph, source, withFormatting);
  161. }
  162.  
  163. // Adds a copy of a run to a content object.
  164. static private void AddRun(ContentObject target, Run source, bool withFormatting = false)
  165. {
  166. var newRun = target.GetRange().Runs.Add();
  167. CopyRun(newRun, source, withFormatting);
  168. }
  169.  
  170. // Copies a paragraph to another paragraph.
  171. static private void CopyParagraph(Paragraph target, Paragraph source, bool withFormatting = false)
  172. {
  173. CopyRevisionId(target.RevisionId, source.RevisionId);
  174. CopyChildren(target, source, withFormatting);
  175. if (withFormatting)
  176. CopyParagraphFormat(target, source);
  177. }
  178.  
  179. // Adds a copy of a text to a content object.
  180. static private void AddText(ContentObject target, Text source, bool withFormatting)
  181. {
  182. var newText = target.GetRange().Texts.Add(source.Value);
  183. CopyText(newText, source, withFormatting);
  184. }
  185. // Copies a text to another text.
  186. static private void CopyText(Text target, Text source, bool withFormatting)
  187. {
  188. target.PreserveSpace = source.PreserveSpace;
  189. CopyChildren(target, source, withFormatting);
  190. }
  191.  
  192. // Adds a copy of a field to a content object.
  193. static private void AddField(ContentObject target, SimpleField source, bool withFormatting)
  194. {
  195. var newField = target.GetRange().SimpleFields.Add(source.Code);
  196. CopySimpleField(newField, source, withFormatting);
  197. }
  198. // Copies a simple field to another simple field.
  199. static private void CopySimpleField(SimpleField target, SimpleField source, bool withFormatting)
  200. {
  201. target.Code = source.Code;
  202. target.CustomData = source.CustomData;
  203. target.Locked = source.Locked;
  204. //parse children
  205. CopyChildren(target, source, withFormatting);
  206. }
  207.  
  208. // Copies a run to another run.
  209. static private void CopyRun(Run target, Run source, bool withFormatting)
  210. {
  211. CopyRevisionId(target.RevisionId, source.RevisionId);
  212. CopyChildren(target, source, withFormatting);
  213. if (withFormatting)
  214. {
  215. target.Style = target.Style;
  216. CopyFont(target.Font, source.Font);
  217. }
  218. }
  219.  
  220. // Copies a revision ID.
  221. static private void CopyRevisionId(RevisionId target, RevisionId source)
  222. {
  223. target.AdditionId = source.AdditionId;
  224. target.DeletionId = source.DeletionId;
  225. target.PropertiesId = source.PropertiesId;
  226. }
  227.  
  228. // Adds a copy of a picture to a content object.
  229. static private void AddPicture(ContentObject target, Picture source, bool withFormatting)
  230. {
  231. var newPicture = target.GetRange().Pictures.Add();
  232. CopyPicture(newPicture, source, withFormatting);
  233. }
  234.  
  235. // Copies a picture to another picture.
  236. static private void CopyPicture(Picture target, Picture source, bool withFormatting)
  237. {
  238. CopyImageData(target.ImageData, source.ImageData, withFormatting);
  239. target.Name = source.Name;
  240. target.Title = source.Title;
  241. CopyChildren(target, source, withFormatting);
  242.  
  243. if (!withFormatting)
  244. return;
  245.  
  246. target.AlternativeText = source.AlternativeText;
  247. target.Hidden = source.Hidden;
  248.  
  249. CopyShapeRotation(target.Rotation, source.Rotation);
  250. CopyShapeSize(target.Size, source.Size);
  251. CopyWrapFormat(target.WrapFormat, source.WrapFormat);
  252. }
  253.  
  254. // Copies image data to another image data.
  255. static private void CopyImageData(ImageData target, ImageData source, bool withFormatting)
  256. {
  257. target.Compression = source.Compression;
  258. target.Source = source.Source;
  259. target.SetImage(source.ToStream(), source.ContentType);
  260. if (!withFormatting)
  261. return;
  262. CopyEdgeExtent(target.Crop, source.Crop);
  263. }
  264.  
  265. // Copies paragraph formatting to another paragraph.
  266. static private void CopyParagraphFormat(Paragraph target, Paragraph source)
  267. {
  268. target.Style = source.Style;
  269. target.Mark.Style = source.Mark.Style;
  270.  
  271. CopyParagraphFormatting(target.Format, source.Format);
  272. //
  273. target.ListFormat.Template = source.ListFormat.Template;
  274. target.ListFormat.LevelNumber = source.ListFormat.LevelNumber;
  275. }
  276.  
  277. // Copies a font to another font.
  278. static private void CopyFont(GcFont target, GcFont source)
  279. {
  280. target.AllCaps = source.AllCaps;
  281. target.AlwaysHidden = source.AlwaysHidden;
  282. target.Animation = source.Animation;
  283. target.Bidi = source.Bidi;
  284. target.Bold = source.Bold;
  285. target.BoldBi = source.BoldBi;
  286. CopyBorder(target.Border, source.Border);
  287. CopyWordColor(target.Color, source.Color);
  288. target.ContextualAlternates = source.ContextualAlternates;
  289. target.DisableCharacterSpaceGrid = source.DisableCharacterSpaceGrid;
  290. target.DoubleStrikeThrough = source.DoubleStrikeThrough;
  291. CopyEastAsianLayout(target.EastAsianLayout, source.EastAsianLayout);
  292. target.Emboss = source.Emboss;
  293. target.EmphasisMark = source.EmphasisMark;
  294. target.Engrave = source.Engrave;
  295. target.FitTextId = source.FitTextId;
  296. target.FitTextWidth = source.FitTextWidth;
  297. target.Hidden = source.Hidden;
  298. target.HighlightColor = source.HighlightColor;
  299. target.HintType = source.HintType;
  300. target.Italic = source.Italic;
  301. target.ItalicBi = source.ItalicBi;
  302. target.Kerning = source.Kerning;
  303. target.Ligatures = source.Ligatures;
  304. target.LocaleName = source.LocaleName;
  305. target.LocaleNameBi = source.LocaleNameBi;
  306. //
  307. target.LocaleNameFarEast = source.LocaleNameFarEast;
  308. target.Name = source.Name;
  309. target.NameAscii = source.NameAscii;
  310. target.NameBi = source.NameBi;
  311. target.NameFarEast = source.NameFarEast;
  312. target.NameOther = source.NameOther;
  313. target.NoProofing = source.NoProofing;
  314. target.NumberForm = source.NumberForm;
  315. target.NumberSpacing = source.NumberSpacing;
  316. target.Outline = source.Outline;
  317. target.Position = source.Position;
  318. target.RightToLeft = source.RightToLeft;
  319. target.Scaling = source.Scaling;
  320.  
  321. CopyShading(target.Shading, source.Shading);
  322. target.Shadow = source.Shadow;
  323. target.Size = source.Size;
  324. target.SizeBi = source.SizeBi;
  325. target.SmallCaps = source.SmallCaps;
  326. target.Spacing = source.Spacing;
  327. target.StrikeThrough = source.StrikeThrough;
  328. target.StylisticSets = source.StylisticSets;
  329.  
  330. target.ThemeAscii = source.ThemeAscii;
  331. target.ThemeBi = source.ThemeBi;
  332. target.ThemeFarEast = source.ThemeFarEast;
  333. target.ThemeOther = source.ThemeOther;
  334. target.Underline = source.Underline;
  335. CopyWordColor(target.UnderlineColor, source.UnderlineColor);
  336. target.VerticalPosition = source.VerticalPosition;
  337. target.WebHidden = source.WebHidden;
  338. }
  339.  
  340. // Copies East Asian layout.
  341. static private void CopyEastAsianLayout(EastAsianLayout target, EastAsianLayout source)
  342. {
  343. target.FitVerticalInLine = source.FitVerticalInLine;
  344. target.HorizontalInVertical = source.HorizontalInVertical;
  345. target.TwoLinesInOne = source.TwoLinesInOne;
  346. target.TwoLinesInOneBrackets = source.TwoLinesInOneBrackets;
  347. }
  348.  
  349. // Copies paragraph formatting.
  350. static private void CopyParagraphFormatting(ParagraphFormat target, ParagraphFormat source)
  351. {
  352. target.Alignment = source.Alignment;
  353. target.BaseLineAlignment = source.BaseLineAlignment;
  354. target.Bidi = source.Bidi;
  355.  
  356. target.DisableLineHeightGrid = source.DisableLineHeightGrid;
  357. target.FarEastLineBreakControl = source.FarEastLineBreakControl;
  358. target.HalfWidthPunctuationOnTopOfLine = source.HalfWidthPunctuationOnTopOfLine;
  359. target.HangingPunctuation = source.HangingPunctuation;
  360. target.Hyphenation = source.Hyphenation;
  361.  
  362. target.KeepTogether = source.KeepTogether;
  363. target.KeepWithNext = source.KeepWithNext;
  364. target.NoLineNumber = source.NoLineNumber;
  365. target.OutlineLevel = source.OutlineLevel;
  366. target.PageBreakBefore = source.PageBreakBefore;
  367. target.TextboxTightWrap = source.TextboxTightWrap;
  368. target.TextFlowDirection = source.TextFlowDirection;
  369. target.WidowControl = source.WidowControl;
  370. target.WordWrap = source.WordWrap;
  371.  
  372. CopyShading(target.Shading, source.Shading);
  373. CopySpacing(target.Spacing, source.Spacing);
  374. CopyIndentation(target.Indentation, source.Indentation);
  375. //copy TabStops
  376. foreach (var tabStop in source.TabStops)
  377. {
  378. if (tabStop.Leader != TabStopLeader.None)
  379. target.TabStops.Add(tabStop.Position, tabStop.Alignment);
  380. else
  381. target.TabStops.Add(tabStop.Position, tabStop.Alignment, tabStop.Leader);
  382. }
  383. //copy borders
  384. CopyBorder(target.Borders.Inside, source.Borders.Inside);
  385. CopyBorder(target.Borders.Left, source.Borders.Left);
  386. CopyBorder(target.Borders.Top, source.Borders.Top);
  387. CopyBorder(target.Borders.Right, source.Borders.Right);
  388. CopyBorder(target.Borders.Bottom, source.Borders.Bottom);
  389. }
  390.  
  391. static private void CopyIndentation(Indentation target, Indentation source)
  392. {
  393. target.AutoAdjustRightIndent = source.AutoAdjustRightIndent;
  394. target.CharacterUnitFirstLineIndent = source.CharacterUnitFirstLineIndent;
  395. target.CharacterUnitLeftIndent = source.CharacterUnitLeftIndent;
  396. target.CharacterUnitRightIndent = source.CharacterUnitRightIndent;
  397. target.FirstLineIndent = source.FirstLineIndent;
  398. target.LeftIndent = source.LeftIndent;
  399. target.MirrorIndents = source.MirrorIndents;
  400. target.RightIndent = source.RightIndent;
  401. }
  402.  
  403. static private void CopySpacing(Spacing target, Spacing source)
  404. {
  405. target.AddSpaceBetweenFarEastAndAlpha = source.AddSpaceBetweenFarEastAndAlpha;
  406. target.AddSpaceBetweenFarEastAndDigit = source.AddSpaceBetweenFarEastAndDigit;
  407. target.LineSpacing = source.LineSpacing;
  408. target.LineSpacingRule = source.LineSpacingRule;
  409. target.LineUnitAfter = source.LineUnitAfter;
  410. target.LineUnitBefore = source.LineUnitBefore;
  411. target.NoSpaceBetweenParagraphsOfSameStyle = source.NoSpaceBetweenParagraphsOfSameStyle;
  412. target.SpaceAfter = source.SpaceAfter;
  413. target.SpaceAfterAuto = source.SpaceAfterAuto;
  414. target.SpaceBefore = source.SpaceBefore;
  415. target.SpaceBeforeAuto = source.SpaceBeforeAuto;
  416. }
  417.  
  418. static private void CopyShading(Shading target, Shading source)
  419. {
  420.  
  421. CopyWordColor(target.BackgroundPatternColor, source.BackgroundPatternColor);
  422. CopyWordColor(target.ForegroundPatternColor, source.ForegroundPatternColor);
  423. target.Texture = source.Texture;
  424. }
  425.  
  426. static private void CopyBorder(Border target, Border source)
  427. {
  428. CopyWordColor(target.Color, source.Color);
  429. target.FrameEffect = source.FrameEffect;
  430. target.LineStyle = source.LineStyle;
  431. target.LineWidth = source.LineWidth;
  432. target.Shadow = source.Shadow;
  433. target.Space = source.Space;
  434. target.Visible = source.Visible;
  435. }
  436.  
  437. static private void CopyWordColor(WordColor target, WordColor source)
  438. {
  439. target.RGB = source.RGB;
  440. // Note: current DsWord OM does not provide means to find where a concrete color
  441. // comes from, so copying theme colors will overwrite RGB even if the RGB value
  442. // should be used. So for this sample, we just ignore theme colors:
  443. // target.ThemeColor = source.ThemeColor;
  444. // target.ThemeShade = source.ThemeShade;
  445. // target.ThemeTint = source.ThemeTint;
  446. }
  447.  
  448. static private void CopyWrapFormat(WrapFormat target, WrapFormat source)
  449. {
  450. target.BehindText = source.BehindText;
  451. target.DistanceBottom = source.DistanceBottom;
  452. target.DistanceLeft = source.DistanceLeft;
  453. target.DistanceRight = source.DistanceRight;
  454. target.DistanceTop = source.DistanceTop;
  455. target.Side = source.Side;
  456. target.Type = source.Type;
  457. //clone list
  458. if (source.WrapPolygon != null)
  459. target.WrapPolygon = source.WrapPolygon.ToList();
  460. }
  461.  
  462. static private void CopyShapeRotation(ShapeRotation target, ShapeRotation source)
  463. {
  464. target.Angle = source.Angle;
  465. target.HorizontalFlip = source.HorizontalFlip;
  466. target.VerticalFlip = source.VerticalFlip;
  467. }
  468.  
  469. static private void CopyShapeSize(ShapeSize target, ShapeSize source)
  470. {
  471. CopyEdgeExtent(target.EffectExtent, source.EffectExtent);
  472. CopyShapeWidth(target.Width, source.Width);
  473. CopyShapeHeight(target.Height, source.Height);
  474. }
  475.  
  476. static private void CopyShapeWidth(ShapeWidth target, ShapeWidth source)
  477. {
  478. target.Relative = source.Relative;
  479. target.RelativeTo = source.RelativeTo;
  480. target.Value = source.Value;
  481. }
  482.  
  483. static private void CopyShapeHeight(ShapeHeight target, ShapeHeight source)
  484. {
  485. target.Relative = source.Relative;
  486. target.RelativeTo = source.RelativeTo;
  487. target.Value = source.Value;
  488. }
  489.  
  490. static private void CopyEdgeExtent(EdgeExtent target, EdgeExtent source)
  491. {
  492. target.AllEdges = source.AllEdges;
  493. target.BottomEdge = source.BottomEdge;
  494. target.LeftEdge = source.LeftEdge;
  495. target.RightEdge = source.RightEdge;
  496. target.TopEdge = source.TopEdge;
  497. }
  498. }
  499. }
  500. }
  501.