1

貸方票の複雑な計算をいくつか実行すると、最初のページは全体の金額の概要です。私がやりたくないのは、すべての規定を実行して要約を計算し、その後それらを再度実行して詳細ビューをレンダリングすることです。詳細ビューを追加した後に置き換えることができるカスタム プレースホルダーを定義することは可能ですか? または、計算を 2 回実行せずに目的の結果を得る別の方法を知っていますか?

編集:

これは、詳細ビューをレンダリングする方法です:

        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');
                    }
                }
            }
        }

前もってありがとう、トバイアス

4

2 に答える 2

2

私が理解していることから、現在のコードは次のようになります。

// 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 を生成することですが、何らかの理由でそれを望まないとおっしゃいました。

あなたが望むものを達成するための次善の方法は、少しごまかして、クロージャーとして実行するコマンドのリストを追跡し、最後にそれらを実行することです。この方法では、現在のコード編成のほとんどを保持しながら、すべての表示を行いますその後;

$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
于 2013-06-18T10:00:39.227 に答える
1

少し前に同様のタスクを実行する必要があったため、複数回反復するのは悪いことです。

最初にすべての計算を行うクラスを作成しました。それを「ペイオフ」クラスと呼びましょう。これは、先月以降に発生したすべての注文に対して繰り返されます。次に、次の情報を作成します。

  • 単品注文(税抜など)
  • 全体像(アイテムの数/全体の税額など)

だから、それはこのように見えるかもしれません

$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 が生成されないようにするために、これを「タスク」(またはその他のもの) に移動しました。この tasked は、月に 1 回 (必要な期間に応じて) 真夜中に cron ジョブによって呼び出されます。

このソリューションは、1 か月あたり最大 40 万件の注文で問題なく機能し、さらに多くのことができる可能性があります。

スタイリッシュな pdf を希望どおりにスタイルできるようにしたい場合は、今日、ある種の LaTeX "Interface" を使用します。ヘッダーとフッターを含むコンテンツ全体のスタイルを設定する方がはるかに簡単だからです。

これがあなたの仕事について考えるのに役立つことを願っています。

于 2013-06-18T10:42:34.873 に答える