CopyParagraphs.cs
//
// This code is part of Document Solutions for Word demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Linq;
using GrapeCity.Documents.Word;
using GcFont = GrapeCity.Documents.Word.Font;
namespace DsWordWeb.Demos
{
// Starting with the v3 release (fall of 2019), DsWord provides built-in
// support for copying and moving of content using the RangeBase.CopyTo()
// and RangeBase.MoveTo() methods, so this sample is now obsolete.
//
// The original SampleParagraphs.docx used in this sample can be
// seen by running the SampleParagraphs sample.
public class CopyParagraphs
{
public GcWordDocument CreateDocx()
{
const string p1start = "This is the first paragraph of the original document";
const string p2start = "This is the second paragraph of the original document";
const string p3start = "This is the third paragraph of the original document";
const string p4start = "This is the fourth paragraph of the original document";
var doc = new GcWordDocument();
// Load an existing DOCX file:
var path = Path.Combine("Resources", "WordDocs", "SampleParagraphs.docx");
doc.Load(path);
Paragraph p1 = null, p2 = null, p3 = null, p4 = null;
foreach (var p in doc.Body.Paragraphs)
{
var t = p.GetRange().Text;
if (t.StartsWith(p1start))
p1 = p;
else if (t.StartsWith(p2start))
p2 = p;
else if (t.StartsWith(p3start))
p3 = p;
else if (t.StartsWith(p4start))
p4 = p;
}
if (p1 == null || p2 == null || p3 == null || p4 == null)
throw new Exception("Unexpected: could not find paragraphs.");
var swapResult = Helper.SwapParagraphs(p1, p3);
swapResult.Item1.GetRange().Runs.Insert("Second swapped paragraph (paragraph 3): ", InsertLocation.Start);
swapResult.Item2.GetRange().Runs.Insert("First swapped paragraph (paragraph 1): ", InsertLocation.Start);
var joinResult = Helper.JoinParagraphs(doc.Body.Paragraphs.Add(), swapResult.Item1, swapResult.Item2);
joinResult.GetRange().Runs.Insert("Jointed first and 3rd paragraphs: ", InsertLocation.Start);
// Add a note at the end of the document:
doc.Body.Paragraphs.Add($"Created by DsWord on {Util.TimeNow():R}.");
// Done:
return doc;
}
// A static helper class that provides methods to copy or move
// DsWord content objects such as paragraphs and runs.
//
// AddRun, AddPicture, AddField, AddText, AddParagraph methods accept parameter
// "withFormatting" which determines whether to copy just the content,
// or content and formatting. Note that if this parameter is true,
// direct formatting is applied to the newly created objects,
// so the connection to the original document style is broken
// (updating the style will not affect the new objects).
static public class Helper
{
// Swaps two paragraphs by inserting a new paragraph before each one,
// copying the content (and optionally formatting) from the other paragraph,
// and the removing the old paragraphs.
static public (Paragraph, Paragraph) SwapParagraphs(Paragraph p1, Paragraph p2, bool withFormatting = true)
{
if (p1.ParentBody != p2.ParentBody)
throw new Exception("Both paragraphs must belong the same parent body.");
var newP2 = p1.GetRange().Paragraphs.Insert(InsertLocation.Before);
CopyParagraph(newP2, p2, withFormatting);
var newP1 = p2.GetRange().Paragraphs.Insert(InsertLocation.Before);
CopyParagraph(newP1, p1, withFormatting);
p1.Delete();
p2.Delete();
return (newP1, newP2);
}
// Copies the contents (and optionally formatting) of two paragraphs into a third one.
static public Paragraph JoinParagraphs(Paragraph target, Paragraph p1, Paragraph p2, bool withFormatting = true)
{
if (p1.ParentBody != p2.ParentBody)
throw new Exception("Both paragraphs must belong the same parent body.");
CopyParagraph(target, p1, withFormatting);
CopyParagraph(target, p2, withFormatting);
return target;
}
// Copy child objects from one content object to another.
static private void CopyChildren(ContentObject target, ContentObject source, bool withFormatting)
{
foreach (ContentObject child in source.Children)
{
switch (child)
{
case Run run:
AddRun(target, run, withFormatting);
break;
case SimpleField field:
AddField(target, field, withFormatting);
break;
case Picture picture:
AddPicture(target, picture, withFormatting);
break;
case Paragraph paragraph:
AddParagraph(target, paragraph, withFormatting);
break;
case Text text:
AddText(target, text, withFormatting);
break;
default:
System.Diagnostics.Debug.Assert(false, "Unexpected: unknown content object type.");
break;
}
}
}
// Joins two paragraphs.
static private Paragraph JoinParagraphs(Paragraph first, Paragraph second, bool withFormatting = false)
{
if (first.ParentBody != second.ParentBody)
throw new Exception("Left and right paragraphs must belong the same parent body.");
var newParagraph = first.ParentBody.Paragraphs.Add();
CopyParagraph(newParagraph, first, withFormatting);
// Note that second paragraph formatting overrides first paragraph formatting:
CopyParagraph(newParagraph, second, withFormatting);
return newParagraph;
}
// Adds a copy of a paragraph to a body.
static private void AddParagraph(Body body, Paragraph source, bool withFormatting = false)
{
var newParagraph = body.Paragraphs.Add();
CopyParagraph(newParagraph, source, withFormatting);
}
// Adds a copy of a paragraph to a content object.
static private void AddParagraph(ContentObject target, Paragraph source, bool withFormatting = false)
{
var newParagraph = target.GetRange().Paragraphs.Add();
CopyParagraph(newParagraph, source, withFormatting);
}
// Adds a copy of a run to a content object.
static private void AddRun(ContentObject target, Run source, bool withFormatting = false)
{
var newRun = target.GetRange().Runs.Add();
CopyRun(newRun, source, withFormatting);
}
// Copies a paragraph to another paragraph.
static private void CopyParagraph(Paragraph target, Paragraph source, bool withFormatting = false)
{
CopyRevisionId(target.RevisionId, source.RevisionId);
CopyChildren(target, source, withFormatting);
if (withFormatting)
CopyParagraphFormat(target, source);
}
// Adds a copy of a text to a content object.
static private void AddText(ContentObject target, Text source, bool withFormatting)
{
var newText = target.GetRange().Texts.Add(source.Value);
CopyText(newText, source, withFormatting);
}
// Copies a text to another text.
static private void CopyText(Text target, Text source, bool withFormatting)
{
target.PreserveSpace = source.PreserveSpace;
CopyChildren(target, source, withFormatting);
}
// Adds a copy of a field to a content object.
static private void AddField(ContentObject target, SimpleField source, bool withFormatting)
{
var newField = target.GetRange().SimpleFields.Add(source.Code);
CopySimpleField(newField, source, withFormatting);
}
// Copies a simple field to another simple field.
static private void CopySimpleField(SimpleField target, SimpleField source, bool withFormatting)
{
target.Code = source.Code;
target.CustomData = source.CustomData;
target.Locked = source.Locked;
//parse children
CopyChildren(target, source, withFormatting);
}
// Copies a run to another run.
static private void CopyRun(Run target, Run source, bool withFormatting)
{
CopyRevisionId(target.RevisionId, source.RevisionId);
CopyChildren(target, source, withFormatting);
if (withFormatting)
{
target.Style = target.Style;
CopyFont(target.Font, source.Font);
}
}
// Copies a revision ID.
static private void CopyRevisionId(RevisionId target, RevisionId source)
{
target.AdditionId = source.AdditionId;
target.DeletionId = source.DeletionId;
target.PropertiesId = source.PropertiesId;
}
// Adds a copy of a picture to a content object.
static private void AddPicture(ContentObject target, Picture source, bool withFormatting)
{
var newPicture = target.GetRange().Pictures.Add();
CopyPicture(newPicture, source, withFormatting);
}
// Copies a picture to another picture.
static private void CopyPicture(Picture target, Picture source, bool withFormatting)
{
CopyImageData(target.ImageData, source.ImageData, withFormatting);
target.Name = source.Name;
target.Title = source.Title;
CopyChildren(target, source, withFormatting);
if (!withFormatting)
return;
target.AlternativeText = source.AlternativeText;
target.Hidden = source.Hidden;
CopyShapeRotation(target.Rotation, source.Rotation);
CopyShapeSize(target.Size, source.Size);
CopyWrapFormat(target.WrapFormat, source.WrapFormat);
}
// Copies image data to another image data.
static private void CopyImageData(ImageData target, ImageData source, bool withFormatting)
{
target.Compression = source.Compression;
target.Source = source.Source;
target.SetImage(source.ToStream(), source.ContentType);
if (!withFormatting)
return;
CopyEdgeExtent(target.Crop, source.Crop);
}
// Copies paragraph formatting to another paragraph.
static private void CopyParagraphFormat(Paragraph target, Paragraph source)
{
target.Style = source.Style;
target.Mark.Style = source.Mark.Style;
CopyParagraphFormatting(target.Format, source.Format);
//
target.ListFormat.Template = source.ListFormat.Template;
target.ListFormat.LevelNumber = source.ListFormat.LevelNumber;
}
// Copies a font to another font.
static private void CopyFont(GcFont target, GcFont source)
{
target.AllCaps = source.AllCaps;
target.AlwaysHidden = source.AlwaysHidden;
target.Animation = source.Animation;
target.Bidi = source.Bidi;
target.Bold = source.Bold;
target.BoldBi = source.BoldBi;
CopyBorder(target.Border, source.Border);
CopyWordColor(target.Color, source.Color);
target.ContextualAlternates = source.ContextualAlternates;
target.DisableCharacterSpaceGrid = source.DisableCharacterSpaceGrid;
target.DoubleStrikeThrough = source.DoubleStrikeThrough;
CopyEastAsianLayout(target.EastAsianLayout, source.EastAsianLayout);
target.Emboss = source.Emboss;
target.EmphasisMark = source.EmphasisMark;
target.Engrave = source.Engrave;
target.FitTextId = source.FitTextId;
target.FitTextWidth = source.FitTextWidth;
target.Hidden = source.Hidden;
target.HighlightColor = source.HighlightColor;
target.HintType = source.HintType;
target.Italic = source.Italic;
target.ItalicBi = source.ItalicBi;
target.Kerning = source.Kerning;
target.Ligatures = source.Ligatures;
target.LocaleName = source.LocaleName;
target.LocaleNameBi = source.LocaleNameBi;
//
target.LocaleNameFarEast = source.LocaleNameFarEast;
target.Name = source.Name;
target.NameAscii = source.NameAscii;
target.NameBi = source.NameBi;
target.NameFarEast = source.NameFarEast;
target.NameOther = source.NameOther;
target.NoProofing = source.NoProofing;
target.NumberForm = source.NumberForm;
target.NumberSpacing = source.NumberSpacing;
target.Outline = source.Outline;
target.Position = source.Position;
target.RightToLeft = source.RightToLeft;
target.Scaling = source.Scaling;
CopyShading(target.Shading, source.Shading);
target.Shadow = source.Shadow;
target.Size = source.Size;
target.SizeBi = source.SizeBi;
target.SmallCaps = source.SmallCaps;
target.Spacing = source.Spacing;
target.StrikeThrough = source.StrikeThrough;
target.StylisticSets = source.StylisticSets;
target.ThemeAscii = source.ThemeAscii;
target.ThemeBi = source.ThemeBi;
target.ThemeFarEast = source.ThemeFarEast;
target.ThemeOther = source.ThemeOther;
target.Underline = source.Underline;
CopyWordColor(target.UnderlineColor, source.UnderlineColor);
target.VerticalPosition = source.VerticalPosition;
target.WebHidden = source.WebHidden;
}
// Copies East Asian layout.
static private void CopyEastAsianLayout(EastAsianLayout target, EastAsianLayout source)
{
target.FitVerticalInLine = source.FitVerticalInLine;
target.HorizontalInVertical = source.HorizontalInVertical;
target.TwoLinesInOne = source.TwoLinesInOne;
target.TwoLinesInOneBrackets = source.TwoLinesInOneBrackets;
}
// Copies paragraph formatting.
static private void CopyParagraphFormatting(ParagraphFormat target, ParagraphFormat source)
{
target.Alignment = source.Alignment;
target.BaseLineAlignment = source.BaseLineAlignment;
target.Bidi = source.Bidi;
target.DisableLineHeightGrid = source.DisableLineHeightGrid;
target.FarEastLineBreakControl = source.FarEastLineBreakControl;
target.HalfWidthPunctuationOnTopOfLine = source.HalfWidthPunctuationOnTopOfLine;
target.HangingPunctuation = source.HangingPunctuation;
target.Hyphenation = source.Hyphenation;
target.KeepTogether = source.KeepTogether;
target.KeepWithNext = source.KeepWithNext;
target.NoLineNumber = source.NoLineNumber;
target.OutlineLevel = source.OutlineLevel;
target.PageBreakBefore = source.PageBreakBefore;
target.TextboxTightWrap = source.TextboxTightWrap;
target.TextFlowDirection = source.TextFlowDirection;
target.WidowControl = source.WidowControl;
target.WordWrap = source.WordWrap;
CopyShading(target.Shading, source.Shading);
CopySpacing(target.Spacing, source.Spacing);
CopyIndentation(target.Indentation, source.Indentation);
//copy TabStops
foreach (var tabStop in source.TabStops)
{
if (tabStop.Leader != TabStopLeader.None)
target.TabStops.Add(tabStop.Position, tabStop.Alignment);
else
target.TabStops.Add(tabStop.Position, tabStop.Alignment, tabStop.Leader);
}
//copy borders
CopyBorder(target.Borders.Inside, source.Borders.Inside);
CopyBorder(target.Borders.Left, source.Borders.Left);
CopyBorder(target.Borders.Top, source.Borders.Top);
CopyBorder(target.Borders.Right, source.Borders.Right);
CopyBorder(target.Borders.Bottom, source.Borders.Bottom);
}
static private void CopyIndentation(Indentation target, Indentation source)
{
target.AutoAdjustRightIndent = source.AutoAdjustRightIndent;
target.CharacterUnitFirstLineIndent = source.CharacterUnitFirstLineIndent;
target.CharacterUnitLeftIndent = source.CharacterUnitLeftIndent;
target.CharacterUnitRightIndent = source.CharacterUnitRightIndent;
target.FirstLineIndent = source.FirstLineIndent;
target.LeftIndent = source.LeftIndent;
target.MirrorIndents = source.MirrorIndents;
target.RightIndent = source.RightIndent;
}
static private void CopySpacing(Spacing target, Spacing source)
{
target.AddSpaceBetweenFarEastAndAlpha = source.AddSpaceBetweenFarEastAndAlpha;
target.AddSpaceBetweenFarEastAndDigit = source.AddSpaceBetweenFarEastAndDigit;
target.LineSpacing = source.LineSpacing;
target.LineSpacingRule = source.LineSpacingRule;
target.LineUnitAfter = source.LineUnitAfter;
target.LineUnitBefore = source.LineUnitBefore;
target.NoSpaceBetweenParagraphsOfSameStyle = source.NoSpaceBetweenParagraphsOfSameStyle;
target.SpaceAfter = source.SpaceAfter;
target.SpaceAfterAuto = source.SpaceAfterAuto;
target.SpaceBefore = source.SpaceBefore;
target.SpaceBeforeAuto = source.SpaceBeforeAuto;
}
static private void CopyShading(Shading target, Shading source)
{
CopyWordColor(target.BackgroundPatternColor, source.BackgroundPatternColor);
CopyWordColor(target.ForegroundPatternColor, source.ForegroundPatternColor);
target.Texture = source.Texture;
}
static private void CopyBorder(Border target, Border source)
{
CopyWordColor(target.Color, source.Color);
target.FrameEffect = source.FrameEffect;
target.LineStyle = source.LineStyle;
target.LineWidth = source.LineWidth;
target.Shadow = source.Shadow;
target.Space = source.Space;
target.Visible = source.Visible;
}
static private void CopyWordColor(WordColor target, WordColor source)
{
target.RGB = source.RGB;
// Note: current DsWord OM does not provide means to find where a concrete color
// comes from, so copying theme colors will overwrite RGB even if the RGB value
// should be used. So for this sample, we just ignore theme colors:
// target.ThemeColor = source.ThemeColor;
// target.ThemeShade = source.ThemeShade;
// target.ThemeTint = source.ThemeTint;
}
static private void CopyWrapFormat(WrapFormat target, WrapFormat source)
{
target.BehindText = source.BehindText;
target.DistanceBottom = source.DistanceBottom;
target.DistanceLeft = source.DistanceLeft;
target.DistanceRight = source.DistanceRight;
target.DistanceTop = source.DistanceTop;
target.Side = source.Side;
target.Type = source.Type;
//clone list
if (source.WrapPolygon != null)
target.WrapPolygon = source.WrapPolygon.ToList();
}
static private void CopyShapeRotation(ShapeRotation target, ShapeRotation source)
{
target.Angle = source.Angle;
target.HorizontalFlip = source.HorizontalFlip;
target.VerticalFlip = source.VerticalFlip;
}
static private void CopyShapeSize(ShapeSize target, ShapeSize source)
{
CopyEdgeExtent(target.EffectExtent, source.EffectExtent);
CopyShapeWidth(target.Width, source.Width);
CopyShapeHeight(target.Height, source.Height);
}
static private void CopyShapeWidth(ShapeWidth target, ShapeWidth source)
{
target.Relative = source.Relative;
target.RelativeTo = source.RelativeTo;
target.Value = source.Value;
}
static private void CopyShapeHeight(ShapeHeight target, ShapeHeight source)
{
target.Relative = source.Relative;
target.RelativeTo = source.RelativeTo;
target.Value = source.Value;
}
static private void CopyEdgeExtent(EdgeExtent target, EdgeExtent source)
{
target.AllEdges = source.AllEdges;
target.BottomEdge = source.BottomEdge;
target.LeftEdge = source.LeftEdge;
target.RightEdge = source.RightEdge;
target.TopEdge = source.TopEdge;
}
}
}
}