DocxFactory Paging Features
The DocxFactory paging features are more complicated to use but DocxFactory has more advanced paging features. The basic rule of thumb is that you should use the Word paging features whenever you can and use the DocxFactory paging features when you have to.
The difference between Word and DocxFactory paging is that Word renders files to printed documents so it knows the size of everything, paragraph, table row, picture etc. and if the page is filled so it can be divided using the paging rules.
But DocxFactory does not render files because rendering files to printed documents would almost be like rewriting Word so it cannot know the size of everything and if the page is filled. Instead, in DocxFactory sizes are measured in table rows. You set the page size in number of table rows and item sizes are the number of table rows in them.
For table rows with a different height than the rest of the table rows or anything other than table rows like paragraphs you can set their equivalent table row size manually. DocxFactory can also calculate item sizes with nested tables (see picture below).
A limit with measuring sizes in table rows is that if you insert a multiline text in a table row that expands the table row height, to DocxFactory it will still be one table row in height even though it might now have the height of several table rows so table rows height cannot be expanded except by other table rows inside them, as explained above.
If you plan to insert multiline text values then you have 2 options: 1. Use a static table row height that is big enough to hold all possible values by either setting the table row height or merging several table rows (usually used for small 2-3 line texts). 2. Breaking the multiline text into single lines and inserting every line into its own child table row expanding the table row height dynamically (usually used for big multiline texts).
A table row border also has a size even though it is very small all the table rows borders in a page can add up to the size of another table row. Because DocxFactory measures sizes in table rows, the table rows with borders and table rows without borders should have the same size otherwise pages that use more table rows without borders will be slightly shorter. To make table rows without borders have the same size as table rows with borders add a white border (or the same color as the background) for table rows without borders.
DocxFactory Paging Exercise
Open docxfactory_paging.docx in the DocxFactory/exercises/templates/ directory.
Open the Bookmark dialog box, sort the bookmarks by location and go through and highlight the bookmarks (see picture below).
The template contains the following bookmarks (see details below):
Account_size6d5_pageSize45
Because the account item is the top level item for all the items in the report, the account item with its header at the top will be repeated for every page in the report.
_pageSize45 sets the size of the page the top level item starts to 45 table rows.
Because account item has table rows with a different size than the rest of the table rows, _size6d5 is used to set the size to 6.5 table rows (excluding child items and the table rows with child items in them).
Detail
The detail item contains the column labels for the deposit and withdraw line items.
The detail item with its column labels will be repeated if a line item does not fit in the page and is moved to the next page.
Deposit_alternate
The deposit line item.
_alternate marks the item as alternating color.
Withdraw_alternate
The withdraw line item.
_alternate marks the item as alternating color.
Filler1_size2
Fills the page to its full size and divides the group into top items that always stay at the top and bottom items that always stay at the bottom and cannot be mixed.
Because the filler item is made up of 3 or more table rows, _size2 says that the page needs to be filled by 2 or more table rows otherwise the page is not filled.
Note: The filler table rows have a white border instead of having no border so the table rows size will be the same as the rest of the table rows with borders.
Dummy1
The dummy item is never pasted and its only purpose is to separate the line and total item borders.
Total_keepWithPrev
The lines total item.
_keepWithPrev says that the item cannot be separated from the previous item. If the total item is moved to the next page then it will take a line item with it from the previous page so it will not be alone on the page.
Spacer1
Adds a spacer item between items in the group.
If the footer and detail items are in the same page then a spacer item is added between them. If the footer item starts in a new page then a spacer will not be added before it.
Footer
The footer item contains the comment and summary items.
The footer is put in a separate item that is only added at the end instead of being a fixed part of the account top level item that will be in every page.
Comment_keepTogether
The report breaks multiline comments into single lines and inserts every line into its own table row instead of using a fixed table row height.
The comment item contains all the comment lines.
_keepTogether says that it cannot be split and must stay whole. If the entire comment does not fit in the page then the comment is moved to the next page.
Note: The comment table rows have a white border instead of having no border so the table rows size will be the same as the rest of the table rows with borders.
CommentLine
Contains a single comment line.
Spacer2
Adds a spacer item between comment items.
Dummy2
The dummy part only purpose is to help differentiate between the comment line item table and the table cell it is in.
Summary
The report summary item.
The summary is in a separate item and not a fixed part of the footer item so if the comments overflow onto the next pages then the summary will not be repeated with the footer item in the next pages.
Note: The summary table rows have a white border instead of having no border so the table rows size will be the same as the rest of the table rows with borders.
Dummy3
The dummy part only purpose is to help differentiate between the summary item table and the table cell it is in.
The exercise introduces the following DocxFactory paging features.
_pageSize<n>
_pageSize sets the page size in number of rows and divides the report into pages.
_pageSize is set at the top level item for the page the top level item starts
More specifically, after an item is pasted if the total size of the items in the page is greater than the page size then a new page is started, all the item parents upto the top level item are copied with their field values and the item is moved to the new page.
Note: DocxFactory does not have a repeat header paging feature but when an item is moved to a new page all its parents are copied to the new page that can contain column labels, header information or a title and are repeated for every page their children continue onto.
Note: In case an item is pasted without pasting its parent first and the missing parent is filled in, if the item does not fit in the page and is moved to a new page then the parent is moved with him. You can paste an item without first pasting its parent for parents that are only needed with their children and there is no need for them alone on the page.
For example: a parent that contains the column labels for its line items. The parent and its column labels is only needed with its line items. There is no need for the parent and its column labels alone on the page.
Note: Because _pageSize activates the DocxFactory paging features and is set at the top level item that starts a new page, it can be set for some top level items and not set for others allowing you to use DocxFactory paging features for some top level items and Word paging features for others.
Note: Because the DocxFactory paging features use page breaks to start a new page all the pages in the new document will never go over their page size and the word paging features will never be activated.
Note: You can also enter page sizes with a decimal point by using a “d” instead of “.” because “.” are not allowed in bookmark names. For example: _pageSize10d5 (for page size 10.5).
_size<n>
_size lets you set the item size manually for items with table rows that have a different height than the rest of the table rows or with anything other than tables rows like paragraphs.
If you are setting the item size for items with child items do not include the child items size and all table rows with child items in them.
Note: You can also enter item sizes with a decimal point by using a “d” instead of “.” because “.” are not allowed in bookmark names. For example: _size1d5 (for size 1.5).
_keepTogether
_keepTogether says that the item cannot be split and must stay whole so either the item fits in the page or the entire item is moved to the next page.
_keepTogether is not needed for items with no children because DocxFactory only moves items when the page size is exceeded so if the item does not have any children then it is the smallest thing that can be moved and it cannot be split. The problem is with the parent items that can be split across pages.
_keepWithPrev
_keepWithPrev says that the item cannot be separated from the previous item pasted in the group so if the item does not fit in the page and is moved to the next page then the previous item is moved with him. For example: use keep with previous for total lines so they will never be alone on the page.
filler<n>
Items named “filler<n>” are page filler items. The filler item fills the page to its full size. There should only be one filler item for a page.
If the filler item is made up of 3 or more table rows then the filler item is expanded to fill the page by repeating the middle table row, the filler item fills the page in increments of one table row and if _size<n> is added then the page needs to be filled by <n> table rows or more otherwise the page is not filled.
If the filler item is made up of less than 3 table rows then the filler item is repeated to fill the page, the filler item fills the page in increments of the filler item size and _size<n> works in the regular way and sets the filler item size.
The filler item in the template divides the item group into top and bottom items. When the page is filled the filler item is inserted between the top and bottom items keeping the top items at the top and pushing the bottom items to the bottom. If a top item is pasted after a bottom item was pasted then the top item is moved to the next page keeping the top items at the top and the bottom item at the bottom.
spacer<n>
Items named “spacer<n>” are group spacer items. The spacer item is added between the items in the group. There should only be one spacer item for a group.
Compile the template.
Create the .DOCX file.
Copy and run the code below.
USING DocxFactory.*. DEFINE VARIABLE i AS INTEGER NO-UNDO. DEFINE VARIABLE j AS INTEGER NO-UNDO. ETIME(TRUE). WordProcessingMerger:loadTemplate( "/opt/DocxFactory/exercises/templates/docxfactory_paging.dfw"). WordProcessingMerger:paste("Account"). DO i = 1 to 10: WordProcessingMerger:paste("Withdraw"). END. /* 1 to 10 */ DO i = 1 to 9: WordProcessingMerger:paste("Deposit"). END. /* 1 to 9 */ WordProcessingMerger:paste("Total"). WordProcessingMerger:paste("Summary"). DO i = 1 to 3: WordProcessingMerger:paste("Comment"). DO j = 1 to 5: WordProcessingMerger:paste("CommentLine"). END. /* 1 to 5 */ END. /* 1 to 3 */ WordProcessingMerger:saveDoc("/tmp/docxfactory_paging.docx"). MESSAGE "Completed (in" ROUND(ETIME(FALSE) / 1000, 3) "seconds)". |
CATCH oErr AS Progress.Lang.AppError: MESSAGE oErr:ReturnValue VIEW-AS ALERT-BOX. END CATCH. |
Note: The detail item and its column labels is only needed with the line items and the footer item containing the comments and the summary item is only needed with its child items, there is no need for them alone on the page.
For that reason the detail and footer items are not pasted and are filled in when their child items are pasted so if the first child item pasted does not fit in the page and is moved to the new page then they are moved with him so they will not remain alone on the page.
Open the created .DOCX file (see picture below).
You can change the number of line items, number of comments etc. in the code and recreate the new document to see how the report is divided into pages.