1

I am using FPDF to generate order invoice to customer, so far everything is working fine, except of some of our item name are mixed with Chinese text, and the output is somehow becoming alien's wording, as attached screenshot:

chinese wording doesn't display correctly

Script to generate PDF invoice:

    <?php

require('fpdf.php');


//function hex2dec
//returns an associative array (keys: R,G,B) from a hex html code (e.g. #3FE5AA)
function hex2dec($couleur = "#000000"){
    $R = substr($couleur, 1, 2);
    $rouge = hexdec($R);
    $V = substr($couleur, 3, 2);
    $vert = hexdec($V);
    $B = substr($couleur, 5, 2);
    $bleu = hexdec($B);
    $tbl_couleur = array();
    $tbl_couleur['R']=$rouge;
    $tbl_couleur['G']=$vert;
    $tbl_couleur['B']=$bleu;
    return $tbl_couleur;
}

//conversion pixel -> millimeter in 72 dpi
function px2mm($px){
    return $px*25.4/72;
}

function txtentities($html){
    $trans = get_html_translation_table(HTML_ENTITIES);
    $trans = array_flip($trans);
    return strtr($html, $trans);
}


class PDF extends FPDF 
{
    //variables of html parser
    protected $B;
    protected $I;
    protected $U;
    protected $HREF;
    protected $fontList;
    protected $issetfont;
    protected $issetcolor;

    function __construct($orientation='P', $unit='mm', $format='A4')
    {
        //Call parent constructor
        parent::__construct($orientation,$unit,$format);

        //Initialization
        $this->B=0;
        $this->I=0;
        $this->U=0;
        $this->HREF='';

        $this->tableborder=0;
        $this->tdbegin=false;
        $this->tdwidth=0;
        $this->tdheight=0;
        $this->tdalign="L";
        $this->tdbgcolor=false;

        $this->oldx=0;
        $this->oldy=0;

        $this->fontlist=array("arial","times","courier","helvetica","symbol");
        $this->issetfont=false;
        $this->issetcolor=false;
    }

    //////////////////////////////////////
    //html parser

    function WriteHTML($html)
    {
        $html=strip_tags($html,"<b><u><i><a><img><p><br><strong><em><font><tr><blockquote><hr><td><tr><table><sup>"); //remove all unsupported tags
        $html=str_replace("\n",'',$html); //replace carriage returns with spaces
        $html=str_replace("\t",'',$html); //replace carriage returns with spaces
        $a=preg_split('/<(.*)>/U',$html,-1,PREG_SPLIT_DELIM_CAPTURE); //explode the string
        foreach($a as $i=>$e)
        {
            if($i%2==0)
            {
                //Text
                if($this->HREF)
                    $this->PutLink($this->HREF,$e);
                elseif($this->tdbegin) {
                    if(trim($e)!='' && $e!="&nbsp;") {
                        $this->Cell($this->tdwidth,$this->tdheight,$e,$this->tableborder,'',$this->tdalign,$this->tdbgcolor);
                    }
                    elseif($e=="&nbsp;") {
                        $this->Cell($this->tdwidth,$this->tdheight,'',$this->tableborder,'',$this->tdalign,$this->tdbgcolor);
                    }
                }
                else
                    $this->Write(5,stripslashes(txtentities($e)));
            }
            else
            {
                //Tag
                if($e[0]=='/')
                    $this->CloseTag(strtoupper(substr($e,1)));
                else
                {
                    //Extract attributes
                    $a2=explode(' ',$e);
                    $tag=strtoupper(array_shift($a2));
                    $attr=array();
                    foreach($a2 as $v)
                    {
                        if(preg_match('/([^=]*)=["\']?([^"\']*)/',$v,$a3))
                            $attr[strtoupper($a3[1])]=$a3[2];
                    }
                    $this->OpenTag($tag,$attr);
                }
            }
        }
    }

    function OpenTag($tag, $attr)
    {
        //Opening tag
        switch($tag){

            case 'SUP':
                if( !empty($attr['SUP']) ) {    
                    //Set current font to 6pt     
                    $this->SetFont('','',6);
                    //Start 125cm plus width of cell to the right of left margin         
                    //Superscript "1" 
                    $this->Cell(2,2,$attr['SUP'],0,0,'L');
                }
                break;

            case 'TABLE': // TABLE-BEGIN
                if( !empty($attr['BORDER']) ) $this->tableborder=$attr['BORDER'];
                else $this->tableborder=0;
                break;
            case 'TR': //TR-BEGIN
                break;
            case 'TD': // TD-BEGIN
                if( !empty($attr['WIDTH']) ) $this->tdwidth=($attr['WIDTH']/4);
                else $this->tdwidth=40; // Set to your own width if you need bigger fixed cells
                if( !empty($attr['HEIGHT']) ) $this->tdheight=($attr['HEIGHT']/6);
                else $this->tdheight=6; // Set to your own height if you need bigger fixed cells
                if( !empty($attr['ALIGN']) ) {
                    $align=$attr['ALIGN'];        
                    if($align=='LEFT') $this->tdalign='L';
                    if($align=='CENTER') $this->tdalign='C';
                    if($align=='RIGHT') $this->tdalign='R';
                }
                else $this->tdalign='R'; // Set to your own
                if( !empty($attr['BGCOLOR']) ) {
                    $coul=hex2dec($attr['BGCOLOR']);
                        $this->SetFillColor($coul['R'],$coul['G'],$coul['B']);
                        $this->tdbgcolor=true;
                    }
                $this->tdbegin=true;
                break;

            case 'HR':
                if( !empty($attr['WIDTH']) )
                    $Width = $attr['WIDTH'];
                else
                    $Width = $this->w - $this->lMargin-$this->rMargin;
                $x = $this->GetX();
                $y = $this->GetY();
                $this->SetLineWidth(0.2);
                $this->Line($x,$y,$x+$Width,$y);
                $this->SetLineWidth(0.2);
                $this->Ln(1);
                break;
            case 'STRONG':
                $this->SetStyle('B',true);
                break;
            case 'EM':
                $this->SetStyle('I',true);
                break;
            case 'B':
            case 'I':
            case 'U':
                $this->SetStyle($tag,true);
                break;
            case 'A':
                $this->HREF=$attr['HREF'];
                break;
            case 'IMG':
                if(isset($attr['SRC']) && (isset($attr['WIDTH']) || isset($attr['HEIGHT']))) {
                    if(!isset($attr['WIDTH']))
                        $attr['WIDTH'] = 0;
                    if(!isset($attr['HEIGHT']))
                        $attr['HEIGHT'] = 0;
                    $this->Image($attr['SRC'], $this->GetX(), $this->GetY(), px2mm($attr['WIDTH']), px2mm($attr['HEIGHT']));
                }
                break;
            case 'BLOCKQUOTE':
            case 'BR':
                $this->Ln(5);
                break;
            case 'P':
                $this->Ln(10);
                break;
            case 'FONT':
                if (isset($attr['COLOR']) && $attr['COLOR']!='') {
                    $coul=hex2dec($attr['COLOR']);
                    $this->SetTextColor($coul['R'],$coul['G'],$coul['B']);
                    $this->issetcolor=true;
                }
                if (isset($attr['FACE']) && in_array(strtolower($attr['FACE']), $this->fontlist)) {
                    $this->SetFont(strtolower($attr['FACE']));
                    $this->issetfont=true;
                }
                if (isset($attr['FACE']) && in_array(strtolower($attr['FACE']), $this->fontlist) && isset($attr['SIZE']) && $attr['SIZE']!='') {
                    $this->SetFont(strtolower($attr['FACE']),'',$attr['SIZE']);
                    $this->issetfont=true;
                }
                break;
        }
    }

    function CloseTag($tag)
    {
        //Closing tag
        if($tag=='SUP') {
        }

        if($tag=='TD') { // TD-END
            $this->tdbegin=false;
            $this->tdwidth=0;
            $this->tdheight=0;
            $this->tdalign="L";
            $this->tdbgcolor=false;
        }
        if($tag=='TR') { // TR-END
            $this->Ln();
        }
        if($tag=='TABLE') { // TABLE-END
            $this->tableborder=0;
        }

        if($tag=='STRONG')
            $tag='B';
        if($tag=='EM')
            $tag='I';
        if($tag=='B' || $tag=='I' || $tag=='U')
            $this->SetStyle($tag,false);
        if($tag=='A')
            $this->HREF='';
        if($tag=='FONT'){
            if ($this->issetcolor==true) {
                $this->SetTextColor(0);
            }
            if ($this->issetfont) {
                $this->SetFont('arial');
                $this->issetfont=false;
            }
        }
    }

    function SetStyle($tag, $enable)
    {
        //Modify style and select corresponding font
        $this->$tag+=($enable ? 1 : -1);
        $style='';
        foreach(array('B','I','U') as $s) {
            if($this->$s>0)
                $style.=$s;
        }
        $this->SetFont('',$style);
    }

    function PutLink($URL, $txt)
    {
        //Put a hyperlink
        $this->SetTextColor(0,0,255);
        $this->SetStyle('U',true);
        $this->Write(5,$txt,$URL);
        $this->SetStyle('U',false);
        $this->SetTextColor(0);
    }

    // Page header
    function Header()
    {
        // Logo
        $this->Image(logo-mono.jpg',10,10,30);
        $this->SetFont('Arial','B',15);
        $this->Cell(138);
        $this->Cell(70,5,'TAX INVOICE',0,0,'C');
        $this->Ln(12);
        // Company Header
        $this->SetFont('Arial','B',9);
        $this->Cell(0,5,'ABC COMPANY (1063511-D)',0,0,'L');
        $this->Ln(0);
        // Line break
        $this->Ln(15);
    }

    // Page footer
    function Footer()
    {
        // Position at 1.5 cm from bottom
        $this->SetY(-15);
        // Arial italic 8
        $this->SetFont('Arial','I',8);
        // Page number
        $this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');
    }
}


//Fetching specific order data and prepare an invoice
$invoice = $buyer->get_completed_transaction(
                        filter_var('1466404785-0J2XQR',FILTER_SANITIZE_STRING),
                        filter_var('T108869482600',FILTER_SANITIZE_STRING),
                        filter_var('LG6j3DYQbnylAFdaSdzcx5J0SYo=',FILTER_SANITIZE_STRING),
                        $mysqli
                    );

if($invoice !== FALSE){

    //Checkout with BRP+CASH or CASH only, 2=BRP+CASH.
    $checkout_method = $invoice->checkout_method;

    //GENERATE INVOICE
    $shipping_addr_1 = $invoice->shipping_address.',';
    $shipping_addr_2 = $invoice->shipping_postcode.' '.$invoice->shipping_city.',';
    $shipping_addr_3 = $invoice->shipping_province.' '.$invoice->shipping_country.'.';

    // Instanciation of inherited class
    $pdf = new PDF('P', 'mm', 'A4');

    $pdf->AliasNbPages();
    $pdf->AddPage();

    $pdf->SetFont('Arial','B',9);
    $pdf->setFillColor(230,230,230);
    $pdf->Cell(50,5,'BILL TO',1,0,'L',1);
    $pdf->Ln(3);
    //
    $pdf->SetFont('Arial','',9);
    $pdf->Cell(0,15,strtoupper($invoice->recipient_name),0,0,'L');
    $pdf->SetFont('Arial','B',8);
    $pdf->Text(146,58,'DATE:');
    $pdf->Text(146,63,'INVOICE #');
    $pdf->Text(146,68,'CUSTOMER ID');
    $pdf->SetFont('Arial','',8);
    $pdf->Text(170,58,date('d/m/Y'));
    $pdf->Text(170,63,$invoice->order_num);
    $pdf->Ln(5);
    $pdf->SetFont('Arial','',8);
    $pdf->Cell(0,15,ucwords(strtolower($shipping_addr_1)),0,0,'L');
    $pdf->Ln(5);
    $pdf->Cell(0,15,ucwords(strtolower($shipping_addr_2)),0,0,'L');
    $pdf->Ln(5);
    $pdf->Cell(0,15,ucwords(strtolower($shipping_addr_3)),0,0,'L');
    //
    /*
    $pdf->Ln(5);
    $pdf->SetFont('Arial','B',8);
    $pdf->Cell(10,25,'Tel:');
    $pdf->SetFont('Arial','',8);
    $pdf->Cell(0,25,$invoice->phone);
    //
    $pdf->Ln(5);
    $pdf->SetFont('Arial','B',8);
    $pdf->Cell(10,25,'Email:');
    $pdf->SetFont('Arial','',8);
    $pdf->Cell(118,25,$invoice->email);
    */
    //
    $pdf->Ln(14);
    $pdf->SetFont('Arial','',8);
    $html = '
    <table border="1">
        <tr>
            <td width="30" height="30" bgcolor="#dddddd" align="left">No</td>
            <td width="90" height="30" bgcolor="#dddddd" align="left">Item Code</td>
            <td width="380" height="30" bgcolor="#dddddd" align="left">Descriptions</td>
            <td width="40" height="30" bgcolor="#dddddd">Qty</td>
            <td width="100" height="30" bgcolor="#dddddd">Price/Unit</td>
            <td width="120" height="30" bgcolor="#dddddd">Amount</td>
        </tr>';

    $i = 1;
    $shipping_rate = SHIPPING_RATE_ALL;
    $total_payment = 0;

    //Loop order items
    $items = unserialize($invoice->cart_item);
    foreach($items as $item){

        //$keys = array_keys($item);
        //$matches = preg_grep('~^p_alt\-variation\-\d+~i', $keys);
        $unit_price = ($checkout_method == 2) ? ($item['p_price']/2) : $item['p_price'];
        $subtotal   = ($checkout_method == 2) ? (($item['p_price']/2) * $item['p_qty']) : ($item['p_price'] * $item['p_qty']);

        $html .= '
            <tr>
                <td width="30" height="30" align="left">'.$i.'</td>
                <td width="90" height="30" align="left">'.$item['p_code'].'</td>
                <td width="380" height="30" align="left">'.$item['p_name'].'</td>
                <td width="40" height="30">'.$item['p_qty'].'</td>
                <td width="100" height="30">'.number_format($unit_price, 2, '.', ',').'</td>
                <td width="120" height="30">'.number_format($subtotal, 2, '.', ',').'</td>
            </tr>';

        $i++;
        $gross_payment += $subtotal;
    }
    //End Loop

    $html .= '
        <tr>
            <td width="30" height="30">&nbsp;</td>
            <td width="90" height="30">&nbsp;</td>
            <td width="380" height="30">&nbsp;</td>
            <td width="40" height="30">&nbsp;</td>
            <td width="100" height="30">&nbsp;</td>
            <td width="120" height="30">&nbsp;</td>
        </tr>
        <tr>
            <td width="30" height="30">&nbsp;</td>
            <td width="90" height="30">&nbsp;</td>
            <td width="380" height="30">&nbsp;</td>
            <td width="40" height="30">&nbsp;</td>
            <td width="100" height="30">&nbsp;</td>
            <td width="120" height="30">&nbsp;</td>
        </tr>

    </table>';

    $pdf->WriteHTML($html);
    //
    $pdf->Ln(2);
    $pdf->SetFont('Arial','',8);
    $pdf->Cell(156,5,'Subtotal',0,0,'R');
    $pdf->Cell(8,5,'$',0,0,'R');
    $pdf->Cell(0,5,number_format($gross_payment,2,'.',','),0,1,'R');
    $pdf->Cell(0,5,'Thank you for your business',0,0,'L');
    $pdf->Cell(-34,5,'Shipping Cost',0,0,'R');
    $pdf->Cell(8,5,'$',0,0,'R');
    $pdf->Cell(0,5,number_format($shipping_rate,2,'.',','),0,1,'R');

    if($checkout_method == 2){
        $pdf->Cell(156,5,'BRP Consume',0,0,'R');
        $pdf->Cell(8,5,'-',0,0,'R');
        $pdf->Cell(0,5,number_format($invoice->total_points_consume,0,'.',','),0,1,'R');
    }

    $pdf->Ln(1);
    $pdf->Cell(125,0,'',0,0,'R');
    $pdf->Cell(65,0,'',1,0,'R');
    $pdf->Ln(1);
    $pdf->SetFont('Arial','B',8);
    $pdf->Cell(156,10,'Total Including GST',0,0,'R');
    $pdf->Cell(8,10,'$',0,0,'R',1);
    $pdf->Cell(0,10,number_format($gst+$gross_payment+$shipping_rate,2,'.',','),0,1,'R',1);
    $pdf->Ln(1);

    //GST calculation
    $gst = round((($gross_payment+$shipping_rate)*6.00)/100, 1);
    $pdf->SetFont('Arial','',8);
    $pdf->SetTextColor('88','88','88');
    $pdf->Cell(156,5,'GST 6%',0,0,'R');
    $pdf->Cell(8,5,'$',0,0,'R');
    $pdf->Cell(0,5,number_format($gst,2,'.',','),0,1,'R');
    $pdf->Ln(1);
    //
    $pdf->Ln(10);
    //$pdf->WriteHTML('<HR>');
    $pdf->SetFont('Arial','B',8);
    $pdf->Cell(90,5,'ABC COMPANY',0,0,'L',0);
    $pdf->Ln(20);
    $pdf->Cell(50,0,'',1,1,'L',0);
    $pdf->Ln(1);
    $pdf->SetFont('Arial','BI',8);
    $pdf->Cell(90,5,'Authorised Signature',0,0,'L',0);


    $path = '/invoice/';
    $file = $invoice->order_num.'.pdf';


    $pdf->Output();


}

?>

I've been look for the solution around and tried with tFPDF, I get error with

Fatal error: Call to undefined method tFPDF::WriteHTML() in C:\pathto\create_invoice_test.php on line 448

I have no idea of how to implement it into current scripts, I need workaround to solve this issue.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Nanny Boy
  • 107
  • 6
  • The problem is solved by using tFPDF (a branch of FPDF) and having a font WITH the language character range you need (i.e., WindowsHelvetica.ttf does not have Chinese). Take a look at my answer here: https://stackoverflow.com/a/56429391/2430549 – HoldOffHunger Jun 04 '19 at 16:35

0 Answers0