merge 2 file docx use tbszip - php

I' using OpenTBS to merge 2 file docx.
include_once('tbszip.php');
$zip = new clsTbsZip();
// Open the first document
$zip->Open('file-1.docx');
$content1 = $zip->FileRead('word/document.xml');
$zip->Close();
// Extract the content of the first document
$p = strpos($content1, '<w:body');
if ($p===false) exit("Tag <w:body> not found in document 1.");
$p = strpos($content1, '>', $p);
$content1 = substr($content1, $p+1);
$p = strpos($content1, '</w:body>');
if ($p===false) exit("Tag </w:body> not found in document 1.");
$content1 = substr($content1, 0, $p);
// Insert into the second document
$zip->Open('file-2.docx');
$content2 = $zip->FileRead('word/document.xml');
$p = strpos($content2, '</w:body>');
if ($p===false) exit("Tag </w:body> not found in document 2.");
$content2 = substr_replace($content2, $content1, $p, 0);
$zip->FileReplace('word/document.xml', $content2, TBSZIP_STRING);
// Save the merge into a third file
$zip->Flush(TBSZIP_DOWNLOAD, 'merge1.docx');
content in file-1.docx include image+text, file-2: only text.
But when gen file merge1.docx, can not gen image from file-1.docx
Please for me a solution, thanks.
P/s: sorry for my english.
when I reversed the order to open the file, file merge1.docx full content. why?
// Open the first document
$zip->Open('file-2.docx');
$content1 = $zip->FileRead('word/document.xml');
$zip->Close();
..........
// Insert into the second document
$zip->Open('file-1.docx');

It is quite difficult to merge two DOCX because of internal elements such as pictures, charts, ...
In the archive, pictures must be saved in the word/media/ directory.
They must be declared in the file /[Content_Types].xml
They also must be assigned to a unique Id in the file /word/_rels/document.xml.rels.
And then the unique Id must be used in a XML element corresponding to the picture in the word/document.xml file.
So in order to merge two DOCX files you have to apply your snippet, then get the pictures from DOCX to the other, and then perform the operation above.
You're using TbsZip, which is used by OpenTBS but it is not the same tool.
OpenTBS won't help you to merge two DOCX together.

Related

merge csv files using PHP

I have a .csv file which I can use with Google maps API to successfully create map data.
What I'm looking to do is merge 2 (or more) .csv files and display the TOTAL data on the Google map in the same way. They are all in the same format.
I have the paths to the 2 csv files and if need be, a blank .csv file in the same directory where the files could be merged to...
Unfortuantely, the .csv files all have an initial 'header row' which would be awesome to omit when merging...
If anyone can point me in the right direction, I'd be very happy. Thanks
edit: I've tried:
$data1 = file_get_contents('google_map_data.csv');
$data2 = file_get_contents('google_map_data2.csv');
$TOTALdata = "google_map_dataALL.csv";
function joinFiles(array $files, $result)
{
if(!is_array($files)) {
throw new Exception('`$files` must be an array');
}
$wH = fopen($result, "w+");
foreach($files as $file)
{
$fh = fopen($file, "r");
while(!feof($fh))
{
fwrite($wH, fgets($fh));
}
fclose($fh);
unset($fh);
fwrite($wH, "\n"); //usually last line doesn't have a newline
}
fclose($wH);
unset($wH);
joinFiles(array($data1, $data2), $TOTALdata);
I'm assuming both files are small, so loading them all in one go should be OK.
The code loads both files then removes the first line off the second one. It also removes any end of line from the first file, but adds it's own to ensure it always has a new line...
$data1 = file_get_contents('google_map_data.csv');
$data2 = file_get_contents('google_map_data2.csv');
$TOTALdata = "google_map_dataALL.csv";
$data2 = ltrim(strstr($data2, PHP_EOL));
file_put_contents($TOTALdata, rtrim($data1).PHP_EOL.$data2);

Read and replace contents in .docx (Word) file

I need to replace content in some word documents based on User input. I am trying to read a template file (e.g. "template.docx"), and replace First name {fname}, Address {address} etc.
template.docx:
To,
The Office,
{officeaddress}
Sub: Authorization Letter
Sir / Madam,
I/We hereby authorize to {Ename} whose signature is attested here below, to submit application and collect Residential permit for {name}
Kindly allow him to support our International assignee
{name} {Ename}
Is there a way to do the same in Laravel 5.3?
I am trying to do with phpword, but I can only see code to write new word files - but not read and replace existing ones. Also, when I simply read and write, the formatting is messed up.
Code:
$file = public_path('template.docx');
$phpWord = \PhpOffice\PhpWord\IOFactory::load($file);
$phpWord->save('b.docx');
b.docx
To,
The Office,
{officeaddress}
Sub:
Authorization Letter
Sir / Madam,
I/We hereby authorize
to
{Ename}
whose signature is attested here below, to submit a
pplication and collect Residential permit
for
{name}
Kindly allow him to support our International assignee
{name}
{
E
name}
This is the working version to #addweb-solution-pvt-ltd 's answer.
//This is the main document in Template.docx file.
$file = public_path('template.docx');
$phpword = new \PhpOffice\PhpWord\TemplateProcessor($file);
$phpword->setValue('{name}','Santosh');
$phpword->setValue('{lastname}','Achari');
$phpword->setValue('{officeAddress}','Yahoo');
$phpword->saveAs('edited.docx');
However, not all of the {name} fields are changing. Not sure why.
Alternatively:
// Creating the new document...
$zip = new \PhpOffice\PhpWord\Shared\ZipArchive();
//This is the main document in a .docx file.
$fileToModify = 'word/document.xml';
$file = public_path('template.docx');
$temp_file = storage_path('/app/'.date('Ymdhis').'.docx');
copy($template,$temp_file);
if ($zip->open($temp_file) === TRUE) {
//Read contents into memory
$oldContents = $zip->getFromName($fileToModify);
echo $oldContents;
//Modify contents:
$newContents = str_replace('{officeaddqress}', 'Yahoo \n World', $oldContents);
$newContents = str_replace('{name}', 'Santosh Achari', $newContents);
//Delete the old...
$zip->deleteName($fileToModify);
//Write the new...
$zip->addFromString($fileToModify, $newContents);
//And write back to the filesystem.
$return =$zip->close();
If ($return==TRUE){
echo "Success!";
}
} else {
echo 'failed';
}
Works well. Still trying to figure how to save it as a new file and force a download.
I have same task to edit .doc or .docx file in php, i have use this code for it.
Reference : http://www.onlinecode.org/update-docx-file-using-php/
$full_path = 'template.docx';
//Copy the Template file to the Result Directory
copy($template_file_name, $full_path);
// add calss Zip Archive
$zip_val = new ZipArchive;
//Docx file is nothing but a zip file. Open this Zip File
if($zip_val->open($full_path) == true)
{
// In the Open XML Wordprocessing format content is stored.
// In the document.xml file located in the word directory.
$key_file_name = 'word/document.xml';
$message = $zip_val->getFromName($key_file_name);
$timestamp = date('d-M-Y H:i:s');
// this data Replace the placeholders with actual values
$message = str_replace("{officeaddress}", "onlinecode org", $message);
$message = str_replace("{Ename}", "ingo#onlinecode.org", $message);
$message = str_replace("{name}", "www.onlinecode.org", $message);
//Replace the content with the new content created above.
$zip_val->addFromString($key_file_name, $message);
$zip_val->close();
}
To read and replace content from Doc file, you can use PHPWord package and download this package using composer command:
composer require phpoffice/phpword
As per version v0.12.1, you need to require the PHP Word Autoloader.php from src/PHPWord folder and register it
require_once 'src/PhpWord/Autoloader.php';
\PhpOffice\PhpWord\Autoloader::register();
1) Open document
$template = new \PhpOffice\PhpWord\TemplateProcessor('YOURDOCPATH');
2) Replace string variables for single
$template->setValue('variableName', 'MyVariableValue');
3) Replace string variables for multi occurrence
- Clone your array placeholder to the count of your array
$template->cloneRow('arrayName', count($array));
- Replace variable value
for($number = 0; $number < count($array); $number++) {
$template->setValue('arrayName#'.($number+1), htmlspecialchars($array[$number], ENT_COMPAT, 'UTF-8'));
}
4) Save the changed document
$template->saveAs('PATHTOUPDATED.docx');
UPDATE
You can pass limit as third parameter into $template->setValue($search, $replace, $limit) to specifies how many matches should take place.
If you find simple solution you can use this library
Example:
This code will replace $search to $replace in $pathToDocx file
$docx = new IRebega\DocxReplacer($pathToDocx);
$docx->replaceText($search, $replace);
Library phpoffice/phpword working is ok.
For correct working you must use the right symbols in your Word document, like that:
${name}
${lastname}
${officeAddress}
and for method "setValue" you need to use only names, like:
'name'
'lastname'
'officeAddress'
Very good working within Laravel, Lumen, and other frameworks
Example:
//This is the main document in Template.docx file.
$file = public_path('template.docx');
$phpword = new \PhpOffice\PhpWord\TemplateProcessor($file);
$phpword->setValue('name','Santosh');
$phpword->setValue('lastname','Achari');
$phpword->setValue('officeAddress','Yahoo');
$phpword->saveAs('edited.docx');

how to add the logo into csv file using ECSVExport in yii?

Yii::import('application.extensions..ECSVExport');
$filename = 'filename.csv';
$csv = new ECSVExport($sheet_generation);
$csv->setOutputFile($outputFile);
$imageUrl = Yii::app()->request->baseUrl.'/themes/optisol/images/resign-icon.png';
$num = cal_days_in_month(CAL_GREGORIAN, $month,$year);
$heading="Attendance for 01"."-".$month."-".$year." To ".$num."-".$month."-".$year." ";
$content=$heading;
$content = $content.$csv->toCSV();
Yii::app()->getRequest()->sendFile($filename, $content, "text/csv", false);
It cannot be done. Not in the way you asked, actually.
A CSV is a text file, and therefore cannot have embedded images like a word processor document can.
If we want the image in the file, you will have to put the file name in the document. Then, the person reading the document can decide what to do with the file name.
A file will look this:
id, name, image, email
1,'Tom', 'image1.png', 'user1#domain.com'
1,'Jones', 'image2.png', 'user2#domain.com'

How to reference the current directory name, filename and file contents with RecursiveDirectoryIterator loop?

In the script below, I'm attempting to iterate over the folders and files inside of the $base folder. I expect it to contain a single level of child folders, each containing a number of .txt files (and no subfolders).
I'm just needing to understand how to reference the elements in comments below...
Any help much appreciated. I'm really close to wrapping this up :-)
$base = dirname(__FILE__).'/widgets/';
$rdi = new RecursiveDirectoryIterator($base);
foreach(new RecursiveIteratorIterator($rdi) as $files_widgets)
{
if ($files_widgets->isFile())
{
$file_name_widget = $files_widgets->getFilename(); //what is the filename of the current el?
$widget_text = file_get_contents(???); //How do I reference the file here to obtain its contents?
$sidebar_id = $files_widgets->getBasename(); //what is the file's parent directory name?
}
}
//How do I reference the file here to obtain its contents?
$widget_text = file_get_contents(???);
$files_widgets is a SplFileInfo, so you have a few options to get the contents of the file.
The easiest way is to use file_get_contents, just like you are now. You can concatenate together the path and the filename:
$filename = $files_widgets->getPathname() . '/' . $files_widgets->getFilename();
$widget_text = file_get_contents($filename);
If you want to do something funny, you can also use openFile to get a SplFileObject. Annoyingly, SplFileObject doesn't have a quick way to get all of the file contents, so we have to build a loop:
$fo = $files_widgets->openFile('r');
$widget_text = '';
foreach($fo as $line)
$widget_text .= $line;
unset($fo);
This is a bit more verbose, as we have to loop over the SplFileObject to get the contents line-by-line. While this is an option, it'll be easier for you just to use file_get_contents.

How to merge docx documents in PHP?

Does anyone know how to merge (concatenate) docx documents with PHP (or Python if it's not possible in PHP)?
To clarify, my server is Linux based. I have 2 existing docx document, I need to put them in a new docx document using PHP or possibly Python.
Merging two different Docx files may be very complicated because Headers, Styles, Charts, Comments, User Modification Traces and other special contents are saved in separate inner XML sub-files in each Docx. Thus, two Docx may have different objects having the same ids. So it would be a very huge job to list all possible objects in the two documents, give them new inner ids, and re-affect them in a single one. Probably only Ms Office can do this currently.
Nevertheless, if you know that your two documents to be merged have the same styles, and if you know you have no charts, headers and other special objects, then the merging becomes something quite easy to perform.
In this case, you only have to use a Zip reader, such as TbsZip, to open the first Docx file (which is technically a zip archive containing XML sub-files) ; then read the sub-file "word/document.xml" and extract the part which is between the tags < w:body >
and < /w:body >.
In the second Docx file, open the "word/content.xml" and insert the previous content just before the tag < /w:body >. Save the result in a new Docx file.
This can be done using TbsZip, like this :
<?php
include_once('tbszip.php');
$zip = new clsTbsZip();
// Open the first document
$zip->Open('doc1.docx');
$content1 = $zip->FileRead('word/document.xml');
$zip->Close();
// Extract the content of the first document
$p = strpos($content1, '<w:body');
if ($p===false) exit("Tag <w:body> not found in document 1.");
$p = strpos($content1, '>', $p);
$content1 = substr($content1, $p+1);
$p = strpos($content1, '</w:body>');
if ($p===false) exit("Tag </w:body> not found in document 1.");
$content1 = substr($content1, 0, $p);
// Insert into the second document
$zip->Open('doc2.docx');
$content2 = $zip->FileRead('word/document.xml');
$p = strpos($content2, '</w:body>');
if ($p===false) exit("Tag </w:body> not found in document 2.");
$content2 = substr_replace($content2, $content1, $p, 0);
$zip->FileReplace('word/document.xml', $content2, TBSZIP_STRING);
// Save the merge into a third file
$zip->Flush(TBSZIP_FILE, 'merge.docx');
You may merge two Word documents with PHPDocX with a single line of code: (Source: Merging Word documents with PHPDocX)
require_once 'path /classes/DocxUtilities.inc';
$newDocx = new DocxUtilities();
$myOptions = array('mergeType' => 0);
$newDocx->mergeDocx('firstWordDoc.docx', 'secondWordDoc.docx', 'mergedWord.docx',
$myOptions);
This merging let you preserve all section structure (paper size, margins, associated footers and headers,...), includes all the required styles, manages all lists (this may seem trivial but it is not so in the OOXML standard), preserves images and charts as well as footnotes, endnotes and comments.
Moreover there is an option to preserve the original numberings (by default the page numbering continues).
One also may, via the mergeType option, to discard the section structure of the merged document and add it at the end of the first document as part of its last section. In this case, of course, the headers and footers are not imported but all other elements are still preserved.
Aspose.Words Cloud SDK for PHP can merge/join several Word Documents into a one Word document while keeping the formatting of appended or destination document depending upon the ImportFormatMode parameter value. Secondly, it is a commercial API but the free pricing plan allows 150 free monthly API Calls.
<?php
require_once('D:\xampp\htdocs\aspose-words-cloud-php-master\vendor\autoload.php');
//TODO: Get your ClientId and ClientSecret at https://dashboard.aspose.cloud (free registration is required).
$ClientSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$ClientId="xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx";
$wordsApi = new Aspose\Words\WordsApi($ClientId,$ClientSecret);
try {
$remoteDataFolder = "Temp";
$localFile = "C:/Temp/02_pages_adobe.docx";
$remoteFileName = "02_pages_adobe.docx";
$localFile1 = "C:/Temp/Sections.docx";
$remoteFileName1 = "Sections.docx";
$outputFileName = "TestAppendDocument.docx";
$uploadRequest = new Aspose\Words\Model\Requests\UploadFileRequest($localFile,$remoteDataFolder."/".$remoteFileName,null);
$wordsApi->uploadFile($uploadRequest);
$uploadRequest1 = new Aspose\Words\Model\Requests\UploadFileRequest($localFile1,$remoteDataFolder."/".$remoteFileName1,null);
$wordsApi->uploadFile($uploadRequest1);
$requestDocumentListDocumentEntries0 = new Aspose\Words\Model\DocumentEntry(array(
"href" => $remoteDataFolder . "/" . $remoteFileName1,
"import_format_mode" => "KeepSourceFormatting",
));
$requestDocumentListDocumentEntries = [
$requestDocumentListDocumentEntries0,
];
$requestDocumentList = new Aspose\Words\Model\DocumentEntryList(array(
"document_entries" => $requestDocumentListDocumentEntries,
));
$request = new Aspose\Words\Model\Requests\AppendDocumentRequest(
$remoteFileName,
$requestDocumentList,
$remoteDataFolder,
NULL,
NULL,
NULL,
$remoteDataFolder . "/" . $outputFileName,
NULL,
NULL
);
$result = $wordsApi->appendDocument($request);
##Download file
$request = new Aspose\Words\Model\Requests\DownloadFileRequest($remoteDataFolder."/".$outputFileName,NULL,NULL);
$result = $wordsApi->downloadFile($request);
copy($result->getPathName(),"AppendOutput.docx");
} catch (Exception $e) {
echo "Something went wrong: ", $e->getMessage(), "\n";
PHP_EOL;
}
?>
P.S: I'm developer evangelist at Aspose.

Categories