Escolar Documentos
Profissional Documentos
Cultura Documentos
Table of Contents 1 Overview and Scope 1.1 Introduction 1.2 Goals 1.3 Non-goals 2 Scenarios 2.1 Specifying a Report Expression in different colors by value range
2.1.1 Test Scenario 2.1.2 Extension Scenarios
2 2 2 3 3 3
3 4
4
4 5
5
5 5
5
5
5
5
6 6
6 6 7 7 7
4 Xbase Extension Features 4.1 Enhancement to shipping preview: Expose PrintCachedPages() 4.2 Enhancements to shipping ReportBuilder and its exposed (FFC) utility classes
4.2.1 Dynamics tab for Report Expressions Properties dialog 4.2.2 Various Properties dialogs get HTML tab 4.2.3 _FRXCURSOR class to expose memberdata cursor handling
9 9 9
9 9 9
10
10 10 11 13
Microsoft Corporation
Reporting Extensibility
1.2 Goals
The following is a list of broad goals. Add minimal product enhancements to allow performance tuning when dynamic Xbase code is, and is not, being used Provide FFC core class code to expose and leverage these enhancements Extend the FFC-supplied Xbase output types (various XML-related output file types) to use dynamic behavior appropriately Add backward-compatible enhancements to VFP-RDL (report definition XML schema) to encourage both the dynamic behavior we supply and permit unspecified additional extensions Expose Reporting Memberdata format through dynamic runtime enhancements and through ReportBuilder extensions Expose ReportBuilder extensibility mechanisms
Microsoft Corporation
Reporting Extensibility
1.3 Non-goals
The following is a list of explicit non- goals. Explicit ReportBuilder UI for emulation of any/all specific Class Designer capabilities. IE, "DynamicFontBold", "DynamicFontItalic", etc properties will not be mimicked exactly, although it should be clear that this is possible given what we provide. Explicit demonstration of all implications of the FFC and VFP-RDL improvements. For example, while we provide the architecture for GDI+-handling report decoration objects, we may not include graph-rendering classes exploiting this architecture. While we provide the dynamic underpinning for use of the ReportListener's AdjustObjectSize method for the creation of custom controls, we may not supply such a custom control (see below for use case scenario). Creation of alternative Report Preview Container interfaces. The shipping Preview Container has been designed to replace the original VFP Preview facility with an Xbase look- and workalike. While many alternatives are possible, it is clear that the community is comfortable with this task and does not need much of a boost. We will add one enhancement to expose a small product improvement (see feature reference below) without which printing from Xbase preview is missing one print-from-preview capability of the original interface. This specification does not cover any alternative Preview UI suggestions that may be provided as examples showing up to use interop features to preview and print VFP reports using non-Xbase code.
Scenarios
Many of the scenarios below have two parts. The first section addresses one or more test scenarios expected to be available from in-the-box, delivered components. The second section addresses extension scenarios, which can be addressed by a tester, community member, or vendor adding components given the techniques demonstrated in-the-box.
Microsoft Corporation
Reporting Extensibility
to the Properties dialog, the Dynamics tab now shows two conditions on the left. When she selects each of them, she sees the difference in the sample on the right. If she is not editing in PROTECTED (end-user) mode, and presses Preview Script, she sees a generated version of the script that will run. The generated script includes a comment for each condition, to identify it with her user-label. Should she or another viewer wish to edit the script directly, they can do so, by using the Run-time extensions feature from the Other dialog tab. They can paste the generated preview version in, if desired. Note: If a non-PROTECTED user moves his or her conditions into explicit script, generally s/he will want to delete them from the conditions list. However it does no harm, except slight performance detriment, to leave the extra CASE statements in. See next note below. When she confirms her changes by pressing OK to dismiss the Properties dialog, the Dynamics Tab saves her changes as XML records in the metadata for this layout control, using a specified reserved name attribute for these records. Note: Explicit script in the reserved first metadata row, with empty name attribute, can be executed along with the Dynamics tab generated script. Dynamics tab-generated script executes last. This gives the end-user last-say in making these cosmetic changes.
Microsoft Corporation
Reporting Extensibility
When James creates HTML output from this report, the underlying XML document contains an appropriate item including the keywords in its <Run/> section, forced to a string version of the evaluated expression. The resulting HTML document contains this information in its <HEAD/> element. The <Run/> section will also contain a Title node, so the HTML document uses this information in place of its defaults. If James uses NOPAGEEJECT to chain multiple reports into a single HTML document, and if he designates keyword expressions for each, multiple sets of keywords are generated in the document <HEAD/> element. The <TITLE/> node for the compound document, like the printer page information and other aspects of the chained run, is extrapolated from the first report in the set.
Microsoft Corporation
Reporting Extensibility
Functional Description
3.1.1 CallAdjustObjectSize
Integer property, description: Indicates whether ReportListener should invoke AdjustObjectSize for all appropriate layout controls. If a user sets any value than the defined values below, an error will occur (existing error number that seems appropriate: 1469, property value is out of bounds).
Value 0 (default) 1 2
Result VFP 9.0 behavior: event triggered for all layout controls if there is code in the Xbase class hierarchy for this event. Do not trigger event, whether or not there is code; dynamic behavior in AdjustObjectSize is not desired or needed for this report run. Always trigger event, whether or not there is code. This value is primarily intended for users who expect to use BindEvents rather than code in the method, to ensure that behavior is not determined by whether or not there is code in the reportListener (since the developer of the bound object may not always know what reportListener class is being used). However it is also useful for helper objects involved in the reporting process to have this capability exposed to them.
The value of this property is interrogated by the baseclass ReportListener once, at the beginning of the report run, before the BeforeReport event. Note that, if the value is 1 or 2, the product does not need to do its 9.0 check, since these values take precedence. This is the same point at which the ReportListener currently checks for user code in AdjustObjectSize part of its FRX-loading process; the evaluation will not change from whenever it's currently done. See additional notes on behavior and usage in CallEvaluateContents section below.
3.1.2 CallEvaluateContents
See CallAdjustObjectSize above works exactly the same way, but governs the use of EvaluateContents event instead of AdjustObjectSize. In addition to evaluation of these properties during the report initialization, we will investigate to see if the Engine can also obey the values of these two properties after the start of the report. It will probably be possible to change the values of CallAdjustObjectSize and CallEvaluateContents in the BeforeBand event, meaning for all layout controls in a single band. This will allow for significant optimization, even for reports that require some dynamic behavior. For example, reports with layout rectangles in page headers, detail bands, and page footers might have one rectangle in a group header band serving as a placeholder for a gdiplus-rendered summary graph. Only the group header band needs CallAdjustObjectSize = .T.. Similarly, a report expression in a page header band might have font alterations for some types of presentations, but all the other
Microsoft Corporation
Reporting Extensibility
bands might have a very large number of report expressions not requiring any EvaluateContents adjustments. In these cases, user code can adjust the CallAdjustObjectSize and CallEvaluateContents properties on a band level, at will. It will not be recommended, and it is probably not feasible, for user code to attempt to finetune performance by turning these properties on and off for individual objects rather than between bands. Especially with AdjustObjectSize, it is difficult to predict in what order, or even how many times, these events occur with respect to other layout controls of the same type within a given band. Also there is no reasonable place/event to do this evaluation and change the property values for each layout control, before AdjustObjectSize and EvaluateContents are actually called for this same layout control. Adding such an event (complete with frxRecNo information to tie it together with the appropriate layout control) would not only be risky but also reduce any runtime performance benefit.
Microsoft Corporation
Reporting Extensibility
This change enables user code to preprocess the FRX in a multi-user-safe way, by making a private copy of the FRX and instructing the engine to use this copy for the current run. Xbase code can create a temporary FRX copy and (for example) remove objects not needed for the current OutputType value or other conditions, such as permissions levels to various kinds of content. Although it is possible to do similar things using events during the report run, this change provides better performance for changes that affect every instance of a layout control in a report run (or remove it altogether, or is a global change of any other type, such as a change to DataEnvironment items). It is also possible to do the same thing (preprocess the FRX table, creating a temporary copy)before issuing the REPORT FORM command, but this approach does not "bind" the preprocessing behavior into the ReportListener system. Making this change allows the FFC listeners to add a preprocessing hook with some built-in intelligence. If the new value is unusable (named file cannot be found, is not a valid FRX, is open in another Designer session or locked by another user for some other reason, etc), the same or similar errors will be thrown as if the REPORT FORM command was issued with an unusable filename originally. Test code: LPARAMETERS WhichTest #DEFINE OtherReport "c:\temp\some.frx" #DEFINE ThisReport "c:\temp\other.frx" CLEAR TRY ox = CREATEOBJECT("r") DO CASE CASE EMPTY(WhichTest) USE (OtherReport) EXCLU CASE WhichTest = 1 MODI REPO (OtherReport) NOWAIT OTHERWISE * we will be setting to non-existant report name ox.fileNotExist = .T. ENDCASE REPORT FORM (ThisReport) object ox CATCH TO err LIST OBJECTS LIKE err MESSAGEBOX(MESSAGE() + " " + MESSAGE(1)) ENDTRY CLEAR ALL CLOSE ALL RETURN DEFINE CLASS r as ReportListener listenertype = 1 fileNotExist = .F. PROCEDURE loadreport IF THIS.fileNotExist THIS.CommandClauses.File = "somethingsomething.frx" ELSE THIS.CommandClauses.File = OtherReport ENDIF ENDPROC ENDDEFINE
From the ReportListener's Xbase code point of view, along with being able to "see" this error in a surrounding TRY-CATCH, the end result is similar to what happens if the Xbase code issues a RETURN .F. from the LoadReport method: no report run occurs. Since this result is already a possibility, it should be handled in the surrounding user code. For example, if the report run is
Microsoft Corporation
Reporting Extensibility
supposed to create a file, it is already a valid possibility that the output target file will not exist after the run. As usual, user code that makes such a change accepts responsibility to make it safely, not remove items critical to report calculations, clean up any temporary files afterwards, etc. We will recommend that CommandClauses.File be restored by user code to contain the same value it would have contained normally in UnloadReport. This user action does not require any response or adjustment in native code, but it allows any followup user code reading the value after the report run to see the correct value. Note that pre-processing the FRX under design during a Report Designer run is not possible in exactly the same way. Because the Report Designer has a lock on the CommandClauses.File FRX or LBX, user code can't make a copy of it easily. (By design, the ReportListener is passed the actual FRX or LBX value, not the temporary FRX or LBX name, during a Design session. We will not change this in Sedna.) We will recommend that Xbase code check ReportDesigner.CommandClauses.IsDesignerLoaded to determine what is possible. In some circumstances, it is possible for user code to compensate for this scenario transparently. In others, user code may have to indicate the unavailability of a certain feature during the designer session. We will provide at least one object illustrating appropriate behavior. Note that, during Designer sessions, if there is a tightly-coupled Builder and Output application pair, it is probably feasible for the Builder to hook the Preview event, create a copy of the FRX on disk in a temporary file with a generated name, and place the fully-pathed name of the copy someplace that the ReportListener-derived class can find it (such as a _* public variable). The ReportListener could then adjust this "safe" copy and pass the name of the copy to the Engine in CommandClauses.File during LoadReport. We will not supply any objects that rely on this technique.
4.2 Enhancements to shipping ReportBuilder and its exposed (FFC) utility classes
4.2.1 Dynamics tab for Report Expressions Properties dialog
Other dynamically tunable aspects, beyond font color, of Report Expressions will also be available from this dialog (optimally, all properties that are readwrite in the EvaluateContents event).
Microsoft Corporation
Reporting Extensibility
Microsoft Corporation
10
Reporting Extensibility
HTMLListener can support an expression that should be evaluated to provide the name of a CSS class attribute, and will almost certainly support the addition of expressions to supply href and title attributes on those layout controls that can use them. XMLListener will provide a mechanism to generate new optional Run section of the VFP-RDL (see below). Descendent classes will have the necessary ability to alter and embellish the contents of this section. For example, HTMLListener can add one or more Run child element to indicate desired reference(s) to external CSS stylesheets. XMLListener will also provide a mechanism to generate Memberdata-describing nodes in the VFPDataSet section of the VFP-RDL (see below). This will leverage the shared Memberdata-handling _FRXCURSOR.VCX object. The additional nodes will thus use the schema already provided in the current Memberdata documentation. By "exploding" the embedded Memberdata XML documents contained in rows of the FRX, and make it easier for consumers of the XML to use this information if desired. For example, an RSSListener will know what report elements are tagged for inclusion in the RSS output without directly parsing the memberdata.
<xs:element name="VFP-Report"> <xs:annotation> <xs:documentation> Contents of VFP-Report element are determined by XMLListener.XMLMode property </xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element ref="VFP-RDL" minOccurs="0"/> <xs:element ref="Data" minOccurs="0"/> <xs:element ref="Run" minOccurs="0"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Run"> <xs:annotation> <xs:documentation> Allows runtime data-dependent document attributes, such as contents of report variables or other accumulated data elements that do not occur in the layout itself, to be added at the conclusion of a report run. Content type is set at xs:any deliberately to allow extensions such as cursor-shaped XML for rows, etc. </xs:documentation> </xs:annotation>
Microsoft Corporation
11
Reporting Extensibility
<xs:complexType mixed="true"> <xs:sequence maxOccurs="unbounded"> <xs:element name="property" type="VFP-Property"/> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="VFP-Property" mixed="true"> <xs:sequence> <xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="id" type="xs:string" use="required"/> <xs:anyAttribute processContents="lax"/> </xs:complexType> We will demonstrate the use of this section by generating Run XML elements from whatever Document Properties and HTML global elements we expose in the supported set of document attributes. For example, document keywords or CSS style sheet references. The FRX-describing section of the VFP-RDL schema will be revised to include Memberdata information. Our VFP-RDL schema will now reference types defined in the VFP Memberdata Schema as an xs:include. See the Memberdata Extensibility topic, in the VFP docs, which contains this simple schema in full (we will not alter it in Sedna). Excerpt from revised VFP-RDL schema, with new element in green and its definition, derived directly from Memberdata schema, in red: <xs:element name="VFP-RDL"> <xs:complexType> <xs:sequence> <xs:element name="VFPDataSet" type="VFPDataSet"/> </xs:sequence> <xs:attribute name="id" type="xs:string" use="required"/> </xs:complexType> </xs:element> <xs:complexType name="VFPDataSet"> <xs:sequence> <xs:element name="VFPFRXLayoutObject" type="VFPFRXLayoutObject" minOccurs="1" maxOccurs="unbounded"/> <xs:element name="VFPFRXLayoutNode" type="VFPFRXLayoutNode" minOccurs="1" maxOccurs="unbounded"/> <xs:element name="VFPDataSource" type="VFPDataSource" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="VFPFRXCommand" type="VFPFRXCommand" minOccurs="0" maxOccurs="1"/> <xs:element name="VFPFRXPrintJob" type="VFPFRXPrintJob" minOccurs="0" maxOccurs="1"/> <xs:element name="VFPFRXMemberData" type="VFPFRXMemberData" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="VFPFRXMemberData"> <xs:annotation> <xs:documentation>Provides information contained in the FRX's embedded MemberData XML documents for various objects.</xs:documentation> </xs:annotation> <xs:attributeGroup ref="Common"/> <xs:attributeGroup ref="ReportTemplate"/> <xs:anyAttribute processContents="lax"/> </xs:complexType>
Microsoft Corporation
12
Reporting Extensibility
Microsoft Corporation
13