Last active
April 30, 2021 16:44
-
-
Save CarlTBarnes/1e0ddd480e083f8feedb4a98f53176a4 to your computer and use it in GitHub Desktop.
Report Manual Paging Class and Template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!This CLASS was written to **replace page checking code** in reports that was in many places | |
!For most all people the **replace** comment will NOT apply. | |
! | |
!This is not an easy an easy thing to do. I cannot explain it all here. | |
! | |
! Steps to Implement ManRpt Class | |
! | |
!1. Add the Extension Template ReportLineHeightMaxSet Template so all lines have | |
! a. Sets all DETAIL PROP:MaxHeight=Height so line Height is exactly correct | |
! b. For all DETAILs defines LnHt_Label LONG variable and sets = DETAIL PROP:Height for use with Height calcs | |
! | |
!2. Add the Below ManRpt CLASS Declarion to DATA and CODE to Local procedures. | |
! 2.1 Search and Replace all Height variable with the new LnHt_Xxxx geenrated variables | |
! | |
!3. Start of "After Opening Report" | |
! [Priority 3600] | |
ManRpt.ReportOpenInit(Report, 167) !167 is the Fudge about. | |
!4. Find CheckPageOverFlow ROUTINE **replace page checking code** | |
! and comment it out | |
! Then add its code to ManRpt.NewPage | |
! | |
!5. Search for all PRINT( and change to new logic **replace page checking code** | |
! | |
!6. Remove old line counting LCNT variable so you get errors to fix **replace page checking code** | |
! | |
!7. Existing REPORT DETAIL cannot have stuff that affect printing and paging | |
! a. DETAILs must NOT have WithPrior() and WithNext() | |
! b. All Detail attributes must be considered e.g. ALONE, TOGETHER | |
! c. BREAK, HEADER, FOOTER must be done manually | |
! d. Details with PageAfter PageBefore should be removed and handled in Code with .NewPage() | |
! | |
!8. Find every PRINT( and do stuff to add ManRpt. | |
!See *Developer* comments | |
SECTION('CLASS Declarion goes in DATA Embed') | |
ManRpt CLASS !Manual Report Class Declarion (Put in "Declaration Section") | |
ReportOpenInit PROCEDURE(*REPORT RptRef, LONG FudgeLines) !After OPEN(Report) call (Report, FudeLines) to Initilize class | |
CheckOverflow PROCEDURE(LONG LnHt_ToCheck),BOOL,PROC !Check if PRINT() overflows page, will Eject, does not +=LNCT, call with (LnHt_Xxx+LnHt_Xxx) | |
AddToLCNT PROCEDURE(LONG LnHt_TotalPrinted) !After PRINT() adds (LnHt_xxx) to LCNT. Does NOT check for Overflow | |
CheckOverflowAndAddToLCNT PROCEDURE(LONG LnHt_ToPrint, LONG LnHt_ExtraRoom=0, LONG ExtraMultiplier=1),BOOL,PROC !Before PRINT() check if fits then +=LNCT. Call with (LnHt_Xxx, Xtra ROom, Multiplier) | |
NewPage PROCEDURE() !When Page Overflows this finishs old page and starts New Page (code was in CheckPageOverflow ROUTINE) | |
ForceNewPage PROCEDURE() !Sets LCNT=99999 so Next CheckOverFlow will go to a New Page. | |
WillLinesOverflow PROCEDURE(LONG LnHt_TotalLinesToCheck),BOOL !Check if lines fit on page, does NOT do NewPage nor + LCNT | |
zDB PROCEDURE(STRING DebugMessage) !Debug Output ManRpt LCNT Lines/Page Information | |
zDebugOff BOOL !Set to True to Turn OFF Debug | |
!---- Class Data ----- | |
RptRef &REPORT,PRIVATE | |
LinesPerPage LONG ,PRIVATE !was LinesPerPage !Total Lines on Page = REPORT{Prop:Height} - Fudge lines | |
LCNT LONG ,PRIVATE !was LCNT !How many lines have printed on the page | |
PagesPrinted LONG ,PRIVATE !was PAGE# !Number of times hit NewPage | |
!------ Internal Methods that are used only by class | |
xWasInitCalled PROCEDURE(),PRIVATE !Chck if forgot to Call ReportOpenInit() and show Message() | |
END | |
SECTION('CLASS Definition goes in Local "Procedures" Embed') | |
!ManRpt Class Procedure Code - Put in "Local Procedures" ======================================== | |
ManRpt.NewPage PROCEDURE() !Called when ManRpt.CheckOverflow() does NOT find enough room to print | |
! *Developer* Modify this procedure to print Page Heading and do Page breaks the way you want to | |
! E.g. you may add code to repeat a subheading | |
CODE | |
SELF.PagesPrinted += 1 ! PAGE#+=1 | |
SELF.LCNT = 0 ! was LCNT=0 | |
Message('*Developer* YOU need to add your page break logic') | |
IF SELF.PagesPrinted<>1 THEN ! IF PAGE#<>1 THEN PRINT(RPT:DetailNewPage). | |
PRINT(RPT:DetailNewPage) | |
END | |
! IF PrintingTotals | |
! PRINT(RPT:BldgTotalsHdg) | |
! SELF.LCNT = LnHt_BldgTotalsHdg !was LCNT=BldgTotalsHdgHeight | |
! RETURN | |
! END | |
PRINT(RPT:PageHdr) | |
SELF.LCNT = LnHt_PageHdr !LCNT=PageHdrHeight | |
RETURN | |
!------------------------------ | |
ManRpt.ForceNewPage PROCEDURE() !Sets LCNT=99999 so Next CheckOverFlow will go to a New Page. | |
CODE | |
SELF.LCNT = 999999 | |
RETURN | |
!=========================================================================================== | |
! Carl notes the below .CheckOverflowAndAddToLCNT() should NOT need to be changed | |
!=========================================================================================== | |
ManRpt.CheckOverflowAndAddToLCNT PROCEDURE(LONG LnHt_ToPrint, LONG LnHt_ExtraRoom=0, LONG ExtraMultiplier=1)!,BOOL,PROC !Check if PRINT() fits on page, +=LNCT, call with (LnHt_Xxx+LnHt_Xxx) | |
IsOverflowed BOOL(False) !^^ Print This ^^ ^^ Allow Room ^^^ ^^ Room for LnHt_ToPrint ^^ | |
PrintPlusXtraLines LONG,AUTO | |
CODE | |
PrintPlusXtraLines = LnHt_ToPrint + LnHt_ExtraRoom !allow extra room for Underline that may not print this time | |
IF ExtraMultiplier > 1 THEN | |
PrintPlusXtraLines += LnHt_ToPrint * (ExtraMultiplier -1) !can say allow room for 2 | |
END | |
IF SELF.WillLinesOverflow(PrintPlusXtraLines) THEN | |
IsOverflowed = True | |
SELF.NewPage() !Page overflow, call the New Page | |
END | |
SELF.AddToLCNT(LnHt_ToPrint) !We ASSume this will PRINT() a Detail this tall after the call | |
RETURN IsOverflowed !Tell the caller if we ejected the page | |
!Example: | |
! ManRpt.CheckThenPrint(LnCt_Detail,0,2) !Print 1, allow room for *2 LnCt_Detail | |
! PRINT(RPT:Detail) !Now Print 1 Detail | |
! !Nothing to do here because CheckThenPrint() already added to LCNT | |
!------------------------------ | |
ManRpt.CheckOverflow PROCEDURE(LONG LnHt_ToCheck)!,BOOL,PROC | |
IsOverflowed BOOL(False) | |
CODE | |
IF SELF.WillLinesOverflow(LnHt_ToCheck) THEN | |
IsOverflowed = True | |
SELF.NewPage() !Page overflow, call the New Page | |
END | |
RETURN IsOverflowed !Tell the caller we ejected the page | |
!Example: | |
! ManRpt.CheckOverflow( LnCt_Detail * 2 + LnHt_Underline) !Will 2 + Underline fit?, ejects page if not room | |
! PRINT(RPT:Detail) !Now Print 1 Detail | |
! ManRpt.PRINTed(LnCt_Detail) !This adds to LCNT | |
!------------------------------ | |
ManRpt.WillLinesOverflow PROCEDURE(LONG LnHt_TotalLinesToCheck)!,BOOL,PRIVATE !Check for new page, but do nothing else | |
IsOverflowed BOOL(False) | |
CODE | |
SELF.xWasInitCalled() | |
IF LnHt_TotalLinesToCheck + SELF.LCNT > SELF.LinesPerPage THEN | |
IsOverflowed = True | |
!this one does NOT --> SELF.NewPage() | |
END | |
RETURN IsOverflowed !Tell the caller we ejected the page | |
!---------------------------- | |
ManRpt.ReportOpenInit PROCEDURE(*REPORT _RptRef, LONG FudgeLines) | |
CODE | |
IF _RptRef &= NULL OR STATUS(_RptRef) <> 0 THEN | |
Message('Programming bug:|ManRpt.ReportOpenInit was called with the REPORT not open, or null.|' & 0{'Proc_Name'}) | |
END | |
SELF.RptRef &= _RptRef | |
SELF.LinesPerPage = _RptRef{PROP:Height} - FudgeLines | |
DB('ManRpt.ReportOpenInit LinesPerPage=' & SELF.LinesPerPage & ' adjusted by Fudge=' & FudgeLines ) | |
SELF.PagesPrinted = 0 | |
SELF.LCNT = 999999 !Force a New Page | |
RETURN | |
!------------------------------ | |
ManRpt.xWasInitCalled PROCEDURE() !Tell Forgot to Call ReportOpenInit | |
CODE | |
IF SELF.LinesPerPage <=0 OR SELF.RptRef &= NULL THEN | |
Message('Programming bug:|ManRpt.ReportOpenInit was not been called before calling CheckOverFlow or Printed.|' & 0{'Proc_Name'}) | |
END | |
RETURN | |
!------------------------------ | |
ManRpt.AddToLCNT PROCEDURE(LONG LnHt_TotalPrinted) !After PRINT(Rpt:Detail) call with Ht Printed | |
CODE | |
SELF.LCNT += LnHt_TotalPrinted | |
RETURN | |
!------------------------------ | |
ManRpt.zDB PROCEDURE(STRING DebugMessage) !Debug Output ManRpt LCNT Lines/Page Information | |
CODE | |
IF ~SELF.zDebugOff THEN | |
DB('ManRpt: LCNT=' & SELF.LCNT &' Lines/Page='& self.LinesPerPage &' Page#='& self.PagesPrinted &' - '& CLIP(DebugMessage)) | |
END | |
RETURN |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!============================================================ | |
#EXTENSION(ReportLineHeightMaxSet,'Report Set Prop:MaxHeight'),PROCEDURE | |
#!--------------------------------------------- | |
#! would like to #RESTRICT use to when a REPORT is available | |
#DISPLAY('Code will be generated for each DETAIL to') | |
#DISPLAY(' set LnHt_DetailName=Report$?Detail{{Prop:Height}') | |
#DISPLAY(' and set Prop:MaxHeight = LnHt_DetailName.') | |
#DISPLAY('') | |
#DISPLAY('Also define a LnHt_DetailName LONG for each DETAIL') | |
#DISPLAY('') | |
#DISPLAY('Below list details to exclude:') | |
#BUTTON('Excluded Details'),MULTI(%ExcludedDetails,%ExcludedDetail),INLINE | |
#PROMPT('Detail Name:',FROM(%ReportControl,%ReportControlType = 'DETAIL',%ReportControlLabel)),%ExcludedDetail | |
#ENDBUTTON | |
#!--------------------------------------------- | |
#! UI to allow not generating | |
#! skip if it has no AT Height defined i.e. Blank | |
#! scan if it contains resize controls | |
#! Report Label, cannot assume "Report? | |
#!--------------------------------------------- | |
#ATSTART | |
#DECLARE(%DetailsWithResize),MULTI,UNIQUE | |
#DECLARE(%DetailsWithExclude),MULTI,UNIQUE | |
#DECLARE(%Current0Label,STRING) | |
#DECLARE(%RptAtH,STRING) | |
#FOR (%ExcludedDetails) | |
#ADD(%DetailsWithExclude,%ExcludedDetail) | |
#ENDFOR | |
#SET(%Current0Label,'') | |
#FOR(%ReportControl) | |
#IF(%ReportControlIndent=0) | |
#SET(%Current0Label,%ReportControlLabel) | |
#! !Label "%Current0Label" %ReportControlStatement | |
#CYCLE | |
#ELSE | |
#IF(EXTRACT(%ReportControlStatement,'RESIZE')>'') | |
#! !In Label "%Current0Label" has resize-> %ReportControlStatement | |
#IF(%Current0Label>'') | |
#ADD(%DetailsWithResize,%Current0Label) | |
#ENDIF | |
#ENDIF | |
#ENDIF | |
#ENDFOR | |
#ENDAT | |
#!--------------------------------------------- | |
#AT(%DataSectionBeforeWindow) | |
#!----------- | |
!ReportLineHeightMaxSet Variables | |
#FOR(%ReportControl),WHERE(%ReportControlLabel>'') | |
#CASE(%ReportControlType) | |
#OF('DETAIL') | |
#OROF('HEADER') | |
#OROF('FOOTER') | |
#ELSE | |
#CYCLE | |
#ENDCASE | |
#! a Blank AT(,,,Height) means no defined ht so leave it out | |
#SET(%RptAtH,EXTRACT(%ReportControlStatement,'AT',4)) | |
#IF(%RptAtH='') | |
!Skipped %ReportControlLabel has no AT() Height: %(REPLACE(%ReportControlStatement,'<13,10>',' ')) | |
#CYCLE | |
#ENDIF | |
#FIND(%DetailsWithResize,%ReportControlLabel) | |
#IF(%DetailsWithResize>'') | |
!Skipped %ReportControlLabel %ReportControlType has RESIZE controls | |
#CYCLE | |
#ENDIF | |
#FIND(%DetailsWithExclude,%ReportControlLabel) | |
#IF(%DetailsWithExclude>'') | |
!Skipped %ReportControlLabel %ReportControlType is Excluded in Template by user | |
#CYCLE | |
#ENDIF | |
#! ReportControlStatement could have a |<13,10> at the end and mess up | |
#!LnHt_%[25]ReportControlLabel LONG !%(CLIP(SUB(%ReportControlStatement,1,40))) | |
LnHt_%[25]ReportControlLabel LONG !%(REPLACE(%ReportControlStatement,'<13,10>',' ')) | |
#IF(%RptAtH='0') | |
!WARNING! %ReportControlLabel has AT(,,,0) Height ZERO this will not print | |
#ENDIF | |
#ENDFOR | |
#!!----------------- Report Structure ------------------------- | |
#!!ReportControlIndent 0=TopLevel 1=Control so hunt >0 for TEXT,RESIZE | |
#!#FOR(%ReportControl) | |
#!#SET(%RptAtH,EXTRACT(%ReportControlStatement,'AT',4)) | |
#!!%ReportControlIndent At4=%RptAtH %ReportControlType => %ReportControlStatement | |
#!#ENDFOR | |
#!----------------- | |
#ENDAT | |
#!-------------------------------- Assign Heights ---------------- | |
#AT(%AfterOpeningReport),PRIORITY(9000) | |
#DECLARE(%RptUse1) | |
!ReportLineHeightMaxSet Template | |
#FOR(%ReportControl),WHERE(%ReportControlLabel>'') | |
#CASE(%ReportControlType) | |
#OF('DETAIL') | |
#OROF('HEADER') | |
#OROF('FOOTER') | |
#ELSE | |
#CYCLE | |
#ENDCASE | |
#! a Blank AT(,,,Height) means no defined ht so leave it out | |
#!Looking at %ReportControlLabel Use=%ReportControlUse | |
#SET(%RptAtH,EXTRACT(%ReportControlStatement,'AT',4)) | |
#IF(~%RptAtH) | |
!Skipped %ReportControlLabel %ReportControlType has no AT() Height | |
#CYCLE | |
#ENDIF | |
#FIND(%DetailsWithResize,%ReportControlLabel) | |
#IF(%DetailsWithResize) | |
!Skipped %ReportControlLabel %ReportControlType has RESIZE controls | |
#CYCLE | |
#ENDIF | |
#FIND(%DetailsWithExclude,%ReportControlLabel) | |
#IF(%DetailsWithExclude) | |
!Skipped %ReportControlLabel %ReportControlType is Excluded in Template by user | |
#CYCLE | |
#ENDIF | |
#! #IF(~%ReportControlUse) | |
#!!%ReportControlLabel %ReportControlType has no USE(ReportControlUse) | |
#! #CYCLE | |
#! #ENDIF | |
#! "%ReportControlUse" does NOT seem to have a value for DETAIL so must Extract it from USE(?xxxx) | |
#SET(%RptUse1,EXTRACT(%ReportControlStatement,'USE',1)) | |
#IF(~%RptUse1) | |
!Skipped %ReportControlLabel %ReportControlType has no USE(%ReportControlUse) | |
#CYCLE | |
#ENDIF | |
#!Generate line for %ReportControlLabel Use=%ReportControlUse RptUse1=%RptUse1 | |
LnHt_%[20]ReportControlLabel = %Report$%RptUse1{PROP:Height} ; %Report$%RptUse1{PROP:MaxHeight} = LnHt_%ReportControlLabel | |
#IF(%RptAtH='0') | |
!WARNING! %ReportControlLabel has AT(,,,0) Height ZERO this will not print unless Height and MaxHeight are set | |
#ENDIF | |
#ENDFOR | |
#ENDAT | |
#!============================================================ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment