Aspose Word .NET Mutiple pages with different header and footer and Page Totals

Hello Support

We have Mutiple page document where the PRODUCT LINE Items will overflow in continuation pages as attached.

  1. We have one header / Footer for first page and then different header/ footer for continuation pages
  2. WE have page wise totals on all the pages

Please let us know how can we do this with ASPOSE Word .net Mail merge .

Is it best to have the Header or Footer so that it will come on all the pages or is there any other way.

We also do not want any Gaps between header / body and footer so that it looks like same table.

Another query is that for Product line items , can we have a Fix Table height that can cover complete page even if we only have 2-3 line items in it .

Regards
Atul

Urgently awaiting your reply

Hi Atul,

Thanks for your inquiry.

*impexdocs:

  1. We have one header / Footer for first page and then different header/ footer for continuation pages*

Please read following documentation link for your kind reference.
How to Create Headers Footers using DocumentBuilder

impexdocs:
2) WE have page wise totals on all the pages

To add sum of numbers of specific column for each page, we suggest you following solution.

  1. After mail merge, please iterate through all rows of table and sum the cell’s contents (numbered value).
  2. You can get the page index of row/cell using LayoutCollector.GetStartPageIndex. This method returns 1-based index of the page where node begins.
  3. Add a text box at the bottom of each page and insert sum value of specific column.

*impexdocs:
Is it best to have the Header or Footer so that it will come on all the pages or is there any other way.

We also do not want any Gaps between header / body and footer so that it looks like same table.*

Could you please share some detail about this query along with input and expected output documents? We will then provide you more information about your query.

impexdocs:
Another query is that for Product line items , can we have a Fix Table height that can cover complete page even if we only have 2-3 line items in it .

Please read following documentation link. Hope this helps you.
Keeping Tables and Rows from Breaking across Pages

If you still face problem, please share your input template document along with your expected output documents for your scenarios. We will then provide you more information about your queries along with code.

Thank you Tahir for the reply

I am attaching the below :

  1. Page1.rtf, Page 2.rtf, Page 3.rtf is the Output how we want . It can go to n number of pages depending on Line items.
  2. TemplateDocument.docx is teh Template we have created with Merge Fields and Bookmark
  3. 1stpage.png is the screenshot how we envision for 1st page
  4. 2ndpage.png is the screenshot how we envision for 2nd page and continuation page.

Below is my queries:

  1. If you check the Documents , we have “Total of this Page” which is coming on every Page . How can we have page wise totals.
  2. If you check the attached image it shows how we are envisioning the Document for 1st page and continuation pages . Let us know if this is OK.
  3. If we have only 2 Product Line items in 3rd page , how can we add blank Rows so that the Body Table merges with the footer Table.
  4. How can we Merge Body Table with Footer Table so that it looks one table.
  5. Can we have repetitive section which is repetitive on all the pages .

Thanks
Atul

Hi Atul,

Thanks for sharing the detail. A document’s section have following types of header/footers.

HeaderEven : Header for even numbered pages.
HeaderPrimary : Primary header, also used for odd numbered pages.
FooterEven : Footer for even numbered pages.
FooterPrimary : Primary footer, also used for odd numbered pages.
HeaderFirst : Header for the first page of the section.
FooterFirst : Footer for the first page of the section.

In your case, we suggest you following solution.

  1. Add first page header (the table) in the HeaderFirst
  2. Add second page header (the table) in HeaderPrimary
  3. Insert =Sum(Above) field at the position of $ItemTotal (The total of this page)

We have attached the modified template document with this post for your kind reference. To check the first and second page header, please check/uncheck “Different First Page” option. See the attached image for detail.

Hope this helps you. Please let us know if you have any more queries.

Thanks for the Quick Reply. I am checking your suggestion for the Sum .

However Please reply back for :

  1. If we have only 2 Product Line items in 3rd page , how can we add
    blank Rows so that the Body Table merges with the footer Table.
  2. How can we Merge Body Table with Footer Table so that it looks one table.

I have attached the screenshot to explain it better

Regards
Atul

Hi Atul,

Thanks for your inquiry.

impexdocs:
3) If we have only 2 Product Line items in 3rd page , how can we add blank Rows so that the Body Table merges with the footer Table.

In this case, we suggest you following solution.

  1. After mail merge, move the cursor to the paragraph of last cell of table
  2. Insert empty paragraphs until table moves to next page
  3. Remove last paragraph from last row of last cell

Please use LayoutCollector.GetStartPageIndex method to get the page number of paragraph.

impexdocs:
4) How can we Merge Body Table with Footer Table so that it looks one table.

Please use the modified template shared in my previous post. Hope this helps you. If you want to merge the table (header) and table in the body, you need to add both tables in the body of section.

If you face any issue, please share following detail for investigation purposes.

  • Please attach your input Word documents.
  • Please

create a standalone/runnable simple application (for example a Console
Application Project
) that demonstrates the code (Aspose.Words code) you used to generate
your output document

  • Please attach the output Word file that shows the undesired behavior.
  • Please attach your target Word document showing the desired behavior. You can
    use Microsoft Word to create your target Word document. I will investigate as to how you are expecting your final document be generated like.

Hello Tahir

Thanks for the Quick Response. We are stil not able to get the Page wise Totals for each pages and the Blank Paragraphs.

Any help will be appreciated.

As suggested Please find the Input Template,
Output Document PDF, and
runnable Sample Application.

Also attached the Query document as what we are facing the issue and wants the guidance as how to achieve it.

Regards
Atul

Hi Atul,

Thanks for sharing the detail. Please note that Aspose.Words mimics the same behavior as MS Word does. MS Word document is flow document and does not contain any information about its layout into lines and pages. Therefore, technically there is no “Page”, “Line” concept in Word document. Pages and lines are created by Microsoft Word on the fly.

Aspose.Words uses our own Rendering Engine to layout documents into pages and lines. The Aspose.Words.Layout namespace provides classes that allow to access information such as on what page and where on a page particular document elements are positioned, when the document is formatted into pages.

To add sum of numbers of specific column for each page, we suggest you following solution.

  1. After mail merge, please iterate through all rows of table and sum the cell’s contents (numbered value).
  2. You can get the page index of row/cell using LayoutCollector.GetStartPageIndex. This method returns 1-based index of the page where node begins.
  3. Add a text box at the bottom of each page and insert sum value of specific column.

Please check following code snippet for your kind reference.

Table table = (Table)doc.FirstSection.Body.GetChild(NodeType.Table, 0, true);
LayoutCollector collector = new LayoutCollector(doc);
int page = 1;
double pageSum = 0.0;
foreach (Row r in table.Rows)
{
    if (collector.GetStartPageIndex(r.LastCell) == page)
    {
        double sum = 0.0;
        bool isNumeric = double.TryParse(r.LastCell.ToString(SaveFormat.Text).Trim(), out sum);
        if (isNumeric)
            pageSum = pageSum + sum;
    }
    else
    {
        Shape shape = new Shape(doc, ShapeType.TextBox);
        shape.AppendChild(new Paragraph(doc));
        shape.FirstParagraph.AppendChild(new Run(doc, pageSum.ToString()));
        shape.Width = 50;
        shape.Height = 20;
        shape.WrapType = WrapType.None;
        shape.RelativeHorizontalPosition = RelativeHorizontalPosition.Character;
        shape.RelativeVerticalPosition = RelativeVerticalPosition.Paragraph;
        shape.Top = 50;
        shape.Left = -30;
        LayoutEnumerator layoutEnumerator = new LayoutEnumerator(doc);
        var renderObject = collector.GetEntity(r.LastCell.FirstParagraph);
        layoutEnumerator.Current = renderObject;
        RectangleF location = layoutEnumerator.Rectangle;
        Console.WriteLine(r.LastCell.FirstParagraph.GetText());
        ((Row)r.PreviousSibling).LastCell.FirstParagraph.AppendChild(shape);
        pageSum = 0.0;
        page++;
    }
}
doc.Save(MyDir + "Out.docx");

Regarding your second query for page 2 contents, please manually create your expected Word document using Microsoft Word and attach it here for our reference. We will investigate as to how you want your final Word output be generated like. We will then provide you more information on this along with code.

Hello Tahir

Thanks for the Reply and the Code Snippet . We were able to get the First page Total using this .
Now we are working on subsequent page Totals.

For the Second Query for Page 2 (or last page ) contents , I ahev attached the Final Output which we require. I have given 2 OPTIONS . Whichever is possible please let us knoe and How is it possible.

Please check the 3rd Page of these documents which is the Last Page of the Docment.

  1. Option 1 : Output_Document(Option 1).rtf
  2. Option 2 : Output_Document(Option 2).rtf
  3. This is the layout how we have designed it . If it is not OK then let us know . : Document_LayoutSectionDetails.rtf

Also let us know how we can merge the Body Section and Footer so that there is no Gap in it.

If you can update the Sample Code which we gave and send us the Final Code with the resolution of both the queries it will be appreciated.

Regards
Atul

Hello Tahir

We are even ready for Priority Support and Custom Work if Aspose for give us assurance if this can be achieved.
We need this implemented in the Sample code we gave .

It will be good if we can gave a Call conference also where we can explain what we want .

Note : This is possoble in Crustal Reports but we want to replace Crystal Reports with ASPOSE WORD…

Its becoming Urgent now as Client wants it quickly.

Regards
Atul

Hi Atul,

Thanks for sharing the detail. We are working over your query and will update you soon.

Hi Atul,

Thanks for sharing the detail.

impexdocs:
Thanks for the Reply and the Code Snippet . We were able to get the First page Total using this .
Now we are working on subsequent page Totals.

You can use the same approach as shared in my previous post to get the total of each page.

impexdocs:
It will be good if we can gave a Call conference also where we can explain what we want .

We do not provide phone support for technical issues but you can contact us via forums and live chat.

impexdocs:
Note : This is possoble in Crustal Reports but we want to replace Crystal Reports with ASPOSE WORD…

Could you please share your expected output document generated by Crystal Reports here for our reference? We will then provide you more information about your query along with code.

impexdocs:
Also let us know how we can merge the Body Section and Footer so that there is no Gap in it.

Please note that Aspose.Words mimics the same behavior as MS Word does. You can create/modify Word documents using Aspose.Words APIs which you can create/modify using MS Words.

A MS Word document contains page header/footer, tables, paragraphs etc. In your scenario, you want followings:

  1. Total of table’s column for each page. For this case, please check code example shared in my previous post.
  2. For last page, increase the table’s height so that it will look like merged table with footer’s table
  3. Remove the distance between tables inside header, footer and body of page so that it looks like one table.

We have modified the template document for your kind reference. Please check the table’s first section headers and footers in attached input and output documents. Please check following code example. Hope this helps you.

Document doc = new Document(MyDir + "input.docx");
DocumentBuilder dcbuild = new DocumentBuilder(doc);
DataTable dtlblPermitNumber = new DataTable();
DataTable dtedn = new DataTable();
DataTable dtPaking = new DataTable();
DataSet dsLineDetail = new DataSet();
dtlblPermitNumber.TableName = "Product";
dtPaking.TableName = "Packing";
dtedn.Columns.Add("EXPORTER");
dtedn.Columns.Add("ShipmentID");
DataRow row;
DataRow row1;
DataRow drPaking;
row = dtedn.NewRow();
row["EXPORTER"] = "ABC PTY LTD\r\nUNIT 12 HILL AVE\r\nROSUSE NSW 2154\r\nAUSTRALIA";
row["ShipmentID"] = "1";
dtedn.Rows.Add(row);
dtlblPermitNumber.Columns.Add("ShipmentID");
dtlblPermitNumber.Columns.Add("PCODE");
dtlblPermitNumber.Columns.Add("DGOODS");
dtlblPermitNumber.Columns.Add("QTY");
dtlblPermitNumber.Columns.Add("UPRICE");
dtlblPermitNumber.Columns.Add("Total");
for (int j = 0; j < 48; j++)
{
    row1 = dtlblPermitNumber.NewRow();
    row1["ShipmentID"] = "1";
    row1["PCODE"] = "PO000" + j;
    row1["DGOODS"] = j + ": 100 CARTONS ASSORTED FOODS 100 CARTONS";
    row1["QTY"] = j + "000";
    row1["UPRICE"] = j + "00" + j;
    row1["Total"] = "1500" + j;
    dtlblPermitNumber.Rows.Add(row1);
}
dtPaking.Columns.Add("ShipmentID");
dtPaking.Columns.Add("Marks");
dtPaking.Columns.Add("NoOfPKGS");
dtPaking.Columns.Add("DesOfGoods");
dtPaking.Columns.Add("NetWT");
dtPaking.Columns.Add("GrossWT");
dtPaking.Columns.Add("Volume");
drPaking = dtPaking.NewRow();
drPaking["ShipmentID"] = "1";
drPaking["Marks"] = "AS ADDRESSED";
drPaking["NoOfPKGS"] = "100 CARTON";
drPaking["DesOfGoods"] = " 1 X 20' CONTAINER STC\r\n100 CARTONS\r\nASSORTED FOODS\r\n15000 KGS";
drPaking["NetWT"] = "22";
drPaking["GrossWT"] = "33";
drPaking["Volume"] = "44";
dtPaking.Rows.Add(drPaking);
dsLineDetail.Tables.Add(dtedn);
dsLineDetail.Tables.Add(dtPaking);
dsLineDetail.Tables.Add(dtlblPermitNumber);
if (dtlblPermitNumber.Rows.Count > 0)
{
    dsLineDetail.Relations.Add(new DataRelation("LineItem", dtedn.Columns["ShipmentID"], dtlblPermitNumber.Columns["ShipmentID"], false));
}
if (dtPaking.Rows.Count > 0)
{
    dsLineDetail.Relations.Add(new DataRelation("LineItem2", dtedn.Columns["ShipmentID"], dtPaking.Columns["ShipmentID"], false));
}
doc.MailMerge.CleanupOptions = MailMergeCleanupOptions.RemoveContainingFields;
doc.MailMerge.CleanupOptions |= MailMergeCleanupOptions.RemoveStaticFields;
doc.MailMerge.CleanupOptions |= MailMergeCleanupOptions.RemoveEmptyParagraphs;
doc.MailMerge.CleanupOptions |= MailMergeCleanupOptions.RemoveUnusedRegions;
doc.MailMerge.CleanupOptions |= MailMergeCleanupOptions.RemoveUnusedFields;
doc.MailMerge.Execute(dtedn);
// doc.MailMerge.ExecuteWithRegions(dtlblPermitNumber);
doc.MailMerge.ExecuteWithRegions(dsLineDetail);
// doc.InsertBreak(BreakType.PageBreak);
doc.MailMerge.DeleteFields();
// Add total 
Table table = (Table)doc.FirstSection.Body.GetChild(NodeType.Table, 0, true);
LayoutCollector collector = new LayoutCollector(doc);
int page = 1;
double pageSum = 0.0;
foreach (Row r in table.Rows)
{
    if (collector.GetStartPageIndex(r.LastCell) == page)
    {
        double sum = 0.0;
        bool isNumeric = double.TryParse(r.LastCell.ToString(SaveFormat.Text).Trim(), out sum);
        if (isNumeric)
            pageSum = pageSum + sum;
    }
    else
    {
        Shape shape = new Shape(doc, ShapeType.TextBox);
        shape.AppendChild(new Paragraph(doc));
        shape.FirstParagraph.AppendChild(new Run(doc, pageSum.ToString()));
        shape.Width = 50;
        shape.Height = 20;
        shape.WrapType = WrapType.None;
        shape.RelativeHorizontalPosition = RelativeHorizontalPosition.Character;
        shape.RelativeVerticalPosition = RelativeVerticalPosition.Paragraph;
        shape.Top = 50;
        shape.Left = -30;
        LayoutEnumerator layoutEnumerator = new LayoutEnumerator(doc);
        var renderObject = collector.GetEntity(r.LastCell.FirstParagraph);
        layoutEnumerator.Current = renderObject;
        RectangleF location = layoutEnumerator.Rectangle;
        // Console.WriteLine(r.LastCell.FirstParagraph.GetText());
        ((Row)r.PreviousSibling).LastCell.FirstParagraph.AppendChild(shape);
        pageSum = 0.0;
        page++;
    }
}
collector = new LayoutCollector(doc);
int pagenumber = collector.GetStartPageIndex(table.LastRow.FirstCell.LastParagraph);
int nextpagenumber = pagenumber + 1;
Row lastrow = (Row)table.LastRow.Clone(true);
foreach (Cell cell in lastrow.Cells)
{
    cell.RemoveAllChildren();
    cell.EnsureMinimum();
}
while (pagenumber != nextpagenumber)
{
    table.Rows.Add(lastrow.Clone(true));
    collector = new LayoutCollector(doc);
    pagenumber = collector.GetStartPageIndex(table.LastRow.FirstCell.LastParagraph);
}
table.LastRow.Remove();
doc.Save(MyDir + "Out.docx");

Hello Tahir

in the “out.docx” which you attached as output , I can see that there is a BLANK Last page . How to avoid that .

Also the $ItemTotal (page total) on 4th Page ( last page) is not coming

Please let us know

Regards
Atul

Hello Tahir

in the “out.docx” which you attached as output , I can see that there is a BLANK Last page . How to avoid that .

Also the $ItemTotal (page total) on 4th Page (only on last page) is not coming

Please let us know

Also I Have attached the Inputtemplate.docx and the OUTPUT which we got using your codes. (ouputtemplate.docx)
Note the Gap in between the Table and the Footer . This Gap reduces or increases depending on the CONTENT of the DESCRIPTION OF GOODS in the PRODUCT TABLE as the Line Items are Dynamically coming and there is no fix amount of Characters in it . It can be of 1 line for one product and 3 lines or 4 lines for another product.

Your Example was good for Fixed Static Data .

Please advise

Regards
Atul

Hi Atul,

Thanks for your inquiry.

impexdocs:
in the “out.docx” which you attached as output , I can see that there is a BLANK Last page . How to avoid that .

Please note that there is last empty paragraph at the end of output document. This is last paragraph in the Body (main text story) of a Section and cannot be removed. The table (in the page’s body) ends at the start of footer of section.

Please set the font size of last paragraph of last section in the document to 1pt and decrease the height of last row of table. Please use Paragraph.ParagraphBreakFont property to set the font size to 1. Use RowFormat.Height property to set the height of row. The height rule of last row of table must be Exactly. Use RowFormat.HeightRule property to set rule height of row. In this case, there will be a small gap between table’s body and footer at the last page of output document.

impexdocs:
Also the $ItemTotal (page total) on 4th Page (only on last page) is not coming

Please use the same code one more time for last page of document. Please check code inside foreach (Row r in table.Rows).

impexdocs:
Also I Have attached the Inputtemplate.docx and the OUTPUT which we got using your codes. (ouputtemplate.docx)
Note the Gap in between the Table and the Footer . This Gap reduces or increases depending on the CONTENT of the DESCRIPTION OF GOODS in the PRODUCT TABLE as the Line Items are Dynamically coming and there is no fix amount of Characters in it . It can be of 1 line for one product and 3 lines or 4 lines for another product.

Please note that MS Word document is flow document. If the contents of table’s row are increased, the table’s row height may vary. In this case, you need to set the row height of table in template document with height rule as exactly. You need to set row height according to your contents and requirements.

Hello Tahir

Sorry for getting back after some days.

We are still not able to get the page Totals on the LAST Page .

$ItemTotal (page total) does not work on Last page if there are more then 2 pages .

It shows the totals all the intermediate pages.

Please let us know what code changes we have to do to achieve this

Regards
Atul

Hi Atul,

Thanks for your inquiry. Please iterate through all rows of table render at last page of document and sum the numbers of last column. Add the Shape node in the last row of table. Please use following code example to achieve your requirements. Hope this helps you.

// .... your code.....
// .... your code.....
// .... your code.....
table.LastRow.Remove();
collector = new LayoutCollector(doc);
pageSum = 0.0;
int lastpage = collector.GetStartPageIndex(table.LastRow.LastCell);
foreach (Row r in table.Rows)
{
    if (collector.GetStartPageIndex(r.LastCell) == lastpage)
    {
        Console.WriteLine(collector.GetStartPageIndex(r.LastCell));
        double sum = 0.0;
        bool isNumeric = double.TryParse(r.LastCell.ToString(SaveFormat.Text).Trim(), out sum);
        if (isNumeric)
            pageSum = pageSum + sum;
    }
}
Shape shp = new Shape(doc, ShapeType.TextBox);
shp.AppendChild(new Paragraph(doc));
shp.FirstParagraph.AppendChild(new Run(doc, pageSum.ToString()));
shp.Width = 50;
shp.Height = 20;
shp.WrapType = WrapType.None;
shp.RelativeHorizontalPosition = RelativeHorizontalPosition.Character;
shp.RelativeVerticalPosition = RelativeVerticalPosition.Paragraph;
shp.Top = 50;
shp.Left = -30;
table.LastRow.LastCell.FirstParagraph.AppendChild(shp);
doc.Save(MyDir + "Out.docx");