【问题标题】:Use placeholder in TCPDF在 TCPDF 中使用占位符
【发布时间】:2013-06-08 13:22:54
【问题描述】:

我对贷方票据进行了一些复杂的计算,第一页是总金额的摘要。 我不想做的是遍历所有规定以计算摘要,然后再次遍历它们以呈现详细视图。 那么是否可以在添加详细视图后定义可以替换的自定义占位符? 或者您知道另一种无需运行两次计算即可获得所需结果的方法?

编辑:

这就是我渲染细节视图的方式:

        foreach($this->_creditNote->provisioningClient->customers as $customer)
        {
            $provisions = $customer->getProvisionsByBillingPeriodSum($this->_creditNote->billingPeriod);
            if((count($provisions) >= 3 && $this->y > 230) || $this->y > 250)
            {
                $this->AddPage();
                $this->SetFillColor(240);
                $this->SetDrawColor(0);
                $this->SetFont('Helvetica', 'B', 10);
                $this->Cell(140, 6, 'Die Provisionen im Einzelnen', 'TB', 0, 'L', 1);
                $this->Cell(30, 6, "Beträge", 'TB', 1, 'R', 1);
                $this->SetXY(25, $this->y-11.5);
                $this->SetTextColor(170,170,170);
                $this->SetFont('Helvetica', '', 7);
                $this->Cell(175, 6, 'Seite ' . $this->getAliasNumPage() . ' von ' . $this->getAliasNbPages(), '', 2, 'R');
                $this->SetY($this->y+6);
                $this->SetFont('Helvetica', '', 9);
                $this->SetTextColor(0,0,0);
            }
            if(count($provisions) > 0)
            {
                $customerData = array();
                $this->SetXY(20, $this->y+1);
                $this->SetFont('Helvetica', 'B', 10);
                $this->Cell(140, 0, $customer->contact->name . " (" . $customer->customerNumber . ")");
                //add customer
                $amount = 0;
                $rows = array();
                foreach($provisions as $provision)
                {
                    $text = $provision->description;
                    $description = "";
                    if($provision->period != "onetime")
                    {
                        if($provision->isPartial($this->_creditNote->billingPeriod))
                            $text .= ", anteilig";
                        $description = $provision->periodName . ", " . $provision->getRuntime($this->_creditNote->billingPeriod);
                    }
                    if($description == "")
                        $description = null;
                    $temp = array($text, $provision->isPartial($this->_creditNote->billingPeriod) ? round($provision->getPartialAmount($this->_creditNote->billingPeriod)/100, 2) : $provision->amount / 100, $description);
                    $amount += $temp[1];
                    $rows[] = $temp;
                }
                $this->Cell(30, 0, number_format($amount, 2, ",", ".") . " €", 0, 1, 'R');
                foreach($rows as $row)
                {
                    $this->SetXY(23, $this->y+1);
                    $this->SetFont('Helvetica', '', 8);
                    $this->Cell(137, 0, $row[0]);
                    $this->Cell(30, 0, number_format($row[1], 2, ",", ".") . " €", 0, 1, 'R');
                    if($row[2])
                    {
                        $this->SetXY(26, $this->y + 1);
                        $this->SetFont('Helvetica', 'I', 8);
                        $this->MultiCell(140, 0, $row[2], 0, 'L');
                    }
                }
            }
        }

提前致谢, 托比亚斯

【问题讨论】:

    标签: php replace tcpdf placeholder


    【解决方案1】:

    据我了解,您当前的代码如下所示:

    // this will contain the computation for every orders
    $orders_infos = array();
    
    // you need $orders_infos to be already filled here, but it is done after
    $total = 0;
    foreach ($orders_infos as $info) {
      $total += $info['total'];
    }
    $html = "html for the overview page: ".$total; // $total is wrong !
    $pdf->writeHTML($html);
    
    // compute infos for every order and display
    foreach ($orders as $k => $order) {
      $orders_infos[$k] = compute_order_infos();
      $html = "html for this order page ".$orders_infos[$k]['total'];
      $pdf->writeHTML($html);
    }
    

    您的问题是概览页面中的总数不正确,因为您在之后运行计算。更改它的简单方法是运行所有计算,然后才生成结果 PDF,但您说出于某种原因您不希望这样做。

    实现您想要的下一个最佳方法是稍微作弊并跟踪以closures 运行的命令列表,然后在最后运行它们,这样您就可以保留当前的大部分代码组织,但之后仍然进行所有显示;

    $commands = array();
    
    // this will contain the computation for every orders
    $orders_infos = array();
    
    // you need $orders_infos to be already filled here, but it is done after
    $total = 0;
    $commands[] = function($pdf, $orders_infos) {
      foreach ($orders_infos as $info) {
        $total += $info['total'];
      }
      $html = "html for the overview page: ".$total;
      $pdf->writeHTML($html);
    };
    
    // compute infos for every order and display
    foreach ($orders as $k => $order) {
      $orders_infos[$k] = compute_order_infos();
      $commands[] = function($pdf, $orders_infos) use ($k) {
        $html = "html for this order page ".$orders_infos[$k]['total'];
        $pdf->writeHTML($html);
      };
    }
    
    // now run all the commands
    foreach ($commands as $command) {
      $command($pdf, $orders_infos);
    }
    

    一旦完成每个计算,您的所有 PDF 编写命令(包括概述)都将在最后执行。

    一个类似但更简单的示例,以便您更好地了解其工作原理:

    $arr = array();
    for ($i = 0; $i < 5; $i++) {
      $arr[$i] = $i;
    }
    $funcs = array();
    foreach ($arr as $k => $v) {
      $funcs[] = function($arr) use($k) {
        echo $arr[$k]."\n";
      };
    }
    
    foreach ($funcs as $func) {
      echo "func: ";
      $func($arr);
    }
    

    显示:

    $ php test.php
    func: 0
    func: 1
    func: 2
    func: 3
    func: 4
    

    【讨论】:

    • 感谢您的回答。我将在我的问题中粘贴一些代码。每个月我都必须生成一些信用票据,以便为有时有很多广告客户的客户提供服务。所以我不想做的是计算摘要渲染它,然后运行所有规定并详细渲染它们。所以我想我可以像 aliasnbpages 等一样使用占位符。我也想过遍历它并将所有需要的数据保存在数组中以在最后呈现它们,但我认为可能有更舒适的方式:D
    【解决方案2】:

    前段时间我不得不做类似的任务,因此知道多次迭代是不好的。

    我创建了一个类,它首先会进行所有计算。让我们称之为“回报”类。这将遍历自上个月以来收到的所有订单。然后它将为

    创建信息
    • 每个单笔订单(免税/等...)
    • 整体视图(项目数量/总税额/等)

    所以它可能看起来像这样

    $payoffInfo=new Payoff($arrayWithOrderInfos);
    
    // do creation of tcpdf object include header/footer/ ...
    $pdf = new TCPDF();
    $pdf->setPDFVersion('1.4');
    
    $pdf->setPrintHeader(FALSE);
    $pdf->setPrintFooter(TRUE);
    
    // create first page and set 'overall' like this ...
    
    $pdf->SetFont('Helvetica', '', 12);
    $pdf->Cell(0, 0, "Overall amount ".$payoffInfo->getItemCount() , 0, 1, 'L');
    $pdf->Ln();
    
    $pdf->SetFont('Helvetica', '', 12);
    $pdf->Cell(0, 0,"Overall amount ".$payoffInfo->getOverallAmount() , 0, 1, 'L');
    $pdf->Ln();
    
    // include more Overview Informations ...
    // Iterate over all single orders ...
    
    foreach($payoffInfo->getOrders() as $item){
        $html = "<p><ul>";
        $html .= "<li>Item ID: ".$item['order_id']."</li>";
        $html .= "<li>Item Price ".$item['price']."</li>";
        $html .= "<li>Item Clear Amount ".$item['price_without_tax']."</li>";
        $html .= "</ul></p>";
        $pdf->writeHTML($html, TRUE, FALSE, TRUE, FALSE, 'L');
    }
    // Mark Items as billed or sth. else so we don't include them again next month
    $payoffInfo->setItemsToStatus("billed"); 
    
    $pdf->Output($yourDesiredLocation, 'F');
    

    为了减少时间并防止在服务器负载高时生成 pdf,我将其移至“任务”(或其他任何内容)。然后,这个任务会在半夜由 cron 作业每月调用一次(取决于您需要的时间段)。

    此解决方案适用于每月约 400k 的订单,并且可能会做得更多。

    如果你想要时尚的 pdf,可以完全按照你想要的样式设置,我今天会使用某种 LaTeX“接口”。因为设置整个内容的样式(包括页眉和页脚)要容易得多。

    希望这可以帮助您反思自己的任务。

    【讨论】:

    • 最后我按照你的方式做了。我计算了总数,并在循环遍历这些规定时存储它们以供以后在渲染时访问。多谢!虽然真的很伤心,但是没有办法在 tcpdf 中使用自定义占位符:(
    猜你喜欢
    • 2013-10-16
    • 2015-09-05
    • 2017-05-28
    • 2012-07-08
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 2021-01-11
    • 1970-01-01
    相关资源
    最近更新 更多