Página 1 de 1

SetUserDataSet()

Publicado: Mié Nov 06, 2013 8:25 pm
por reinaldocrespo
Hi.
I was used to using :SetUserDataSet() with frh. It seems like this method is no supported under frx. I would typically print a report using a data source such as a browse object and have only the selected records be considered for the report. To do this, I would assign as data source the browse object calling the :SetUserDataSet() method.
The runtime error I get is this:
Quote:
Error description: Warning BASE/1004 Message not found: TFASTREPORT:SETUSERDATASET

Here is some code to demonstrate what I mean:

:SetUserDataSet( "Cursor", cFields ,;//"pathno",;
{ || nAt := 1, ;
EVAL( oBrw:bBookMark, oBrw:aSelected[ 1 ] ),;
EVAL( bResync ) },;
{ || nAt++, ;
oBrw:Skip(),; //EVAL( oBrw:bBookMark, oBrw:aSelected[ nAt ] ),;
EVAL( bResync ) },;
{ || nAt--, ;
oBrw:Skip( -1 ),;//EVAL( oBrw:bBookMark, oBrw:aSelected[ nAt ] ),;
EVAL( bResync ) },;
{ || nAt > LEN( oBrw:aSelected ) },; //iif( oBrw:nDataType == DATATYPE_ARRAY,nAt > LEN( oBrw:aArrayData ), oBrw:Eof() ) },;
{ |cFld| OSend( oBrw, cFld ):Value() } )

Here is another example of :SetUserDataSet() use:

:SetUserDataSet( "ChartData", "Group;count",;
{ || nAt := 1 },;
{ || nAt++ },;
{ || nAt-- },;
{ || nAt > LEN( ::aChartSummary ) },;
{ |cFld| nCol := iif( UPPER( cFld ) == "GROUP", 1, 2 ),;
::aChartSummary[ nAt, nCol ] } )

My question is this: Is there a new method to replace :SetUserDataSet()? How?
Thank you.
Reinaldo.

SetUserDataSet()

Publicado: Jue Nov 07, 2013 10:15 am
por ignacio
Example Sergey:
:SetUserDataset( "Customer", "Custno;Company",;
{|| Customer->(DBGoTop()) }, {|| Customer->(DbSkip()) }, ;
NIL, {|| !Customer->(Eof()) },;
{|f| Customer->(FieldGet( FieldPos( f ) ) ) } )

Source code:
METHOD SetUserDataset( cAlias, cFields, bGotop, bSkipPlus1, bSkipMinus1,;
bCheckEof, bGetValue ) CLASS frReportManager
LOCAL aFields, aData, aRow, aNames
LOCAL xValue
LOCAL cField, cType
LOCAL nAt, nLen, nDec, nFor
aFields := {}
aNames := {}
aData := {}
cField := hb_tokenGet( cFields, 1, ";" )
nAt := 2
Eval( bGotop )
DO WHILE !Empty( cField )
xValue := Eval( bGetValue, cField )
cType := ValType( xValue )
SWITCH cType
CASE "C"
nLen := Max( Len( xValue ), 250 )
nDec := 0
EXIT
CASE "D"
nLen := 8
nDec := 0
EXIT
CASE "N"
nLen := 20
nDec := 5
EXIT
CASE "L"
nLen := 1
nDec := 0
EXIT
END SWITCH
AAdd( aFields, cField + "," + cType + "," + ;
LTrim( Str( nLen ) ) + "," + LTrim( Str( nDec ) ) )
AAdd( aNames, cField )
cField := hb_tokenGet( cFields, nAt ++, ";" )
ENDDO
nLen := Len( aFields )
DO WHILE Eval( bCheckEof )
aRow := Array( nLen )
FOR nFor := 1 TO nLen
aRow[ nFor ] := Eval( bGetValue, aNames[ nFor ] )
NEXT
AAdd( aData, aRow )
Eval( bSkipPlus1 )
ENDDO
RETURN ::AddArray( cAlias, aData, aFields )

SetUserDataSet()

Publicado: Jue Nov 07, 2013 3:03 pm
por reinaldocrespo
Ignacio;
Hi. Thank you for the code. I can see how that would work. I hope you are not annoyed by my questions below:
#1. Is this method already included in your implementation of TFastReport() or XFastReport()? The reason I'm asking is because I'm trying to understand how these x and t classes work. I'm afraid that the method you provided on your answer is already included in the x or t class and the reason I'm getting the runtime error is because I'm inheriting from the wrong parent. On the other hand, if this method is not included on any of the base classes, then I would think it should be. Don't you?
#2. Is there not a risk of running out of memory by having to load the complete dataset into a memory array? Furthermore, If the data source is a dynamic cursor, then the whole cursor would have to be read into memory before the report can start. Otherwise the report may start to print as the resulting cursor is being sent to the workstation. This allows for faster response times which always pleases users. Therefore I ask: do you ever plan to implement a SetUserDataSource() method without having to read the complete dataset into a memory array?
Here is my implementation of the TFastReport class used on my tests for your comments:
//Inherit from TFastReport as I think it inherits from XFastReport
//and has some extra methods?
//
CLASS TMyFastReport FROM TFastReport //XFastReport
VAR cFrLicense INIT "..."
VAR cXaLicense INIT "..."
METHOD DestroyFR() INLINE ::end()

METHOD AddReport() INLINE 0
METHOD ClearDataSets() INLINE NIL
METHOD RemoveReport() INLINE NIL
METHOD LoadFromBlob( nWorkArea, cFieldName )

END CLASS
//---------------------------------------------------------- --------------------------------------
METHOD LoadFromBlob( nWorkArea, cFieldName )
LOCAL cAlias := Alias( nWorkArea )

RETURN ::LoadFromString( (cAlias)->( cFieldName ) )
//-----------------------------------------------
Again, thank you very much for your answers.
Reinaldo.

SetUserDataSet()

Publicado: Jue Nov 07, 2013 4:51 pm
por ignacio
Hello,
(1) Take a look at class TFRREPORTMANAGER
(2) There is no memory risk. In our tests we are faster than Sergey. Absolutely no plans on doing a SetUserDataset() like Sergey. Use ADO connection (with a forward only cursor, better STATIC than DYNAMIC) if you feel that way it will be faster.
Regards,

SetUserDataSet()

Publicado: Jue Nov 07, 2013 6:45 pm
por reinaldocrespo
Hi. Thank you for replying.
I could not find TFrReportManager(). I think you meant frReportManager? from FrxSourceFrReportManager.prg ?

CLASS frReportManager FROM TFastReport

If it is indeed TFrReportManger(), then please point where I can find it.
Thank you,
Reinaldo.

SetUserDataSet()

Publicado: Jue Nov 07, 2013 8:19 pm
por ignacio
reinaldocrespo escribió el jue, 07 noviembre 2013 18:45Hi. Thank you for replying.
I could not find TFrReportManager(). I think you meant frReportManager? from FrxSourceFrReportManager.prg ?

CLASS frReportManager FROM TFastReport

If it is indeed TFrReportManger(), then please point where I can find it.
Thank you,
Reinaldo.
You are right.
Regards,