Get Remaining Page Size when Last Section in Word Document Spans Multiple Pages using C# .NET

@awais.hafeez,

thank you for the explanation! that definitely makes things more clear. I tried adding a second paragraph with one line to make sure it was counting correctly, and it doesn’t seem like it is:

builder.writeln("suuuuuuuuuuuuper long line like really long this should probably wrap onto a new line but let's keep typing to make sure. and it should have a bigger paragraph height than other pages");
builder.writeln("just another paragraph to make sure everything is counting correctly");
String offset1 = Double.toString(getParagraphOffsetModifier(builder));
builder.writeln(String.format("paragraph size: %s", offset1));
builder.insertBreak(BreakType.PAGE_BREAK);
builder.writeln("second page");
String offset2 = Double.toString(getParagraphOffsetModifier(builder));
builder.writeln(String.format("paragraph size: %s", offset2));
builder.insertBreak(BreakType.PAGE_BREAK);
builder.writeln("third page");
String offset3 = Double.toString(getParagraphOffsetModifier(builder));
builder.writeln(String.format("paragraph size: %s", offset3));

Document doc = builder.getDocument();
doc.updatePageLayout();
doc.save("paragraphHeight.docx", SaveFormat.DOCX);

and the updated function (with a couple of logs to see what paragraph heights we are getting on the page):

private double getParagraphOffsetModifier(DocumentBuilderExtension builder) throws Exception {
  Document doc = builder.getDocument();
  doc.updatePageLayout();
  LayoutCollector lc = new LayoutCollector(doc);
  LayoutEnumerator le = new LayoutEnumerator(doc);
// grab every paragraph in the current section
  ParagraphCollection paragraphs = doc.getLastSection().getBody().getParagraphs();
  double offset = 0;
  for (Paragraph para : paragraphs) {
// if paragraph is on the current page and has content, add its height to offset
    if (lc.getStartPageIndex(para) == doc.getPageCount()
        && !(para.toString(SaveFormat.TEXT).trim().equals("")
        || para.getChildNodes().getCount() == 0)) {
      le.setCurrent(lc.getEntity(para));
      le.moveParent();
      double paragraphBottom = le.getRectangle().getY() + le.getRectangle().getHeight();
      while (le.movePrevious()) {
      }
      double paragraphTop = le.getRectangle().getY();
      double paragraphHeight = paragraphBottom - paragraphTop;
      offset += paragraphHeight;
      System.out.println(String.format("paragraph: %s", paragraphHeight));
    }
}
System.out.println(String.format("page %s total: %s", doc.getPageCount(), offset));
return Math.ceil(offset);
}

the console spits out:
paragraph: 27.598003387451172
paragraph: 41.39699935913086
page 1 total: 68.99500274658203
page 2 total: 0.0
page 3 total: 0.0

so, we are still getting zero on the second/third pages, and the paragraphs seem to be miscounting. the second paragraph should be smaller than the first. given that the first paragraph has two lines, and the second only has one, it looks like it is counting the first paragraph in the second paragraph height calculation. 41.4 - 27.6 = 13.8, which is what we would expect the height of the second paragraph to be if each line is the same height.

for the zero-height pages, it seems that the lc.getStartPageIndex(para) == doc.getPageCount() is returning false for those paragraphs, for some reason.

@zackforbing,

You can move cursor to the last Line of a Page and calculate its position without using LayoutCollector. Please check if the following solution is acceptable for you?

Document doc = new Document("C:\\Temp\\source.docx");

LayoutEnumerator le = new LayoutEnumerator(doc); // Start from first Page
int pageIndex = 1;
do {
    int linesCounter = 1;
    le.moveFirstChild(); // Move to the first Column
    le.moveFirstChild(); // Move to the first Line
    // Move to the last Line on Page
    while (le.moveNext()) // Iterate through Lines
        linesCounter++;

    System.out.println("Page " + pageIndex + " has " + linesCounter +
            " Lines and 'bottom' of last Line is " + le.getRectangle().getY() + le.getRectangle().getHeight());

    le.moveParent();
    le.moveParent();
    pageIndex++;
}
while (le.moveNext()); // Iterate through Pages

since this function is being called during the process of document generation and we only care about the current page when this is called, that solution seems to be wasteful. I was able to greatly simplify the previous solution and remove iteration over the paragraphs into this, and it works great. thank you for your help!

private double getParagraphOffsetModifier(DocumentBuilderExtension builder) throws Exception {
  Document doc = builder.getDocument();
  doc.updatePageLayout();
  LayoutCollector lc = new LayoutCollector(doc);
  LayoutEnumerator le = new LayoutEnumerator(doc);
  Paragraph para = doc.getLastSection().getBody().getLastParagraph();
  double offset = 0;
  le.setCurrent(lc.getEntity(para));
  le.moveParent();
  while (le.movePrevious()) {
    offset += le.getRectangle().getHeight();
  }
  return Math.ceil(offset);
}

@zackforbing,

It is great that you were able to find what you were looking for. Please let us know any time you may have any further queries in future.