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 SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

REPORT FORM ... TO PRINTER

EinTerraner

Technical User
Jul 17, 2024
33
1
8
DE
good... whatever your timezone is :)

I've no Idea what i did wrong. but since 15 Years it worked well for me.

1st Step i prepare two Cursors named "DRU_KOPF" and "DRU_DATA".
DRU_KOPF has only one record and it contains directives and basic informations for my report like report Title-, Header- and Footer-sections.
DRU_DATA is filled with all data used in several Detail-sections. Also some boolean fields for the "Print when"-clause
But now there is a strange beahvior and a difference between the PREVIEW and TO PRINTER
Code:
...
&&creating DRU_DATA
     SELECT * FROM (SourceData) INTO CURSOR DRU_DATA WHERE ...
     SELECT DRU_DATA
     SELETE TAG ALL
     ALTER TABLE DRU_DATA ADD ..... && add some directives for the report
     ....
&&creating ReportFile Lc_Dest
     Lc_Dest = <function for the desired FRX-File>
&&select printername Lc_Port
SET PRINTER TO NAME (Lc_Port)

select DRU_DATA
go top
if Tf_View       && preview this document
    SET CLASSLIB TO (ThisForm.ClassLibrary) ADDITIVE
    Lo_Form = NEWOBJECT("_defobject_form")
    WITH Lo_Form
        .TitleBar = 1
        .BorderStyle = 3
        .height = SYSMETRIC(22)
        .width = (.Height/6)*5
        .autocenter = .t.
        .name = GETWORDNUM(ThisForm.Name, 1, "ß")+"_"+This.Name
        .alwaysontop = .t.
        .closable = .T.
        .ControlBox = .T.
        .MaxButton = .f.
        .MinButton = .f.
        .Themes = .t.
        .Caption = ALLTRIM(Lc_Name)
        .Show(1)
        SELECT Dru_Data
        REPORT FORM (Lc_Dest) PREVIEW WINDOW (.Name)
        .WindowState = 0
        .release()
    ENDWITH

else             && print this document
    IF ReportNoPrompt
        REPORT FORM (Lc_Dest) TO PRINTER NOCONSOLE NOOPTIMIZE
    ELSE
        REPORT FORM (Lc_Dest) TO PRINTER PROMPT NOCONSOLE
    ENDIF

endif

with PREVIEW it works well and i'll get the correct amount of pages like this snippet to see
Frm_022.jpg
but the TO PRINTER output generates something between 50 and 80 pages and they look like this snippet
Frm_023.jpg
it only prints the 1st Line from my DRU_DATA file cpl hundred times.

the ridiculous part now:
if i add a line like tzhe BROWSE
Code:
    SET ORDER TO DRU_BELG IN Dru_Data
    GO TOP IN Dru_Data
    SELECT (Dru_Data
BROWSE LAST FIELDS DISLINE, ARTKURZ, ARTMENG, ARTVKPR, ARTGSUM
or a INKEY(1)
Code:
    SET ORDER TO DRU_BELG IN Dru_Data
    GO TOP IN Dru_Data)
    SELECT Dru_Data
=INKEY(1)
The TO PRINTER output is correct
Frm_024.jpg
IT DRIVES ME CRAZY
 
Private datasessions? Of either the form or the rest of the code?

I just observer you do the preview within the form:
Code:
        REPORT FORM (Lc_Dest) PREVIEW WINDOW (.Name)
        .WindowState = 0
        .release()
And then, after form release you do the actual printing. Well, why separate preview and printing?

My guess is the only explanation I have for this bad behavior: Your actual printing does not have the actual print data selected, because the form uses a private datasession or your other code runs in another datasession.

The most relevant in your correction code is the SELECT DRU_DATA, I guess.
 
why separate preview and printing
Well. While working on a document we'd like to have a preview without printing it. especially, when i make some changes in the reportfile.
You placed the code where i do the PREVIEW only. This works in any situation without problems. Only the REPORT FORM (myform) TO PRINTER NOCONSOLE produces the funky output by repeating the 1st Record from my DRU_DATA.
I had no problem until 2 days ago, where i added a new field and a new Detail-Section in the report.

other funny thing is:
If i run this programm with open Fox-debugger and without the INKEY(1)-Line. it works also fine.

I guess it's a timing problem by W11 (also W10 just tested... W7 I'll try later). Mby DRU_DATA cursor was not yet correctly saved by the OS. Same problem i've also with an much much older programm, where the code is almost same like before (truncated) posted above. There i get a errormessage "Record out of range" if i just startet the printing the 1st time. preview has there also no problems. 2nd try to print works then fine

Just Tested:
I tried to replace the one second delay like shown
Code:
FLUSH IN (.Dru_Data) FORCE
*=INKEY(1)
Well... the behavieor changed to No Data in Detail-Sections in the Output-File (PDF) only Title/Summary/Header and Footer Sections

BTW: for PREVIEW i use REPORTBEAHVIOR 90 and for TO PRINTER i use 80. Reason is, if i create any PDF-Files as output, i can not select any TEXT in the PDF-File when printet as "90"
 
The wrong report behaviour is clearly the wrong selected workarea. So you could be victim of a very old bug of reports that use the wrong workarea when run while a grid has focus.
 
hum... if I change the REPORT FORM...TO PRINTER PREVIEW it works clearly
i use the private datasession in the form where i start the printing. I also tried both, and there is no difference between DATASESSION 1 or 2.

when i leave the INKEY(1)... delay for one second in the compiled EXE version it works randomly sometimes or even not. I've raised it to 2 seconds and in the EXE did work the last 15 times.

can U tell me all versionnumbers of the latest FoxPro-files? or a link, where i can verify my files? Those links (m$) i had before does not work anymore.
Mby i've some old files here
Frm_025.jpg

PS: if i click on the printer symbol in the preview-window it works also correct
Frm_026.jpg
 
While working on a document we'd like to have a preview without printing it.
Using the exit door toolbar icon from the preview toolbar closes the preview without printing it, so you don't need this separation.

And printing from the preview should print like the preview, indeed. It's the natural way to print what's previewed by having a REPORT FORM... PREVIEW TO PRINTER. The separation is clearly the reason you don't print the same thing that you previewed because of some change in the datasession, current workarea, or both.

As you start the report preview within the preview form you defined, when it uses a private datasession the data cursor would also only exist within that form and releasing the form closes the whole private datasession and you'd not be able to print what the preview showed, because all the workareas of that are not existing anymore. As you say it worked before I don't think the preview form uses a private datasession. Anyway, you better do both preview and printing in one go, then you can't get into the situation of printing something different than shown in the preview. That's clearly the simplest solution and that should always be favored, shouldn't it?

Do you fear you'll misclick the print button instead of exit? You could adjust the print preview toolbar and provide it with an EXE by providing the foxuser.dbf. In your adjusted toolbar you could separate the exit from the print button more distinctively, for example. But generally speaking the PREVIEW actually does not show a preview in parallel to printing, it always shows the preview before printing and the toolbar allows you not only to zoom or navigate pages, but also decide to exit instead of printing. There's no need to separate printing from previewing, therefore.

And all that is true for any version of VFP.

What makes adjusting the toolbar even simpler is using FoxyPreviewer instead of the VFP report apps.
 
Last edited:
Regarding your version question, btw: 9.0.0.7423 is the last version Hotfix 3 of SP2, so you're up to date with that.
 
change in the datasession, current workarea, or both.
as You see in the top-posting i do this within the same procedure. I just have the IF (then) <do preview> ELSE <do printing> ENDIF
there is actually no way i'll loose some datasessions and or workareas.
the funny thing is 50% of using it it works and other 50% it fails.
but this procedure exist UNCHANGED already since 2010 without any troubles. but now since abt 10 days i've those malfunctions on W11 and also W10 (test on W7 not yet done)

so there's no need to separate printing from previewing, therefore.
there is a really big reason to seperate the printing/preview functions.
We have to print one document for multiple recipients with the special difference (im working now on it) some PDF will be send by mail and others with Snail-Mail. The most important difference in those documents is the receivers adress in the document-header-section
It would be very tedious and labor-intensive to click the print button for each output (up to 200 times).

the 2nd reason for seperate preview/printing is also important to keep track for "document was already printed". if i do the print directly from the perview-form-print-button i can not recognize the event "document send to printer". very important to prevent multiple printing. the "alredy-printed" will be stored with the DATETIME() in the personal-file of the recipient. some printings run unattended if, for example, reminders are created.

As you start the report preview within the preview form you defined, when it uses a private datasession the data cursor would also only exist within that form and releasing the form closes the whole private datasession and you'd not be able to print what the preview showed, because all the workareas of that are not existing anymore.
i have my seperate datasession and it did not change anything before i do this program
Here now the actual code (whole case)
Code:
** all FK_* ar predefined function-directives
** ie FK_REPORIG -> printing Original-Doc, FK_REPVORG -> Preview Original-Doc
** ie FK_REPDUPL -> printing Copy-Doc, FK_REPVDUP -> Preview Copy-Doc
    DO CASE
&& Druckausgabe Beleg
    CASE INLIST(Tc_Fnkt, FK_REPORIG, FK_REPDUPL, FK_REPORDU, FK_REPLIEF, FK_REPSPDE, FK_REPDSUM, FK_REPDTOT)

** need this, because cant select text in PDF-Output if 90
SET REPORTBEHAVIOR 80

** converting  <DefaultRepoName>.FRX to <readablename>.FRX
        USE (FORCEEXT(Lc_Repo,"frx")) ALIAS T1 IN 0
        Lc_Dest = ADDBS(JUSTPATH(DBF("T1")))+FORCEEXT(Lc_Name, "FRX")
        SELECT T1
        SET SAFETY OFF
        COPY TO (Lc_Dest) FOR .t.
        SET SAFETY ON
        USE IN T1

        SELECT (.Dru_Data)
        GO TOP IN (.Dru_Data)
** Just delay cuz printing faillure
=INKEY(2)
** Just delay cuz printing faillure
        IF PEMSTATUS(This,"ReportNoPrompt",5) ;
        .and. This.ReportNoPrompt
            REPORT FORM (Lc_Dest) TO PRINTER NOCONSOLE
        ELSE
            REPORT FORM (Lc_Dest) TO PRINTER PROMPT NOCONSOLE
        ENDIF
        SET PRINTER TO DEFAULT

&& Voransicht Beleg
    CASE INLIST(Tc_Fnkt, FK_REPVORG, FK_REPVDUP, FK_REPVLIE, FK_REPVSPD, FK_REPVSUM, FK_REPVTOT)

    SET REPORTBEHAVIOR 90

** converting  <DefaultRepoName>.FRX to <readablename>.FRX
        USE (FORCEEXT(Lc_Repo,"frx")) ALIAS T1 IN 0
        Lc_Dest = ADDBS(JUSTPATH(DBF("T1")))+FORCEEXT(Lc_Name, "FRX")
        SELECT T1
        SET SAFETY OFF
        COPY TO FORCEEXT(Lc_Dest, "FRX") FOR .t.
        SET SAFETY ON
        USE IN T1

** need external preview window, cuz IN active form lack of size
        SET CLASSLIB TO (ThisForm.ClassLibrary) ADDITIVE
        Lo_Form = NEWOBJECT("_defobject_form")
**        Lo_Form = NEWOBJECT("basic_form")
        WITH Lo_Form
            .TitleBar = 1
            .BorderStyle = 3
            .height = SYSMETRIC(22)
            .width = (.Height/6)*5
            .autocenter = .t.
            .name = GETWORDNUM(ThisForm.Name, 1, "ß")+"_"+This.Name
            .alwaysontop = .t.
            .closable = .T.
            .ControlBox = .T.
            .MaxButton = .f.
            .MinButton = .f.
            .Themes = .t.
            .Caption = ALLTRIM(Lc_Name)
            .Show(1)
            SELECT(This.Dru_Data)
            REPORT FORM (Lc_Dest) PREVIEW WINDOW (.Name)
            .WindowState = 0
            .release()
        ENDWITH

&& Bearbeitung Beleg
    CASE Tc_Fnkt == FK_REPEDIT                    && Druckformular bearbeiten

    SET REPORTBEHAVIOR 90

** Only for Operatoer-Staff accessible to make some modifications
        ThisForm.Visible = .f.
        IF IsExe
            _Screen.WindowState = 2
            _Screen.Visible = .t.
        ENDIF

        SELECT (.Dru_Data)
        GO TOP IN (.Dru_Data)
        MODIFY REPORT (Lc_Repo)
        IF IsExe
            _Screen.Visible = .f.
        ENDIF
        ThisForm.Visible = .t.

    ENDCASE
 
I am confused about your new code posting, because it does a MODIFY report, not a report preview and no printing.

Anyway, you can't set your preview form to have a private datasession to heal this problem, when you open and prepare the workareas for printing before starting the form, the form would create a new empty datasession and print nothing.

I do understand why you only preview one of many reports when you run a batch of outputs, fine, but how is that preview using the same data? Does it use data of just one customer to test the output or does it run the preview of one lengthy report with all data when later you print customer by customer? Are you even printing from the same data? Or is the report preparation completely different for preview and actual batch run?

Or is it even worse and the report uses a private datasession so anything you do before running the report will have anythinhg to do with the data printed as that is only determined by the report data environment?

You have not yet reacted to whether your report run that actually prints is done while a grid has focus or not. You're doing the print run without your preview form, so that's not a question about the preview form but about what form is active while you print to printer.
 
Last edited:
Regarding your version question, btw: 9.0.0.7423 is the last version Hotfix 3 of SP2, so you're up to date with that.
I've already checked that on Woody's blog. Are there any other files that might be out of date?
I use some OCX files like those
Frm_031.jpgFrm_030.jpg

Frm_029.jpgFrm_028.jpg
 
What would common controls do in your report? Do you use any OLE object printing?
 
I am confused about your new code posting, because it does a MODIFY report, not a report preview and no printing.
As You see the proramm runs a DO CASE with three possibilities and it depends of the FK_<number> i pass to this method,
1.CASE) printing (user and operator access allowed)
2.CASE) preview (user and operator access allowed)
3.CASE) modify (user access denied, operator access allowed)
This method is a part of a specified object.

i have a master_file_io_object with the basic I/O-Methods like
Object.Data_Load(DataKey as variant, Tc_Target as Cursor)
and much more methods to care basic-functions about the datafile(s). Some methods are triggred by windows-SHCNE_DISKEVENTS.
in this Basic-Object is the above mentioned CODE in the Method Object._PrintOut(Tc_Fnkt as Integer)
and also the two for printintusage dedicated alias-properties (DRU_KOPF and DRU_DATA). This two cursors will be updated with the requiered data-content like header-data in DRU_KOPF (adress, names, documentname/number for document-data....). DRU_DATA has the data for the Detail-section in the report.

for document-printing-functions i have a new object, based on this Basic one. In here is the preparationcode for both "DRU_"-files

so all access to any needed cursors and/or objects are always in the same form with same DATASESSION. There is no connection to outside of ThisForm (except whaever the REPORT FORM... does)


You have not yet reacted to whether your report run that actually prints is done while a grid has focus or not.
in the above mentioned object i have several cursors for dedicated basic-functions, This way I never have a conflict when juggling the data.
Code:
**
WITH This   && my default_file_io object
    .TimStmp = DATETIME()                    && Timestamp when Object created (for Logging-File)
    IF TYPE("ThisForm") == "O"                && usage in or outside of a form-object
        Lc_Temp = "_"+.Name+"_"+ThisForm.Name
    ELSE
        Lc_Temp = "_"+.Name+SYS(2015)
    ENDIF
    .LocTime = {.:}                            && filled on access to local miorrored data
    .SrvTime = {.:}                            && filled on access to server main data
    .DisAlias = "DIS"+Lc_Temp                && for GRID-Display usage
    .DruAlias = "DRU"+Lc_Temp                && printing header data
    .LocAlias = "LOC"+Lc_Temp                && access to local mirrored data
    .RelAlias = "REL"+Lc_Temp                && relation to 2nd file for DisAlias
    .SavAlias = "SAV"+Lc_Temp                && temp cursor for This.Data_Save
    .SrvAlias = "SRC"+Lc_Temp                && temp cursor for This.Data_Load
    .TmpAlias = "TMP"+Lc_Temp                && temp, only used in a closed method
    .TstAlias = "TST"+Lc_Temp                && temp, for data reconstruction and integrity checking
    .UpdAlias = "UPD"+Lc_Temp                && for SHCNE-Diskevents
all above (sometimes) used cursors will be closed in the DESTROY-Method
The dedicated cursors for REPORT FORM-Usage has fixed names
Code:
This.Dru_Date = "DRU_DATA"
This.Dru_Kopf = "DRU_KOPF"
Since I use a private data session, these names can only be used in this session anyway. If I have another window with the same function, then they cannot be different because they cannot see each other.
I have been using this object function since "PRE-FOXPRO times"

This way, I never need to know WHERE and HOW i need acces to any datafiles. Even if they are in a native table or included in a DB


What would common controls do in your report? Do you use any OLE object printing?
no. not really 😁
I also suspect that these OCX's are not used in the REPORT FORM. But you can ask if there is anything known about this.
 
Last edited:
I am confused
Me too 🤣 but...

In a fit of desperation, anger and resignation, I did something that would make other professional programmers shake their heads. But apparently somehow it was successful.

As you can see, I have wrapped the preview section in a form so that it can be made large enough to read the content. This form is not actually necessary for ... TO PRINTER ... But I have now packed the lines of code for the decision between direct printing and one with previous printer selection in just such a form, but with the parameters
Code:
.Height = 10
.Width = 10
.Top = -100
so that this window does not flicker around on the screen unnecessarily.

until now all reports printed correctly.. even in the compiled exe-version

This problem is not solved, but a detour is provided.
 
Which points in the direction that a change of focus of controls (by starting a new form) helps.

Again: There is a well known bug/behavior of a report taking the grid alias as the driving report workarea instead of the currently selected workarea, if a grid has focus while you do REPORT FORM. The solution/workaraound for that is setting focus to any non grid control. You even go the extra mile of adding a textbox to a form that only consists of a grid, if you absolutely need to print from that form.
 
There is a well known bug/behavio
Do You have a link where this bug is mentioned?

I've some forms, where i do start the REPORT FORM... stuff and the most time the grid has the focus, and the grid.corntrolsource is not my reportsource.
since 2006/2010 i never had any problems running this ... until cpl days ago

one of my own used forms has only 2 grids and 2 buttons and 2 images as fake-button. last compilation was Jan. 24. Its used for daily cash closing (Tahesabschluß)
The main display (grid) has 4 different display modes and has usually the focus until i click on the Image for printing oder preview
1) Daily sales compact
2) Daily sales detailed
3) Invoice display by numbers and their properties
4) List of items sold on the selected day
For the REPORT FORM thingamajig, the part to be printed is extracted from this display and passed on to the method specified above.
 
Last edited:
problem occurs only if you use the same cursor from the grid to do the report.
No, you got that inverse. If the grid cursor is the report cursor, you'd be fine, if the grid cursor differs from what you want to use for the report, it will still drive the report and the report therefore fails to print what you want.

So, look, add a report control and print ALIAS() from it. If that's the grid recordsource instead of DRU_DATA, you know all you need to do is set focus to something else than the grid before REPORT FORM. and there is no need for running a dummy preview form you don't use as preview window as you print directly, all your dummy preview window helps with is getting rid of the grid focus situation, that's not needing a form, that's only needing any other control.

Important: The preview is okay, so in preview that report control printing ALIAS() will be DRU_DATA, in the print run it will be the grid cursor or table alias. You don't do the preview, though, not in this REPORT FORM. So, sorry, that's unimportant, anyway, you'll surely not see DRU_DATA, as that would print okay, the bummer will be that ALIAS() will be the grid recordsource. That is, if you reset everything to what it was before.

Obviously you'll not like to go back as the problem is solved, it will only show you that this was the reason.
 
Last edited:
Chriss, does this mean thath everytime you execute a REPORT FORM... you have to make sure that a grid doesn't have focus? Most of the time a Command Button "Print" will have the focus that you clicked before printing, but when images as fake buttons are used (like EinTerraner mentioned) or keyboard shortcuts, it would be importent to always direct the focus away from the grid before a REPORT FORM. That's an important information!
 
but when images as fake buttons are used (like EinTerraner mentioned)
even click on Images make the previous object loose theie focus (sry... wrtong answer)
 
Last edited:

Part and Inventory Search

Sponsor

Back
Top