2009-07-03 12 views
9

मैं एकाधिक पृष्ठों के साथ एक पीडीएफ बनाने की कोशिश करता हूं और पृष्ठ ब्रेक के लिए तैयार करने के लिए प्रत्येक व्यक्तिगत तत्व (मल्टीसेल) की ऊंचाई की गणना करने के लिए अग्रिम की गणना करने की आवश्यकता है। दस्तावेज़ीकरण के मुताबिक GetCharWidth/GetStringWidth जैसे कुछ फ़ंक्शन हैं जो मुझे स्वयं करने में सहायता करने के लिए हैं, लेकिन एक संभावित प्रदर्शन खोने के अलावा मैं शायद इसे वैसे भी सही नहीं करूँगा। एक और अधिक सुरुचिपूर्ण तरीके से अपने लक्ष्य को प्राप्त करने के लिए सुझाव?टीसीपीडीएफ में मल्टीसेल/लिखने HTMLCell की ऊंचाई की गणना कैसे करें?

संदर्भ: TCPDF

उत्तर

1

पद Revisited: Tcpdf – Variable Height Table Rows With MultiCell उपयोगी जानकारी का एक बहुत कुछ है। यह एक छोटा अंश है:

getNumLines() ... वास्तव में एक विशेष चौड़ाई को देखते हुए हमें यह निर्धारित करने के कितने लाइनों पाठ की एक स्ट्रिंग का समय लग जाएगा अनुमति देता है। असल में, यह हमें ऐसा करने की अनुमति देता है जो मैं मल्टीसेल का उपयोग कर रहा था, वास्तव में कुछ भी चित्रित किए बिना।

$linecount = max($pdf->getNumLines($row['cell1data'], 80),$pdf->getNumLines($row['cell2data'], 80 
+0

दोनों getNumLines() और getStringHeight (के रूप में सरणी के लिए और अधिक डेटा जोड़ सकता है,) केवल एक 'अनुमानित ऊंचाई' (डॉक्स देखें) दे। यह कार्य हमेशा सही ढंग से काम नहीं करते हैं यदि पाठ सेल की दाएं सीमा के ठीक पहले या बस समाप्त होता है - जिसके परिणामस्वरूप पंक्तियों को एक दूसरे के शीर्ष पर मुद्रित किया जाता है। इसके बजाय तकनीक का उपयोग करें उदाहरण के लिए 20. –

3

मेरे अनुभव से, यह पहले से सेल ऊंचाई यह पता लगाने की लगभग असंभव है: यह कोड की एक पंक्ति के साथ निर्धारित अधिकतम सेल ऊंचाई करने के लिए हमें देता है। टीसीपीडीएफ के पेज ब्रेक हैंडलिंग फ़ंक्शंस का उपयोग करना बहुत आसान है, अगर आप पेजब्रेक में जा रहे हैं तो आपको पहले से ही बताता है। अन्यथा, आप pagebreak, अपने आप को, जो है मैं क्या कर समाप्त हो गया के तर्क को संभाल सकता है एक स्वचालित पृष्ठ विराम के लिए अनुमति देने के लिए सही करने के लिए झूठी

$yy = $this->pdf->GetY(); 

$check_pagebreak = $this->pdf->checkPageBreak($height+$padding,$yy,false); 

बदलें,: यहाँ उदाहरण कोड है।

इसके अलावा, यदि आपको इसकी आवश्यकता हो, तो यहां एक और छोटी युक्ति है: अपने दस्तावेज़ को दो पास में बनाने के लिए लेनदेन सुविधाओं का उपयोग करने पर विचार करें। पहला पास सभी ऊंचाइयों और कोशिकाओं, पेजब्रैक इत्यादि को समझने के लिए उपयोग किया जाता है। आप अपने सभी लाइनहेथ और लाइनों को प्रति पृष्ठ सरणी में भी स्टोर कर सकते हैं। दूसरे पास, अपने दस्तावेज़ को सभी सही जानकारी के साथ बनाएं और पेजबैक लॉजिक की आवश्यकता नहीं है (दूसरा पास अलग-अलग विधि से चलाया जा सकता है, कोड को पढ़ने में आसान रखने के लिए, और आपकी स्वच्छता के लिए)।

21

मुझे यह मिला: डी !!!!!

एक और pdf2 वस्तु

// pdf2 set x margin to pdf1's xmargin, but y margin to zero 
// to make sure that pdf2 has identical settings, you can clone the object (after initializing the main pdf object) 
$pdf2 = clone $pdf; 
pdf2->addpage 
pdf2->writeCell 
$height = pdf2->getY() 
pdf2->deletePage(pdf2->getPage()) 
pdf1->checkPageBreak($height); 
pdf1->writeCell() 

W00tness बनाएं: डी

+0

पहले मैं इस उत्तर के बारे में थोड़ा सा संदेह था, लेकिन यह काफी अच्छा काम करता है। वास्तव में अब तक की कोशिश की गई किसी भी अन्य विधि से बेहतर है। यद्यपि आपको $ pdf1 –

+0

के समान फ़ॉन्ट पर $ pdf2 डालना नहीं भूलना चाहिए, वास्तव में निष्पक्ष होने के लिए काफी अच्छा काम करता है। यदि आप क्लोनिंग कर रहे हैं तो फ़ॉन्ट वैसे भी वही होना चाहिए। यदि आप गतिशील रूप से जेनरेट करने के लिए इसका उपयोग कर रहे हैं तो यह न भूलें कि चौड़ाई भी महत्वपूर्ण है – LeonardChallis

+0

यह मल्टीसेल के लिए $ ln = 0 के लिए काम नहीं करता है, क्योंकि तब कर्सर सही चलता है और getY() नीचे नहीं देता है "उच्चतम" सेल (यदि पाठ इसमें फिट होने में बहुत लंबा था - इस प्रकार अलग-अलग सेल ऊंचाइयों)। –

13

यह एक पुरानी सवाल है, लेकिन TCPDF (7 दिसंबर 2011 तक) वर्तमान संस्करण है एक समारोह getStringHeight कहा जाता है कि आप के लिए अनुमति देता है वास्तव में मल्टीसेल को कॉल करने से पहले मल्टीसेल को पारित एक स्ट्रिंग की परिणामी ऊंचाई की गणना करें। फिर इस ऊंचाई का उपयोग विभिन्न चीजों के लिए किया जा सकता है, मूल प्रश्न में गणना, और टेबल बनाने के दौरान पंक्ति ऊंचाई निर्धारित करने के लिए भी। महान काम करता है।

किसी और मामले में इस समस्या के समाधान की तलाश में कुछ जानकारी जैसे मैंने किया था।

+0

"... तालिका बनाते समय पंक्ति ऊंचाई सेट करने के लिए भी" ==> हां। मैं यह देखने के लिए थोड़ा झुका हुआ था कि मल्टीकल्स स्वचालित रूप से सबसे ऊंची सेल की ऊंचाई तक पंक्ति ऊंचाई सेट नहीं करता है। लेकिन पंक्ति में पाठ की अधिकतम ऊंचाई का उपयोग करके, इस विधि से प्राप्त, एक आसान पर्याप्त फिक्स है। –

6

जबकि कार्वेल का जवाब बहुत अच्छा है, टीसीपीडीएफ का उल्लेख है कि getStringHeight अनुमानित ऊंचाई देता है। उपयोगी रूप से प्रलेखन $height के रूप में सामने आने वाली सटीक ऊंचाई प्राप्त करने के लिए एक बहुत व्यापक तकनीक प्रदान करता है। क्यों वे खुद का उपयोग नहीं करते हैं एक रहस्य है ...

// store current object 
$pdf->startTransaction(); 
// store starting values 
$start_y = $pdf->GetY(); 
$start_page = $pdf->getPage(); 
// call your printing functions with your parameters 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
$pdf->MultiCell($w=0, $h=0, $txt, $border=1, $align='L', $fill=false, $ln=1, $x='', $y='',  $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0); 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// get the new Y 
$end_y = $pdf->GetY(); 
$end_page = $pdf->getPage(); 
// calculate height 
$height = 0; 
if ($end_page == $start_page) { 
    $height = $end_y - $start_y; 
} else { 
    for ($page=$start_page; $page <= $end_page; ++$page) { 
     $pdf->setPage($page); 
     if ($page == $start_page) { 
      // first page 
      $height = $pdf->h - $start_y - $pdf->bMargin; 
     } elseif ($page == $end_page) { 
      // last page 
      $height = $end_y - $pdf->tMargin; 
     } else { 
      $height = $pdf->h - $pdf->tMargin - $pdf->bMargin; 
     } 
    } 
} 
// restore previous object 
$pdf = $pdf->rollbackTransaction(); 
+0

यह एक समस्या है यदि $ ln = 0, क्योंकि तब $ start_y = $ end_y। मेरी इच्छा है कि कर्सर को सही स्थानांतरित करने से पहले वे वाई के मूल्य को स्टोर करेंगे। –

+0

तो आपको प्रत्येक मल्टीसेल के बाद $ ln = 1 का उपयोग करना होगा और y और X को रीसेट करना होगा। –

+2

नोट! नवीनतम संस्करण में कुछ गुण सुरक्षित हैं और आपको निम्न को बदलना होगा: '$ pdf-> h' से' $ pdf-> getPageHeight() ',' $ pdf-> bmargin' से $ pdf-> getBreakMargin() ' , और '$ pdf-> tmargin' से $ pdf-> getMargins() [' top '] ' – TheStoryCoder

1

उपयोग TCPDF उदाहरण 20

  1. गिना जा रहा है MultiCell ऊंचाइयों एक बुरा सपना कोशिकाओं/कॉलम विभिन्न पृष्ठों पर खत्म करता है, तो हो सकता है।

  2. लेनदेन या अतिरिक्त पीडीएफ ऑब्जेक्ट्स का उपयोग करके चीजें बहुत धीमी हो सकती हैं।

  3. कोशिकाओं मुद्रित होने से पहले 'अनुमानित' (दस्तावेज़ देखें) ऊंचाई की गणना करने के लिए getNumLines() और getStringHeight() जैसे कार्यों का उपयोग करना हमेशा सही ढंग से काम नहीं करता है। विशेष रूप से यदि पाठ सेल की दाएं सीमा के ठीक पहले या बस समाप्त होता है - जिसके परिणामस्वरूप पंक्तियों को एक दूसरे के शीर्ष पर मुद्रित किया जाता है।

मैं Example 20 में इस्तेमाल तकनीक जहां विभिन्न पृष्ठों की अधिकतम Y मान नई पंक्ति की स्थिति की गणना करने के लिए उपयोग किया जाता है पसंद करते हैं।

उदाहरण केवल दो कॉलम प्रिंट करता है, लेकिन मैंने कॉलम की एक सरणी मुद्रित करने में सक्षम होने के लिए अपना मुख्य कार्य बदल दिया। जाहिर है आप इस तरह के प्रत्येक स्तंभ के फ़ॉन्ट, बॉर्डर, आदि

public function MultiRow($columnsArray) { 
    $page_start = $this->getPage(); 
    $y_start = $this->GetY(); 

    $pageArray = array(); 
    $yArray  = array(); 

    // traverse through array and print one column at a time. 
    $columnCount = count($columnsArray); 
    for($i=0; $i<$columnCount; $i++) 
    { 
     if($i+1 < $columnCount) 
     { 
      // Current column is not the last column in the row. 
      // After printing, the pointer will be moved down to 
      // the right-bottom of the column - from where the 
      // next multiCell in the following loop will use it 
      // via $this->GetX(). 
      $ln = 2; 
     } 
     else 
     { 
      // Current column is the last column in the row. 
      // After printing, the pointer will be moved to new line. 
      $ln = 1; 
     } 
     $this->MultiCell(30, 0, $columnsArray[$i], 1, 'L', 1, $ln, 
      $this->GetX() ,$y_start, true, 0); 

     $pageArray[$i] = $this->getPage(); 
     $yArray[$i]  = $this->GetY(); 

     // Go to page where the row started - to print the 
     // next column (if any). 
     $this->setPage($page_start); 
    } 

    // Test if all columns ended on the same page 
    $samePage = true; 
    foreach ($pageArray as $val) { 
     if($val != $pageArray['0']) 
     { 
      $samePage = false; 
      break; 
     } 
    } 

    // Set the new page and row position by case 
    if($samePage == true) 
    { 
     // All columns ended on the same page. 
     // Get the longest column. 
     $newY = max($yArray); 
    } 
    else 
    { 
     // Some columns ended on different pages. 
     // Get the array-keys (not the values) of all columns that 
     // ended on the last page. 
     $endPageKeys = array_keys($pageArray, max($pageArray)); 

     // Get the Y values of all columns that ended on the last page, 
     // i.e. get the Y values of all columns with keys in $endPageKeys. 
     $yValues = array(); 
     foreach($endPageKeys as $key) 
     { 
      $yValues[] = $yArray[$key]; 
     } 

     // Get the largest Y value of all columns that ended on 
     // the last page. 
     $newY = max($yValues); 
    } 

    // Go to the last page and start at its largets Y value 
    $this->setPage(max($pageArray)); 
    $this->SetXY($this->GetX(),$newY); 
} 
संबंधित मुद्दे