PDF drops table cells in conditional Footer

I am building a document that must be printed in Word and PDF format. I have a stripped-down code example attached to replicate the problem. The footer uses the Word IF condition to determine if it is the last page or not. A different footer is shown on the last page than on the other pages. Footers are contained in table cells. For this example, there is a one-row table with two cells. The first cell is left justified and the second cell is right justified.
The problem is that all but the first cell of the table are removed if printing to PDF. In Word, it works perfectly.
Here is the code (also attached as a text file)

public void AsposeTest(string someText, bool asPDF)
{
    Document doc = null;
    DocumentBuilder builder = null;
    byte[] byteArray = Encoding.ASCII.GetBytes(someText);
    MemoryStream stream = new MemoryStream(byteArray);
    doc = new Document(stream, new LoadOptions(LoadFormat.Html, string.Empty, string.Empty));
    builder = new DocumentBuilder(doc);
    Aspose.Words.Section currentSection = builder.CurrentSection;
    PageSetup pageSetup = currentSection.PageSetup;
    // conditional footer, last pg or only single page doc versus all other pages
    builder.MoveToHeaderFooter(HeaderFooterType.FooterPrimary);
    // insert a table with 2 columns to hold footer
    builder.StartTable();
    // Calculate table width as total page width with left and right marins subtracted.
    double tableWidth = pageSetup.PageWidth - pageSetup.LeftMargin - pageSetup.RightMargin;
    ///////////////////////////////////////////////////////////////////// left side footer
    builder.InsertCell();
    builder.CurrentParagraph.ParagraphFormat.Alignment = ParagraphAlignment.Left;
    builder.CellFormat.Width = tableWidth * .50;
    Field field = builder.InsertField("IF \"", null);
    FieldStart fieldStart = field.Start;
    // Move DocumentBuilder cursor to the next run after field start.
    builder.MoveTo(fieldStart.NextSibling.NextSibling);
    builder.InsertField("PAGE", null);
    builder.Write("\" = \"");
    builder.InsertField("NUMPAGES", null);
    builder.Write("\" \""); //start open quote of true condition
    // Insert Conditional Part Of Footer Cell Into Builder (true part)
    builder.InsertHtml("Left Justified Footer for LAST pg");
    builder.Write("\" \""); //close quote for true condition and open quote of false condition
    // Insert Conditional Part Of Footer Cell Into Builder (false part)
    builder.InsertHtml("Left Justified Footer for OTHER pgs");
    builder.Write("\""); //close quote for false condition

    ///////////////////////////////////////////////////////////////////// right side footer
    builder.InsertCell();
    builder.CurrentParagraph.ParagraphFormat.Alignment = ParagraphAlignment.Right;
    builder.CellFormat.Width = tableWidth * .50;
    field = builder.InsertField("IF \"", null);
    fieldStart = field.Start;
    // Move DocumentBuilder cursor to the next run after field start.
    builder.MoveTo(fieldStart.NextSibling.NextSibling);
    builder.InsertField("PAGE", null);
    builder.Write("\" = \"");
    builder.InsertField("NUMPAGES", null);
    builder.Write("\" \""); //start open quote of true condition
    // Insert Conditional Part Of Footer Cell Into Builder (true part)
    builder.InsertHtml("right Justified Footer for LAST pg");
    builder.Write("\" \""); //close quote for true condition and open quote of false condition
    // Insert Conditional Part Of Footer Cell Into Builder (false part)
    builder.InsertHtml("right Justified Footer for OTHER pgs");
    builder.Write("\""); //close quote for false condition
    builder.EndRow();
    builder.EndTable();
    doc.UpdateTableLayout();
    doc.UpdateFields();
    // print out word or PDF format
    if (asPDF)
        doc.Save(Response, "filename.pdf", ContentDisposition.Attachment, SaveOptions.CreateSaveOptions(SaveFormat.Pdf));
    else
    {
        doc.Save(Response, "filename.docx", ContentDisposition.Attachment, SaveOptions.CreateSaveOptions(SaveFormat.Docx));
        Response.End();
    }
}

This message was posted using Aspose.Live 2 Forum (private + attachment)

I noticed that the “keep post private” is checked, an also greyed out so I can’t uncheck it. I do not care about making it private, especially if it will help someone else solve there issues.

This is re-post for: https://forum.aspose.com/t/75714
This previous post was marked as private for some reason, so I am reposting it:
I am building a document that must be printed in Word and PDF format. I have a stripped-down code example attached to replicate the problem. The footer uses the Word IF condition to determine if it is the last page or not. A different footer is shown on the last page than on the other pages. Footers are contained in table cells. For this example, there is a one-row table with two cells. The first cell is left justified and the second cell is right justified.
The problem is that all but the first cell of the table are removed if printing to PDF. In Word, it works perfectly.
Here is the code (also attached as a text file)

public void AsposeTest(string someText, bool asPDF)
{
    Document doc = null;
    DocumentBuilder builder = null;
    byte[] byteArray = Encoding.ASCII.GetBytes(someText);
    MemoryStream stream = new MemoryStream(byteArray);
    doc = new Document(stream, new LoadOptions(LoadFormat.Html, string.Empty, string.Empty));
    builder = new DocumentBuilder(doc);
    Aspose.Words.Section currentSection = builder.CurrentSection;
    PageSetup pageSetup = currentSection.PageSetup;
    //conditional footer, last pg or only single page doc versus all other pages
    builder.MoveToHeaderFooter(HeaderFooterType.FooterPrimary);
    //insert a table with 2 columns to hold footer
    builder.StartTable();
    // Calculate table width as total page width with left and right marins subtracted.
    double tableWidth = pageSetup.PageWidth - pageSetup.LeftMargin - pageSetup.RightMargin;
    ///////////////////////////////////////////////////////////////////// left side footer
    builder.InsertCell();
    builder.CurrentParagraph.ParagraphFormat.Alignment = ParagraphAlignment.Left;
    builder.CellFormat.Width = tableWidth * .50;
    Field field = builder.InsertField(" IF \"", null);

    FieldStart fieldStart = field.Start;
    // Move DocumentBuilder cursor to the next run after field start.
    builder.MoveTo(fieldStart.NextSibling.NextSibling);
    builder.InsertField("PAGE", null);
    builder.Write("\" = \"");
    builder.InsertField("NUMPAGES", null);
    builder.Write("\" \""); //start open quote of true condition
                            // Insert Conditional Part Of Footer Cell Into Builder (true part)
    builder.InsertHtml("Left Justified Footer for LAST pg");
    builder.Write("\" \""); //close quote for true condition and open quote of false condition
                            // Insert Conditional Part Of Footer Cell Into Builder (false part)
    builder.InsertHtml("Left Justified Footer for OTHER pgs");
    builder.Write("\""); //close quote for false condition

    ///////////////////////////////////////////////////////////////////// right side footer
    builder.InsertCell();
    builder.CurrentParagraph.ParagraphFormat.Alignment = ParagraphAlignment.Right;
    builder.CellFormat.Width = tableWidth * .50;
    field = builder.InsertField("IF \"", null);
    fieldStart = field.Start;
    // Move DocumentBuilder cursor to the next run after field start.
    builder.MoveTo(fieldStart.NextSibling.NextSibling);
    builder.InsertField("PAGE", null);
    builder.Write("\" = \"");
    builder.InsertField("NUMPAGES", null);
    builder.Write("\" \""); //start open quote of true condition
                            // Insert Conditional Part Of Footer Cell Into Builder (true part)
    builder.InsertHtml("right Justified Footer for LAST pg");
    builder.Write("\" \""); //close quote for true condition and open quote of false condition
                            // Insert Conditional Part Of Footer Cell Into Builder (false part)
    builder.InsertHtml("right Justified Footer for OTHER pgs");
    builder.Write("\""); //close quote for false condition
    builder.EndRow();
    builder.EndTable();
    doc.UpdateTableLayout();
    doc.UpdateFields();
    // print out word or PDF format
    if (asPDF)
        doc.Save(Response, "filename.pdf", ContentDisposition.Attachment, SaveOptions.CreateSaveOptions(SaveFormat.Pdf));
    else
    {
        doc.Save(Response, "filename.docx", ContentDisposition.Attachment, SaveOptions.CreateSaveOptions(SaveFormat.Docx));
        Response.End();
    }
}

This message was posted using Aspose.Live 2 Forum (private + attachment)

Hello
Thanks for your request.
I managed to reproduce the problem on my side.
Your request has been linked to the appropriate issue. You will be notified as soon as it is fixed.

Hello. We just purchased .Total last week and the project I am working on is highly dependant on the PDF rendering the same as the Word document. I am getting a bit nervous because you guys usually have an answer for me in just a few hours. Could I get a status update on this, please?

Hello,
Thanks for your additional information.
Unfortunately, currently, I cannot provide you any reliable estimate regarding this issue. We will be sure to inform you of any development regarding this problem.
Sincerely apologies for such an uncomfortable coincidence.
I will try to find a workaround for your problem, and will answer you soon.

Hi there,
Thanks for your inquiry.
We will give you an estimate after the appropriate developer has taken a look into the issue.
In the mean time you can try using the work around below which uses text boxes to layout content instead of tables. All content appears in the rendered output using this technique.

Document doc = null;
DocumentBuilder builder = null;
byte[] byteArray = Encoding.ASCII.GetBytes(someText);
MemoryStream stream = new MemoryStream(byteArray);
doc = new Document(stream, new LoadOptions(LoadFormat.Html, string.Empty, string.Empty));
builder = new DocumentBuilder(doc);
Aspose.Words.Section currentSection = builder.CurrentSection;
PageSetup pageSetup = currentSection.PageSetup;
// conditional footer, last pg or only single page doc versus all other pages
builder.MoveToHeaderFooter(HeaderFooterType.FooterPrimary);
// Calculate table width as total page width with left and right marins subtracted.
double tableWidth = pageSetup.PageWidth - pageSetup.LeftMargin - pageSetup.RightMargin;
///////////////////////////////////////////////////////////////////// left side footer
// Create and format the left side textbox
Shape leftShape = new Shape(doc, ShapeType.TextBox);
leftShape.AppendChild(new Paragraph(doc));
leftShape.Height = pageSetup.FooterDistance;
leftShape.Width = tableWidth / 2;
leftShape.Stroked = false;
// The textbox appears on the left hand side.
leftShape.HorizontalAlignment = HorizontalAlignment.Left;
// Clone the left side textbox and change formatting for the right side
Shape rightShape = (Shape) leftShape.Clone(true);
// The textbox appears on the right hand side.
rightShape.HorizontalAlignment = HorizontalAlignment.Right;
// Insert the shape into the current paragraph and move to the first paragraph of the textbox.
builder.InsertNode(leftShape);
builder.MoveTo(leftShape.FirstParagraph);
builder.CurrentParagraph.ParagraphFormat.Alignment = ParagraphAlignment.Left;
Field field = builder.InsertField("IF \"", null);
FieldStart fieldStart = field.Start;
// Move DocumentBuilder cursor to the next run after field start.
builder.MoveTo(fieldStart.NextSibling.NextSibling);
builder.InsertField("PAGE", null);
builder.Write("\" = \"");
builder.InsertField("NUMPAGES", null);
builder.Write("\" \""); //start open quote of true condition
// Insert Conditional Part Of Footer Cell Into Builder (true part)
builder.InsertHtml("Left Justified Footer for LAST pg");
builder.Write("\" \""); //close quote for true condition and open quote of false condition
// Insert Conditional Part Of Footer Cell Into Builder (false part)
builder.InsertHtml("Left Justified Footer for OTHER pgs");
builder.Write("\""); //close quote for false condition
///////////////////////////////////////////////////////////////////// right side footer
builder.MoveToHeaderFooter(HeaderFooterType.FooterPrimary);
builder.InsertNode(rightShape);
builder.MoveTo(rightShape.FirstParagraph);
field = builder.InsertField("IF \"", null);
fieldStart = field.Start;
// Move DocumentBuilder cursor to the next run after field start.
builder.MoveTo(fieldStart.NextSibling.NextSibling);
builder.InsertField("PAGE", null);
builder.Write("\" = \"");
builder.InsertField("NUMPAGES", null);
builder.Write("\" \""); //start open quote of true condition
// Insert Conditional Part Of Footer Cell Into Builder (true part)
builder.InsertHtml("right Justified Footer for LAST pg");
builder.Write("\" \""); //close quote for true condition and open quote of false condition
// Insert Conditional Part Of Footer Cell Into Builder (false part)
builder.InsertHtml("right Justified Footer for OTHER pgs");
builder.Write("\""); //close quote for false condition
doc.UpdateFields();

Thanks,

I have a question and a new issue related to the work-around provided.
First, the question. This bug has definately caused issues with the functionality of the application that we are rolling out in the beginning of April. Could you please provide a sense of what the timeline will be to correct the problem? In other words, is it being worked on now and you hope to have a resolution in the next couple weeks, has it been added the the to-do list that will be included with a future release, etc.? While I realize that you are probably unable to commit to a timeline, any information (general or otherwise) will help me when I present an update on this project, which will include the new limitations to the project requirements imposed by this Aspose bug. Thanks.
Now, the new issue:
When using the textbox work-around, the “IF” condition of the first page footer does not recalculate itself. I had the same problem when using the table/cell method, but was able to correct it using a doc.UpdateTableLayout and doc.UpdateFields() command. I am currently using both of those and a UpdatePageLayout() trying to get the fields to refresh inside the textbox, but this does not work. Once the document opens into MS Word, you can hit twice to toggle the field codes and it will recalcuate the IF statement properly.
There are two footers, primary and first page. Both footers are identical, but required for the IF statements to work in all cases (1 pg versus multi-page document) Also, in my actual project, I have a first page header, so I must include a first page footer as well. The IF condition is to provide a different footer on the last page.
This issue can be replicated by running the following example. This example will put a centered footer on each page, with the last page (or first page if only a one-page document) being different. I have stripped most of the extraneous code out of the following example:

public void AsposeTest(string atLeastTwoPagesOfText, bool asPDF)
{
    Document doc = null;
    DocumentBuilder builder = null;
    byte[] byteArray = Encoding.ASCII.GetBytes(atLeastTwoPagesOfText);
    MemoryStream stream = new MemoryStream(byteArray);
    doc = new Document(stream, new LoadOptions(LoadFormat.Html, string.Empty, string.Empty));
    builder = new DocumentBuilder(doc);
    Aspose.Words.Section currentSection = builder.CurrentSection;
    PageSetup pageSetup = currentSection.PageSetup;
    pageSetup.DifferentFirstPageHeaderFooter = true;

    // Calculate table width as total page width with left and right marins subtracted.
    double tableWidth = pageSetup.PageWidth - pageSetup.LeftMargin - pageSetup.RightMargin;
    builder.MoveToHeaderFooter(HeaderFooterType.FooterFirst); //note that is command is the only difference between first page / primary code blocks 
                                                              ///////////////////////////////////////////////////////////////////// footer FIRST PAGE
    Shape textbox = new Shape(builder.Document, ShapeType.TextBox);
    textbox.AppendChild(new Paragraph(builder.Document));
    textbox.Width = tableWidth;
    textbox.Stroked = false;
    textbox.HorizontalAlignment = HorizontalAlignment.Center;
    builder.InsertNode(textbox);
    builder.MoveTo(textbox.FirstParagraph);
    builder.CurrentParagraph.ParagraphFormat.Alignment = ParagraphAlignment.Center;
    textbox.Height = pageSetup.FooterDistance;
    Field field = builder.InsertField("IF \"", null);
    FieldStart fieldStart = field.Start;
    // Move DocumentBuilder cursor to the next run after field start.
    builder.MoveTo(fieldStart.NextSibling.NextSibling);
    builder.InsertField("PAGE", null);
    builder.Write("\" = \"");
    builder.InsertField("NUMPAGES", null);
    builder.Write("\" \""); //start open quote of true condition
                            // Insert Conditional Part Of Footer Cell Into Builder (true part)
    builder.InsertHtml("This footer on LAST PG (or First Pg of single pg document)");
    builder.Write("\" \""); //close quote for true condition and open quote of false condition
                            // Insert Conditional Part Of Footer Cell Into Builder (false part)
    builder.InsertHtml("Footer for all OTHER pgs");
    builder.Write("\""); //close quote for false condition
    builder.MoveToHeaderFooter(HeaderFooterType.FooterPrimary);//note that is command is the only difference between first page / primary code blocks 
                                                               ///////////////////////////////////////////////////////////////////// footer PRIMARY
    textbox = new Shape(builder.Document, ShapeType.TextBox);
    textbox.AppendChild(new Paragraph(builder.Document));
    textbox.Width = tableWidth;
    textbox.Stroked = false;
    textbox.HorizontalAlignment = HorizontalAlignment.Center;
    builder.InsertNode(textbox);
    builder.MoveTo(textbox.FirstParagraph);
    builder.CurrentParagraph.ParagraphFormat.Alignment = ParagraphAlignment.Center;
    textbox.Height = pageSetup.FooterDistance;
    field = builder.InsertField("IF \"", null);
    fieldStart = field.Start;
    // Move DocumentBuilder cursor to the next run after field start.
    builder.MoveTo(fieldStart.NextSibling.NextSibling);
    builder.InsertField("PAGE", null);
    builder.Write("\" = \"");
    builder.InsertField("NUMPAGES", null);
    builder.Write("\" \""); //start open quote of true condition
                            // Insert Conditional Part Of Footer Cell Into Builder (true part)
    builder.InsertHtml("This footer on LAST PG (or First Pg of single pg document)");
    builder.Write("\" \""); //close quote for true condition and open quote of false condition
                            // Insert Conditional Part Of Footer Cell Into Builder (false part)
    builder.InsertHtml("Footer for all OTHER pgs");
    builder.Write("\""); //close quote for false condition
    doc.UpdateTableLayout();
    doc.UpdatePageLayout();
    doc.UpdateFields();

    // print out word or PDF format
    if (asPDF)
        doc.Save(Response, "filename.pdf", ContentDisposition.Attachment, SaveOptions.CreateSaveOptions(SaveFormat.Pdf));
    else
    {
        doc.Save(Response, "filename.doc", ContentDisposition.Attachment, SaveOptions.CreateSaveOptions(SaveFormat.Doc));
        Response.End();
    }
}

Hi

Thanks for your additional information.
Unfortunately, I cannot give you any estimate at the moment. Our developers will analyze the issue and then we will be able to provide you more information.
Regarding your new issue - I managed to reproduce the problem, your request has been linked to the appropriate issue, You will be immediately notified as soon as it is fixed.

Hi there,
Thanks for your inquiry.
Do you need to use tables or textboxes to layout the footer? Perhaps you could just use tabstops as demonstrated in this thread here. I am assuming from your message the bug above does not occur when the IF field is in a table or body. Have you checked this?
Using my method above you can still achieve the correct output by manually inserting the content for the first page footer after building the document. You can UpdatePageLayout and then use the code below in place of an IF field.

if (doc.PageCount == 1)
    builder.Write("This footer on LAST PG (or First Pg of single pg document)");
else
    builder.Write("Footer for all OTHER pgs");

We will inform you as soon as we have any further feedback regarding your issues.
Thanks,

The text needs to wrap within each table cell, so tabs won’t work. A series of multiple column definitions might work, but could get messy. The cell structure is not allows balanced. Perhaps you could provide an example of adding a footer that looks like the following using columns:
╒═════════════╤════════════════╕
│some text │ page 1 │
│that wraps │ │
├─────────────┴────────────────┤
│ some other text │
╘══════════════════════════════╛
What I would really like is for the product to just work properly. Everything works perfectly using tables except when saving as a PDF. Note also that if you save as Word and allow MS Word to save as PDF, it saves properly, so it should be possible to fix this. Using the workaround of using textboxes will give me a shortterm patch with reduced functionality but only if you guys can fix the bug I found using that method. I am really hoping that this problem can be resolved soon. I put my name on the line recommending Aspose to be purchased and it was a significant part of our budget. I really need to be able to show a working product soon.

Manually adding the footer after the document built using the method suggested by Adam Skelton is not a good solution. The size of the footer can change the number of pages. Also, if the document is editted after the footers are created, then the footer will not correct itself.
Has “the appropriate developer taken a look into the issue” so that I can have a estimate on fixing this issue?

Hi there,
Thanks for your inquiry.
Of course there will be a proper fix available, the suggestions we gave above are only work arounds for now so the functionality you are looking for works in the mean time.
There is good news, this issue has been analysed and fixed at the same time. The fix will be included in the next release of Aspose.Words. This should be due out in early March.
Thanks,

This is very good news. Just to clarify because I reported two bugs in this post: In March there will be a new release that will include a fix that addresses the table cells being suppressed when saving as PDF using the Table method I described above? Yes?
Next, will I be automatically notified when the new release is available?
Thanks.

Hi

Thanks for your inquiry. Yes you are right. The fix of the issue with table will be included in the next release of Aspose.Words. When the new version will be released, we will post the notification message in this thread and you will get e-mail notification.
Best regards,

After receiving the March newsletter, which annouced a new version with updates, I downloaded the update, recompiled and the problem still exists. I am also confused because the date stamp on the DLL is 02/07/2011, which predates this post.
Please alleviate my anxiety.
Thanks.

Hi

Thanks for your inquiry. Unfortunately, the issue is still unresolved. I will let you know once there is something new regarding this issue.
When the new version with this fix will be released, we will post the notification message in this thread and you will get e-mail notification.
Best regards,

Please may I have a better response. This issue is now making me look quite the fool and hurting my reputation, as I am making a presentation on a high-profile product we are building using Aspose. I am the developer who researched Aspose and recommended it. Being that it was a big chunk of our budget, it was not easy to convince the directors of our organization to purchase Aspose. When running up against the bugs I was having, I was relieved by the statement, “There is good news, this issue has been analysed and fixed at the same time. The fix will be included in the next release of Aspose.Words. This should be due out in early March.”
There is no way I can go back to the directors with, “oops, I guess it didn’t get fixed as promissed and I have no information when it will be.” They will be demanding I get a refund.
So, please, a few more specifics would be appreciated. And when it does get fixed, I would appreciate a hot fix rather than having to wait until the next release. I would also suggest a better QA team.

Hello.
Thank you for your request.
Unfortunately I can not promise you that we can provide you a hotfix of this problem. You will need to wait for the official release which will include this fix. I’ll add two issues in my monthly report with the appropriate comments. This will increase the priority of these issues. And also added comments to the issues in our defect database. We will inform you of any developments.

Could I get an explanation please to take to the directors of my organization. What happened between, “it is fixed, just wait for the next release in March” and “it is not fixed yet, you still have to wait for another release?” When is the next official release? I already waited for this release and deadlines are backing up on me. Despite all the bugs I keep running into, I like the product and want to make it work. But I need more information when I go to the directors and explain why I do not have a working product. I need a better timeline and information on why I don’t have a fix already when I explained to them that there would be one in March.