title: How can I use TCPDF to make 2x6 sheets of labels that include 2D barcodes WITHOUT using columns OR 3rd-party classes?
body: <p>For three weeks (I guess I'm that slows!) I've tried to use TCPDF's own examples as well as some suggestions found on this site to figure out how to do this using database records. Mr. Asuni has responded to some requests for help when others ask how to use 3rd party patches (classes) to get things going, only that it CAN be done in TCPDF without such classes. For whatever reason (perhaps my own misunderstanding) I have not been able to use TCPDF to print labels using his columns approach.</p>
  
  <p>Neither have I been willing to ditch TCPDF in favor of other possible solutions (reasons I won't go into). <a href="https://stackoverflow.com/questions/15458221/php-tcpdf-export-for-standard-address-labels">PHP TCPDF Export for Standard Address Labels</a> is an example of a question asked/solved here when the needed functionality was gained by switching to fpdf17.</p>
  
  <p>So I stayed stuck until today, even trying some wonderful code written in French, but I couldn't convince it to create the structure I need.</p>
  
  <p>Because questions like the one I cited above have been "hit" on so many times (on this site and elsewhere) without seeming resolution I decided to read all I could, work code until I was bleary-eyed, and test, retest and test some more.</p>
  
  <p>I finally found a way to make a PDF from a database that would make PDFs containing pages of 6 labels (2 across, three down), in the AVERY 5164 format. And I've been able to do it without using the columns approach of TCPDF OR any 3rd-party patches or classes.</p>
  
  <p>Just about anyone should be able to alter my solution for their own needs if they pay close attention to the meanings of the variables in my code.</p>
  
  <p>I'm POSITIVE there must be a more elegant (and correct!) way to get the results I did, so I'm VERY open to suggestions about how my code could be improved.</p>
  
  <p>And, before I get burned, yes, I KNOW that the database call needs to be PDO. I am stuck with what my client gives me access to.</p>
  
  <p>Last, just to give an idea of how long it took to produce various PDFs of varying numbers of records:
  12 records (2 pages) --> 4 seconds to download activation
  200 records --> 44 seconds
  file sizes were reasonable (I failed to write any down, though.... sorry!)</p>
  
  <h2>Here's my solution [NOTE: My db connection file is an include not given below for obvious reasons]:</h2>
  
  <pre><code>// value from url calling this page - this client wants results by year every time
  $colname_year = "-1";
  if (isset($_GET['year'])) {
    $colname_year = $_GET['year'];
  }
  //I DO include Mr. Asuni's credits in my file, but it's left out here for brevity's sake.
  //----------------
  require_once('../../tcpdf/tcpdf.php');
  // create new PDF document
  $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
  // set document information
  $pdf-&gt;SetCreator(PDF_CREATOR);
  $pdf-&gt;SetAuthor('whoever you are');
  $pdf-&gt;SetTitle('what you want to call it');
  $pdf-&gt;SetSubject('your subject');
  $pdf-&gt;SetKeywords('TCPDF, PDF, HHMWC, QR, CODE');
  // set default monospaced font
  $pdf-&gt;SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
  // set margins
  $pdf-&gt;SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
  // set auto page breaks
  $pdf-&gt;SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
  // set image scale factor
  $pdf-&gt;setImageScale(PDF_IMAGE_SCALE_RATIO);
  // set some language-dependent strings
  require_once('../../tcpdf/results/lang/eng.php');
  $pdf-&gt;setLanguageArray($l);
  // --------------
  // add a page
  $pdf-&gt;AddPage();
  // set the font
  $pdf-&gt;SetFont('helvetica', '', 10);
  // set style for barcode
  $style = array(
      'border' =&gt; 2,
      'vpadding' =&gt; 'auto',
      'hpadding' =&gt; 'auto',
      'fgcolor' =&gt; array(0,0,0),
      'bgcolor' =&gt; false, //array(255,255,255)
      'module_width' =&gt; 1, // width of a single module in points
      'module_height' =&gt; 1 // height of a single module in points
  );
  // connect to database
  require_once('../../../Connections/con1.php');
  mysql_select_db($database_con1, $con1); // Get needed records from database
  $query_info = sprintf("select regkey, name1, name2, company, city, state, volunteer, meal, choice, golf from convregis where (name1&lt;&gt;'Anonymous Donation' and print='0' and completed='Yes' and hold='0' and year=%s) order by name2, name1 ASC", GetSQLValueString($colname_year, "text"));
  $info = mysql_query($query_info, $con1) or die(mysql_error());
  $num_fields = mysql_num_fields($info);
  $j=0; // the field number
  $x=1; // the record number
  while($row = mysql_fetch_array($info)) { 
    for($j=0; $j&lt;$num_fields; $j++) {
       $name = mysql_field_name($info, $j);
       $object[$x][$name] = $row[$name];
    }
    $x++; // get next record set
  }
  //set variables for placement of QR CODE and text lines
  $size=40; // mm size of QRCODE / H = QR-CODE Best error correction
  $qrlm=40; // left margin of code on left
  $qrlm2=140; // left margin of code on right
  $qrvm=40; // vertical placement (how far down the page) of BOTH codes on first row
  $l=20; // left margin of text, left side
  $l2=120; // left margin of text, right side
  $y=15; // vertical placement (how far down the page) of BOTH texts on first row
  // There will be two records per row - there will be three rows
  $ii = count($object); // total number of record rows to do
  for($i=1; $i&lt;=$ii; $i++) {    //$object[$i]['field_name'] / this sets $i = $x above
      if ($i&lt;=$ii) {
          $codeurl = "https:clientwebsiteaddress/attend.php?regkey=".$object[$i]['regkey'];
          ///write the QR CODE
          $pdf-&gt;write2DBarcode($codeurl, 'QRCODE,H', $qrlm, $qrvm, $size, $size, $style, 'N');
          // the QR CODE, when scanned by a smartphone at the convention's
          //registration packet pickup table, triggers an update to the
          //database in the attend.php page, setting a registrant to "in attendance" 
          $regkey=$object[$i]['regkey']; //assign row data to a variable and manipulate as needed
          $fullname=strtoupper($object[$i]['name2']).", ".strtoupper($object[$i]['name1']);
          $vol=$object[$i]['volunteer'];
          $company=strtoupper($object[$i]['company']);
          $city=$object[$i]['city'];
          $state=$object[$i]['state'];
           $meal=$object[$i]['meal'];
           $golf=$object[$i]['golf'];
           if ($golf&lt;&gt;"1") {
               $golf=" ";
               } else {
               $golf="GOLF";
           }
           if ($meal&lt;&gt;"1") {
               $meal=" ";
              } else {
              $meal="MEAL: ".strtoupper($object[$i]['choice']);
          }
          if ($meal&lt;&gt;" ") {
              $mealgolf=$meal."        /       ".$golf;
              } else {
              $mealgolf=$golf;
          }
          //write the lines of text
          $pdf-&gt;Text($l, $y, $fullname.'               '.$vol);
          $pdf-&gt;Text($l, $y+5, $regkey.'               '.$city.', '.$state);
          $pdf-&gt;Text($l, $y+10, $company);
          $pdf-&gt;Text($l, $y+15, $mealgolf);
          $i++; // get next record
          if ($i&lt;=$ii) {
              $codeurl2 = "https:clientwebsiteaddress/attend.php?regkey=".$object[$i]['regkey'];
              $pdf-&gt;write2DBarcode($codeurl2, 'QRCODE,H', $qrlm2, $qrvm, $size, $size, $style, 'N');
              $regkey2=$object[$i]['regkey'];
              $fullname2=strtoupper($object[$i]['name2']).", ".strtoupper($object[$i]['name1']);
              $vol2=$object[$i]['volunteer'];
              $company2=strtoupper($object[$i]['company']);
              $city2=$object[$i]['city'];
               $state2=$object[$i]['state'];
              $meal2=$object[$i]['meal'];
              $golf2=$object[$i]['golf'];
              if ($golf2&lt;&gt;"1") {
                      $golf2=" ";
                      } else {
                      $golf2="GOLF";
              }
              if ($meal2&lt;&gt;"1") {
                  $meal2=" ";
                  } else {
                  $meal2="MEAL: ".strtoupper($object[$i]['choice']);
              }
              if ($meal2&lt;&gt;" ") {
                  $mealgolf2=$meal2."        /       ".$golf2;
                  } else {
                  $mealgolf2=$golf2;
              }
              $pdf-&gt;Text($l2, $y, $fullname2.'               '.$vol2);
              $pdf-&gt;Text($l2, $y+5, $regkey2.'               '.$city2.', '.$state2);
              $pdf-&gt;Text($l2, $y+10, $company2);
              $pdf-&gt;Text($l2, $y+15, $mealgolf2);
              $qrvm=$qrvm+85; $y=$y+85; // add 85 mm drop to vertical alignment of qrcodes
              if($i&lt;=$ii and $qrvm&gt;210) {  //no more room on this page but more records to do
                  $qrvm=40; // reset qrcode vertical alignment
                  $y=15; // reset where texts write
                  $pdf-&gt;AddPage();
              }
          }
      }
  } // end of PDF (no more records to do)
  $pdf-&gt;Output($year.'EnvelopeLabels.pdf', 'I'); //Close and output PDF document
  ?&gt;
  </code></pre>
  
  <p>I hope I didn't break anything by altering the code a little to remove sensitive info.
  Thanks for a great site- I've learned a lot and hope to have helped someone in return now!</p>