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

VFP Report: How to horizontally print blocks based on a cursor 3

Status
Not open for further replies.

Manuch

Programmer
May 6, 2022
16
IT
Hello,
I've been developing VFP customization for over two year and this forum has been a huge huge help to me, I just registered and this is my first thread here, I probably wouldn't be here if it wasn't for this wonderful site.

I'm editing a report I made some months ago, I'm editing it to add some totals in the last page of the print, I sincerely forget VFP very fast because I only receive requests for VFP customization rarely.
I went for using the "Summary" block instead of "Page Footer" + a counter to detect the last page, even if many posts from decades ago recommend not to use the Summary, but it seems to work fine in VFP 9.

The number of blocks I have to print depends on the user settings, I would like to print something like this:

img_yzsye7.png


Where each cell has its code defined by the user (F1 - G3 - SCAT. - ...) above and the total count of these product below (only present 11 under F1 in my screenshot).

These blocks are not static and are defined by the user, I would like to dynamically print this cell (from left to right), any suggestion?
In the title I mentioned a cursor because in my code, before the report, I make a cursor with the description of the block and the total, so I have a cursor ready like this:

cod: F1,
sum: 11
--------
cod: G3,
sum: 46
--------
.......

Of course I could define static blocks and print the unused blocks empty, but I would like to know if there's a way to make it dynamic.

In case it may help I post my whole report too with the new blocks I would like to add.

img_ssxz4z.png


Thank you very much,
Emanuele.


Edit: I feel like I wasn't clear enough, I know you can loop and print vertically making a group, but can I do the same horizontally somehow? The number of blocks I have to print is dynamic, I don't know how many cells I have to print.
 
Hello Emanuele and welcome.

It sounds to me that what you need is a cross-tab. One of the forum regulars here, Tamar, has written some articles about how to do this. See:


and


I suggest you start by having a look at these articles, and then coming back her if you have any specific questions.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
First of all: thanks a lot for pointing me in the right direction, also Tamar documents are without a doubt very well written and extremely useful.

I personally struggled for a couple of hours but didn't manage to understand much because of my poor knowledge of vfp reports, not proud of that.
I don't think I can include FastXTab in my report because I don't generate reports directly, the "standard" way, but through a software called Arca Evolution:

img_rgqfgd.png


To be honest I don't even know how to generate reports or how they work without the "capsule" of this software Arca Evolution.
The only time I needed to declare a function and use it in my report I added it under the "Functions" button (bottom-right).

The second solution ( seemed too complex to me for my small use case.


I think I'm going for a "cheap" solution, also because I don't think it is worth wasting too much for such a small problem.
Please don't judge me bad, I'm a full-stack developer that occasionally writes customizations for Arca Evolution, my VFP programs run well, but I'm not too good with reports (also I forgot everything about reports since I made this).

Again very thanks,
Emanuele.
 
There is no option to print left to right, so if values are in the same vertical position they need to be in one record. I'd not go about this printing data, but create the maximum grid fill in labels with unique values, close the designer. Then open the FRX as a DBF with USE yourreport.FRX and look for the label captions in records of the report.

Later at runtime you can change these records to put in whatever you need in each cell, so you'd prefill these labels before you do the REPORT FORM command and the data to print won't need to come from the report cursor records but is put in before printing. For example if you fill in R1C1 to R2C11 you know which label captions are in which row/column cell.

I'd only care for the line objects and their length after you get this working.

You can perhaps also get something going by making use of the "print when" option that's available for every report object. But you don't want to maintain 2*11*4 = 88 boolean fields to control which grid lines are drawn and which not, do you? So instead of controlling the footer with data, change the FRX itself by manipulating it as a DBF. Every FRX is in fact a DBF, which is why USE yourreport.FRX will work. You mainly only need to find out which records of the FRX are about your footer labels, but that's easy by finding the label captions you put in.

Chriss
 
EDIT:
Before I waste anyone's time for no reason, my problem was just I needed to call RELEASE before re-declaring the GLOBAL variable, this long answer is just to explain this issue I had, sorry, I just discovered it.
I leave the rest of my answer in case this ugly thing may help someone, if you have any idea on how to improve it please tell me, it'd be very appreciated.

---------------------------------------------------------------

Thank you very much myearwood and Chris Miller.

I'm going for the approach kindly suggested by myearwood
I'm going to put down 15 (only 2 in the screenshot below) static cells, from left to right, with the rule to print only if the element it has to print it's defined.
This cell has a textbox above that prints "codImballo(<n>,1)" and one below that prints "codImballo(<n>,2)"

img_b4pi9f.png


These cells have this rule, to hide them if not needed:

EMPTY(codImballo(<n>,1))

where <n> is the number of the cell, last one (at the right border) has 15.


"codImballo" is a global array (matrix) I declare in my program and fill with the totals before the report.
The first position contains the description and the second the total.


Just for reference, this is how I declare the array, calculate the totals and fill the array

[pre]
PUBLIC ARRAY codImballo(15,15)
SELECT TOP(15) ;
Imballo as Codice,;
SUM(CEILING(repdata.QtaEvadibile / repdata.QtaImb)) as Totale;
FROM repdata ;
WHERE Imballo IS NOT NULL GROUP by Imballo INTO CURSOR _codImballo ;
ORDER BY Codice

LOCAL counter
counter = 1
SELECT _codImballo
&& preparo array globale che sarà poi stampato nel "Summary" del report
SCAN
codImballo(counter,1) = _codImballo.Codice
codImballo(counter,2) = _codImballo.Totale

counter = counter + 1

If(counter > 15) Then
Exit() && massimo 15 tipologie di imballo supportate
EndIf
ENDSCAN
USE IN _codImballo[/pre]


For what I remember I never used global variables in VFP and right now I'm having an issue.
I went for a global variable because for what I know I can only access cursors from inside the report generator and I can't reference a position of a cursor directly (like cursor[1].field), so I used an array and had to declare it globally to be accessible in the scope of the report.

My issue is that it seems I can't update the array once filled, once I fill a position I can't unset it.
The first time I generate the report it's all fine, the second time when I change the parameters and the report changes, my array does not.
I checked my cursor _codImballo, from which I generate the array, it gets generated correctly, it's just VFP that doesn't update my global array for some reason.

I tried redeclaring, reassigning it whole, after and before the next report, but it seems once I set a position of this global array it always remains set!


Right now, ugly or not, it's working as intended if it wasn't for this problem with the global variable.
Can you suggest me alternatives to remove this issue or do you know why VFP does this? It could be caused by the capsule of this software "Arca Evolution", really I have no idea.

Again a million thanks for the kind answers,
Emanuele.
 
You declare a OUBLIC array:

PUBLIC ARRAY codImballo(15,15)

I think you think you need it public to be seen by the report. Well, reports also see local vars, local to the code that makes the REPORT FORM call.
On the other side, RELEASE codImballo after the result, and you don't have residue data from previous runs.

In very sort: Care for the scope of your vars. PUBLIC is a bad design decision. IT really is PUBLIC in scope, and that does not only mean it's accessible anywhere else in all other code running in the same VFP process, but it also stays in memory and is only released when you either explicitly call RELEASE varname or when the process ends.

Even going through the line PUBLIC ARRAY codImballo(15,15) once more does NOT reset the array to all .F. elements. If you declare a PUBLIC variable that already was declared before you don't get an error and the var stays as is:

Code:
Release gaValues

Local i
For i=1 to 10
    createarray(i)
    ?
EndFor 

Function createarray(ti)
   Public array gaValues[10]
   gaValues[ti]='set'
   
   Local i
   For i=1 to 10
      ?? gaValues[i]
   EndFor 
EndFunc

As each call only sets one element you expect this to print:
[pre] set .F. .F. .F. .F. .F. .F. .F. .F. .F.
.F. set .F. .F. .F. .F. .F. .F. .F. .F.
.F. .F. set .F. .F. .F. .F. .F. .F. .F.
.F. .F. .F. set .F. .F. .F. .F. .F. .F.
.F. .F. .F. .F. set .F. .F. .F. .F. .F.
.F. .F. .F. .F. .F. set .F. .F. .F. .F.
.F. .F. .F. .F. .F. .F. set .F. .F. .F.
.F. .F. .F. .F. .F. .F. .F. set .F. .F.
.F. .F. .F. .F. .F. .F. .F. .F. set .F.
.F. .F. .F. .F. .F. .F. .F. .F. .F. set
[/pre]

Instead it prints:
[pre] set .F. .F. .F. .F. .F. .F. .F. .F. .F.
set set .F. .F. .F. .F. .F. .F. .F. .F.
set set set .F. .F. .F. .F. .F. .F. .F.
set set set set .F. .F. .F. .F. .F. .F.
set set set set set .F. .F. .F. .F. .F.
set set set set set set .F. .F. .F. .F.
set set set set set set set .F. .F. .F.
set set set set set set set set .F. .F.
set set set set set set set set set .F.
set set set set set set set set set set[/pre]
Because each call only sets one element, but the previously set elements are kept the way they are.

So release your array after you printed, or better yet design your code to not need a public array for printing, i.e. create a local array in the code which also calls the report.

Chriss
 
Very thanks for the advice and explanation Chris.

Sadly, for how this software "Arca Evolution" works, I can't avoid declaring it public.
I tried replacing PUBLIC with LOCAL, but sadly the report, run this way, doesn't have access to the local scope, I receive this error when the report is ran and it crashesh:

img_ohtkol.png


Sadly I don't call DO REPORT (or the correct command) directly, I just write the SQL initial query, and the VFP code to run before and after the SQL command and the DO REPORT.
I declared and filled my array inside the "After SQL Command" event (just before the DO REPORT), but sadly the locals declared here are not visible in the scope of the report.

Just for the sake of curiosity I tried declaring locals in the other events I have available before the report, but still none of the locals are visible from the report.
All cursor are visible from the report though (I already knew this).


These are the buttons I use to edit these events:

img_ychv5g.png



At the end I kept the GLOBAL and added the RELEASE call inside the "After report" event, that is run right after the report is done.
 
Well, the code that populates the array doesn't need to create it, You can pass in an array by reference, then populate it in a function, then call the report, this doesn't need to be all in one method, but you surely can rearrange code so a local array is present when the report finally needs it to print it.

Even if you don't see for now, how to rearrange things, there is the solution to unset the array, you can RELEASE codImballo after the report printed. In the next run you get a new, completely unpopulated array.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top