Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to detect an empty dataset when I export with Crystal Report

Status
Not open for further replies.

Nro

Programmer
May 15, 2001
337
CA
I have an old app in VFP 9 to print certificate of analysis in PDF, then it’s send to the customer as an e-mail attachment. The process is very automated and the user only have to acknowledge the message and it is sent automatically.

Now, sometimes the Certificate produce in PDF is empty. We think it’s probably a human error in the laboratory but the person in charge of sending the document is not able to verify the content of each certificate for one order.

I’m using very simple code to create the Crystal object (RDC), changing some properties and export it in PDF format.

Code:
FUNCTION EprtReport(tcReport AS String, ;
 tnCROpenReportMethod AS Integer)

loCrystalReport = NEWOBJECT("CrystalRuntime.Application.11")

loRep = loCrystalReport.OpenReport(tcReport, tnCROpenReportMethod) 

*
* Set some prop.
*
loRep.Expport(.F.)

I know, in the “craxddrt.dll” lib. there is an event called “NoData” but I never program classes with session OLEPUBLIC and Implement in VFP.

Code:
DEFINE CLASS myCrClass AS session OLEPUBLIC

IMPLEMENTS IReportEvent IN "..\bin\craxddrt.dll"

PROCEDURE IReportEvent_NoData(;
  pCancel AS LOGICAL) AS VOID;

 HELPSTRING "Fires this event when there is no data"
 * add user code here

ENDPROC

PROCEDURE IReportEvent_BeforeFormatPage(;
  PageNumber AS Number) AS VOID;

 HELPSTRING "Fires this event before formatting a page"
 * add user code here

ENDPROC

PROCEDURE IReportEvent_AfterFormatPage(;
  PageNumber AS Number) AS VOID;

 HELPSTRING "Fires this event after formatting a page"
 * add user code here

ENDPROC

PROCEDURE IReportEvent_FieldMapping(;
  reportFieldArray AS VARIANT, ;
  databaseFieldArray AS VARIANT, ;
  useDefault AS LOGICAL) AS VOID
  
 HELPSTRING "If database is changed while verifing database"
 * add user code here

ENDPROC

ENDDEFINE


I’d like to have, if possible, some examples on how to instantiate a Crystal report object and override the NoData event so I’ll be able to tell my user that the document he’s about to send is empty.

Thanks for your advice and your time.

Nro


 
Nro,

Before looking at your question more closely, could I ask you a favour.

Because of an issue with the forum software, your post is difficult to read on some systems. This is not your fault. It arises when someone posts a block of code, and the code includes lines that are larger than a certain width. In this case, it is the line that starts [tt]PROCEDURE IReportEvent_FieldMapping[/tt] in your second block of code. The effect is that, in some cases, it is impossible to read any of the thread without constantly scrolling horizontally forward and back to bring it into view.

This is something that the forum management knows about, and I hope will do something about.

In the meantime, could you edit you post so as to get rid of the line mentioned above. You can do that simply by breaking the line into two shorter lines at a suitable point.

I hope other people reading this post will also take note, and try to avoid posting code with lines longer than, say, 80 - 85 characters.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I have an old app in VFP 9 to print certificate of analysis in PDF, then it’s send to the customer as an e-mail attachment. The process is very automated and the user only have to acknowledge the message and it is sent automatically.

Now, sometimes the Certificate produce in PDF is empty. We think it’s probably a human error in the laboratory but the person in charge of sending the document is not able to verify the content of each certificate for one order.

I’m using very simple code to create the Crystal object (RDC), changing some properties and export it in PDF format.

Code:
FUNCTION EprtReport(tcReport AS String, ;
	tnCROpenReportMethod AS Integer)

loCrystalReport = ;
	NEWOBJECT("CrystalRuntime.Application.11")
loRep = loCrystalReport.OpenReport(tcReport, ;
	tnCROpenReportMethod)

*
* Set some prop.
*
loRep.Expport(.F.)

I know, in the “craxddrt.dll” lib. there is an event called “NoData” but I never program classes with session OLEPUBLIC and Implement in VFP.

Code:
DEFINE CLASS myCrClass AS ;
	session OLEPUBLIC

IMPLEMENTS IReportEvent IN "..\bin\craxddrt.dll"

PROCEDURE IReportEvent_NoData(;
 pCancel AS LOGICAL) AS VOID;

 HELPSTRING "Fires this event when there is no data"
 * add user code here

ENDPROC

PROCEDURE IReportEvent_BeforeFormatPage(;
 PageNumber AS Number) AS VOID;

 HELPSTRING "Fires this event before formatting a page"
 * add user code here
ENDPROC

PROCEDURE IReportEvent_AfterFormatPage(;
 PageNumber AS Number) AS VOID;

 HELPSTRING "Fires this event after formatting a page"
 * add user code here
ENDPROC

PROCEDURE IReportEvent_FieldMapping(;
 reportFieldArray AS VARIANT, ;
 databaseFieldArray AS VARIANT, ;
 useDefault AS LOGICAL) AS VOID;

 HELPSTRING "Database is changed while verifing database"
 * add user code here
ENDPROC

ENDDEFINE

I’d like to have, if possible, some examples on how to instantiate a Crystal report object and override the NoData event so I’ll be able to tell my user that the document he’s about to send is empty.

Thanks for your advice and your time.

Nro
 
Hello Mike
Is it better ?
Thanks
 
Nro, look at the right bottom of your original post, you can edit it, not for long, but for a day after posting. Reposting with shorter lines doesn't change the problem, the problematic post will still make the whole thread wider. I don't have a problem with your post width, but not everyone is having an HD display.

Regarding your main question, once you have such an implementation - this doesn't need to be implemented based on a session, by the way, especially if you don't want it to cause a new datasession take custom as the base class.

Just in that aspect, it's really unfortunate to use the session as the base class for something related to a report, that should run in the same datasession its called from. The help topic of define class explaining the IMPLEMENTS clause lists an example, that shows it's not necessary to base your classes implementing a COM interface as session:
Code:
DEFINE CLASS MyPublisherClass [highlight #FCE94F]AS Custom[/highlight] OLEPUBLIC
   IMPLEMENTS Publisher IN "MyBookStore.dll"
   PROCEDURE Publisher_ShowPrice(cGetID AS Long) AS Short
   ENDPROC
ENDDEFINE
It's not even important your class is defined as OLEPUBLIC.

Now you might for a simple test put a message box inside the IReportEvent_NoData and set pCancel=.T.

To make use of the class, you need
1. an instance of the class that implements the interface itself, I guess that's loRep in your original code
2. an instance of your new class also implementing the interface. So create an object of it: loHandler = CreateObject("myCrClass")
3. A call to EVENTHANDLER binding your class instance (the event handler) to the COM object: Eventhandler(loRep, loHandler)

That's it, mainly, you find an example working with the Adodb.Recordset COM class in the help topic of the EVENTHANDLER() function. You might first get this to work, as the Adodb.Recordset surely is easier to cope with than a Crystal report class.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Nro, sorry to have to go on about this, but it wasn't enough to post your message again. The problem is that the original post is still there. What I was asking was that you edit the original post That would have got rid of the problem. If the Edit button is still visible, you can still do that. If not, never mind. I see Olaf has already given you some help. I will try to do so too.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
To add to Olaf's answer, once you've dealt with the binding, etc., you will need to arrange it so that the NoData event actually cancels the report (assuming that's what you want to do).

That's quite easy. Just take this code:

Code:
PROCEDURE IReportEvent_NoData(;
 pCancel AS LOGICAL) AS VOID;

 HELPSTRING "Fires this event when there is no data"
 * add user code here

ENDPROC

and add your own code to set the parameter to .F. You can also put any other code you like in there, such as a message to the user to tell them what you are doing. For example:

Code:
PROCEDURE IReportEvent_NoData(;
 pCancel AS LOGICAL) AS VOID;

 HELPSTRING "Fires this event when there is no data"

[b]  MESSAGEBOX("No certificate data available")
  pCancel = .F.[/b]

ENDPROC

The procedure doesn't have to return anything. Just setting pCancel to .F. will cancel the report.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike,

myself said:
Now you might for a simple test put a message box inside the IReportEvent_NoData and set pCancel=.T.

So a) I addressed that, too, and b) pCancel=.T. should cancel the report, not pCancel=.F.

Bye, Olaf.

Olaf Doschke Software Engineering
 
pCancel=.T. should cancel the report, not pCancel=.F.

Yes, of course. My mistake.

Nro, thanks for fixing the wide-line issue. The thread is completely readable now. You might not have noticed the problem yourself, as it only seems to appear with monitors below a certain resolution (and also presumably on mobile devices). As I said before, the forum management is aware of the issue.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thanks for your help Mike and Olaf but I found another way to return the number of rows printed;

Code:
FUNCTION EprtReport(tcReport AS String, ;
 tnCROpenReportMethod AS Integer)

loCrystalReport = ;
	NEWOBJECT("CrystalRuntime.Application")

loRep = loCrystalReport.OpenReport(tcReport, ;
	tnCROpenReportMethod) 

*
* Set some prop.
*

loRep.Expport(.F.)

lnNumberOfRecordSelected = ;
	loRep.PrintingStatus.NumberOfRecordSelected

RETURN lnNumberOfRecordSelected <> 0
Since I’m not developing in Foxpro anymore (I’m very sad about that, and a little bit angry too) I’d never really learn how to work with event binding, Interfaces with OLE objects. All I used was automation and I think the object model in VFP was a lot easier to learn.

Thanks again.

Nro
 
Good to see you found a solution, Nro. I should have thought of the PrintingStatus object. By the way, that object also has a NumberOfPages property which would be an alternative way of getting the same information. Either way, it is clearly much simpler than event binding, etc.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I totally agree with Mike,

and indeed the event binding is quite a hurdle of being able to debug code. Anything that simply can happen (events) let a debugger trace window of the debugger jump to what happens and that's sometimes hard enough with the native events, a pain with timers (which therefore also can be silenced to not influence your step by step code tracing).

That means all in all, while I know the EVENTHANDLER function of VFP, I more often made use of BINDEVENTS(), but overall tend to avoid this concept where possible. It's intransparent. When you inherit code making excessive use of events - sarcasm mode on: Javascript : sarcasm mode off - you start looking at two or three code snippets in parallel or nested in a seemingly Escheresque way to find out what happens under which conditions within a closure.

In a way, once the wiring works out nice, every single event code can precisely concentrate on what exactly to do for this specific event. But it makes program flow less obvious.

One of the ineffective ways VFPs IMPLEMENTS clause works is you need to have the full-blown list of interface events, even if you only want to care for one specific event, so often you have all the default empty code sections per event and that alone makes navigating that code less effective, the document view still also shows the full-blown list of empty default behavior unmodified events.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top