//
// 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;
namespace DsWordWeb.Demos
{
// This sample shows how to insert the whole body of an existing DOCX into
// another document at a location where an arbitrary search string is found.
// One interesting point in this sample is that the code ensures that the
// insert position is valid, i.e. the source content (all paragraphs of
// the source document) can be inserted at the found point. If necessary,
// the target is split so that there is a content object of a valid type
// at the point where the source is to be inserted.
// In this sample, the target document is JsFrameworkExcerpt.
// The source document inserted is SampleParagraphs, and it is inserted
// on page 2 of the source document, immediately before the string
// "software design principles".
public class InsertAtFound
{
public GcWordDocument CreateDocx()
{
// The string to find. The source document will be inserted before this string:
const string findPattern = "software design principles";
// Target document where the source document will be inserted:
var doc = new GcWordDocument();
doc.Load(Path.Combine("Resources", "WordDocs", "JsFrameworkExcerpt.docx"));
// Source document that will be inserted into the target:
var sourceDoc = new GcWordDocument();
sourceDoc.Load(Path.Combine("Resources", "WordDocs", "SampleParagraphs.docx"));
// Note: the inserted document starts with a 'Heading 1', which adds a page break.
// We change it to 'Heading 2' to avoid this so that the result is more clear:
sourceDoc.Body.Paragraphs.First.Style = sourceDoc.Styles[BuiltInStyleId.Heading2];
// Find the first occurrence of the search string:
var findResult = doc.Body.Find(findPattern, new FindOptions(doc) { IgnoreCase = true }).FirstOrDefault();
if (findResult == null)
throw new Exception("Unexpected: search string not found.");
// Find a valid insertion point near the found string:
var insertObject = CreateInsertPoint(findResult);
// Copy the source document to the target at insertion point:
sourceDoc.Body.CopyTo(insertObject.GetRange(), InsertLocation.Before);
// Done:
return doc;
}
// Walk up the parent chain and determine where we are - inside body, cell or contentcontrol.
// Return the original object if we are inside body or cell.
// Return contentcontrol if we are inside contentcontrol.
private static ContentObject GetAnchorObject(ContentObject testedObject)
{
var originalObject = testedObject;
while (true)
{
if (testedObject.ParentContent == null)
return originalObject;
else if (testedObject is Cell)
return originalObject;
else if (testedObject is ContentControl)
return testedObject;
else
testedObject = testedObject.ParentContent;
}
}
// This method assumes that testObject is always an entity inside a paragraph.
private static Paragraph GetParentParagraph(ContentObject testObject)
{
while (testObject != null)
{
if (testObject is Paragraph)
return (Paragraph)testObject;
testObject = testObject.ParentContent;
}
throw new ArgumentException("testObject is not inside a paragraph.");
}
private static ContentObject CreateInsertPoint(FindResult fr)
{
var anchorObject = GetAnchorObject(fr.Range.First());
var foundParagraph = GetParentParagraph(anchorObject);
if (fr.StartIndex > 0 && anchorObject is Text)
anchorObject = ((Text)anchorObject).Split(fr.StartIndex);
if (foundParagraph == anchorObject)
anchorObject = foundParagraph.Split(anchorObject, InsertLocation.End);
else
anchorObject = foundParagraph.Split(anchorObject, InsertLocation.Before);
return anchorObject;
}
}
}