Thursday, April 9, 2009

SET TALK appears to be on when running reports with SP2

I've been using VFP 9 SP2 ever since it first came out which was a long time ago. Yeah, I know there was that nasty Data Group bug, but to me, the enhancements in SP2 far outweighed the negative. Now that Microsoft has released a hotfix for the Data Group bug, I'm hoping more developers jump on the bandwagon and start adopting SP2. That said, a colleague reminded me last night about a bug where text is echoed to the screen as if a mysterious SET TALK ON had been issued.

This is a bug, but it’s one that you can easily fix yourself. You see, some of the new enhancements in SP2 were not implemented in the core VFP exe. They were implemented with a creative use of several Report Listener subclasses that reside in the FFC directory. When you run reports with SP2, the default behavior is to utilize these Report Listeners instead of the base VFP Report Listener class. The bug exists in one of those classes so you can change it yourself.

Modify the fxListener class of the _ReportListener class library and change the code in the LoadReport method. Simply move This.setFRXDataSessionEnvironment() so it comes before This.createHelperObjects() and the problem is solved.  

If you’re running on Vista, however, you have to be aware of the Virtual Store and work around it. When you edit the fxListener class, Vista makes a copy of the _ReportListener class library in the Virtual Store and your modifications are actually saved there and not in the C:\Program Files\Microsoft Visual FoxPro 9\FFC directory as you expected. Because a Virtual Store is specific to each user, it means the change you just made only works for the login you’re currently using. As soon as you switch to another login, the changes don’t exist for that user. To permanently fix the bug, move the _ReportListener class library from your Virtual Store back to the C:\Program Files\Microsoft Visual FoxPro 9\FFC directory, overwriting the original. Also, be sure to delete the _ReportListener class library from the Virtual Store for all users. If you forget this step, those users could be accessing an old copy of the class library.

8 comments:

Christian said...

Thank for sharing this, Cathy! We'll make the move real soon now!

Saulo Morais Lara said...

Very good. I was crazy find for this. thanks

Anonymous said...

Cathy, it doesn't work for me on XPsp3 - VFP9sp2. After making the changes to the vcx, I copied them into my class folder which my app is pointing to. I verified the changes were in the vcx file, and they were. I have a clean VFP9 to sp2 install, skipping sp1. The work around I've had to re-implement is to add "set console off" before the report form and "set console on" afterwards. Also note that using the "NoConsole" keyword to the report form command does not work.

Cathy Pountney said...

Dear Anonymous,

Why are you copying the vcx to your class folder? When the reporting engine instantiates a report listener, it does so from the FFC directory ... unless you've customized the report output app and redirected which listeners are instantiated.

Stanley Barnett said...

Hi Cathy,

Thanks for replying...

< Why are you copying the vcx to your class folder?
To avoid dll hell from future updates... I copy all all the classes my applications use into their own class folders and include thwe class folder in the apps path.

Now you are the expert here and I'm willing to take any advice that you give... Also, I have both books titled "The Visual FoxPro Report Writer" and "Whats New in 9". I've also read/studied them. The first book has no info about this new object oriented approach, and the later book where Doug presented his material covered it but not in enough detail to start utilizing it past its generic behavior.

My fustration with this new report writer is real... I can see and I know from both your presentations at the 2007 SW conference that it is quite capible, but so is the C language, as for me and what I've been able to put together using this new writer, you may as well as give me a cd with the C language and say "it will do it", and ofcourse if you know the C language, it can.

I have several what seems to be simple problems to solve and I'm not getting anywhere. Enough crying.......

1. I downloaded the latest xsource and fll folder files from CodePlex and extracted them into the xsouce and fcc folders under VFP9.
2. I then created new apps from the "ReportBuilder, Output, & Preview" projects and placed the .app files in my projects App filder and pointed to them in my main.prg like this:

Set REPORTBEHAVIOR 90
_ReportBuilder = '.\Apps\ReportBuilder.app'
_ReportOutput = '.\Apps\ReportOutput.app'
_ReportPreview = '.\Apps\ReportPreview.app'

3. I also copied the report listener vcx from the fcc folder into my projects class folder.

Cathy, some of the simple things I need to fix is;
1. the 32??? pages to print in the print dialog when there are really only 3. (client complaints)
2. How can I tell if the user
a) pressed cancel from the preview form, with object type 1
b) pressed cancel from the print form, with both object types 0 and/or 1.

4. What do I modify, and how do I pipe it all together

5. Also, what am I missing here? In the commands;

loListener = createobject("MyReportListener")
report form MyReport object loListener

I read this as loListener as an EMPTY object with no functionality. If so, then what good is it and how can it possible suggest anything to the report engine?

6. Samples/examples with remarks are very helpful. Is there any collections of these.

Cathy, I believe that once I know where things go and how the engines think, the battle will will be half over.

Thanks so much!
Stanley Barnett

Eric Selje said...

You rock.

wiplast said...
This comment has been removed by a blog administrator.
Jay said...

Cathy,

Thanks for the post, but it is out of date, or something.

Following is the code from my version of the:

_Reportlistener.LoadReport

As you can see, while I have the
"THIS.setFRXDataSessionEnvironment()"
line, I don't have the other.
I tried simply adding set talk off, but this didn't help. Before I spend a bunch of time on this, do you happen to have a solution?


===================================
THIS.clearErrors()

THIS.setFRXDataSessionEnvironment()

THIS.resetDataSession()
THIS.frxHeaderRecno = -1

IF NOT ISNULL(THIS.Successor)
WITH THIS.Successor
.AddProperty("isSuccessor",.T.)
.AddProperty("commandClausesFile",THIS.commandClausesFile )
.PrintJobName = THIS.PrintJobName
.CommandClauses = THIS.CommandClauses
.LoadReport()
ENDWITH
ENDIF