I have an XLSM File, where I need to edit some Cell Values with PHP. As I couldn't find a proper library, which can actually edit an xlsm file (most read excel and create a whole new excel file, which in this case would delete the macros inside the excel or even throw too many exceptions), I decided to unzip the xlsm file and directly edit the worksheet xml file by changing the values in the cells:
<c r="K15" s="52">
<v>83221.56</v>
</c>
For example I would change the Value inside the "v" Tag.
As Simple XML doesnt work, because it messes up some namespaces inside the file, I decided to edit it with Regular Expressions.
So far so good - i got the change in the file. But Formulars inside the Excel file, that depend on the cell I just changed the Value in won't recognize my change. When you open the Excel file, it properly shows the correct value, but other cells that use that changed value in their formula won't update.
Does anyone have any idea how to properly change the XML File and keeping the excel in tact?
Thanks!
As I could not figure out a solution in PHP and previous solutions with C++ (Is there a PHP library for XLSM(Excel with Macro) parsing/editing?) where to complicated for me, I found a solution with python, I want to share.
My environment is Ubuntu 16.04, I have Python installed. I have installed https://editpyxl.readthedocs.io/en/latest/
I placed a little script in the same directory as the PHP script, which I call with PHP:
from editpyxl import Workbook
import sys
import logging
logging.basicConfig()
if len(sys.argv) != 4:
print("Three arguments accepted, got " + (str(len(sys.argv) -1)))
print("Argument 1: Sheet name, Argument 2: Cell Identifier, Argument 3: New Value")
sys.exit();
wb = Workbook()
source_filename = r'OriginalFile.xlsm'
wb.open(source_filename)
ws = wb[sys.argv[1]]
ws.cell(sys.argv[2]).value = sys.argv[3]
destination_filename = "NewFile.xlsm"
wb.save(destination_filename)
wb.close()
In PHP I call it via
exec('python excel.py "SheetName" "CellName" "NewValue"')
Seems to be a workaround but it works (especially on Linux) and is very easy to implement. This solution has a performance limitation though. The python script reads, changes the value and saves the excel in each runtime. If you only have some values to change, this might not be a problem but if you plan to edit larger Excel Files with a larger amount of cells to edit, you might write the complete code that edits the xlsm in python.
This code, however, works for me. It edits the Excel and all Formulars/Calculations inside stay fine, also the Macros are still untouched.
Related
I am trying to convert a DOCX file to PDF with PHPWord. When I execute the script it looks like that some style elements are not converted. In the DOCX file I have one image, two tables with border 1px and hidden borders and I am using Tabs.
When I execute the script I get a PDF file without the image, all the Tabs are replaced with Space and all the tables have a border 3px.
Does someone know why I am missing these styles?
Here is my script:
while ($data2 = mysql_fetch_array($rsSql)){
$countLines=$countLines+1;
$templateProcessor->setValue('quantity#'.$countLines, $data2['quantity']);
$templateProcessor->setValue('name#'.$countLines, $data2['name']);
$templateProcessor->setValue('price#'.$countLines, "€ " .$data2['price'] ."");
}
\PhpOffice\PhpWord\Settings::setPdfRenderer('./dompdf');
\PhpOffice\PhpWord\Settings::setPdfRendererPath('./dompdf');
\PhpOffice\PhpWord\Settings::setPdfRendererName('DOMPDF');
$temp_file = tempnam(sys_get_temp_dir(), 'Word');
\$templateProcessor->saveAS($temp_file);
$phpWord = \PhpOffice\PhpWord\IOFactory::load($temp_file);
$xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord , 'PDF');
$xmlWriter->save('result.pdf');
header("Content-type:application/pdf");
header("Content-Disposition:attachment;filename='result.pdf'");
readfile("result.pdf");
After a look on the source code, it seems that PHPWord previously converts the document into an HTML representation before letting it be saved it into PDF by dompdf, another converter.
That's what the opened issue #1139 confirms, moreover it deals with styles missing:
The PDF writers being used are taking in the HTML output, which also lacks the styling. The classes are being defined in the <style> tag, but they are just not being used.
Also the last message adds:
This still seems to be an issue. html and pdf outputs do not replicate the some styles in docx (header / footers).
Concerning your border problem, another SO question shows a similar issue in a conversion HTML -> PDF. A solution was to edit the CSS style, which you obviously cannot perform in your sample code, unless you proceed to pre-convert into HTML.
In conclusion, you may not solve your problem in the short term. If you won't be a part of the dev team, you could submit bug reports to them (and not to dompdf, since it's an HTML-to-PDF converter and they are outside the scope). Github lets you to add DOCX files to the issue report.
Alternatives
You could check out a SO question 204860 about server sides PDF editing library. Below two alternatives, one is free software, the other is closed source and priced.
LibreOffice
Another way is to use LibreOffice in headless mode (command line execution without interface):
libreoffice --headless --convert-to pdf <filename_to_convert>
A PHP wrapper for LibreOffice, Office Converter is also available here if you don't want to bother using libreoffice through exec().
Check if LibreOffice conversion will suit your needs (it may not cover all cases, but be satisfying your scope).
Aspose
The best converter I ever used at work is Aspose, an API covering Documents with Aspose.Words package, Worksheets with Aspose.Cells, Presentations with Aspose.Slides and so on. But it's closed-source and pretty expensive (and you'll pay for updates if you want them after your license expiration).
There is a way to use it in PHP through Java (Aspose.Words and Aspose.Cells) or .NET (Aspose.Words same seems to go with Aspose.Cells).
When i import my php files to ftp all the code of each file stands on 1 line. Then when there is a commentary it puts in commentary all the code that comes after. How to do to import file and keep the form ?
I found the answer, i just had to change the uploading format. Put binary instead of automatic.
I have been trying to find a simple way to create OpenOffice calc files with no success.
I have tried:
openTBS - Seems to work writing an xml and a template file but can't find anything about how the xml file format.
Ods php generator - I tried this one as it provides clear examples, but when I copy the files to my server I always get corrupted files
Php doc writer - Tried an example and got an sxw file. I don't even know what that is
ODS-PHP - No documentation, only one example for creating 4 cells
Everything looks old, stalled and undocumented. ¿Any suggestion?
I have used opentbs successfully.
You can generate both excel and calc files. It also nice that you can "reuse" your html implementation so to speak.
Maybe this thread could get you going http://www.tinybutstrong.com/forum.php?thr=3069
Do the html version first.. then edit for calc/excel
Spout from Box works well enough for me. There are some missing features but it is simple to use, has a fluent API, and has no dependencies (it supports composer but you can use it standalone and its dependency graph has zero depth 😉 ).
Here's my "array of objects to ODS" pipeline, using Spout:
(I'm not using their recommended use import because all this code fits in a much larger file that I didn't want to contaminate and the $factory pattern looks cleaner to me anyway)
$factory = 'Box\Spout\Writer\Common\Creator\WriterEntityFactory';
$factory::createODSWriter()
->openToBrowser('filename.ods')
->addRow($factory::createRow([
$factory::createCell(__('Heading 1')),
$factory::createCell(__('Heading 2')),
$factory::createCell(__('Heading 3')),
]))
->addRows(array_map(function($row) use ($factory) {
return $factory::createRow([
$factory::createCell($row->first_val),
$factory::createCell($row->second_val),
$factory::createCell($row->third_val),
]);
}, loadDataFromSomewhere()))
->close();
Greetings !!
I have to insert a logo(image) on the row[0],column[0].I am using "Spreadsheet_Excel_Writer" for that.i tried its insertBitmap() methode ,program working fine but it doesn't show the bitmap image on xls sheet,instead blank row. what could be reason ? can you please let me know the exact string format for the argument. Is there any other way to insert image on xls sheet using PHP5.i am very new to php ,it will be a great help .
Have a nice time ahead !!
[edit]
Here is the code, as per Aman's comment below:
$sew =& new Spreadsheet_Excel_Writer ();
$worksheet =& $sew->addWorksheet (substr (strval ($name).strval ($sht), 0, 31));
$worksheet->insertBitmap ($row,$col,$image,$x,$y,$scale_x,$scale_y);
I never could get Spreadsheet_Excel_Writer to work properly with image insertions. Not sure if it's a bug in the library or what. But in any case, S_E_W is hideously outdated, you should switch to PHPExcel instead, which supports recent Excel formats (including .xlsx) for reading AND writing, whereas S_E_W is limited to BIFF 5.0, which is Excel '95 (or thereabouts) and only supports writing.
I've just ran a test using Spreadsheet_Excel_Writer. SEW saves the excel file using BIFF5 format. Open Office Calc will read images from BIFF8, but not from BIFF5 files.
EDIT
Further testing:
Setting SEW to write BIFF8 by using $workbook->setVersion(8); still doesn't write the bitmap image correctly as a BIFF8 file. It would seem that unless you want to rewrite SEW to store images correctly for BIFF8, then you won't see them when opening the file in OOCalc... without reading through the OOCalc or SEW code, I couldn't say what the problem is. Nor does Gnumeric read the image when the file is saved as BIFF5, but it will display the image correctly when the file is saved as BIFF8.
I've gotten this to work. The thing is, this writer is EXTREMELY sensitive to cell overwriting.
Your syntax is correct.
Things to look out for:
Make sure the file is 24 bit BMP. That's the only thing this writer supports.
Make sure nothing overwrites the cell where you place the image.
Make sure that the image path is correct.
And make sure the scale is set. If it's not set, it goes to 0 which doesn't display the image. The default is noted as 1, but it's not.
Greetings !!
I have to insert a logo(image) on the row[0],column[0].I am using "Spreadsheet_Excel_Writer" for that.i tried its insertBitmap() methode ,program working fine but it doesn't show the bitmap image on xls sheet,instead blank row. what could be reason ? can you please let me know the exact string format for the argument. Is there any other way to insert image on xls sheet using PHP5.i am very new to php ,it will be a great help .
Have a nice time ahead !!
[edit]
Here is the code, as per Aman's comment below:
$sew =& new Spreadsheet_Excel_Writer ();
$worksheet =& $sew->addWorksheet (substr (strval ($name).strval ($sht), 0, 31));
$worksheet->insertBitmap ($row,$col,$image,$x,$y,$scale_x,$scale_y);
I never could get Spreadsheet_Excel_Writer to work properly with image insertions. Not sure if it's a bug in the library or what. But in any case, S_E_W is hideously outdated, you should switch to PHPExcel instead, which supports recent Excel formats (including .xlsx) for reading AND writing, whereas S_E_W is limited to BIFF 5.0, which is Excel '95 (or thereabouts) and only supports writing.
I've just ran a test using Spreadsheet_Excel_Writer. SEW saves the excel file using BIFF5 format. Open Office Calc will read images from BIFF8, but not from BIFF5 files.
EDIT
Further testing:
Setting SEW to write BIFF8 by using $workbook->setVersion(8); still doesn't write the bitmap image correctly as a BIFF8 file. It would seem that unless you want to rewrite SEW to store images correctly for BIFF8, then you won't see them when opening the file in OOCalc... without reading through the OOCalc or SEW code, I couldn't say what the problem is. Nor does Gnumeric read the image when the file is saved as BIFF5, but it will display the image correctly when the file is saved as BIFF8.
I've gotten this to work. The thing is, this writer is EXTREMELY sensitive to cell overwriting.
Your syntax is correct.
Things to look out for:
Make sure the file is 24 bit BMP. That's the only thing this writer supports.
Make sure nothing overwrites the cell where you place the image.
Make sure that the image path is correct.
And make sure the scale is set. If it's not set, it goes to 0 which doesn't display the image. The default is noted as 1, but it's not.