1. What is WooCommerce?

WooCommerce is a powerful, open-source e-commerce plugin designed for WordPress. It transforms a WordPress website into a fully functional online store, allowing users to sell products, manage inventory, and process payments. WooCommerce is known for its flexibility, extensive customization options, and ease of integration with existing WordPress themes and plugins.

2. Why is WooCommerce So Popular?

WooCommerce has become the go-to e-commerce solution for millions of businesses worldwide due to its user-friendly nature and extensive feature set. Some key reasons for its popularity include:

  • Flexibility and Customization: WooCommerce is highly customizable with numerous extensions and themes.
  • Cost-Effective: As an open-source solution, it’s free to use, with affordable premium add-ons available.
  • Integration with WordPress: Seamlessly integrates with WordPress, making it ideal for businesses already using WordPress.
  • Active Community and Support: With a vast community and extensive documentation, troubleshooting and finding resources are easy.

3. Why Offer the Option to Download Products as PDF? Especially for B2B Business

For B2B businesses, providing a downloadable product catalog as a PDF offers several advantages:

  • Offline Access: Customers can view product catalogs without needing an internet connection.
  • Ease of Sharing: PDF catalogs can be easily shared with decision-makers or procurement teams.
  • Quick Reference: For businesses that regularly order, a PDF catalog offers a convenient reference tool.
  • Branding and Professionalism: A well-designed PDF catalog enhances the brand image and adds a touch of professionalism.

4. How to Implement Download Product Catalog as PDF Using Custom Coding with TCPDF

Step 1: Adding a Button to the Catalog Page

To start, you’ll need to add a button on the category page that users can click to download the catalog as a PDF. You can do this by editing your WooCommerce theme’s archive-product.php file and adding a custom button:

add_action('woocommerce_before_shop_loop', 'add_pdf_download_button');

function add_pdf_download_button() {
    echo '<button id="download-pdf-catalog" class="button">Download Product Catalog as PDF</button>';
}

Step 2: Handling the Button Click with AJAX

When the button is clicked, an AJAX request should be sent to the server to generate the PDF. You can achieve this using jQuery:

jQuery(document).ready(function($) {
    $('#download-pdf-catalog').click(function() {
      //get current category page id
      var category_id = <?php echo get_queried_object_id(); ?>;
      var category_name = '<?php echo get_queried_object()->name; ?>';
      //ajax call to update status
      jQuery.ajax({
        url: '<?php echo admin_url('admin-ajax.php'); ?>',
        type: 'POST',
        data: {
            action: 'ajax_download_catalog',
            category_id: category_id,
            category_name: category_name
        },
        success: function (response) {
            //alert(response);
            if(response!="PDF Download Failes"){
            //opne in new tab
            window.open(response, '_blank');
              //window.location.href = response;
              
            }
        }
      });


    });
});

Step 3: Create the PDF on the Server with TCPDF

In your functions.php file, add a function to handle the AJAX request and generate the PDF:

You need to download the TCPDF library for PHP and upload it to your server from here: https://tcpdf.org/

<?php
//ajax action for ajax_download_catalog
add_action('wp_ajax_ajax_download_catalog', 'ajax_download_catalog');
add_action('wp_ajax_nopriv_ajax_download_catalog', 'ajax_download_catalog');
function ajax_download_catalog() {
   $category_id= $_POST['category_id'];
   //get category name using category id
    $category = get_term_by('id', $category_id, 'product_cat');
    $category_name = $category->name;
   //woocommerce code to get all products under category id and add 12 products limit order by product name
    $args = array(
         'post_type' => 'product',
         'posts_per_page' => -1,
         'tax_query' => array(
              array(
                'taxonomy' => 'product_cat',
                'field'    => 'term_id',
                'terms'    => $category_id,
              ),
         ),
         'orderby' => 'title',
         'order' => 'ASC'
    );
     
    $query = new WP_Query($args);
    $products = $query->posts;
//include TCPDF library
require_once(get_template_directory().'/TCPDF-main/tcpdf.php');
// Extend the TCPDF class to create custom Header and Footer
class MYPDF extends TCPDF {
     //Page header
     private $headerTitle; // Property to store header text
    // Constructor to accept the header title
    public function __construct($headerTitle, $orientation = 'P', $unit = 'mm', $format = 'A4', $unicode = true, $encoding = 'UTF-8', $diskcache = false, $pdfa = false) {
        // Call parent constructor
        parent::__construct($orientation, $unit, $format, $unicode, $encoding, $diskcache, $pdfa);
        // Set the header title
        $this->headerTitle = $headerTitle;
    }
     public function Header() {
         // Logo
         if ($this->getPage() == 1) {
         $logo = 'https://www.yourwebsite.com/wp-content/uploads/2023/05/logo-3.png';
         // Set the logo position and size

       // Set the logo dimensions in pixels
       $logoWidthPx = 75; // Width in pixels
       $logoHeightPx = 65; // Height in pixels

       // Convert pixels to millimeters (assuming 96 DPI)
       $logoWidthMm = $logoWidthPx * 0.264583;
       $logoHeightMm = $logoHeightPx * 0.264583;

       $logoLeftMargin = 70 * 0.264583; // 70 pixels

       // Set font for the header title
       $this->SetFont('helvetica', 'B', 32);

       // Add a cell for the header title, centered
       $this->SetY(4); // Align the header text at the same vertical position
       $this->Cell(0, $logoHeightMm, 'ALDUZ TRADING', 0, 1, 'C');
       $this->SetFont('helvetica', 'N', 18);
       $this->Cell(0, $logoHeightMm, 'www.alduztrading.com (917)837-8989', 0, 1, 'C');
       //$this->Cell(0, $logoHeightMm, '(917)837-8989', 0, 1, 'C');

       // Draw a line below the header
       //$this->Line(10, $logoHeightMm + 8, $this->getPageWidth() - 10, $logoHeightMm + 8);
         }
     }
    //  public function Footer() {
    //       // Set the position for the line above the footer text
    //       $linePosition = -20; // Position for the line 35mm from the bottom
  
    //       // Draw a line above the footer text
    //       $this->Line(10, $this->getPageHeight() + $linePosition, $this->getPageWidth() - 10, $this->getPageHeight() + $linePosition);
  
    //       // Set position for footer text at 30 mm from bottom
    //       $this->SetY(-10);
  
    //       // Set font for footer
    //       $this->SetFont('helvetica', '', 10);
  
    //       // Footer content
    //       $footerContent = "yourwebsite, Address, NY 11378 US\n+1 phone, email@gmail.com";
  
    //       // Add footer content
    //       $this->MultiCell(0, 10, $footerContent, 0, 'C', 0, 1, '', '', true);
  
    //       // Set font for page number
    //       $this->SetFont('helvetica', 'I', 8);
  
    //       // Page number
    //       $this->Cell(0, 10, 'Page ' . $this->getAliasNumPage() . '/' . $this->getAliasNbPages(), 0, false, 'C', 0, '', 0, false, 'T', 'M');
    //   }
 
  
 }

// create new PDF document
$category_name = strtolower($category_name);
$category_name = ucwords($category_name);
// Define custom page size (e.g., width: 210mm, height: 297mm, which is A4)
$customPageSize = array(210, 310); // A4 size
$pdf = new MYPDF($category_name.' Catalog', PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
// set document information
$pdf->setCreator(PDF_CREATOR);
$pdf->setAuthor('Your company name');
$pdf->setTitle($category_name.' Catalog');
$pdf->setSubject('TCPDF Tutorial');
$pdf->setKeywords('TCPDF, PDF, example, test, guide');

// set default header data
//add custom logo
$PDF_HEADER_LOGO1 = 'https://www.yourwebsite.com/wp-content/uploads/2023/05/logo-3.png';
$PDF_HEADER_TITLE1 = $category_name.' Catalog';
$PDF_HEADER_STRING1 = 'YOUR COMPANY INC.';
$pdf->setHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, $PDF_HEADER_TITLE1, $PDF_HEADER_STRING1, array(0,64,255), array(0,64,128));
$pdf->setFooterData(array(0,64,0), array(0,64,128));
// set header and footer fonts
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
// set default monospaced font
$pdf->setDefaultMonospacedFont(PDF_FONT_MONOSPACED);
// set margins
$pdf->setMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->setHeaderMargin(PDF_MARGIN_HEADER);
$pdf->setFooterMargin(PDF_MARGIN_FOOTER);
// set auto page breaks
$pdf->setAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
// set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
// set some language-dependent strings (optional)
if (@file_exists(dirname(__FILE__).'/lang/eng.php')) {
	require_once(dirname(__FILE__).'/lang/eng.php');
	$pdf->setLanguageArray($l);
}

// ---------------------------------------------------------
// set default font subsetting mode
$pdf->setFontSubsetting(true);
// Set font
// dejavusans is a UTF-8 Unicode font, if you only need to
// print standard ASCII chars, you can use core fonts like
// helvetica or times to reduce file size.
$pdf->setFont('dejavusans', '', 14, '', true);
// Add a page
// This method has several options, check the source code documentation for more information.
//$pdf->AddPage();
$pdf->AddPage('L', 'A4');
//$pdf->Cell(0, 0, 'A4 LANDSCAPE', 1, 1, 'C');
// set text shadow effect
$pdf->setTextShadow(array('enabled'=>true, 'depth_w'=>0.2, 'depth_h'=>0.2, 'color'=>array(196,196,196), 'opacity'=>1, 'blend_mode'=>'Normal'));
// Set some content to print
// Define the total number of products
//$total_products = 27; // You can change this to your desired number
// Sample image URL
//$sample_image_url = 'https://via.placeholder.com/150'; // Placeholder image URL (150x150)
// Initialize the HTML string
$html = '<div class="container" style="max-width: 1420px; margin-left: auto; margin-right: auto;">';
// Loop through products
//for ($product_count = 0; $product_count < $total_products; $product_count++) {
    $product_count = 0;
    $total_products = count($products);
    foreach ($products as $product) {
    // Start a new table every 9 products
    if ($product_count % 9 == 0) {
        if ($product_count > 0) {
            // Close the previous table
            $html .= '</tbody></table></div><div style="height: 30px;"></div>';
            //add page pdf page break
        }
        // Open a new table
        $html .= '<div class="table-container" style="border-color: #fff;">
                  <table class="shop_table" cellspacing="0" style="width: 100%; border-collapse: collapse; border-color: #fff;">
                  <tbody style="border-color: #fff;">';
    }
    // Start a new row every 3 products
    if ($product_count % 3 == 0) {
        $html .= '<tr class="product-row" style="border: none; border-color: #fff;">';
    }
    $product_id = $product->ID;
        $product = wc_get_product($product_id);
        $product_name = $product->get_name();
        $product_price = $product->get_price();
        $product_image = wp_get_attachment_url($product->get_image_id());
        //if space in image name need to copy and create new image after replacing space with -
        $directoryPath = dirname($product_image);
        $directoryPath = str_replace('https://www.yourwebsite.com/', '', $directoryPath);
        $directoryPath = str_replace('http://www.yourwebsite.com/', '', $directoryPath);
        $directoryPath = $_SERVER['DOCUMENT_ROOT'].$directoryPath;
        $pathinfo = pathinfo($product_image);
        $filename = $pathinfo['filename'].'.'.$pathinfo['extension'];
        if (strpos($filename, ' ') !== false) {
            // Define the new filename by replacing spaces with underscores
            $newFilename = str_replace(' ', '-', $filename);
            // Full path to the new image
            $newFilePath = $directoryPath . '/' . $newFilename;
            $oldFilePath = $directoryPath . '/' . $filename;
            if (file_exists($oldFilePath)) {
                // Copy the original file to the new file
                if (copy($oldFilePath, $newFilePath)) {
                    //set read permission to new path
                    chmod($newFilePath, 0644);
                    // echo "Image '$filename' has been copied to '$newFilename'.<br>";
                    $product_image = $newFilePath;
                    $product_image = str_replace($_SERVER['DOCUMENT_ROOT'], 'https://www.yourwebsite.com/', $product_image);
                } else {
                    //echo "Failed to copy '$filename'.<br>";
                }
            } else {
                // echo "The original file '$filename' does not exist.<br>";
            }
        
        } 
         //end
        $product_link = get_permalink($product_id);
    // Add a product cell with an image
    $html .= '<td>
               <div style="padding: 20px;text-align:center;">
                                  <a class="woocommerce-thumbnail" href="'.$product_link.'" style="text-decoration:none;">
                                      <img src="'.$product_image.'" style="image height 150px;width : auto;" height="150px" style="text-decoration:none; align:center;">
                                  </a><br />
                                  <a style="text-decoration:none;color: #000; font-weight: 500;font-size: 12px;font-family: Montserrat, sans-serif;" class="product-title" href="'.$product_link.'">'.$product_name.'</a>
                                  <br />
                                  <span style="color: #000; font-size: 16px; font-weight: 600; font-family: Montserrat, sans-serif;" class="price">
                                      <span class="woocommerce-Price-amount amount"><bdi><span class="woocommerce-Price-currencySymbol">$</span>'.$product_price.'</bdi></span>
                                  </span>
                              </div>
              </td>';

    // Close the row every 3 products
    if (($product_count + 1) % 3 == 0) {
        $html .= '</tr>';
    }
    $product_count++;
}

// Complete the last row if it's not complete
if ($total_products % 3 != 0) {
    $html .= '</tr>';
}

// Close the last table
$html .= '</tbody></table></div>';

// Close the container
$html .= '</div>';

// Output the HTML
ini_set('max_execution_time', 300);
// Print text using writeHTMLCell()
//$pdf->writeHTMLCell(0, 0, '', '', $html, 0, 1, 0, true, '', true);
$pdf->writeHTML($html, true, false, true, false, '');
$upload_dir = wp_upload_dir();
// Define the path to save the PDF
$upload_path = $_SERVER['DOCUMENT_ROOT'].'/wp-content/uploads/'; // This is the directory path
//$upload_url = $upload_dir['url'];   // This is the directory URL
// Define a unique filename for the PDF
//remove space and specila characters from category name
$category_name = preg_replace('/[^A-Za-z0-9\-]/', '', $category_name);
$pdf_file_name = $category_name.'.pdf';
//$filename = 'sample-' . time() . '.pdf';

// Full path to save the file
$file_path = $upload_path . '/' . $pdf_file_name;
// Save the PDF to the file
$pdf->Output($file_path, 'F');
// ---------------------------------------------------------
echo 'https://www.yourwebsite.com/wp-content/uploads/'.$pdf_file_name;
// Close and output PDF document
// This method has several options, check the source code documentation for more information.
//$pdf->Output('example_001.pdf', 'I');
    die();
   
}

The above code will generate a PDF with an A4 size and a landscape layout, with an added header only on the first page. The product details are Name, price, image, and link to the corresponding product details page. You can edit the code and make the necessary changes. Below is the screenshot of how the PDF will look like.