Hi all!
I began working on this problem around December 2000 and I searched all around for examples, but couldn't find any. Here's what I did. If you use it, please let me know and also keep comments as they are.
The function listed below is part of a membership database system I programmed for my church. It allows church staff to create mail merged letters and mailing labels from the database and create a PDF file, which can be printed predictably from any browser.
Hope this helps.
God bless!
Truman
P.S. I want to be able to program a function where users can select from a list of Avery preset labels and also choose which label on the page to start printing from (like if the page of labels was already partially used). But the following function just assumes you're using a new sheet of labels. If anyone does program that function, please let me know. I'd like to apply it to my application.
<?php
/*
The Ascribe Community Portal System
June 28, 2001
by Truman Leung <tru@hawaiitown.net>
Honolulu, Hawaii, USA
"Ascribe greatness to our God, the Rock.
His works are perfect and all His ways are just."
... praise Jesus Christ!
baptism/letters.n.labels.php
*/
include_once("include/consolidate.by.location.php");
function CreateLettersLabels($sessionId, $letterMarginTopInInches='1.9', $letterMarginLeftInInches='1', $letterMarginRightInInches='1.4', $letterMarginBottomInInches='.75', $letterFontFace='Times-Roman', $letterFontFaceItalic='Times-Italic', $letterFontSize='11.5', $labelHeighInInches='1.00', $labelWidthInInches='2.63', $numLabelsAcross='3', $numLabelsDown='10', $labelMargin='16', $fontSize='10.5', $fontFace='Helvetica') {
$pageHeightInInches = 11;
$pageWidthInInches = 8.5;
$pdffilename = "baptism.letters.n.labels.$sessionId.pdf";
$pixelsPerInch = 72;
$paragraphIndent = $pixelsPerInch/2;
// PROCESS GENERATE LETTERS
$db = new NHdb_DB_Sql;
$db2 = new NHdb_DB_Sql;
// GET LETTER TEXT
$db->query("select quote1, quote2, body from letter where id='13'");
$db->next_record();
$quote1_original = $db->f("quote1");
$quote2_original = $db->f("quote2");
$body_original = $db->f("body");
// TODAY'S DATE
$todayMonth = date("F");
$todayDay = ereg_replace("^0", "", date("d"));
$todayYear = date("Y");
$today = $todayMonth." ".$todayDay.", ".$todayYear;
// GET RECIPIENTS
$db->query("select masterdemographics.MemberID, LName, FName, MI FROM masterdemographics, baptismregistration WHERE EGR <> 'Yes' and nomail <> 'Yes' AND baptismregistration.MemberID=masterdemographics.MemberID AND sessionId='$sessionId' order by LName");
## run all records into an array
$numMembers = $db->nf();
$fieldNames = "MemberID, LName, FName, MI";
$fieldName = explode(", ", $fieldNames);
$memberCounter=0;
$z = 12378910458723;
// get members names
while ($db->next_record()) {
reset($fieldName);
while(list($key,$val)=each($fieldName)) {
$member[$memberCounter][$val] = $db->f($val);
}
$memberCounter++;
}
// get addresses
reset($member);
while(list($memberCounter,$val)=each($member)) {
$db->query("select address, address2, city, state, zip, locationId from location, memberlocationmap where MemberId='" . $val["MemberID"] . "' and locationId=location.id and type2='mailing'");
if ($db->nf() == 0)
$db->query("select address, address2, city, state, zip, locationId from location, memberlocationmap where MemberId='" . $val["MemberID"] . "' and locationId=location.id and type2='street'");
if ($db->nf() > 0) {
$db->next_record();
$member[$memberCounter]["address"] = $db->f("address");
$member[$memberCounter]["address2"] = $db->f("address2");
$member[$memberCounter]["city"] = $db->f("city");
$member[$memberCounter]["state"] = $db->f("state");
$member[$memberCounter]["zip"] = $db->f("zip");
$member[$memberCounter]["locationId"] = $db->f("locationId");
} else {
$member[$memberCounter]["address"] = "No address on record";
$member[$memberCounter]["locationId"] = $z;
$z++;
}
}
$location = ConsolidateByLocation($member);
$numLetters = count($location);
## GENERATE LABELS LINE BY LINE
## that is, run label information into an two-dimensional array called $letterAddress
$labelCounter = 0;
reset($location);
while(list($pageNumber,$row_location)=each($location)) {
$lineCounter = 0;
$n=0;
while(list($key2,$thisnameline)=each($row_location["nameLines"])) {
$label[$labelCounter][$lineCounter] = $thisnameline;
// if the nameline is greater than 29 characters long, split into two lines
if (strlen($label[$labelCounter][$lineCounter]) > 29) {
$parts = explode(" ", $label[$labelCounter][$lineCounter]);
$namelineCounter = 0;
while (list ($key, $val) = each ($parts)) {
$nameline[$namelineCounter] .= $val." ";
if (strlen($nameline[$namelineCounter])>29) {
$label[$labelCounter][$lineCounter] = trim($nameline[$namelineCounter]);
$lineCounter++;
$namelineCounter++;
$nameline[$namelineCounter] = " ";
}
}
} else {
$lineCounter++;
}
if ($namelineCounter > 0 && trim($nameline[$namelineCounter])<>"") {
$label[$labelCounter][$lineCounter] = trim($nameline[$namelineCounter]);
$lineCounter++;
}
if ($nameline) unset($nameline);
// if there are too many names, advance to the next label
if ($n==2 or $n==6 or $n==10) {
$labelCounter++;
$lineCounter = 0;
}
$n++;
}
if ($row_location["address2"]) {
$label[$labelCounter][$lineCounter] .= $row_location["address2"];
$lineCounter++;
}
if ($row_location["address"]) {
$label[$labelCounter][$lineCounter] .= $row_location["address"];
$lineCounter++;
}
if ($row_location["city"]) $label[$labelCounter][$lineCounter] .= $row_location["city"]." ";
if ($row_location["state"]) $label[$labelCounter][$lineCounter] .= $row_location["state"]." ";
if ($row_location["zip"]) $label[$labelCounter][$lineCounter] .= $row_location["zip"];
$labelCounter++;
}
// CALCULATION OF LABEL SETTINGS
$pageHeight = $pageHeightInInches * $pixelsPerInch;
$pageWidth = $pageWidthInInches * $pixelsPerInch;
$labelHeight = $labelHeighInInches * $pixelsPerInch;
$labelWidth = $labelWidthInInches * $pixelsPerInch;
$numLabels = count($label);
$numLabelsOnLastPage = $numLabels % ($numLabelsAcross*$numLabelsDown);
$leftRightMargin = ($pageWidth - ($numLabelsAcross * $labelWidth)) / 2;
$topBottomMargin = ($pageHeight - ($numLabelsDown * $labelHeight)) / 2;
$lineHeight = $fontSize + 2;
$startX = $leftRightMargin + $labelMargin;
$startY = $pageHeight - $topBottomMargin - $labelMargin - $lineHeight;
$printWidth = $labelWidth-$labelMargin*2;
if ( ($numLabelsAcross*$numLabelsDown) > $numLabels) {
$numPages = 1;
} elseif ($numLabelsOnLastPage == 0) {
$numPages = ($numLabels-$numLabelsOnLastPage)/($numLabelsAcross*$numLabelsDown);
} else {
$numPages = ($numLabels-$numLabelsOnLastPage)/($numLabelsAcross*$numLabelsDown)+1;
}
// CALCULATIONS OF LETTER SETTINGS
$letterMarginTop = $letterMarginTopInInches * $pixelsPerInch;
$letterMarginLeft = $letterMarginLeftInInches * $pixelsPerInch;
$letterMarginRight = $letterMarginRightInInches * $pixelsPerInch;
$letterMarginBottom = $letterMarginBottomInInches * $pixelsPerInch;
$startLetterX = $letterMarginLeft;
$startLetterY = $pageHeight - $letterMarginTop - $letterLineHeight;
$letterLineHeight = $letterFontSize + 2.5;
$letterWidth = $pageWidth - $letterMarginLeft - $letterMarginRight;
$letterMiddleX = $startLetterX + ($letterWidth / 2);
// OPEN THE FILE
$fp = fopen($pdffilename, "w");
// OPEN THE PDF STREAM
$pdf = pdf_open($fp);
pdf_set_info($pdf, "Author", "New Hope Membership Application");
pdf_set_info($pdf, "Title", "Letters re Bulletin Tabs and Mailing Labels for Avery 5960 White Laser Labels");
pdf_set_info($pdf, "Creator", "Truman Leung");
// pdf_set_info($pdf, "Subject", "Mailing Labels");
// RUN THE LETTERS INTO THE PDF FILE
// CYCLE THROUGH PAGES
reset($location);
while(list($pageNumber,$row_location)=each($location)) {
// START NEW PAGE
pdf_begin_page($pdf, $pageWidth, $pageHeight);
pdf_add_outline($pdf, "Letter to ". $row_location["nameLines"][0]);
pdf_set_value($pdf, "textrendering", 0);
// DETERMINE THE START HEIGHT BASED ON LETTER LENGTH
$x = $startLetterX;
$y = $startLetterY;
$total_length = strlen($body_original) + strlen($quote1_original) + strlen($quote2_original);
if ($total_length < 1400) {
$y -= $letterLineHeight * (10-($total_length/100));
$letterFontSize='12';
$letterLineHeight = 14.5;
} else {
$letterFontSize='10.8';
$letterLineHeight = 13;
}
pdf_set_font($pdf, $letterFontFace, $letterFontSize , "host");
$widthOfToday = pdf_stringwidth($pdf, $today);
pdf_show_xy($pdf, $today, $x, $y);
// RESET X TO LEFT MARGIN AND INCREMENT DOWN TWO LINES
$x = $startLetterX;
$y -= $letterLineHeight * 2;
// PRINT ADDRESSEE INFO
while(list($key2,$nameline)=each($row_location["nameLines"])) {
pdf_show_xy($pdf, $nameline, $x, $y);
$y -= $letterLineHeight;
}
// PRINT OUT THE ADDRESS
if ($tab[$i]["address2"]) {
pdf_show_xy($pdf, $row_location["address2"], $x, $y);
$y -= $letterLineHeight;
}
if ($row_location["address"]) {
pdf_show_xy($pdf, $row_location["address"], $x, $y);
$y -= $letterLineHeight;
}
if ($row_location["city"]) {
pdf_show_xy($pdf, $row_location["city"]." ", $x, $y);
$x += pdf_stringwidth($pdf, $row_location["city"]." ");
}
if ($row_location["state"]) {
pdf_show_xy($pdf, $row_location["state"]." ", $x, $y);
$x += pdf_stringwidth($pdf, $row_location["state"]." ");
}
if ($row_location["zip"]){
pdf_show_xy($pdf, $row_location["zip"], $x, $y);
$x += pdf_stringwidth($pdf, $row_location["zip"]);
}
// RESET X TO LEFT MARGIN AND INCREMENT DOWN TWO LINES
$x = $startLetterX;
$y -= $letterLineHeight * 2;
// PRINT THE SALUTATION LINE
$salutation = "Dear " . $row_location["salutation"] . ",";
pdf_show_xy($pdf, $salutation, $x, $y);
// INCREMENT DOWN TWO LINES
$y -= $letterLineHeight * 2;
// PRINT QUOTE #1
pdf_set_font($pdf, $letterFontFaceItalic, $letterFontSize , "host");
// divide up the quote equally among the number of lines
$quote1 = $quote1_original;
$lengthWhole = pdf_stringwidth($pdf, $quote1);
$numLines = $lengthWhole / $letterWidth;
$numLines = explode(".", $numLines);
$numLines = $numLines[0] + 1;
// make a little bigger than exact, else last word won't print
$lineWidth = ($lengthWhole/$numLines) + 10;
$quote1 = explode(" ", $quote1);
$numQuote1Words = count($quote1);
$w=-1;
if ($numQuote1Words > 1) {
for ($z=0;$z<$numQuote1Words;$z++) {
$lineThisWord .= $quote1[$z]." ";
$linePrevWord .= $quote1[$w]." ";
$w++;
// IF "THIS" IS TOO LONG, THEN PRINT "PREV"
if (pdf_stringwidth($pdf, $lineThisWord) > $lineWidth) {
// FIND THE X FOR THE CENTERED QUOTE LINE (MINUS PREV WORD)
$x = $letterMiddleX - ((pdf_stringwidth($pdf, $linePrevWord)) / 2);
pdf_show_xy($pdf, $linePrevWord, $x, $y);
$y -= $letterLineHeight;
unset($linePrevWord);
$lineThisWord = $quote1[$z]." ";
}
// IF WE ARE ON THE LAST WORD, THEN PRINT "THIS"
if ($z == ($numQuote1Words-1)) {
$x = $letterMiddleX - ((pdf_stringwidth($pdf, $lineThisWord)) / 2);
pdf_show_xy($pdf, $lineThisWord, $x, $y);
$y -= $letterLineHeight;
unset($linePrevWord);
unset($lineThisWord);
}
}
// RESET X TO LEFT MARGIN AND INCREMENT
$x = $startLetterX;
$y -= $letterLineHeight;
}
// PRINT BODY OF LETTER
pdf_set_font($pdf, $letterFontFace, $letterFontSize , "host");
// RUN LETTER INTO PARAGRAPH ARRAY
$paragraph = explode("<br>", $body_original);
$numParagraphs = count($paragraph);
// LOOP THROUGH PARAGRAPH ARRAY
for ($p=0;$p<$numParagraphs;$p++) {
$paragraphText = explode(" ", $paragraph[$p]);
$numWords = count($paragraphText);
$w=-1;
$lineCounter=1;
if ($numWords > 0) {
for ($z=0;$z<$numWords;$z++) {
if (ereg("^<", $paragraphText[$z]) and ereg(">$", $paragraphText[$z])) {
$command = ereg_replace("^<", "", $paragraphText[$z]);
$command = ereg_replace(">$", "", $command);
} else {
$lineThisWord .= $paragraphText[$z]." ";
}
$linePrevWord .= $paragraphText[$w]." ";
$w++;
// IF "THIS" IS TOO LONG, THEN PRINT "PREV"
if (pdf_stringwidth($pdf, $lineThisWord) > $letterWidth) {
if ($lineCounter == 1 && $numWords > 8) $x += $paragraphIndent;
pdf_show_xy($pdf, trim($linePrevWord), $x, $y);
$y -= $letterLineHeight;
unset($linePrevWord);
$lineCounter++;
$x = $startLetterX;
$lineThisWord = $paragraphText[$z]." ";
}
// IF WE ARE ON THE LAST WORD, THEN PRINT "THIS"
if ($z == ($numWords-1)) {
if ($lineCounter == 1 && $numWords > 8) $x += $paragraphIndent;
pdf_show_xy($pdf, trim($lineThisWord), $x, $y);
$y -= $letterLineHeight;
unset($linePrevWord);
unset($lineThisWord);
$lineCounter++;
$x = $startLetterX;
}
}
// if the array element is empty then increment half-line
} else {
$y -= 5;
}
} // END LOOP THROUGH PARGRAPHS
// PRINT QUOTE #2
pdf_set_font($pdf, $letterFontFaceItalic, $letterFontSize, "host");
// divide up the quote equally among the number of lines
$quote2 = $quote2_original;
if ($paragraph && $quote2) {
// INCREMENT
$y -= $letterLineHeight;
}
$lengthWhole = pdf_stringwidth($pdf, $quote2);
$numLines = $lengthWhole / $letterWidth;
$numLines = explode(".", $numLines);
$numLines = $numLines[0] + 1;
// make a little bigger than exact, else last word won't print
$lineWidth = ($lengthWhole/$numLines) + 15;
$quote2 = explode(" ", $quote2);
$numQuote2Words = count($quote2);
$w=-1;
if ($numQuote2Words > 1) {
for ($z=0;$z<$numQuote2Words;$z++) {
$lineThisWord .= $quote2[$z]." ";
$linePrevWord .= $quote2[$w]." ";
$w++;
// IF "THIS" IS TOO LONG, THEN PRINT "PREV"
if (pdf_stringwidth($pdf, $lineThisWord) > $lineWidth) {
// FIND THE X FOR THE CENTERED QUOTE LINE (MINUS PREV WORD)
$x = $letterMiddleX - ((pdf_stringwidth($pdf, $linePrevWord)) / 2);
pdf_show_xy($pdf, $linePrevWord, $x, $y);
$y -= $letterLineHeight;
unset($linePrevWord);
$lineThisWord = $quote2[$z]." ";
}
// IF WE ARE ON THE LAST WORD, THEN PRINT "THIS"
if ($z == ($numQuote2Words-1)) {
$x = $letterMiddleX - ((pdf_stringwidth($pdf, $lineThisWord)) / 2);
pdf_show_xy($pdf, $lineThisWord, $x, $y);
$y -= $letterLineHeight;
unset($linePrevWord);
unset($lineThisWord);
}
}
}
pdf_end_page($pdf);
}
// RUN THE MAILING LABELS INTO THE PDF FILE
$labelCounter=0;
// CYCLE THROUGH PAGES
for ($i=0; $i<$numPages; $i++) {
pdf_begin_page($pdf, $pageWidth, $pageHeight);
pdf_add_outline($pdf, "Labels - pg ".($i+1));
pdf_set_value($pdf, "textrendering", 0);
// if it's the last page
if ($i==($numPages-1)) $lastPageLabelCounter = 0;
// CYCLE THROUGH ROWS
for ($j=0; $j<$numLabelsDown; $j++) {
$y = $startY - ($labelHeight*$j);
// CYCLE THROUGH COLUMNS WITHIN A ROW
for ($k=0; $k<$numLabelsAcross; $k++) {
if ($i==($numPages-1)) $lastPageLabelCounter++;
$x = $startX + ($labelWidth*$k);
if ($k==2) $x += 12;
// Check whether the line fits within the width of the label
pdf_set_font($pdf, $fontFace, $fontSize , "host");
$tempFontSize = $fontSize;
$numLines = count($label[$labelCounter]);
for ($l=0;$l<$numLines;$l++) {
if (pdf_stringwidth($pdf, $label[$labelCounter][$l]) > $printWidth) {
// if too wide, reduce the font size
$tempFontSize -= 2;
}
}
pdf_set_font($pdf, $fontFace, $tempFontSize , "host");
// WRITE LABEL LINES
for ($l=0;$l<$numLines;$l++) {
if ($label[$labelCounter][$l]) {
pdf_show_xy($pdf, $label[$labelCounter][$l], $x, ($y - $lineHeight*$l));
}
}
$labelCounter++;
unset($tempFontSize);
// IF ITS THE LAST LABEL, FINISH PAGE
if ($lastPageLabelCounter && $lastPageLabelCounter == $numLabelsOnLastPage) {
break;
}
}
if ($lastPageLabelCounter && $lastPageLabelCounter == $numLabelsOnLastPage) {
break;
}
}
pdf_end_page($pdf);
}
pdf_close($pdf);
fclose($fp);
return $pdffilename;
}
?>