0

I'm trying to create an excel file, about 10 worksheets of 3 columns and roughly 30 rows each. I'm trying to highlight some groups of cells on each worksheet by setting some style properties (in addition to a couple cell mergers and column resizing). I'm finding that the document drops the styles after about the 4th worksheet.

My question is: can I do something to increase the number of styles I can apply to my document? Could it be that I am neglecting to do some cleanup? Some setting I'm missing?

I noticed some memory issue questions on SO that seemed related, so I checked the memory limits and tried cacheing. As far as I can tell, that doesn't seem to be the issue (please refute me if I'm wrong though!).

I created a toy example to demonstrate the problem. On my test server, the styles give out on the 3rd worksheet (about 50 applications). Toy example (EDIT: Due to this answer I changed the example a little so that the styles are clearly in disjoint regions).

EDIT: I tried the same thing on a different server (perhaps a slightly newer version of PHPExcel as well) and all the styles appear to be preserved in Excel5 formatted output, even after increasing the complexity and size.

<?php
require_once 'classes/PHPExcel.php';

ini_set('memory_limit','64M'); // The default memory_limit in php.ini is at least this as well
$cacheMethod = \PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;
$cacheSettings=array( 'memoryCacheSize'=>'32MB');
\PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);

$o = new \PHPExcel();

$style1 = array(
'fill'=>array(
   'type'=> \PHPExcel_Style_Fill::FILL_SOLID,
   'color'=>array('rgb'=>'CCFFCC'),
),
'font'=>array( 
    'size'=>17, 
    'name'=>'Calibri Light',
    'bold'=>false
),
);
$style2 = array(
'fill'=>array(
   'type'=> \PHPExcel_Style_Fill::FILL_SOLID,
   'color'=>array('rgb'=>'FFCCCC'),
),
'font'=>array( 
    'size'=>17, 
    'name'=>'Calibri Light',
    'bold'=>false
),
);
$maxws = 10;
$maxrow=40;
for ($ws=0;$ws<$maxws;$ws++){
$o->setActiveSheetIndex($ws);
$o->getActiveSheet()->setTitle("TEST $ws");
for ($row=1;$row<$maxrow; $row++){
    if ($row % 2){
           $o->getActiveSheet()
            ->getCell("A$row")
            ->setValue("Styled!");
           $o->getActiveSheet() ->getStyle("A$row") ->applyFromArray($style1);
    }else{
           $o->getActiveSheet()
            ->getCell("A$row")
            ->setValue("Default");
    }
       $o->getActiveSheet()
            ->getCell("B$row")
            ->setValue("Default");
    if ( ! ($row % 2)){
           $o->getActiveSheet()
            ->getCell("C$row")
            ->setValue("Other style!");
           $o->getActiveSheet() ->getStyle("C$row") ->applyFromArray($style2);
    }else{
           $o->getActiveSheet()
            ->getCell("C$row")
            ->setValue("Default");
    }
}
if ($ws+1<$maxws) $o->createSheet($ws+1);
}
//echo "Peak memory usage ". (memory_get_peak_usage(true)/1024/1024) . " MB\r\n"; die();
$filename = 'export_test.xls';
header("Content-Type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=\"$filename.xls\"");
header("Cache-Control: max-age=0");
$objWriter = \PHPExcel_IOFactory::createWriter($o, "Excel5");
$objWriter->save("php://output");
exit;
Community
  • 1
  • 1
amomin
  • 396
  • 1
  • 6
  • 14

2 Answers2

2

Style limitations for OfficeOpenXML .xlsx files (Excel2007 Writer):

  • Unique cell formats/cell styles: 64,000
  • Fill styles: 256
  • Line weight and styles: 256
  • Unique font types: 1,024 global fonts available for use; 512 per workbook Number formats in a workbook: Between 200 and 250, depending on the language version of Excel that you have installed

Style limitations for BIFF .xls files (Excel5 Writer):

  • Colours in a workbook: 56
  • Cell styles in a workbook: 4,000
  • Custom number formats: Between 200 and 250, depending on the language version of Excel you have installed.

Where possible, try to set styles in PHPExcel for a range of cells, rather than for individual cells; so rather than do

$o->getActiveSheet() ->getStyle("A$row") ->applyFromArray($style);

in your for loop, do

$o->getActiveSheet() ->getStyle("A1:A$maxrow") ->applyFromArray($style);

after the for loop has finished

Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • Many thanks for the very useful details. Regarding the range comment (which is also very useful!), in my toy example I set the styles on the individual cells intentionally for illustrative purposes; in my application the cells (groups) on which the styles were applied were not contiguous or uniformly styled, so this was not an option. – amomin Jan 29 '14 at 19:22
  • 1
    The difference between "style ranges" and "cell styles" is that each counts 1 toward those limits... so a style range A1:A3 will count as 1 style toward the limit, whereas cell styles for A1, A2 and A3 will count as 3 styles toward the limit.... but there are also performance and memory benefits in using cell ranges wherever possible. While it isn't always possible to do so, it's always beneficial to use style ranges wherever possible. – Mark Baker Jan 29 '14 at 20:47
  • Thanks for explaining this distinction. I will update my example to reflect my intent to ask about numerous "style ranges" which cannot be consolidated, which probably isn't clear as currently stated. As far as I know, it's not possible to specify discontinuous ranges such as "A1:A2, C2:C3" in a single style element. If that's incorrect please let me know because it would be relevant. – amomin Jan 29 '14 at 22:50
  • 1
    At the moment, no it isn't possible to specify a series of ranges, nor is it possible to specify column or row styles (e.g. `A:C` or `1:3`) – Mark Baker Jan 30 '14 at 00:23
1

This is not a complete answer but solves the issue for me.

The problem was the export format "Excel5" in the createWriter factory method. Switching to "Excel2007" fixes the issue (the styles I expect to see appear correctly). This works both for my real application and the toy example.

In code:

header("Content-Disposition: attachment; filename=\"$filename.xlsx\"");
header("Cache-Control: max-age=0");
$objWriter = \PHPExcel_IOFactory::createWriter($o, "Excel2007");
amomin
  • 396
  • 1
  • 6
  • 14
  • I was using "Excel5", and found that it only loops 48 times and stops applying style. And changed it to 'Excel2007' and fixed my issue. Thank you! – Adam C. Jun 23 '14 at 15:07