We're sorry Aspose doesn't work properply without JavaScript enabled.

Free Support Forum - aspose.com

Image Repeater

I’m currently building a system that allows a user to target a bookmark in a template word doc and associate certain data points from our system with it. To accomplish this, I’m simply iterating over the bookmarks collection and seeing if I have an association for each bookmark stored in our database. One of the data points we need to show is a series of images. The end user wants the images displayed in a two by two grid (4 on each page) with optional captions for each image.


What’s the best way to accomplish this? One idea we were kicking around is dynamically building a table and just adding the images to the cells as we add them…

Thanks

Hi Jason,

Thanks for your request. Yes, I think, building a table would be the best and easiest way to achieve this.

Also, you can use PageBreakBefore option to control page breaks:

http://www.aspose.com/documentation/.net-components/aspose.words-for-.net/aspose.words.paragraphformat.pagebreakbefore.html

Best regards,

The table builder is working really well, except for one minor problem. In the system we are building, the user will be able to specify the number of columns and the number of rows per page. I’m currently determining the size of the page, then dividing that up depending on number of columns or rows. So for example, if the user wants two rows per page, each image should have a height of roughly half the page height.

I have this working pretty well until headers and footers are thrown into the mix. At that point the height is off and the images no longer fit the page correctly. Here’s the code I’m using:

double containerWidth = section.PageSetup.PageWidth -
section.PageSetup.LeftMargin -
section.PageSetup.RightMargin -
section.PageSetup.Borders.Left.DistanceFromText -
section.PageSetup.Borders.Right.DistanceFromText -
section.PageSetup.Borders.Left.LineWidth -
section.PageSetup.Borders.Right.LineWidth;

double containerHeight = section.PageSetup.PageHeight -
section.PageSetup.TopMargin -
section.PageSetup.BottomMargin -
section.PageSetup.Borders.Top.DistanceFromText -
section.PageSetup.Borders.Bottom.DistanceFromText -
section.PageSetup.Borders.Top.LineWidth -
section.PageSetup.Borders.Bottom.LineWidth -
section.PageSetup.HeaderDistance -
section.PageSetup.FooterDistance;

double cellSpacing = 5;
int numColumns = node.PhotoGrid_NumberColumns ?? 2;
int numRows = node.PhotoGrid_NumberRows ?? 2;
double cellWidth = (containerWidth - (cellSpacing numColumns)) / numColumns;
double cellHeight = (containerHeight - (cellSpacing numRows)) / numRows;


Based on some other forum posts, you can see I tried throwing the header and footer distance in, but that doesn’t seem to change when I add more content to the header. Any suggestions on how to get the actual header and footer height? Or is there a cleaner way to get the usable height and width of a page?

Thanks

Hi Jason,

Thanks for your inquiry.

I'm afraid there is no direct way to find the current height of a header or footer or the amount of free space on a page. However you can use the work around code below to calculate the actual size of a header or footer. Please note that you will need Aspose.Words version 9.7 or above for one of the required methods. I have attached the main class to this post.

// Calcuate the height of the header in points.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

double headerHeight = CalculateHeightOfHeaderFooterInPoints(doc.FirstSection.HeadersFooters[HeaderFooterType.HeaderPrimary]);

// As a test, add a line to show this position in the document.

Shape lineShape = new Shape(doc, ShapeType.Line);

lineShape.StrokeColor = Color.Red;

lineShape.StrokeWeight = 2;

lineShape.Width = doc.FirstSection.PageSetup.PageWidth;

lineShape.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;

lineShape.RelativeVerticalPosition = RelativeVerticalPosition.Page;

lineShape.Left = 0;

lineShape.Top = headerHeight;

doc.FirstSection.Body.FirstParagraph.AppendChild(lineShape);

///

/// Calcuates the actual height of a header or footer, seen as the maximum of either the top margin or

/// the height of the content within the header or footer.

///

public static double CalculateHeightOfHeaderFooterInPoints(HeaderFooter headerFooter)

{

// Add a bit of extra space in points.

const double buffer = 5;

PageSetup ps = headerFooter.ParentSection.PageSetup;

// Distance from the edge of the page based on whether the input is a header or footer.

double distanceFromPage = headerFooter.IsHeader ? ps.HeaderDistance : ps.FooterDistance;

// Render the header or footer to image.

Image nodeImage = RenderNode(headerFooter, null);

// Calcuate the height of the header or footer.

double headerHeight = ConvertUtil.PixelToPoint(nodeImage.Height) + distanceFromPage + buffer;

return Math.Max(headerHeight, ps.TopMargin);

}

Thanks,

Thanks for the reply.

This looks like it will do exactly what I need, but I can’t find either the Image class, or the RenderNode method. What namespace are they in?

I’m pretty sure I’m using words 10.1 (for .NET)

Hello

Thanks for your request. Please see the attachment to the Adam’s post.

Best regards,

I had a little trouble with the code provided, but thankfully I didn’t actually need the part that wasn’t working. Below is what I ended up with. You guys are great, thanks!



public double CalculateHeightOfHeaderFooterInPoints(HeaderFooter headerFooter)
{
// Add a bit of extra space in points.
const double buffer = 5;
PageSetup ps = headerFooter.ParentSection.PageSetup;
// Distance from the edge of the page based on whether the input is a header or footer.
double distanceFromPage = headerFooter.IsHeader ? ps.HeaderDistance : ps.FooterDistance;
		<span style="color:lime;">// Calcuate the height of the header or footer.</span>
		<span style="color:#93c763;">double</span> headerHeight <span style="color:#e8e2b7;">=</span> <span style="color:#678cb1;">ConvertUtil</span><span style="color:#e8e2b7;">.</span>PixelToPoint(GetNodeHeight(headerFooter)  ) <span style="color:#e8e2b7;">+</span> distanceFromPage <span style="color:#e8e2b7;">+</span> buffer;

		<span style="color:#93c763;">return</span> <span style="color:#678cb1;">Math</span><span style="color:#e8e2b7;">.</span>Max(headerHeight, ps<span style="color:#e8e2b7;">.</span>TopMargin);
	}

	
	<span style="color:#93c763;">public</span> <span style="color:#678cb1;">Double</span> GetNodeHeight(<span style="color:#678cb1;">Node</span> node)
	{
		<span style="color:lime;">// Run some argument checks.</span>
		<span style="color:#93c763;">if</span> (node <span style="color:#e8e2b7;">==</span> <span style="color:#93c763;">null</span>)
			<span style="color:#93c763;">throw</span> <span style="color:#93c763;">new</span> <span style="color:#678cb1;">ArgumentException</span>(<span style="color:#ec7600;">"Node cannot be null"</span>);

		
		<span style="color:#93c763;">var</span>	imageOptions <span style="color:#e8e2b7;">=</span> <span style="color:#93c763;">new</span> Aspose<span style="color:#e8e2b7;">.</span>Words<span style="color:#e8e2b7;">.</span>Saving<span style="color:#e8e2b7;">.</span><span style="color:#678cb1;">ImageSaveOptions</span>(<span style="color:#678cb1;">SaveFormat</span><span style="color:#e8e2b7;">.</span>Png);

		<span style="color:lime;">// Store the paper color to be used on the final image and change to transparent.</span>
		<span style="color:lime;">// This will cause any content around the rendered node to be removed later on.</span>
		<span style="color:#678cb1;">Color</span> savePaperColor <span style="color:#e8e2b7;">=</span> imageOptions<span style="color:#e8e2b7;">.</span>PaperColor;
		imageOptions<span style="color:#e8e2b7;">.</span>PaperColor <span style="color:#e8e2b7;">=</span> <span style="color:#678cb1;">Color</span><span style="color:#e8e2b7;">.</span>Transparent;

		<span style="color:lime;">// There a bug which affects the cache of a cloned node. To avoid this we instead clone the entire document including all nodes,</span>
		<span style="color:lime;">// find the matching node in the cloned document and render that instead.</span>
		<span style="color:#678cb1;">Document</span> doc <span style="color:#e8e2b7;">=</span> (<span style="color:#678cb1;">Document</span>)node<span style="color:#e8e2b7;">.</span>Document<span style="color:#e8e2b7;">.</span>Clone(<span style="color:#93c763;">true</span>);
		node <span style="color:#e8e2b7;">=</span> doc<span style="color:#e8e2b7;">.</span>GetChild(<span style="color:#678cb1;">NodeType</span><span style="color:#e8e2b7;">.</span>Any, node<span style="color:#e8e2b7;">.</span>Document<span style="color:#e8e2b7;">.</span>GetChildNodes(<span style="color:#678cb1;">NodeType</span><span style="color:#e8e2b7;">.</span>Any, <span style="color:#93c763;">true</span>)<span style="color:#e8e2b7;">.</span>IndexOf(node), <span style="color:#93c763;">true</span>);

		<span style="color:lime;">// Create a temporary shape to store the target node in. This shape will be rendered to retrieve</span>
		<span style="color:lime;">// the rendered content of the node.</span>
		Aspose<span style="color:#e8e2b7;">.</span>Words<span style="color:#e8e2b7;">.</span>Drawing<span style="color:#e8e2b7;">.</span><span style="color:#678cb1;">Shape</span> shape <span style="color:#e8e2b7;">=</span> <span style="color:#93c763;">new</span> Aspose<span style="color:#e8e2b7;">.</span>Words<span style="color:#e8e2b7;">.</span>Drawing<span style="color:#e8e2b7;">.</span><span style="color:#678cb1;">Shape</span>(doc, Aspose<span style="color:#e8e2b7;">.</span>Words<span style="color:#e8e2b7;">.</span>Drawing<span style="color:#e8e2b7;">.</span><span style="color:#678cb1;">ShapeType</span><span style="color:#e8e2b7;">.</span>TextBox);
		<span style="color:#678cb1;">Section</span> parentSection <span style="color:#e8e2b7;">=</span> (<span style="color:#678cb1;">Section</span>)node<span style="color:#e8e2b7;">.</span>GetAncestor(<span style="color:#678cb1;">NodeType</span><span style="color:#e8e2b7;">.</span>Section);

		<span style="color:lime;">// Assume that the node cannot be larger than the page in size.</span>
		shape<span style="color:#e8e2b7;">.</span>Width <span style="color:#e8e2b7;">=</span> parentSection<span style="color:#e8e2b7;">.</span>PageSetup<span style="color:#e8e2b7;">.</span>PageWidth;
		shape<span style="color:#e8e2b7;">.</span>Height <span style="color:#e8e2b7;">=</span> parentSection<span style="color:#e8e2b7;">.</span>PageSetup<span style="color:#e8e2b7;">.</span>PageHeight;
		shape<span style="color:#e8e2b7;">.</span>FillColor <span style="color:#e8e2b7;">=</span> <span style="color:#678cb1;">Color</span><span style="color:#e8e2b7;">.</span>Transparent; <span style="color:lime;">// We must make the shape and paper color transparent.</span>

		<span style="color:lime;">// Don't draw a surronding line on the shape.</span>
		shape<span style="color:#e8e2b7;">.</span>Stroked <span style="color:#e8e2b7;">=</span> <span style="color:#93c763;">false</span>;

		<span style="color:#678cb1;">Node</span> currentNode <span style="color:#e8e2b7;">=</span> node;

		<span style="color:lime;">// If the node contains block level nodes then just add a copy of these nodes to the shape.</span>
		<span style="color:#93c763;">if</span> (currentNode <span style="color:#93c763;">is</span> <span style="color:#678cb1;">InlineStory</span> <span style="color:#e8e2b7;">||</span> currentNode <span style="color:#93c763;">is</span> <span style="color:#678cb1;">Story</span>)
		{
			<span style="color:#678cb1;">CompositeNode</span> composite <span style="color:#e8e2b7;">=</span> (<span style="color:#678cb1;">CompositeNode</span>)currentNode;

			<span style="color:#93c763;">foreach</span> (<span style="color:#678cb1;">Node</span> childNode <span style="color:#93c763;">in</span> composite<span style="color:#e8e2b7;">.</span>ChildNodes)
			{
				shape<span style="color:#e8e2b7;">.</span>AppendChild(childNode<span style="color:#e8e2b7;">.</span>Clone(<span style="color:#93c763;">true</span>));
			}
		}
		<span style="color:#93c763;">else</span>
		{
			<span style="color:lime;">// Move up through the DOM until we find node which is suitable to insert into a Shape (a node with a parent can contain paragraph, tables the same as a shape).</span>
			<span style="color:lime;">// Each parent node is cloned on the way up so even a descendant node passed to this method can be rendered. </span>
			<span style="color:lime;">// Since we are working with the actual nodes of the document we need to clone the target node into the temporary shape.</span>
			<span style="color:#93c763;">while</span> (<span style="color:#e8e2b7;">!</span>(currentNode<span style="color:#e8e2b7;">.</span>ParentNode <span style="color:#93c763;">is</span> <span style="color:#678cb1;">InlineStory</span> <span style="color:#e8e2b7;">||</span> currentNode<span style="color:#e8e2b7;">.</span>ParentNode <span style="color:#93c763;">is</span> <span style="color:#678cb1;">Story</span> <span style="color:#e8e2b7;">||</span> currentNode<span style="color:#e8e2b7;">.</span>ParentNode <span style="color:#93c763;">is</span> Aspose<span style="color:#e8e2b7;">.</span>Words<span style="color:#e8e2b7;">.</span>Drawing<span style="color:#e8e2b7;">.</span><span style="color:#678cb1;">ShapeBase</span> <span style="color:#e8e2b7;">||</span> currentNode<span style="color:#e8e2b7;">.</span>NodeType <span style="color:#e8e2b7;">==</span> <span style="color:#678cb1;">NodeType</span><span style="color:#e8e2b7;">.</span>Paragraph))
			{

				<span style="color:#678cb1;">CompositeNode</span> parent <span style="color:#e8e2b7;">=</span> (<span style="color:#678cb1;">CompositeNode</span>)currentNode<span style="color:#e8e2b7;">.</span>ParentNode<span style="color:#e8e2b7;">.</span>Clone(<span style="color:#93c763;">false</span>);
				currentNode <span style="color:#e8e2b7;">=</span> currentNode<span style="color:#e8e2b7;">.</span>ParentNode;
				parent<span style="color:#e8e2b7;">.</span>AppendChild(node<span style="color:#e8e2b7;">.</span>Clone(<span style="color:#93c763;">true</span>));
				node <span style="color:#e8e2b7;">=</span> parent; <span style="color:lime;">// Store this new node to be inserted into the shape.</span>

			}

			<span style="color:lime;">// Add the node to the shape.</span>
			shape<span style="color:#e8e2b7;">.</span>AppendChild(node<span style="color:#e8e2b7;">.</span>Clone(<span style="color:#93c763;">true</span>));
		}

		<span style="color:lime;">// We must add the shape to the document tree to have it rendered.</span>
		parentSection<span style="color:#e8e2b7;">.</span>Body<span style="color:#e8e2b7;">.</span>FirstParagraph<span style="color:#e8e2b7;">.</span>AppendChild(shape);

		<span style="color:lime;">// Render the shape to stream so we can take advantage of the effects of the ImageSaveOptions class.</span>
		<span style="color:lime;">// Retrieve the rendered image and remove the shape from the document.</span>
		<span style="color:#678cb1;">MemoryStream</span> stream <span style="color:#e8e2b7;">=</span> <span style="color:#93c763;">new</span> <span style="color:#678cb1;">MemoryStream</span>();
		shape<span style="color:#e8e2b7;">.</span>GetShapeRenderer()<span style="color:#e8e2b7;">.</span>Save(stream, imageOptions);
		shape<span style="color:#e8e2b7;">.</span>Remove();
		
		<span style="color:#93c763;">double</span> nodeHeight <span style="color:#e8e2b7;">=</span> <span style="color:#ffcd22;">0</span>;

		<span style="color:lime;">// Load the image into a new bitmap.</span>
		<span style="color:#93c763;">using</span> (<span style="color:#678cb1;">Bitmap</span> renderedImage <span style="color:#e8e2b7;">=</span> <span style="color:#93c763;">new</span> <span style="color:#678cb1;">Bitmap</span>(stream))
		{
			<span style="color:lime;">// Extract the actual content of the image by cropping transparent space around</span>
			<span style="color:lime;">// the rendered shape.</span>
			<span style="color:#678cb1;">Rectangle</span> cropRectangle <span style="color:#e8e2b7;">=</span> FindBoundingBoxAroundNode(renderedImage);
			nodeHeight <span style="color:#e8e2b7;">=</span> cropRectangle<span style="color:#e8e2b7;">.</span>Height;
		}

		<span style="color:#93c763;">return</span> nodeHeight;
	}</pre></div>

Hi there,

It's great it's working for you. If you have any further queries, please feel free to ask.

Thanks,