Question
· Jun 8, 2018

How to convert page number to roman numeral in ZEN Report?

Im using below code to display page number. But i only display as 1,2..etc. I need to display it as I,II,III..etc...

special="page-number"

Discussion (15)0
Log in or sign up to continue

How will it be triggered in the ZENReport without calling it in the display? below is my sample.

Import User

///Test.TestReport

Class Test.TestReport Extends ZenReport

{ /// This XML defines the display for this report. /// This is used to generate the XSLT stylesheets for both HTML and XSL-FO. XData ReportDisplay [ XMLNamespace = "http://www.intersystems.com/zen/report/display" ] 

<!-- Optional Pagefooter element. Does not apply in HTML output. -->
<pagefooter>
<item special="page-number"/>
</pagefooter>

}

Method OutputData() As %Status
{

blahblahblah

}

///Closed

}

I'll try to answer just the conversion question. It looks like someone has asked about roman numerals before here:

https://community.intersystems.com/post/roman-number-converter

However the conclusion was that the referenced article in that question here:

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.FrameSet.cls?KEY=GVRF_basicfeatures

Doesn't support roman numeral conversion. Now there's a billion ways to do this yourself, and I was inspired by the unary method in one of the answers here, instead of complex loops:

https://stackoverflow.com/questions/12967896/converting-integers-to-roman-numerals-java

So I made something similar for ObjectScript, and it gets the job done in a very simple way. Note that it doesn't use a full Subtractive method for conversion, for that you'll need more cases. The replaces could be structured differently too but I wanted it to be as understandable as possible. Call it in your report however you like.

ClassMethod RomanNumeralConversion(pNum) As %Status {
   set roman = ""
   for x=1:1:pNum {
    set roman = roman_"I"
   }
 
   set roman = $REPLACE(roman,"IIIII", "V")
   set roman = $REPLACE(roman,"IIII","IV")
   set roman = $REPLACE(roman,"VV","X")
   set roman = $REPLACE(roman,"VIV", "IX")
   set roman = $REPLACE(roman,"XXXXX", "L")
   set roman = $REPLACE(roman,"LL", "C")
   set roman = $REPLACE(roman,"LXL", "XC")
   set roman = $REPLACE(roman,"CCCCC", "D")
   set roman = $REPLACE(roman,"CCCC", "CD")
   set roman = $REPLACE(roman,"DD", "M")
   set roman = $REPLACE(roman,"DCD", "CM")
   return roman
}

Unfortunately I don't know how to go about altering that value after or before it's been generated. You may have to experiment with including custom functions in your tags that output page numbers, or try to get the value from the special tag into one of your custom tag functions. Whatever you do, there doesn't seem to be a native way and you'll have to do something custom.

You can change the XSLFO Stylesheet dynamically or statically. See XSLFOSTYLESHEET

So, there is a class-report, for example MyApp.ReportDemo.

Series of steps:

  1. remove option XSLFOSTYLESHEET, if any, and recompile class
  2. generate XSLFO Stylesheet:
    SAMPLES>d $system.OBJ.DisplayError(##class(MyApp.ReportDemo).GenerateToFile($system.CSP.GetFileName($system.CSP.GetDefaultApp($zu(5))_"/MyApp.ReportDemo.xsl"),4))
  3. make changes to MyApp.ReportDemo.xsl
  4. add the parameter XSLFOSTYLESHEET and recompile the class again
    /// If defined, this provides a reference to the external
    /// stylesheet to use in generating the XSL-FO (PDF) report.
    /// If it is not provided, a stylesheet will be generated 
    /// from the ReportDisplay XData block.
    Parameter XSLFOSTYLESHEET As String = "MyApp.ReportDemo.xsl";

Now open the report in your browser/command line/etc. Profit!

Important: if you change something in ReportDisplay, you need to repeat the steps again.

Page numbering in Roman Numerals

Need add the attribute format to the element <fo:page-sequence>, i.e.

<fo:page-sequence master-reference='blablabla' format ='I' .. >

Possible value format:

  • format="1" results in 1 2 3 . .
  • format="01" results in 01 02 03
  • format="a" results in a b c . .
  • format="A" results in A B C. .
  • format="i" results in i ii iii iv . .
  • format="I" results in I II III IV . .
  • more..

Example:

  1. Do all the steps according to Zen Report Tutorial
  2. Insert the page number into <pagefooter>
    <!-- Optional Pagefooter element. Does not apply in HTML output. -->
    <pagefooter>
    <item special="page-number"/>
    </pagefooter>
  3. Insert the following code into the class:
    ClassMethod ReplaceStream(
      ByRef stream As %Stream.TmpBinary,
      format) [ Private ]
    {
      tmp=##class(%Stream.TmpBinary).%New()
      while 'stream.AtEnd {
        tmp.Write($replace(stream.Read($$$MaxLocalLength),"<fo:page-sequence ",$$$FormatText("<fo:page-sequence format=%1 ",$$$quote(format))))
      }
      stream.CopyFrom(tmp)
    }
    
    /// d ##class(MyApp.ReportDemo).Test()
    ClassMethod Test(format "1")
    {
      /*
        •0 = XML
        •1 = HTML
        •2 = PDF
        •3 = ToHTML Stylesheet
        •4 = ToXSLFO Stylesheet
        •5 = XSD Schema
        •6 = PrintPS
        •7 = Excel
        •8 = XSLFO
        •9 = ToEXCEL
        •10=xlsx
        •11=TIFF
        •12=pdfprint
        •13=displayxlsx
        •14=fo2pdf
        •15=foandpdf
      */
      
      xslfo=##class(%Stream.TmpBinary).%New()
    
      t=..%New()
      t.GenerateReportToStream(.xslfo,4)
      ..ReplaceStream(.xslfo,format)
      t.toxslfostream=xslfo
      d $system.OBJ.DisplayError(t.GenerateReport("c:\temp\test.pdf",2))
    }
  4. SAMPLES>##class(MyApp.ReportDemo).Test("I")
    or
    SAMPLES>##class(MyApp.ReportDemo).Test("01")
    or
    SAMPLES>##class(MyApp.ReportDemo).Test("A")
  5. open test.pdf. Profit!