PHPWord - setting font inside Template Processor - php

I am using PHPWord to load a template file and create a new one from it.
$templateName = 'QuoteTemplate1.docx';
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor($templateName);
$values = ['clientAddressName' => $quote->company_name]; // this array typically has more values
foreach ($values as $key => $value) {
$templateProcessor->setValue($key, $value);
}
Then I am adding a custom built table to this template, the code is like this:
$table = new PhpOffice\PhpWord\Element\Table([
'borderSize' => 0,
'borderColor' => 'none',
'width' => 9200,
'unit' => PhpOffice\PhpWord\SimpleType\TblWidth::TWIP
]);
$table->addRow();
$table->addCell(150)->addText('Cell A1');
$table->addCell(150)->addText('Cell A2');
$table->addCell(150)->addText('Cell A3');
$table->addRow();
$table->addCell(150)->addText('Cell B1');
$table->addCell(150)->addText('Cell B2');
$table->addCell(150)->addText('Cell B3');
$templateProcessor->setComplexBlock('quoteItemTable', $table);
I want to add font and paragraph styles to the text in this custom table - and here lies the problem.
If I try something like this:
$templateProcessor->addParagraphStyle('rightAlign', ['alignment' => 'right']);
The I get errors (addParagraphStyle is not a recognized method of $templateProcessor). And if I try:
$phpWord = new \PhpOffice\PhpWord\PhpWord();
$phpWord->addParagraphStyle('rightAlign', ['alignment' => 'right']);
$table->addCell(25)->addText('Cell A1', 'fontStyle', 'rightAlign');
Then I get no errors, but my rightAlign paragraph style is ignored. Please note I get the same results when I try the steps with font styles as well as paragraph styles.
How can I set my own font and paragraph styles inside a template processor?

The following worked for me:
$my_template = new \PhpOffice\PhpWord\TemplateProcessor(storage_path('template1.docx'));
$table = new \PhpOffice\PhpWord\Element\Table();
$myFontStyle = array('name' => 'Minion Pro', 'size' => 10, 'bold' => true);
$myParagraphStyle = array('align'=>'center', 'spaceBefore'=>50, 'spaceafter' => 50);
$table->addRow();
$table->addCell()->addText('Cell 1', $myFontStyle, $myParagraphStyle );
$table->addCell()->addText('Cell 2', $myFontStyle, $myParagraphStyle );
$table->addCell()->addText('Cell 3', $myFontStyle, $myParagraphStyle );
$my_template->setComplexBlock('table', $table);

Related

How can I combine text resizing with bolding in footer?

I can alternate bold and normal text in a footer (thanks to ejuhjav) but only if I don't try to style the text.
In the following example, the letter 'T' comes out bold because it's at the default size (12).
If I reduce the text, the bolding is dropped. I've also tried using named font styles and created font style objects. No luck.
Is there something simple I'm missing?
// create footer
$footer = $section->addFooter();
$textrun = $footer->addTextRun();
// define bold style
$boldFontStyleName = 'BoldText';
$phpWord->addFontStyle($boldFontStyleName, array('bold' => true));
// add content
$textrun->addText('T', $boldFontStyleName);
$textrun->addText(' ++353 1 555 0001 ',
array('name' => 'Helvetica', 'size' => 8));
$textrun->addText('E',
array('name' => 'Helvetica', 'size' => 8), $boldFontStyleName);
$textrun->addText(' abc.def#ghk.ie ',
array('name' => 'Helvetica', 'size' => 8));
$textrun->addText('W',
array('name' => 'Helvetica', 'size' => 8), $boldFontStyleName);
$textrun->addText(' abcd.ie/wxz',
array('name' => 'Helvetica', 'size' => 8));
and here goes the third time then :)
the addText function definition is:
addText(string $text, mixed $fStyle = null, mixed $pStyle = null)
i.e. the font styles are given with the second parameter and thus the rows where you have the $boldFontStyleName variable as third attribute the font is not bolded.
The easiest way to fix this would be to to just define couple of additional font styles:
// create footer
$footer = $section->addFooter();
$textrun = $footer->addTextRun();
// define font styles
$boldFontStyleName = 'BoldText';
$phpWord->addFontStyle($boldFontStyleName, array('bold' => true));
$smallFontStyleName = 'smallText';
$phpWord->addFontStyle($smallFontStyleName, array(
'name' => 'Helvetica',
'size' => 8,
));
$boldSmallFontStyleName = 'BoldSmallText';
$phpWord->addFontStyle($boldSmallFontStyleName, array(
'bold' => true,
'name' => 'Helvetica',
'size' => 8,
));
// add content
$textrun->addText('T', $boldFontStyleName);
$textrun->addText(' ++353 1 555 0001 ', $smallFontStyleName);
$textrun->addText('E', $boldSmallFontStyleName);
$textrun->addText(' abc.def#ghk.ie ', $smallFontStyleName);
$textrun->addText('W', $boldSmallFontStyleName);
$textrun->addText(' abcd.ie/wxz', $smallFontStyleName);

$textrun->addText content being processed before $footer->addText content

I want to have a footer that contains 3 lines of text, with a vertical space (like a blank line) between lines 2 and 3.
Because line 3 contains bold and normal text, I have to implement it as a textrun.
But there should be a line break between lines 1 and 2, so I use addText for both of these.
Unfortunately, the order in which the footer content is displayed is as follows:
textrun
footerText1
footerText2
The textrun gets processed first and appears above the other lines!
How do I get the order right?
My footer code is:
// create footer
$footer = $section->addFooter();
// textrun declaration removed from here
// create footer content
$footerText1 = "Blah blah blah.";
$footerText2 = "Ipsum loret Ipsum loret Ipsum loret.";
// define font styles
$smallFontStyleName = 'smallText';
$phpWord->addFontStyle($smallFontStyleName, array(
'name' => 'Helvetica',
'size' => 8,
));
$boldSmallFontStyleName = 'BoldSmallText';
$phpWord->addFontStyle($boldSmallFontStyleName, array(
'bold' => true,
'name' => 'Helvetica',
'size' => 8,
));
// define paragraph spacing styles
$phpWord->addParagraphStyle('line1FooterStyle', array( 'spaceAfter'=>20));
$phpWord->addParagraphStyle('line2FooterStyle', array( 'spaceAfter'=>380));
// add content
$footer->addText($footerText1,
array('name' => 'Helvetica', 'size' => 8),
array('space' => array('after' => 20))
);
$footer->addText($footerText2,
array('name' => 'Helvetica', 'size' => 8),
array('space' => array('after' => 380))
);
// textrun relocated to here
$textrun = $footer->addTextRun();
$textrun->addText('T', $boldSmallFontStyleName);
$textrun->addText(' ++353 1 555 0001 ', $smallFontStyleName);
$textrun->addText('E', $boldSmallFontStyleName);
$textrun->addText(' abc.def#ghk.ie ', $smallFontStyleName);
$textrun->addText('W', $boldSmallFontStyleName);
$textrun->addText(' abcd.ie/wxz', $smallFontStyleName);
OK, I saw the problem and fixed it. I had declared the textrun before the $footer->addText lines. Which means the textrun code was inserted first, incorrectly. D'oh!

XML Parsing error; PHPWord

I am using PHPOffice/PHPWord in my Laravel Application. It is used to generate a .docx document with results in tables. This works great for a document of 3 tables with 6 rows, but when there are more rows the document is generated but when opening it the following error occurs:
We're sorry, We can't open (documentname) because we found a problem with its contents.
Details: XML parsing error Location: Part:/word/document.xml, Line: 2, Column 14349.
Now, I have started working on another result page where I would also want to generate a .docx document. This will contain 5 tables, but with 3 rows I get the same XML parsing error but in a different location (Location: Part: /word/document.xml, Line:4, Column:2888). Could someone explain to me whether this is a error in my code, or phpword/words?
I have done some troubleshooting by deleting everything, and slowly adding new rows. I have found the error but how could i fix it. The first two tables are generated good..
$phpWord = new \PhpOffice\PhpWord\PhpWord();
$section = $phpWord->addSection();
$section->addImage('../public/img/2.jpg', array('width' => 230, 'height' => 65, 'alignment' => 'left'));
$section->addText('Project IDs:' . $parameter);
$header =$section->addHeader();
$header->addText('Results Summary');
$section->addLine(
array(
'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(16),
'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0),
'positioning' => 'absolute',
)
);
$tableName = 'rStyle';
$phpWord->addFontStyle($tableName, array('italic' => true, 'size' => 12));
$thName = 'tStyle';
$phpWord->addFontStyle($thName, array('bold' => true, 'size' => 9));
$section->addText('General Information Table', $tableName);
$fancyTableStyle = array('borderSize' => 6, 'borderColor' => '999999');
$spanTableStyleName = 'Overview tables';
$phpWord->addTableStyle($spanTableStyleName, $fancyTableStyle);
$table = $section->addTable($spanTableStyleName);
$table->addRow(null, array('tblHeader' => true, 'cantSplit' => true));
$table->addCell(1750)->addText('Project ID',$thName);
$table->addCell(1750)->addText('Description',$thName);
$table->addCell(1750)->addText('Notes',$thName);
foreach ($id_array_explode as $char) {
$table->addRow();
$singlenumber = (int)$char;
$cursor = $collection->find(array("id" => $singlenumber));
foreach ($cursor as $document) {
$table->addCell(1750)->addText($document["project_id"]);
$table->addCell(1750)->addText($document["description"]);
$table->addCell(1750)->addText($document["notes"]);
}
}
$section->addText('
');
$section->addLine(
array(
'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(16),
'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0),
'positioning' => 'absolute',
)
);
$section->addText('Input Table', $tableName);
$table1 = $section->addTable($spanTableStyleName);
$table1->addRow(null, array('tblHeader' => true, 'cantSplit' => true));
$table1->addCell(1750)->addText('Project ID',$thName);
$table1->addCell(1750)->addText('#',$thName);
foreach ($id_array_explode as $char) {
$table1->addRow();
$singlenumber = (int)$char;
$cursor = $collection->find(array("id" => $singlenumber));
foreach ($cursor as $document) {
if (is_array($document['input'])) {
foreach ($document['input'] as $samples) {
$table1->addCell(1750)->addText($document["project_id"]);
$table1->addCell(1750)->addText($samples['nr']);
}
}
}
}
$section->addText('
');
$section->addLine(
array(
'width' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(16),
'height' => \PhpOffice\PhpWord\Shared\Converter::cmToPixel(0),
'positioning' => 'absolute',
)
);
$section->addText('Output Table', $tableName);
$table2 = $section->addTable($spanTableStyleName);
//// THIS IS WHERE THE ERROR OCCURS!!
$table2->addRow(null, array('tblHeader' => true, 'cantSplit' => true));
$table2->addCell(1750)->addText('ID',$thName);
Thank you!
SOLUTION
Oke, so I have deleted the whole document and added every single sentence separately to see where the error occurred. This led to seeing that the error came from the data which I was getting. It couldn't handle ">" and "&" signs!
So, if you every have this error, check the data which you're printing!
A better solution is to add the following line of code before you do anything with the word document:
PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true);
This will automatically escape any problematic characters.
Indeed, It comes from your data : you have a XML special character in it and when Word, parses your doc, it doesn't understand.
I solved this problem by using htmlspecialchars(). I'm not sure it is the best way but it works.
Not very familiar with PHPWord, but make sure the encoding of your document and the data you are inserting into it are the same. Used to have the same problem with an old library for creating excel files.

Nested tables with phpdocx

Im trying to create a nested table with the library phpdocx. In their documentation they write that it is possible to have a nested table in a table cell. But its not clearly written how to make it work..
I tried the following code:
$valuesTable = array(
array(
array(array(1,2,34),12,13,14),
array(21,22,23,24),
array(31,32,33,34),
);
$params = array(
'border' => 'single',
'tableAlign' => 'center',
'borderWidth' => 10,
'borderColor' => 'B70000',
'textProperties' => array('bold' => true, 'font' => 'Algerian', 'fontSize' => 18),
);
$docx->addTable($valuesTable, $params);
But the cell is just empty. Is there an easy way to get this nested table displayed?
I finally found the solution. It is possible with WordFragments.
$innerData = array(1,2,3,4);
$innerTable = new \WordFragment($docx);
$innerTable->addTable($innerData, array('rawWordML' => true));
$tableParams = array(); // Add here the table params
$outerData = array("A", "B", $innerTable);
$outerTable->addTable($outerData, $tableParams);

Regarding footer issue in pdf file creation using php and fpdf library

I have created and successfully created my pdf file in php with fpdf
library support.
But the problem is my footer is showing more space.
I want to reduce the space underneath my text. My output is like
this:
Here my code goes:
<?php
require('fpdf/fpdf.php');
class PDF extends FPDF {
function Header() {
$this->SetY(0.208333);
}
function Footer() {
if ($this->footer <> 1)
{
$this->SetY(-15);
}
else
{
echo "bye";
}
}
}
//class instantiation
$pdf=new PDF("l","in",array(8.5,4.17));
$pdf->SetFont('Arial','',8);
$pdf->footer = -15;
//Array2
$datas = array
(
'Address1' => array
(
'Name' => 'Vijaya',
'Area' => 'Valasaravakkam',
'City' => 'Chennai',
),
'Address2' => array
(
'Companyname' => 'Vy Systems',
'Area' => 'Valasaravakkam',
'City' => 'Chennai',
),
'Address3' => array
(
'Companyname' => 'Vy Systems1',
'Area' => 'Valasaravakkam1',
'City' => 'Chennai1',
),
);
//Array2
$datas1 = array
(
'Address4' => array
(
'Name' => 'Jaya',
'Area' => 'Valasaravakkam',
'City' => 'Chennai',
),
);
foreach($datas1 as $address1 => $details1)
{
//pdf_set_text_pos($pdf, 1240, 490);
//$pdf->ln(1);
foreach($datas as $address => $details)
{
$pdf->SetMargins(0,0,0.3);
$pdf->AddPage();
if((is_array($details)) and (is_array($details1)))
{
foreach($details1 as $rows1 => $value1)
{
$pdf->SetX(0.520833);
$pdf->MultiCell(0, 0.2, $value1, 0, "L");
}
$pdf->ln(1.96);
foreach($details as $rows => $value)
{
$pdf->SetX(5);
$pdf->MultiCell(5, 0.2, $value, 0, "L");
}
}
}//end of sub foreach
}//end of main foreach
$pdf->Output();
?>
I didn't follow the code completely, but it seems you're using the Header and Footer methods to set Y and nothing more, expecting that to be enough to correctly position the MultiCells being output outside of the Header and Footer. Maybe so, but the interaction of positioning inside and outside the Header/Footer isn't well defined.
For example, the process may be something like this: Y is calculated for the MultiCell, that trips the footer, the footer changes Y, the MultiCell is output. Is this the original Y, the revised (by the footer Y), or some other value? Absent a precise definition of what happens, you've set up a complex sequence of things that would be very difficult to sort out.
I would suggest vastly simplifying the code. You may find that the automatic header/footer tripping isn't helpful at all. In that case, turn off the auto page break, get rid of the Footer/Header functions, and totally control each page yourself. That way at least you have a clear, reliable model of what's going on.

Categories