/* * FastReport.prg * Clase TFastReport * * Copyright 2020 Ignacio Ortiz de Zúñiga * Copyright 2020 https://Xailer.com * All rights reserved * */ #include "Xailer.ch" #include "error.ch" #include "FastReport.ch" /* Errores: 100-199: Errores de carga de DLL 200-299: Errores de contexto incorrecto 300-399: Errores de uso incorrecto */ STATIC aReports := {} STATIC nLibLoads := 0 //------------------------------------------------------------------------------ RESERVED FUNCTION FR_EventHandler( nInstance, nEvent, nCargo ) LOCAL xRet IF nInstance > 0 .AND. nInstance <= Len( aReports ) .AND. aReports[ nInstance ] != NIL xRet := aReports[ nInstance ]:ProcessEvent( nEvent, nCargo ) ENDIF RETURN xRet //------------------------------------------------------------------------------ RESERVED FUNCTION FR_FreeLib() IF nLibLoads <= 0 FR_FreeLibrary() RETURN .T. ENDIF RETURN .F. //------------------------------------------------------------------------------ CLASS XFastReport FROM TComponent PUBLISHED: PROPERTY lAbortOnErrors INIT .T. PROPERTY lDelFRVars INIT .T. PROPERTY lSynchroData INIT .F. PROPERTY cFileName INIT "" WRITE LoadFromFile EDITOR PE_FRFilename PROPERTY cResName INIT "" PROPERTY cResIco INIT "" PROPERTY cFRLicense INIT "" PROPERTY cXALicense INIT "" PROPERTY cTitle INIT "" PROPERTY cLanguage INIT "" WRITE SetLanguage EDITOR PE_FRLanguage PROPERTY cDllPath INIT "" EVENT OnBeforeCreate( oSender ) // --> Nil EVENT OnEndPreview( oSender ) // --> Nil EVENT OnAfterPrint( oSender, cObject ) // --> Nil EVENT OnAfterPrintReport( oSender ) // --> Nil EVENT OnBeforeConnect( oSender, cObject ) // --> Nil EVENT OnBeforePrint( oSender, cObject ) // --> Nil EVENT OnBeginDoc( oSender ) // --> Nil EVENT OnClickObject( oSender, cObjectm, nButton ) // --> Nil EVENT OnDblClickObject( oSender, cObjectm, nButton ) // --> Nil EVENT OnEndDoc( oSender ) // --> Nil EVENT OnGetValue( oSender, cVarName ) // --> Value EVENT OnMouseOverObject( oSender, cObject ) // --> Nil EVENT OnPreview( oSender ) // --> Nil EVENT OnPrintPage( oSender, nCopyPage ) // --> Nil EVENT OnPrintReport( oSender ) // --> Nil EVENT OnProgress( oSender, nProgressType, nProgress ) // --> Nil EVENT OnProgressStart( oSender, nProgressType, nProgress ) // --> Nil EVENT OnProgressStop( oSender, nProgressType, nProgress ) // --> Nil EVENT OnBeforeLoad( oSender ) // --> NIL EVENT OnAfterLoad( oSender ) // --> NIL EVENT OnCreate( oSender ) // --> NIL EVENT OnBtnSendMail( oSender ) // --> NIl or xValue EVENT OnBtnPrint( oSender ) // --> NIl or xValue EVENT OnBtnGenPdf( oSender ) // --> NIl or xValue EVENT OnPageChanged( oSender, nPage ) // --> NIL EVENT OnDesignSaveReport( oSender, lSaveAs ) // --> lSuccess EVENT OnDesignLoadReport( oSender ) // --> lSuccess PUBLIC: PROPERTY oPreview PROPERTY oEngineOptions AS TFrEngineOptions PROPERTY oPrintOptions AS TFrPrintOptions PROPERTY oPreviewOptions AS TFrPreviewOptions PROPERTY oReportOptions AS TFrReportOptions DATA aDatasets INIT {} DATA nLastError INIT 0 READONLY DATA cLastError INIT "" READONLY METHOD New( oParent ) // --> Self METHOD Create( oParent ) // --> Self METHOD Free() // --> NIL METHOD SetLicense( cFRLicense, cXALicense )// --> lSuccess METHOD DelError() INLINE ( ::nLastError := 0, ::cLastError := "" ) // --> NIL METHOD GetErrors() // --> aErrors METHOD ShowReport( lKeepLastReport, oControl ) // -> nHandle METHOD PrepareReport( lKeepLastReport ) // -> lSuccess METHOD ShowPreparedReport( lKeepLastReport, oControl ) // -> nHandle METHOD DesignReport() // -> lSuccess METHOD DoExport( cFilter ) METHOD LoadFromFile( cFile ) // -> cFile METHOD LoadFromResource( cResource ) // -> cResource METHOD LoadFPFile( cFile ) INLINE ::LoadFromFile( cFile ) // -> cFile METHOD LoadFromString( cString ) // -> cFile METHOD SaveToFile( cFileName ) // -> lSuccess METHOD SaveToString( cString ) // -> lSuccess METHOD Clear() // -> lSuccess METHOD ClearData() // -> NIL METHOD SaveToFPFile( cFileName ) // -> lSuccess METHOD LoadStyleSheetFromFile( cFileName ) // -> lSuccess METHOD LoadStyleSheetFromString( cString ) // -> lSuccess METHOD Print() // -> lSuccess METHOD SetTitle( cTitle ) // -> lSuccess METHOD SetIcon( cIcon ) // -> lSuccess METHOD GetProperty( cObjetName, cProperty ) // -> xValue METHOD SetProperty( cObjName, cProperty, xValue ) // --> NIL METHOD AddDataSet( cName, oDataset ) // --> oDataset METHOD AddArray( cName, aData, aFields ) // --> oDataset METHOD AddDbf( cName, aFields ) // --> oDataset METHOD DelDataset( oDataset ) // --> lSuccess METHOD SetMasterDetail( cMasterName, cDetailName, aFields ) // --> lSuccess METHOD ClearMasterDetail( cMasterName, cDetailName ) // --> lSuccess METHOD LoadLangRes( cName ) // -> lSuccess METHOD LoadLangFile( cName ) // -> lSuccess METHOD AddFunction( cPrototype, cCategory, cDescription ) // --> lSuccess METHOD AddCategory( cCategory) // --> lSuccess METHOD AddVariable( cName, xValue ) // --> lSuccess METHOD SetVariable( cName, xValue ) // --> lSuccess METHOD GetVariable( cName ) INLINE( ::GetVariableC( cName ), ::GetCargo() ) // --> xValue METHOD DeleteVariable( cName ) // --> lSuccess METHOD DeleteCategory( cName ) // --> lSuccess METHOD ClearVariables() // --> lSuccess METHOD SaveVariables() // --> lSuccess METHOD RestoreVariables() // --> lSuccess METHOD VariablesList( cCategory ) // --> aList METHOD CategoriesList( lClear ) // --> aList METHOD Calc( cPascalExp ) // --> METHOD SetADOConnectStr( cName, cConnectstring ) // --> lSuccess METHOD SetFormatSettings( nSetting, xValue ) // --> lSuccess METHOD PreviewClose() // --> lSuccess METHOD FieldValue( cTable, cField ) INLINE ::Calc( "DATA.FIELDVALUE('" + cTable + "','" + cField + "')" ) METHOD StopReport() // Sergey compatibility methods METHOD ReportOptions() INLINE ::oReportOptions METHOD PrintOptions() INLINE ::oPrintOptions METHOD EngineOptions() INLINE ::oEngineOptions METHOD PreviewOptions() INLINE ::oPreviewOptions RESERVED: METHOD ProcessEvent( nEvent, nCargo ) EXTERN FR_ProcessEvent // Utilizados desde el objeto TFrxDataset METHOD AddFrDataSet( cName ) // -> nDBPos METHOD AddFrField( nDB, cField, nType, nLen ) // -> lSuccess METHOD AddFrRecord( nDB ) // -> lSuccess METHOD AddFrValue( nDB, cField, xValue ) // -> lSuccess METHOD SetDBComplete( nDB ) // -> lSuccess METHOD AddComplete( nDB ) INLINE Aadd( ::aDatasets, NIL ) // simular existencia de dataset cuando se hace a pedal METHOD ClearDB( nDB ) METHOD SetDBName( nDB, cName ) METHOD SetCargoB( cValue ) METHOD frSetBounds( nLeft, nTop, nWidth, nHeight ) METHOD Prepared() INLINE ::lPrepared METHOD ForceReload() PROTECTED: DATA pObject INIT 0 DATA aAdoConn INIT {} DATA cResData INIT "" DATA nInstance INIT 0 DATA nLoaded INIT NOT_LOADED READONLY // 0 Not Loaded, 1 Design, 2 Normal DATA lLicensed INIT .F. DATA lPrepared INIT .F. METHOD Initialize() METHOD UnInitialize() METHOD Installed() INLINE ( nLibLoads > 0 ) METHOD AfterLoad() METHOD LoadReport( lDesign ) METHOD LoadData( lDesign ) METHOD LoadFromFileC( cFileName ) METHOD LoadFromResourceC( nResID, cResName ) METHOD LoadFPFileC( cFileName ) METHOD LoadFromStringC( cString ) METHOD SetIconC( cResIco ) METHOD LoadProperty( cObjetName, cProperty ) METHOD ShowReportC( lKeepLastReport, hWindow ) METHOD ShowPreparedReportC( hWindow ) // -> nHandle METHOD PrepareReportC( lKeepLastReport ) METHOD DesignReportC() METHOD AddVariableC( cVarName ) METHOD SetVariableC( cVarName ) METHOD GetVariableC( cVarName ) METHOD VariablesListC( cCategory ) METHOD CategoriesListC( lClear ) METHOD GetCargo() METHOD SetCargo( xValue ) METHOD PutProperty( cObject, cProperty, xValue ) METHOD SetError( nError, cError ) METHOD SetMasterDetailC( cMasterName, cDetailName, cMasterFields, cDetailFields ) METHOD SetADOConnectStrC( cName, cConnectstring ) // --> lSuccess METHOD SetFormatSettingsC( nFlag, cValue ) METHOD CalcC( cPascalExp ) METHOD GetErrorsC() METHOD SetLanguage( cValue ) METHOD DoExportC( cFilter ) // -> lSuccess METHOD InitializeC() METHOD PrintC() METHOD ClearReport() END CLASS //------------------------------------------------------------------------------ METHOD New( oParent ) CLASS XFastReport ::Super:New( oParent ) RETURN Self //------------------------------------------------------------------------------ METHOD Create( oParent ) CLASS XFastReport ::Super:Create( oParent ) ::OnBeforeCreate() ::Initialize() ::OnCreate() // Establecemos licencia IF !Empty( ::cFRLicense ) .AND. !Empty( ::cXALicense ) ::lLicensed := ::SetLicense( ::cFRLicense, ::cXALicense ) ENDIF // Establecemos lenguaje IF !Empty( ::cLanguage ) ::LoadLangRes( ::cLanguage ) ENDIF RETURN Self //------------------------------------------------------------------------------ METHOD Initialize() CLASS XFastReport LOCAL cDll, cVer IF ::nInstance != 0 RETURN NIL ENDIF IF ::oParent != Nil ::oParent:InsertComponent( Self ) ENDIF IF !Empty( ::cDllPath ) cDll := ::cDllPath + "\frx.dll" ELSE cDll := "frx.dll" ENDIF IF !File( cDll ) ::SetError( 100, "Fast-Report DLL not found: " + cDll ) RETURN NIL ENDIF cVer := DllFileVersion( cDll ) IF cVer != FR_DLLVER ::SetError( 100, "Incorrect DLL version (" + cVer + ") . Should be: " + FR_DLLVER ) RETURN NIL ENDIF ::nInstance := Len( aReports ) + 1 IF ::InitializeC() AAdd( aReports, Self ) nLibLoads ++ ELSE ::nInstance := 0 ENDIF ::oEngineOptions := TFrEngineOptions():Create( Self ) ::oPrintOptions := TFrPrintOptions():Create( Self ) ::oPreviewOptions := TFrPreviewOptions():Create( Self ) ::oReportOptions := TFrReportOptions():Create( Self ) RETURN NIL //------------------------------------------------------------------------------ METHOD Free() CLASS XFastReport LOCAL oDS nLibLoads -- ::UnInitialize() // Eliminamos datasets FOR EACH oDS IN ::aDatasets IF oDS != NIL oDS:End() ENDIF NEXT ::aDatasets := {} IF ::nInstance != 0 IF Len( aReports ) <= ::nInstance aReports[ ::nInstance ] := NIL ENDIF ::nInstance := 0 ENDIF ::nLoaded := NOT_LOADED ::lPrepared := .F. RETURN NIL //------------------------------------------------------------------------------ METHOD ShowReport( lKeepLastReport, oControl ) CLASS XFastReport LOCAL hWindow := 0 LOCAL hPreview IF oControl != NIL hWindow := oControl:Handle ELSEIF ::oPreview != NIL hWindow := ::oPreview:Handle ENDIF DEFAULT lKeepLastReport TO .F. IF ::lPrepared hPreview := ::ShowPreparedReportC( hWindow ) ELSE ::LoadReport( .F. ) ::LoadData( .F. ) ::lPrepared := .t. hPreview := ::ShowReportC( lKeepLastReport, hWindow ) ENDIF IF oControl == NIL .AND. ::oPreview != NIL ::oPreview:hWindow := hPreview ::oPreview:Adjust() ENDIF RETURN hPreview //------------------------------------------------------------------------------ METHOD ShowPreparedReport( lKeepLastReport, oControl ) CLASS XFastReport LOCAL hWindow := 0 LOCAL hPreview IF oControl != NIL hWindow := oControl:Handle ELSEIF ::oPreview != NIL hWindow := ::oPreview:Handle ENDIF DEFAULT lKeepLastReport TO .F. IF ::lPrepared hPreview := ::ShowPreparedReportC( hWindow ) ENDIF IF hPreview != NIL .AND. oControl == NIL .AND. ::oPreview != NIL ::oPreview:hWindow := hPreview ::oPreview:Adjust() ENDIF RETURN hPreview //------------------------------------------------------------------------------ METHOD Print() CLASS XFastReport LOCAL lSuccess ::PrepareReport() lSuccess := ::PrintC() RETURN lSuccess //------------------------------------------------------------------------------ METHOD PrepareReport( lKeepLastReport ) CLASS XFastReport DEFAULT lKeepLastReport TO .F. IF !::lPrepared ::LoadReport( .F. ) ::LoadData( .F. ) ::lPrepared := ::PrepareReportC( lKeepLastReport ) ENDIF RETURN ::lPrepared //------------------------------------------------------------------------------ METHOD DesignReport() CLASS XFastReport ::LoadReport( .T. ) ::LoadData( .T. ) RETURN ::DesignReportC() //------------------------------------------------------------------------------ METHOD DoExport( cFilter ) CLASS XFastReport LOCAL lSuccess ::PrepareReport() lSuccess := ::DoExportC( cFilter ) RETURN lSuccess //------------------------------------------------------------------------------ METHOD LoadReport( lDesign ) CLASS XFastReport LOCAL oIcon LOCAL cFile, cExt LOCAL lSuccess := .f. DEFAULT lDesign TO .t. IF !::lCreated .OR. ::nLoaded != NOT_LOADED RETURN .T. ENDIF IF Empty( ::cResIco ) oIcon := Application:oMainForm:oIcon IF oIcon != NIL .AND. !Empty( oIcon:cName ) .AND. !File( oIcon:cName ) ::cResIco := oIcon:cName ENDIF ENDIF ::ClearReport() ::LoadData( lDesign ) ::OnBeforeLoad( lDesign ) // Guardamos todas las variables que hubiera podido incluir IF ::lDelFRVars ::SaveVariables() ENDIF ::lPrepared := .f. IF !Empty( ::cFilename ) IF !( ":" $ ::cFilename ) .AND. Left( ::cFilename, 2 ) <> "\\" cFile := Application:cDirectory + ::cFilename ELSE cFile := ::cFilename ENDIF IF File( cFile ) cExt := Upper( FileExtension( cFile ) ) IF cExt == "FR3" lSuccess := ::LoadFromFileC( cFile ) ELSEIF cExt == "FP3" lSuccess := ::LoadFPFileC( cFile ) ::lPrepared := .T. ENDIF ELSE ::SetError( 200, cFile + ": File not found on LoadFromFile()" ) ENDIF ELSEIF !Empty( ::cResName ) lSuccess := ::LoadFromResourceC( 0, ::cResName ) ELSEIF !Empty( ::cResData ) lSuccess := ::LoadFromStringC( ::cResData, .f. ) ENDIF ::SetADOConnectStr() ::nLoaded := IIF( lSuccess, IIF( lDesign, DESIGN_LOADED, FULL_LOADED ), NOT_LOADED ) IF lSuccess ::AfterLoad() ENDIF RETURN lSuccess //------------------------------------------------------------------------------ // Antes de cargar el fichero del informe hay que cargar todos los datasets // y sus relaciones master-detail. Si se cargo anteriormente en modo diseño // luego habrÁ que recargarlo de nuevo con todos sus datos METHOD LoadData( lDesign ) CLASS XFastReport LOCAL oDataset LOCAL lModified DEFAULT lDesign TO .T. lModified := .F. // Cargamos datasets FOR EACH oDataset IN ::aDatasets IF oDataset != NIL WITH OBJECT oDataset IF !:IsActive() :Build() lModified := .t. ENDIF IF :nLoaded == NOT_LOADED :Load( lDesign ) lModified := .t. ELSEIF :nLoaded == DESIGN_LOADED .AND. !lDesign :Load( lDesign ) lModified := .t. ENDIF END WITH ENDIF NEXT // Establecesmos relaciones maestro-detalle si las hay IF lModified FOR EACH oDataset IN ::aDatasets IF oDataset != NIL WITH OBJECT oDataset IF :oDsMaster != NIL .AND. !Empty( :aRelationFields ) .AND. !:lMasterDetail ::SetMasterDetail( :oDsMaster:cName, :cName , :aRelationFields ) :lMasterDetail := .t. ENDIF END WITH ENDIF NEXT ENDIF RETURN lModified //------------------------------------------------------------------------------ METHOD AfterLoad() CLASS XFastReport LOCAL oDS, aProp, Value // Establecemos título IF !Empty( ::cTitle ) ::SetTitle( ::cTitle ) ENDIF // Establecemos icono IF !Empty( ::cResIco ) ::SetIcon( ::cResIco ) ENDIF // Establecemos licencia IF !::lLicensed .AND. !Empty( ::cFRLicense ) .AND. !Empty( ::cXALicense ) ::lLicensed := ::SetLicense( ::cFRLicense, ::cXALicense ) ENDIF // Borramos todas las variables del informe y recuperamos las del usuario IF ::lDelFRVars ::RestoreVariables() ENDIF // Establecemos variables para Xailer ::DeleteCategory('Xailer') ::AddCategory('Xailer') ::AddVariable('Application:cCompany', Application:cCompany ) ::AddVariable('Application:cCopyright', Application:cCopyright ) ::AddVariable('Application:cDescription', Application:cDescription ) ::AddVariable('Application:cDirectory', Application:cDirectory ) ::AddVariable('Application:cFilename', Application:cFilename ) ::AddVariable('Application:cTitle', Application:cTitle ) ::AddVariable('Application:cVersion', Application:cVersion ) FOR EACH aProp IN ASort( Appdata:aProperties,,,{|x,y| x[ 1 ] < y[ 1 ] } ) Value := __ObjSendMsg( AppData, aProp[ 1 ] ) IF Valtype( Value ) $ "CNDL" ::AddVariable('Appdata:' + aProp[ 1 ], Value ) ENDIF NEXT FOR EACH oDS IN ::aDatasets IF oDS != NIL oDS:AfterLoad() ENDIF NEXT ::oEngineOptions:AfterLoad() ::oPrintOptions:AfterLoad() ::oPreviewOptions:AfterLoad() ::oReportOptions:AfterLoad() ::OnAfterLoad() RETURN nil //------------------------------------------------------------------------------ METHOD LoadFromFile( cFilename ) CLASS XFastReport ::FcFilename := cFilename ::cResname := "" ::cResData := "" ::nLoaded := NOT_LOADED ::lPrepared := .f. RETURN ::LoadReport() //------------------------------------------------------------------------------ METHOD LoadFromResource( cResource ) CLASS XFastReport ::cResName := cResource ::FcFileName := "" ::cResData := "" ::nLoaded := NOT_LOADED ::lPrepared := .f. RETURN ::LoadReport() //------------------------------------------------------------------------------ METHOD LoadFromString( cString ) CLASS XFastReport ::cResData := cString ::FcFileName := "" ::cResName := "" ::nLoaded := NOT_LOADED ::lPrepared := .f. RETURN ::LoadReport() //------------------------------------------------------------------------------ METHOD SetIcon( cResource ) CLASS XFastReport // ::LoadReport() RETURN ::SetIconC( cResource ) //------------------------------------------------------------------------------ METHOD GetProperty( cObjName, cProperty ) CLASS XFastReport IF !::lPrepared ::LoadReport() ENDIF ::LoadProperty( cObjName, cProperty ) RETURN ::GetCargo() //------------------------------------------------------------------------------ METHOD SetProperty( cObjName, cProperty, xValue ) CLASS XFastReport LOCAL cValue, cLine LOCAL nLen, nFrom SWITCH ValType( xValue ) CASE "A" cValue := "" AEval( xValue, {|v| cValue += "'" + ToString( v ) + "'" + CRLF } ) EXIT CASE "C" IF At( CRLF, xValue ) == 0 cValue := "'" + xValue + "'" ELSE nFrom := 1 nLen := Len( xValue ) cValue := "" DO WHILE nFrom <= nLen cLine := ReadLine( xValue, @nFrom ) cValue += "'" + cLine + "'" + CRLF ENDDO ENDIF EXIT CASE "N" nLen := IIF( xValue == Int( xValue ), 0, 4 ) cValue := LTrim( Str( xValue, 15, nLen ) ) EXIT CASE "L" cValue := IIF( xValue, "True", "False" ) EXIT CASE "D" cValue := "'" + DToC( xValue ) + "'" EXIT END SWITCH IF !::lPrepared ::LoadReport() ENDIF RETURN ::PutProperty( cObjName, cProperty, cValue ) //------------------------------------------------------------------------------ METHOD SetVariable( cName, xValue ) CLASS XFastReport IF ValType( xValue ) == "C" xValue := "'" + xValue + "'" ENDIF IF !::lPrepared .AND. !::LoadReport() RETURN .F. ENDIF ::SetCargo( xValue ) RETURN ::SetVariableC( cName ) //------------------------------------------------------------------------------ METHOD AddVariable( cName, xValue ) CLASS XFastReport IF ValType( xValue ) == "C" xValue := "'" + xValue + "'" ENDIF IF !::lPrepared .AND. !::LoadReport() RETURN .F. ENDIF ::SetCargo( xValue ) RETURN ::AddVariableC( cName ) //------------------------------------------------------------------------------ METHOD VariablesList( cCategory ) CLASS XFastReport LOCAL cTemp IF Empty( cCategory) .OR. (!::lPrepared .AND. !::LoadReport() ) RETURN {} ENDIF ::SetCargo( "" ) IF ::VariablesListC( cCategory ) IF !Empty( cTemp := ::GetCargo() ) RETURN hb_Atokens( cTemp, CRLF ) ENDIF ENDIF RETURN {} //------------------------------------------------------------------------------ METHOD CategoriesList( lClear ) CLASS XFastReport LOCAL cTemp IF !::lPrepared .AND. !::LoadReport() RETURN {} ENDIF ::SetCargo( "" ) IF ::CategoriesListC( lClear ) IF !Empty( cTemp := ::GetCargo() ) RETURN hb_Atokens( cTemp, CRLF ) ENDIF ENDIF RETURN {} //------------------------------------------------------------------------------ METHOD AddDataSet( cName, oDataset ) CLASS XFastReport LOCAL oDS WITH OBJECT oDS := TFrXailerDataset():New( ::oParent ) :oReport := Self :cName := cName :oDataset := oDataset :Create() END WITH ::nLoaded := NOT_LOADED ::lPrepared := .f. RETURN oDS //------------------------------------------------------------------------------ METHOD AddArray( cName, aData, aFields ) CLASS XFastReport LOCAL oDS WITH OBJECT oDS := TFrArrayDataset():New( ::oParent ) :oReport := Self :cName := cName :aData := aData :aFields := aFields :Create() END WITH ::nLoaded := NOT_LOADED ::lPrepared := .f. RETURN oDS //------------------------------------------------------------------------------ METHOD AddDbf( cName, aFields ) CLASS XFastReport LOCAL oDS WITH OBJECT oDS := TFrDbfDataset():New( ::oParent ) :oReport := Self :cName := cName :aFields := aFields :Create() END WITH ::nLoaded := NOT_LOADED ::lPrepared := .f. RETURN oDS //------------------------------------------------------------------------------ METHOD DelDataset( oDataset ) CLASS XFastReport LOCAL nAt nAt := AScan( ::aDatasets, {|v| v != NIL .AND. v == oDataset } ) IF nAt > 0 ::aDatasets[ nAt ] := NIL ENDIF ::nLoaded := NOT_LOADED ::lPrepared := .f. RETURN nAt > 0 //------------------------------------------------------------------------------ METHOD SetMasterDetail( cMasterName, cDetailName, aFields ) CLASS XFastReport LOCAL oDsMaster, oDsDetail LOCAL aTemp LOCAL cMasterFields, cDetailFields LOCAL cValue, cTemp1, cTemp2 LOCAL nFor, nAt cDetailFields := "" cMasterFields := "" IF ( nAt := AScan( ::aDatasets, {|v| v != NIL .AND. Upper(v:cName) == Upper( cMasterName) } ) ) > 0 oDsMaster := ::aDatasets[ nAt ] ELSE LogDebug( "XAILER: TFastReport:SetMasterDetail() --> Master table " + cMasterName + " not found" ) RETURN .F. ENDIF IF ( nAt := AScan( ::aDatasets, {|v| v != NIL .AND. Upper(v:cName) == Upper( cDetailName) } ) ) > 0 oDsDetail := ::aDatasets[ nAt ] ELSE LogDebug( "XAILER: TFastReport:SetMasterDetail() --> Detail table " + cDetailName + " not found" ) RETURN .F. ENDIF FOR nFor := 1 TO Len( aFields ) cValue := aFields[ nFor ] cTemp1 := hb_tokenGet( cValue, 1, "=" ) cTemp2 := hb_tokenGet( cValue, 2, "=" ) IF Empty( cTemp2 ) cTemp2 = cTemp1 ENDIF aTemp := hb_aTokens( cTemp1, ";" ) FOR EACH cValue IN aTemp IF !oDsDetail:FieldExists( cValue ) LogDebug( "XAILER: TFastReport:SetMasterDetail() --> Detail Field " + cValue + " not found" ) RETURN .F. ENDIF NEXT IF !oDsMaster:FieldExists( cTemp2 ) LogDebug( "XAILER: TFastReport:SetMasterDetail() --> Master Field " + cTemp2 + " not found" ) RETURN .F. ENDIF cDetailFields += cTemp1 cMasterFields += cTemp2 IF nFor < Len( aFields ) cDetailFields += ";" cMasterFields += ";" ENDIF NEXT nFor RETURN ::SetMasterDetailC( cMasterName, cDetailName, cMasterFields, cDetailFields ) //------------------------------------------------------------------------------ METHOD SetError( nError, cText ) CLASS XFastReport ::nLastError := nError ::cLastError := cText IF ::lAbortOnErrors WITH OBJECT ErrorNew() :SubSystem := "XAILER" :SubCode := nError :Severity := ES_ERROR :Description := "TFastReport Error" :Operation := ::cLastError Eval( ErrorBlock(), :__WithObject() ) END WITH ENDIF RETURN NIL //------------------------------------------------------------------------------ METHOD Calc( cPascalExp ) CLASS XFastReport IF !::lPrepared ::LoadReport() ENDIF IF ::CalcC( cPascalExp ) RETURN ::GetCargo() ENDIF RETURN Nil //------------------------------------------------------------------------------ METHOD GetErrors() CLASS XFastReport LOCAL aErrors, cErrors IF !::lPrepared ::LoadReport() ENDIF cErrors := ::GetErrorsC() IF !Empty( cErrors ) RETURN hb_atokens( cErrors, ";" ) ENDIF RETURN {} //------------------------------------------------------------------------------ METHOD SetLanguage( cValue ) CLASS XFastReport ::FcLanguage := cValue IF !Empty( ::cLanguage ) ::LoadLangRes( ::cLanguage ) ENDIF RETURN NIL //------------------------------------------------------------------------------ METHOD SetADOConnectStr( cName, cConnectstring ) CLASS XFastReport LOCAL lSuccess IF PCount() == 0 IF Len( ::aAdoConn ) > 0 AEval( ::aAdoConn, {|v| ::SetADOConnectStrC( v[ 1 ], v[ 2 ] ) } ) lSuccess := .T. ELSE lSuccess := .F. ENDIF ELSE IF ( lSuccess := ::SetADOConnectStrC( cName, cConnectstring ) ) AAdd( ::aAdoConn, {cName, cConnectstring } ) ENDIF ENDIF RETURN lSuccess //------------------------------------------------------------------------------ METHOD SetFormatSettings( nSetting, xValue ) CLASS XFastReport LOCAL cValue SWITCH ValType( xValue ) CASE "A" cValue := "" AEval( xValue, {|v| cValue += v + CRLF } ) EXIT CASE "C" cValue := xValue EXIT OTHERWISE cValue := AllTrim( ToString( xValue ) ) END SWITCH RETURN ::SetFormatSettingsC( nSetting, cValue ) //------------------------------------------------------------------------------ METHOD Clear() CLASS XFastReport LOCAL oDS // Eliminamos datasets FOR EACH oDS IN ::aDatasets IF oDS != NIL oDS:End() ENDIF NEXT ::aDatasets := {} ::ClearDB( -1 ) ::nLoaded := NOT_LOADED ::lPrepared := .F. RETURN ::ClearReport() //------------------------------------------------------------------------------ METHOD ClearData() CLASS XFastReport LOCAL oDS // Zap en datasets FOR EACH oDS IN ::aDatasets IF oDS != NIL oDS:ClearDB() ENDIF NEXT ::nLoaded := NOT_LOADED ::lPrepared := .F. RETURN NIL //------------------------------------------------------------------------------ METHOD ForceReload() CLASS XFastReport LOCAL oDS FOR EACH oDS IN ::aDatasets IF oDS != NIL oDS:ForceReload() ENDIF NEXT ::nLoaded := NOT_LOADED ::lPrepared := .F. RETURN NIL