The best way to do this is using a series of print statement. Though its not as easy as designing using Report Writer, worth doing it especially when it comes to printing BILLS (especially when multi-part is required). I use something like the following. (Just give you an idea to proceed with...)
=DM_INVOICE()
=DM_PRINT( (Invoice_Text_File))
FUNCTION DM_INVOICE
*-------------------
*PARAM lRefNo, lRefDt, lSrvNo, lSuppInv, lCurrency, lExgRate, lAcName
LOCAL lCmd, nHeaderLines, nPages, nLines, nDataLines, nFooterLines, nLinesPerPage, nHeaderSkip
LOCAL nTotal, lPort, cHeadItem, cCurrWord, cWord51
LOCAL cHead1,cHead2,cHead3,cHead4,cHead5,cHead6,lInputMask, nFootCount
LOCAL mAdd1, mAdd2, mAdd3, ltmpStr, nly_Points
nVTotal = 0.000
nCTotal = 0.000
nPW = 0
nLinesPerPage = _PLENGTH
nHeaderSkip = 12
nHeaderLines = nHeaderSkip + 11 && No of Lines to skip before printing....(Pre-Printed Header)
nFooterLines = 25
nDataLines = nLinesPerPage - (nFooterLines + nHeaderLines) && 22
nLines = 0
nPages = 1
nFootCount = 0
mAdd1 = ""
mAdd2 = ""
mAdd3 = ""
ltmpStr= space(11)
SELECT ("DEBMAS")
SET ORDER TO TAG ACNO
IF SEEK(TRIM(oGltr.CustAc))
IF TYPE("CHGINVHDR")="L" THEN
IF CHGINVHDR THEN
mRepHead = "DELIVERY NOTE"
ENDIF
ENDIF
mAdd1 = Trim(Address1)
mAdd2 = Trim(City)
mAdd3 = Trim(State)
Else
mAdd1 = mAddress
mAdd2 = mTelephone
endif
If !empty(mDelAd1)
mAdd2 = mDelAd1
mAdd3 = mdelAd2
ltmpStr= "DELIVER "
Endif
cHead1 = PADR("Code : " + oGltr.CustAc, 50) + "Ref.No : " + oGltr.RefNo
cHead2 = PADR("Name : " + mCustName, 50) + "DATE : " + DTOC(oGltr.Date)
cHead3 = PADR("Address : " + mAdd1, 50) + "D.N # : " + mdocno
cHead4 = PADR(lTmpStr + mAdd2, 50) + "L.P.O # : " + mLpoNo
cHead5 = PADR(" " + mAdd3, 50) + "DATE : " + DTOC(mLpoDt)
cHead6 = IIF( !Empty(mJobNo), PADR("JOB # : " + mJobNo,50), padr(" ", 50)) + "S.NO : " + mSno
*!* 1 2 3 4 5 6 7 8 9
*!* 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234
*!* Item Code | Description | Qty.| Price | Disc. | Total"
*!* xxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxxxxxx|9999.99|99999.999|9999.999|99999.999
cHeadItem = "Item Code | Description | Qty.| Rate | Disc. | Total"
nPW = 80 &&LEN(cHeadItem)
SET headings off
_SCREEN.Show
WAIT window "Printing..." NOWAIT
SET alter to &mUserPath\oInv.txt
SET alter on
SET console off
*---- Print Header
FOR i = 1 to nHeaderSkip &&nHeaderLines
?
NEXT
*----
? SPACE(40-(LEN(mRepHead)*1.5/2)) + CHR(14) + mRepHead + CHR(20)
?
? cHead1
? cHead2
? cHead3
? cHead4
? cHead5
? cHead6
? Repl("-", nPW)
? cHeadItem
? Repl("-", nPW)
*------------------End of Header
SELECT("BENTRY")
SCAN FOR !DELETED()
nLines = nLines + 1
IF (nLines > nDataLines)
nLines = 0
nFootCount = 0
nPages = nPages + 1
?
?
?
? space(65) + "Continued..."
?
nFootCount = 5
*FOR i = 1 to 5 && Skip till the Header
FOR i = nFootCount+1 to nFooterLines
?
NEXT
*------------------Print Header
FOR i = 1 to nHeaderSkip &&nHeaderLines
?
NEXT
? SPACE(40-(LEN(mRepHead)*1.5/2)) + CHR(14) + mRepHead + CHR(20)
?
? cHead1
? cHead2
? cHead3
? cHead4
? cHead5
? cHead6
? Repl("-", nPW)
? cHeadItem
? Repl("-", nPW)
*------------------End of Header
ENDIF
? PADR(MODEL,15)+[ ]+PADR(DESC,27)+[ ]+ STR(QTY,7,2) + [ ] + ;
STR(Amount,9,3) + [ ]+ STR(DISCOUNT,8,3) + [ ] + STR(VALUE,9,3)
*nVTotal = nVTotal + VALUE
ENDSCAN
If (nLines > 0) && Skip until the footer
For i = nLines TO (nDataLines - 1)
?
Next
Endif
nFootCount = 0
? Repl("_", nPW)
IF oGltr.Discount <> 0
? PADR("Gross Amount : " + LTRIM(str(oGltr.SalesAmt + oGltr.Discount,12,3)), 30) + ;
PADR("Discount : " + LTRIM(str(oGltr.Discount,12,3)), 25) + "Net Amount : " + str(oGltr.SalesAmt , 12,3)
ELSE
? PADL("Total : " + str(oGltr.SalesAmt , 12,3),80)
ENDIF
? Repl("-", nPW)
cWord = ToDinars(oGltr.SalesAmt)
? "Total : " + cWord
? Repl("_", nPW)
?
?
? PADR("Received By: " + mRepHead1 ,40) + PADL("For " + mLocName,40)
IF TYPE("oLocation.LY_ENABLE")="L" Then
IF oLocation.LY_ENABLE Then
IF ( oGltr.SalesAmt >= oLocation.LY_Value ) Then
nLy_Points = INT(ROUNDTO(oGltr.SalesAmt,oLocation.LY_Value)/oLocation.LY_Value) * oLocation.LY_POINTS
IF !EMPTY(oGltr.Rpt_LoyaltyCard) Then
? [Your ]+ALLTRIM(oLocation.LY_NAME)+ ;
[ Card No.]+ ALLTRIM(oGltr.Rpt_LoyaltyCard) +;
[,]+ALLTRIM(oLocation.LY_PREFIX)+ [ Earned:]+ALLTRIM(STR(nLy_Points,10,0))+[.]
ELSE
? [You could've earned ]+ALLTRIM(STR(nLy_Points,10,0))+[ ]+ ALLTRIM(oLocation.LY_PREFIX)+;
[. Apply now and start collecting.]
ENDIF
ENDIF
ELSE
?
ENDIF
ELSE
?
ENDIF
? padr(mFootNote1,75) + "E&O.E"
nFootCount = 10
*----- Skip till the next page
FOR i = nFootCount+1 to nFooterLines && Skip till the next page
?
NEXT
SET alter to
SET alter off
SET Console On
_SCREEN.cls
SET headings on
RETURN .T.
FUNCTION DM_Print
LPARAMETERS cFile
LOCAL lPrt
lPrt = RTRIM(oDefault.PrtPort)
lPrt = IIF(EMPTY(lPrt),"LPT1",lPrt)
IF TYPE("oAPIRUN") <> "O"
PUBLIC oAPIRUN
oAPIRUN = NEWOBJECT("api_apprun","process.vcx")
ENDIF
oAPIRUN.icCommandLine = "&mUserFilePath\VCHPRINT.BAT "+cFile +[ ]+ lPrt
oAPIRUN.icWindowMode = "HID"
IF !oAPIRUN.LaunchAppAndWait() && Didnt execute properly
RUN &mUserFilePath\VCHPRINT.BAT &cFile &lPrt && Run original batch file in Normal Mode
ENDIF
ENDFUNC