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

VFP9 Report Chaining 1

Status
Not open for further replies.

stanlyn

Programmer
Sep 3, 2003
945
US
Hi,

Wondering if anyone knows if this is possible using VFP9 report writer and chaining.

1. The output is 8.5 x 11 paper containing 2 rows (addressees) from the database as the form will be cut in half to make 2 postcards, each addressed to a different recipient.

2. The back of each page, (postcard) needs to have some variables printed on them that must match up with the row or person from the front side. Such as print the addressee's name on both sides.

3. I currently have each side designed as separate report forms and somehow, I need to get them together on the same piece of paper when they are printed as duplex.

4. Double runs (one for each report) is not desirable. It needs to be generated so it can be printer to a duplex printer of as pdf output for printing at a different place and time.

Any idea on how to pull this off?

Thanks, Stanley
 
I think you need a cursor with two adjacent records per postcard, and a page break between each record when you use a duplex printer.



Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
Hello again Stanley.

The usual way to do this would be to create two separate reports, one for the addresses and one for the stuff on the back (let's call them Side A and Side B respectively). (I think you are already doing that.)

To understand the next step, let's for a moment assume that you only have one address on each sheet, rather than two side by side.

You would then loop through your underlying address table. For each address, execute [tt]REPORT FORM SideA NEXT 1[/tt] with a [tt]NOPAGEJECT[/tt] clause. And then execute [tt]REPORT FORM SideB NEXT 1[/tt] without a [tt]NOPAGEEJECT[/tt] clause. The [tt]NEXT 1[/tt] clause tells it to only process the current record. Assuming yo are printing to a duplex printer, that would give you what you want, but for only one addresss per sheet.

So now comes the complicated bit. Because a report can only process one record at a time from the driving table, you will need to create a cursor that contains a pair of addresses. The first record in the cursor would contain the data from addresses 1 and 2; the second record from addresses 3 and 4; and so on. You use that cursor to drive the report.

You then need your Side A report to show the first address fields on the left, and the second on the right. Again, use [tt]NEXT 1[/tt] and [tt]NOPAGEJECT[/tt] as above.

And you need to take a similar approach with your SideB data.

I think that should work, although I've never done anything like this myself, so I can't be sure.

A completely different approach might be to use labels rather than reports, since labels can automatically handle the side-by-side requirement. You would still use NOPAGEEJECT for the Side A, and not for SideB. But I'm not completely sure if that would work, so be prepared to experiment.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Stanley,

First, I would take Mike's suggestion. Personally, I would try to create it all in a single cursor instead of two (just my approach). However, my "shortcuts" sometimes end up taking longer instead of shorter, so you can take that for what it's worth.

In either case, the cursor(s) structure and record sequence may be dependent on the manner in which your printer collates the duplex output. I may be wrong, but I think that could vary among printer brands.

Good luck!

Steve
 
I would use one cursor, two records per card (one front and then back), with the layout being chosen based on whether the underlying recno() was odd or even
via the Print When for each element on the design

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
On reflection, I think Steve's solution might be better than mine. So you would have a single cursor, with one record for each pair of addresses. The record would contain all the fields for the two addresses, and all the fields for the back of the sheet. That way, you should be able to print the whole job with a single REPORT FORM (no need to loop through the cursor, and no need for NOPAGEEJECT).

Provided everything is lined up correctly - in particular with the correct height for the Details band - it should print the way you want it on a duplex printer. (For good measure, tick "Start on new page" on the Band page of the Detail Band Properties.)

The difficulty will be actually creating the cursor. I can't off hand think of any way to do that with a SQL SELECT. You will have to loop through the original table, picking up data from the current record and the next record, and then skipping over the second record next time round the loop. Not impossible, but it will need a bit of thought.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike said:
address on each sheet, rather than two side by side.

Don't know if this makes any difference in your process, but instead of side by side, it is top half of page for postcard #1 and bottom half for postcard #2. Each sheet makes two 8.5" x 5.5" postcards.

Would it be easier to do this as one 8.5x11 page or two 8.5 x 5.5 pages with nopageeject on first page?

So, does side-by-side vs top-half & bottom-half designs change the implementation of what has been said so far?

Thanks, Stanley



 
The fact that it is top-and-bottom rather than side-by-side shouldn't make any difference. Either way, the Detail band will contain all the fields for one pair of addresses. It's just a question of how you arrange them.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike said:
Detail band will contain all the fields for one pair of addresses.

I think I would create a cursor from the original data (SQL or dbf) which would contain the data for TWO records. That would mean two fields (named differently obviously) for each address item and two fields for each item on the other page - all in the same record. (Hopefully you wouldn't run into record length or file size limits).

I think it would take some code to do this. But it's doable. It might require two REPORT FORM statements instead of one. I'm not sure, maybe Mike can speak to that.

My mistake: Mike DID say one PAIR of addresses. I read it too fast.

HTH

Steve
 
That's right, Steve. I did say "pair" of addreses. So the first record in the cursor would contain data for Address 1 and Address2; the second record for Address 3 and Address 4; and so on. And each record would contain data for both the front and back of the sheet.

But I don't think it would require two REPORT FORMs. Provided the fields are arranged within the report so that you get a page break after the second address and before the back-of-page- info for the first address, it should come out right.

Stanley, please keep in mind that I have never actually tried to do anything like this. You might need to experiment a bit to get it right. But I hope that the info that Steve, Griff and I have given you here will give you a good start.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike said:
You might need to experiment a bit to get it right.

Especially since printers vary in their output & alignment. Even more true when printing on a pre-printed form where the characters need to be placed in their box or on a line, or a box on the form needs to be checked. Experimentation is a must.

Steve
 
Good news...

and thanks to everyone! I have it working perfectly and here is the code... The report forms only has the gc* variable names assigned and no other bindings.

Code:
Set Path To '.\, .\reports, .\programs, .\data'
Set Escape On

Release All Like gc*
Public gcZZZNameTop, gcZZZNameBottom, gcFullNameTop, ;
	gcFullNameBottom, gcCoupon, gcSenderPhone
gcZZZNameTop = 'TopZZZ.Com'
gcZZZNameBottom = 'BottomZZZ.NET'
gcCoupon = '202207PC'

Public gcSenderName, gcSenderAddress, gcSenderCityStateZip, gcSenderSite, gcSenderEmail, ;
	gcLine1Rear, gcLine2Rear
gcLine1Rear = 'This is special line 1 on the rear!'
gcLine2Rear = 'This is special line 2 on the rear'

If ! Used('rv_GlobalDB')
	Use 'rv_GlobalDB' In 0
Endif

Select('rv_GlobalDB')
gcSenderName = rv_GlobalDB.company
gcSenderAddress = rv_GlobalDB.address1
gcSenderCityStateZip = Alltrim(rv_GlobalDB.city) + ', ' + Alltrim(rv_GlobalDB.state) + '  ' + ;
	ALLTRIM(rv_GlobalDB.zip)
gcSenderSite = rv_GlobalDB.website
gcSenderEmail = rv_GlobalDB.email
gcSenderPhone = rv_GlobalDB.phone

Use In Select('rv_GlobalDB')

Public gcAddress1Top, gcAddress1Bottom, gcAddress2Top, gcAddress2Bottom, ;
	gcCSZTop, gcCSZBottom

If Used('rv_ML1')
	Use In Select('rv_ML1')
Endif

Delete View 'rv_ML1'

Create Sql View 'rv_ML1' Connection AppData ;
	AS Select Top 4 ;
	pk, full_name, first_name, middle_name, last_name, company_name, address1, ;
	address2, city, state, postal_code, county_code, county_name ;
	From MailingList ;
	where 1=1

Use 'rv_ML1' In 0
Select 'rv_ML1'

Set Multilocks On
CursorSetProp("Buffering", 5, "rv_ML1")

Select 'rv_ML1'
Requery()
Go Top

Create Cursor curPrint (top_ZZZ C(40), bott_ZZZ C(40), top_comp C(40), bott_comp C(40), ;
	top_full C(40), bott_full C(40), top_addr1 C(40), bott_addr1 C(40), ;
	top_addr2 C(40), bott_addr2 C(40), top_csz C(40), bott_csz C(40))

Do While !Eof('rv_ML1')
	Select 'rv_ML1'
	x=Iif(Mod(Recno('rv_ML1'), 2) = 0, 'Even', 'Odd')

	Select 'curPrint'
	If x = 'Odd'
		Append Blank
		Replace top_zzz With gcZZZNameTop
		Replace top_comp With Iif(Isnull(rv_ML1.company_name), '', rv_ML1.company_name)
		Replace top_full With rv_ML1.full_name
		Replace top_addr1 With rv_ML1.address1
		Replace top_addr2 With rv_ML1.address2
		Replace top_csz With Alltrim(rv_ML1.city) + ', ' + Alltrim(rv_ML1.state) + '  ' + Alltrim(rv_ML1.postal_code)
	Else
		Replace bott_zzz With gcZZZNameBottom
		Replace bott_comp With Iif(Isnull(rv_ML1.company_name), '', rv_ML1.company_name)
		Replace bott_full With rv_ML1.full_name
		Replace bott_addr1 With rv_ML1.address1
		Replace bott_addr2 With rv_ML1.address2
		Replace bott_csz With Alltrim(rv_ML1.city) + ', ' + Alltrim(rv_ML1.state) + '  ' + Alltrim(rv_ML1.postal_code)
	Endif

	Select 'rv_ML1'
	Skip 1
Enddo

Select 'curPrint'
Go Top

lcPrinterName = Getprinter()

If Empty(lcPrinterName)
	Messagebox('No printer chosen...',0,'Printer Not Chosen')
	Return
Endif

Set Printer To Name (lcPrinterName)

Do While !Eof('curPrint')
	gcZZZNameTop = curPrint.top_zzz
	gcZZZNameBottom = curPrint.bott_zzz
	gcCompanyTop = curPrint.top_comp
	gcCompanyBottom = curPrint.bott_comp
	gcFullNameTop = curPrint.top_full
	gcFullNameBottom = curPrint.bott_full
	gcAddress1Top = curPrint.top_addr1
	gcAddress1Bottom = curPrint.bott_addr1
	gcAddress2Top = curPrint.top_addr2
	gcAddress2Bottom = curPrint.bott_addr2
	gcCSZTop = curPrint.top_csz
	gcCSZBottom = curPrint.bott_csz

	Report Form 'mailinglist_front' Next 1 To Printer Nopageeject
	Report Form 'mailinglist_rear' Next 1 To Printer

	Skip 1
Enddo

Use In Select('curPrint')
Use In Select('rv_ML1')

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top