I am working with phpWord and bringing changes to the header/footer content gives me a real hard time. What I am trying is to have header content arranged in a table. The table is created through the code I write. But the styles I try to apply to the table placed in a header does not take effect.
Following is a part of my code in which I may be making a mistake.
$phpWordObj = new PhpWord();
$section = $phpWordObj->addSection();
$styleTable = array('borderSize' => 18, 'borderColor' => '006699');
$phpWordObj->addTableStyle('My Custom Style', $styleTable);
//ADD HEADER TO DOCUMENT
$header = $section->addHeader();
$header->firstPage();
$table = $header->addTable();
$table->addRow();
//logo
$table->addCell(2000)->addImage(
'../vendor/phpoffice/phpword/samples/resources/PhpWord.png',
array('width' => 80, 'height' => 80, 'align' => 'left')
); //logo
$cell = $table->addCell(7000);
$textrun = $cell->addTextRun();
$textrun->addText(htmlspecialchars('Custom Name goes here...'));
$headerGen = $section->addHeader();
$tableGenHeader = $headerGen->addTable();
$tableGenHeader->addRow();
//logo
$tableGenHeader->addCell(2000)->addImage(
'../vendor/phpoffice/phpword/samples/resources/PhpWord.png',
array('width' => 80, 'height' => 80, 'align' => 'left')
);
$cellGenHeader = $tableGenHeader->addCell(7000);
$textrunGenHeader = $cellGenHeader->addTextRun();
$textrunGenHeader->addText(htmlspecialchars('Custom Name goes here...'));
All I want is borders to appear so that the header contents can be differentiated from each other.
Thanks!
The $phpWordObj->addTableStyle(...) adds a new table style that you need to reference in the table addition (i.e. it is not a global definition). Adding the style name as a parameter to your addTable calls should do the trick:
$table = $header->addTable('My Custom Style');
Related
I am creating table using phpword and add to template. In output file, The table column are reverse in order. I have create cell correctly.
<?php
$data=[
['cell 1 row 1','cell 2 row 1'],
['cell 1 row 2','cell 2 row 2']
];
//phpword
require_once '../vendor/autoload.php';
use PhpOffice\PhpWord\TemplateProcessor;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Settings;
use PhpOffice\PhpWord\SimpleType\TblWidth;
use PhpOffice\PhpWord\Style\Table;
use PhpOffice\PhpWord\Writer\Word2007\Element\Container;
use PhpOffice\PhpWord\Shared\XMLWriter;
$fontStyle = new \PhpOffice\PhpWord\Style\Font();
$fontStyle->setName('Times');
$phpWord = new PhpWord();//phpword object
$section = $phpWord->addSection();//section
$tbl = $section->addTable(array(
/*'ltr' => true,*/
/*"layout" => Table::LAYOUT_AUTO,
"width" => 100 * 50, //in word 1% == 50 unit (with in 1/50)
"unit" => TblWidth::PERCENT,
'lineHeight' => 1*/
));
for($i=0;$i < 40;$i++){
$tbl->addRow();
$tbl->addCell(150)->addText("cell 1 row:$i");
$tbl->addCell(150)->addText("cell 2 row:$i");
$tbl->addCell(150)->addText("cell 3 row:$i");
$tbl->addCell(150)->addText("cell 4 row:$i");
//$tbl->addCell(150)->addMultiLineText("cell\n4 row:$i");
}
$xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY, './', Settings::hasCompatibility());
$containerWriter = new Container($xmlWriter, $section);
$containerWriter->write();
$elXml = $xmlWriter->getData();
// remplace our templateContent
Settings::setOutputEscapingEnabled(false);
$templateProcessor =new TemplateProcessor('testing_tabledirection.docx');
$templateProcessor->setValue('table', $elXml);
Settings::setOutputEscapingEnabled(true);
$pathToSave ='output_tabledirection.docx';
$templateProcessor->saveAs($pathToSave);
?>
The table column order has been fixed by removing empty array as parameter from addTable().
$tbl = $section->addTable(array());
to
$tbl = $section->addTable();
style name should passed to addTable
$table = $section->addTable([$tableStyle]);
Step to define table style
create array and define style for table
$tableStyle = array(
'borderColor' => '006699',
'borderSize' => 6,
'cellMargin' => 50
);
define style to phpword object
$phpWord->addTableStyle('myTable', $tableStyle);
Add style when create table from section
$table = $section->addTable('myTable');
I am using TCPDF library to generate a PDF file dynamically in my Laravel Project.
I have a requirement to create the Table Of Content section dynamic and set the header of each page using Summary titles. And to give link to each items below which will lead user to the start of that section/content.
Example:
My Table Of Content
Summary ............................... 1
Organization & Management Structure.... 5
Credit History......................... 7
Public Records......................... 8
So,
My page 1 should have header as Summary
Page 2 to 4 should have header as Summary(Cont.)
Page 5 => Organization & Management Structure
Page 6 => Organization & Management Structure(Cont.)
Page 7 => History
Page 8 => Public Records
If you can help me by sending some tricks I can use to complete this, it will be a great help. Thanks!
Honestly, what you're describing sounds like the content of example 45 included TCPDF examples where you could get by just using the built-in TOC generator.
Something I didn't like about the example however is it's lack of body text. So I created a simple example with very basic document structure and randomly generated text below. The idea would be that you set a Bookmark right before you begin writing your content for each section and then have the TOC generator do the rest.
Setting the bookmark right before rendering your content makes it so you don't have to calculate the position of the bookmark. By default it'll take it's current position. I use a pre-built array here and very basic output for simplicity's sake.
Notes:
here may be edge cases where the content immediately overflows to the next page without outputting on the current page. I decided that was out of scope for now since you may not encounter it, but figured I'd note the possibility of it happening.
It may seem obvious, but it's worth mentioning anyway: If adding a page before starting your new section, call the Bookmark method after addPage.
You can view the output of my script: here
As mentioned, I based this off example 045 which you can view on the TCPDF example page. You can also use HTML to format the TOC entries made this way, see example 059.
<?php
// Include the main TCPDF library (search for installation path).
// Change this for your installation.
require_once('TCPDF-6.2.17/tcpdf.php');
// create new PDF document
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT,
PDF_PAGE_FORMAT, true, 'UTF-8', false);
// set default monospaced font
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
// set auto page breaks
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
// set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
//These will become the different colors for our TOC labels.
//Main section is a dark blue, sub-section is a lighter blue. This is
//strictly optional, but I kind of like it myself.
$level_colors = array(
0 => array(0, 0, 66),
1 => array(0, 0, 100),
2 => array(0, 0, 130),
);
/**
* Just produces some filler text.
*/
function gen_random_section_text($min = 70, $max = 300) {
$words = array('Iris', 'Daffodil', 'Dandelion', 'Daisy', 'Orchid', 'Lily',
'Rhododendron', 'Sakura', 'Blossom', 'Larkspur', 'Anemone', 'Hydrangea');
$word_max_index = count($words)-1;
$word_count = rand($min, $max);
$output = array();
for($i = 0; $i < $word_count; $i++) {
$output[] = $words[rand(0, $word_max_index)];
}
return implode(' ', $output);
}
// ---------------------------------------------------------
// set font
$pdf->SetFont('times', '', 14);
/**
* I'll build our list of sections outright for this example.
*/
$sections[] = array(
'title' => 'Summary',
'content' => '<p>'.gen_random_section_text(20,30).'</p>',
'level' => 0,
);
$sections[] = array(
'title' => 'Organization & Management',
'content' => '<p>'.gen_random_section_text(100,200).'</p>'.
'<p>'.gen_random_section_text(120,230).'</p>',
'level' => 0,
);
$sections[] = array(
'title' => 'Hiring Procedures',
'content' => '<p>'.gen_random_section_text(100,200).'</p>',
'level' => 1,
);
$sections[] = array(
'title' => 'In Absence of HR',
'content' => '<p>'.gen_random_section_text(30,100).'</p>',
'level' => 2,
);
$sections[] = array(
'title' => 'History',
'content' => '<p>'.gen_random_section_text().'</p>',
'level' => 0,
);
$sections[] = array(
'title' => 'History (1990-2000)',
'content' => '<p>'.gen_random_section_text().'</p>',
'level' => 1,
);
$sections[] = array(
'title' => 'History (2001-Present)',
'content' => '<p>'.gen_random_section_text().'</p>',
'level' => 1,
);
//Now we'll take our fake sections and add pages/content as needed.
foreach($sections as $section) {
$headertag = 'h1';
if(empty($section['level'])) {
//Both not set and value of 0 will evaluate true here.
//I'm adding new pages for any top-level section here, but you don't need to.
$pdf->addPage();
$level = 0;
} else {
//Any non-zero level header I'll give an h2.
$headertag = 'h2';
$level = $section['level'];
}
//We add a bookmark right before we start our output for the section copy.
$bookmark_style = $level > 0 ? 'I' : 'B'; //Make subheading italic.
$pdf->Bookmark($section['title'], $level, -1, '', $bookmark_style, $level_colors[$level], -1, '');
//See below for some notes on the Bookmark method.
//Then we output our content.
$pdf->WriteHTML("<{$headertag}>".htmlspecialchars($section['title'], ENT_COMPAT, 'UTF-8').
"</{$headertag}> {$section['content']}");
}
// add a new page for TOC
$pdf->addTOCPage();
// write the TOC title
$pdf->SetFont('times', 'B', 16);
//Writes my little "TOC Note"
$pdf->MultiCell(0, 0, 'My Table Of Content', 0, 'C', 0, 1, '', '', true, 0);
$pdf->Ln();
$pdf->SetFont('dejavusans', '', 12);
// add a simple Table Of Content at first page
// (check the example n. 59 for the HTML version)
$pdf->addTOC(1, 'courier', '.', 'INDEX', 'B', array(128,0,0));
// end of TOC page
$pdf->endTOCPage();
//Close and output PDF document
$pdf->Output('example_045.pdf', 'I');
For reference, the parameters for Bookmark are, at time of writing, here:
#param $txt (string) Bookmark description.
#param $level (int) Bookmark level (minimum value is 0).
#param $y (float) Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;).
#param $page (int|string) Target page number (leave empty for current page). If you prefix a page number with the * character, then this page will not be changed when adding/deleting/moving pages.
#param $style (string) Font style: B = Bold, I = Italic, BI = Bold + Italic.
#param $color (array) RGB color array (values from 0 to 255).
#param $x (float) X position in user units of the bookmark on the selected page (default = -1 = current position;).
#param $link (mixed) URL, or numerical link ID, or named destination (# character followed by the destination name), or embedded file (* character followed by the file name).
Using PHPWord, I'm trying to align to the right a date field in word template.
$right = array('align' => 'right');
$objTextRun = $firstSection->addTextRun(array_merge($right, $singleLineHeight));
$firstSection->addField('DATE', array('dateformat' => 'dd/MM/yyyy'), array());
but the date remains aligned to the left, and only the line before is aligned to the right. Need help please.
You are adding your date to the section instead of the textrun (where you have your right alignment rules defined). So with that fixed:
$right = array('align' => 'right');
$objTextRun = $firstSection->addTextRun(array_merge($right, $singleLineHeight));
$objTextRun->addField('DATE', array('dateformat' => 'dd/MM/yyyy'), array());
I'm writing a Drupal 7 module to display child nodes of a module in the content.
Nodes have a field parent_nodes (node reference) where one ore more nodes are selected as parents.
First, I've created a view projects with a block view display subprojects, displaying nodes of type project with a field_parent_project contextual filter.
This is my module:
<?php
function projects_preprocess_node(&$variables) {
if ($variables['type'] == 'project') {
if (isset($variables['view_mode']) && $variables['view_mode'] == 'full') {
_projects_add_subprojects($variables);
}
}
}
function _projects_add_subprojects(&$variables) {
$nid = $variables['nid'];
$view = views_get_view('projects');
$preview = $view->preview('subprojects', array($nid));
$subprojects = array(
'#title' => t('Subprojects'),
'#label_display' => 'above',
'#weight' => 10,
//'#theme' => 'field',
'#markup' => $preview,
);
if (!isset($variables['content']['subprojects'])) {
$variables['content']['subprojects'] = array();
}
$variables['content']['subprojects'][] = $subprojects;
dpm($variables['content']);
}
This is working, adding the view display output to the node's content.
Only some things aren't working:
title (label)
weight do not change display position when rendered with other contents (it's always the first, above body).
If I uncomment the '#theme' => 'field' line, title is shown as a label, but nothing is rendered. This is because the field theme is used and I guess it needs #items and does not use the #markup element.
I cannot use a children nodes as reference, but only parent nodes.
The solution must be independent to theme, so no not answer "change your theme template" or similar
How can I show children nodes in node? I'm looking for a way to get something interpretable how a it is was a field
If you didn't already know, the Viewfield module allows you to specify a View as a field in your content type. This may save you some coding but you may not want a whole module to do such a specific task so...
If you want to continue with the custom code which you've written, then you need to re-structure your added content to the correct render array structure that Drupal expects. Try something like this:
$subprojects_view_output = array(
'#type' => 'markup',
'#markup' => $preview,
);
$subprojects = array(
'#theme' => 'field',
'#weight' => 10,
'#title' => t('Subprojects'),
'#items' => $subprojects_view_output,
);
With the above, the title/label for your field as well as the content of the field (the view itself) should show up. The code is untested so may not be 100% correct in terms of syntax and all but hopefully gives you a path to a solution.
EDIT: I tested the above and it does not work because in order to use the existing theme_field function it seems that Drupal expects more information required to render a field like the #field_name, #field_type, #entity_type, etc. as you should see in the warning messages.
Essentially, you are faking a field and you will need to provide Drupal with all the info it expects if you want to continue to use the built-in theme_field function, including all the variables as expected in the preprocess functions.
Alternatively, you can continue to use your original code and add a #prefix to get your title/label to render like this:
$subprojects = array(
'#weight' => 10,
'#prefix' => '<div id="subprojects-view">asdf:</div>',
//'#theme' => 'field',
'#markup' => $preview,
);
Then style the title/label with CSS accordingly. I didn't have any problems with the weighting as you described.
Thanks to #nmc, this is my final solution. If no results are found, it does not display the title. The check for results is done by if (count($view->result) == 0). Weight is working.
<?php
function projects_preprocess_node(&$variables) {
$type = $variables['type'];
if ($type == 'project' || $type == 'customer') {
if (isset($variables['view_mode']) && $variables['view_mode'] == 'full') {
_projects_add_subprojects_markup($variables);
}
}
}
function _projects_add_subprojects_markup(&$variables) {
$nid = $variables['nid'];
$view = views_get_view('projects');
$preview = $view->preview('subprojects', array($nid));
if (count($view->result) == 0) {
return;
}
$variables['content']['subprojects'] = array(
'#weight' => 10,
'#prefix' => '<h2>' . t('Subprojects') . '</h2>',
'#markup' => $preview,
);
}
Hello Im currently writing a product syncronisation script for magento. I know how to add a new product with a given attribute set. However one of the atributes i am using is a size field. When a new size is encounterd I want to add this option to the attribute, I am wondering how to do this please?
Here is a script to add new option to attribute from Product View or Block:
$attributeInfo = Mage::getResourceModel('eav/entity_attribute_collection')
->setCodeFilter(YOUR_ATTRIBUTE_CODE)
->getFirstItem();
$options = $attributeInfo->getSource()->getAllOptions(false);
$_optionArr = array(
'value' => array(),
'order' => array(),
'delete' => array()
);
foreach ($options as $option) {
$_optionArr['value'][$option['value']] = array($option['label']);
}
$_optionArr['value']['option_1'] = array(NAME_OF_OUR_NEW_OPTION);
$attribute->setOption($_optionArr);
$attribute->save();
...
Put a file ie: test-attribute.php in your Magento root.
<?php
// Include and start Magento
require_once dirname(__FILE__).'/app/Mage.php';
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
// Load attribute model and load attribute by attribute code
$model = Mage::getModel('catalog/resource_eav_attribute')->load('some_dropdown_attribute', 'attribute_code');
// Get existing options
$options = $model->getSource()->getAllOptions(false);
// Get the count to start at
$count = count($options) + 1;
// Prepare array
$data = array(
'option' => array(
'value' => array(),
'order' => array()
)
);
// You can loop here and increment $count for multiple options
$key = 'option_'.$count;
$data['option']['value'][$key] = array('Test '.$count);
$data['option']['order'][$key] = 0;
// Add array to save
$model->addData($data);
// Save
$model->save();
Should create a new option called Test X on the attribute. Tested on Magento Enterprise 1.11.2
After doing some more looking around I finaly found out how to do it. Then I found a extension to xml-api that extends api to support operations such as one i wanted to do.
The extension i used was MagentoeXtended