Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Writer;
   4  
   5  use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
   6  use PhpOffice\PhpSpreadsheet\Calculation\Functions;
   7  use PhpOffice\PhpSpreadsheet\HashTable;
   8  use PhpOffice\PhpSpreadsheet\Shared\File;
   9  use PhpOffice\PhpSpreadsheet\Spreadsheet;
  10  use PhpOffice\PhpSpreadsheet\Worksheet\Drawing as WorksheetDrawing;
  11  use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
  12  use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
  13  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Chart;
  14  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Comments;
  15  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\ContentTypes;
  16  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\DocProps;
  17  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Drawing;
  18  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Rels;
  19  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\RelsRibbon;
  20  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\RelsVBA;
  21  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\StringTable;
  22  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Style;
  23  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Theme;
  24  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Workbook;
  25  use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet;
  26  use ZipArchive;
  27  
  28  class Xlsx extends BaseWriter
  29  {
  30      /**
  31       * Office2003 compatibility.
  32       *
  33       * @var bool
  34       */
  35      private $office2003compatibility = false;
  36  
  37      /**
  38       * Private writer parts.
  39       *
  40       * @var Xlsx\WriterPart[]
  41       */
  42      private $writerParts = [];
  43  
  44      /**
  45       * Private Spreadsheet.
  46       *
  47       * @var Spreadsheet
  48       */
  49      private $spreadSheet;
  50  
  51      /**
  52       * Private string table.
  53       *
  54       * @var string[]
  55       */
  56      private $stringTable = [];
  57  
  58      /**
  59       * Private unique Conditional HashTable.
  60       *
  61       * @var HashTable
  62       */
  63      private $stylesConditionalHashTable;
  64  
  65      /**
  66       * Private unique Style HashTable.
  67       *
  68       * @var HashTable
  69       */
  70      private $styleHashTable;
  71  
  72      /**
  73       * Private unique Fill HashTable.
  74       *
  75       * @var HashTable
  76       */
  77      private $fillHashTable;
  78  
  79      /**
  80       * Private unique \PhpOffice\PhpSpreadsheet\Style\Font HashTable.
  81       *
  82       * @var HashTable
  83       */
  84      private $fontHashTable;
  85  
  86      /**
  87       * Private unique Borders HashTable.
  88       *
  89       * @var HashTable
  90       */
  91      private $bordersHashTable;
  92  
  93      /**
  94       * Private unique NumberFormat HashTable.
  95       *
  96       * @var HashTable
  97       */
  98      private $numFmtHashTable;
  99  
 100      /**
 101       * Private unique \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\BaseDrawing HashTable.
 102       *
 103       * @var HashTable
 104       */
 105      private $drawingHashTable;
 106  
 107      /**
 108       * Create a new Xlsx Writer.
 109       *
 110       * @param Spreadsheet $spreadsheet
 111       */
 112      public function __construct(Spreadsheet $spreadsheet)
 113      {
 114          // Assign PhpSpreadsheet
 115          $this->setSpreadsheet($spreadsheet);
 116  
 117          $writerPartsArray = [
 118              'stringtable' => StringTable::class,
 119              'contenttypes' => ContentTypes::class,
 120              'docprops' => DocProps::class,
 121              'rels' => Rels::class,
 122              'theme' => Theme::class,
 123              'style' => Style::class,
 124              'workbook' => Workbook::class,
 125              'worksheet' => Worksheet::class,
 126              'drawing' => Drawing::class,
 127              'comments' => Comments::class,
 128              'chart' => Chart::class,
 129              'relsvba' => RelsVBA::class,
 130              'relsribbonobjects' => RelsRibbon::class,
 131          ];
 132  
 133          //    Initialise writer parts
 134          //        and Assign their parent IWriters
 135          foreach ($writerPartsArray as $writer => $class) {
 136              $this->writerParts[$writer] = new $class($this);
 137          }
 138  
 139          $hashTablesArray = ['stylesConditionalHashTable', 'fillHashTable', 'fontHashTable',
 140              'bordersHashTable', 'numFmtHashTable', 'drawingHashTable',
 141              'styleHashTable',
 142          ];
 143  
 144          // Set HashTable variables
 145          foreach ($hashTablesArray as $tableName) {
 146              $this->$tableName = new HashTable();
 147          }
 148      }
 149  
 150      /**
 151       * Get writer part.
 152       *
 153       * @param string $pPartName Writer part name
 154       *
 155       * @return \PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart
 156       */
 157      public function getWriterPart($pPartName)
 158      {
 159          if ($pPartName != '' && isset($this->writerParts[strtolower($pPartName)])) {
 160              return $this->writerParts[strtolower($pPartName)];
 161          }
 162  
 163          return null;
 164      }
 165  
 166      /**
 167       * Save PhpSpreadsheet to file.
 168       *
 169       * @param string $pFilename
 170       *
 171       * @throws WriterException
 172       */
 173      public function save($pFilename)
 174      {
 175          if ($this->spreadSheet !== null) {
 176              // garbage collect
 177              $this->spreadSheet->garbageCollect();
 178  
 179              // If $pFilename is php://output or php://stdout, make it a temporary file...
 180              $originalFilename = $pFilename;
 181              if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
 182                  $pFilename = @tempnam(File::sysGetTempDir(), 'phpxltmp');
 183                  if ($pFilename == '') {
 184                      $pFilename = $originalFilename;
 185                  }
 186              }
 187  
 188              $saveDebugLog = Calculation::getInstance($this->spreadSheet)->getDebugLog()->getWriteDebugLog();
 189              Calculation::getInstance($this->spreadSheet)->getDebugLog()->setWriteDebugLog(false);
 190              $saveDateReturnType = Functions::getReturnDateType();
 191              Functions::setReturnDateType(Functions::RETURNDATE_EXCEL);
 192  
 193              // Create string lookup table
 194              $this->stringTable = [];
 195              for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
 196                  $this->stringTable = $this->getWriterPart('StringTable')->createStringTable($this->spreadSheet->getSheet($i), $this->stringTable);
 197              }
 198  
 199              // Create styles dictionaries
 200              $this->styleHashTable->addFromSource($this->getWriterPart('Style')->allStyles($this->spreadSheet));
 201              $this->stylesConditionalHashTable->addFromSource($this->getWriterPart('Style')->allConditionalStyles($this->spreadSheet));
 202              $this->fillHashTable->addFromSource($this->getWriterPart('Style')->allFills($this->spreadSheet));
 203              $this->fontHashTable->addFromSource($this->getWriterPart('Style')->allFonts($this->spreadSheet));
 204              $this->bordersHashTable->addFromSource($this->getWriterPart('Style')->allBorders($this->spreadSheet));
 205              $this->numFmtHashTable->addFromSource($this->getWriterPart('Style')->allNumberFormats($this->spreadSheet));
 206  
 207              // Create drawing dictionary
 208              $this->drawingHashTable->addFromSource($this->getWriterPart('Drawing')->allDrawings($this->spreadSheet));
 209  
 210              $zip = new ZipArchive();
 211  
 212              if (file_exists($pFilename)) {
 213                  unlink($pFilename);
 214              }
 215              // Try opening the ZIP file
 216              if ($zip->open($pFilename, ZipArchive::OVERWRITE) !== true) {
 217                  if ($zip->open($pFilename, ZipArchive::CREATE) !== true) {
 218                      throw new WriterException('Could not open ' . $pFilename . ' for writing.');
 219                  }
 220              }
 221  
 222              // Add [Content_Types].xml to ZIP file
 223              $zip->addFromString('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->spreadSheet, $this->includeCharts));
 224  
 225              //if hasMacros, add the vbaProject.bin file, Certificate file(if exists)
 226              if ($this->spreadSheet->hasMacros()) {
 227                  $macrosCode = $this->spreadSheet->getMacrosCode();
 228                  if ($macrosCode !== null) {
 229                      // we have the code ?
 230                      $zip->addFromString('xl/vbaProject.bin', $macrosCode); //allways in 'xl', allways named vbaProject.bin
 231                      if ($this->spreadSheet->hasMacrosCertificate()) {
 232                          //signed macros ?
 233                          // Yes : add the certificate file and the related rels file
 234                          $zip->addFromString('xl/vbaProjectSignature.bin', $this->spreadSheet->getMacrosCertificate());
 235                          $zip->addFromString('xl/_rels/vbaProject.bin.rels', $this->getWriterPart('RelsVBA')->writeVBARelationships($this->spreadSheet));
 236                      }
 237                  }
 238              }
 239              //a custom UI in this workbook ? add it ("base" xml and additional objects (pictures) and rels)
 240              if ($this->spreadSheet->hasRibbon()) {
 241                  $tmpRibbonTarget = $this->spreadSheet->getRibbonXMLData('target');
 242                  $zip->addFromString($tmpRibbonTarget, $this->spreadSheet->getRibbonXMLData('data'));
 243                  if ($this->spreadSheet->hasRibbonBinObjects()) {
 244                      $tmpRootPath = dirname($tmpRibbonTarget) . '/';
 245                      $ribbonBinObjects = $this->spreadSheet->getRibbonBinObjects('data'); //the files to write
 246                      foreach ($ribbonBinObjects as $aPath => $aContent) {
 247                          $zip->addFromString($tmpRootPath . $aPath, $aContent);
 248                      }
 249                      //the rels for files
 250                      $zip->addFromString($tmpRootPath . '_rels/' . basename($tmpRibbonTarget) . '.rels', $this->getWriterPart('RelsRibbonObjects')->writeRibbonRelationships($this->spreadSheet));
 251                  }
 252              }
 253  
 254              // Add relationships to ZIP file
 255              $zip->addFromString('_rels/.rels', $this->getWriterPart('Rels')->writeRelationships($this->spreadSheet));
 256              $zip->addFromString('xl/_rels/workbook.xml.rels', $this->getWriterPart('Rels')->writeWorkbookRelationships($this->spreadSheet));
 257  
 258              // Add document properties to ZIP file
 259              $zip->addFromString('docProps/app.xml', $this->getWriterPart('DocProps')->writeDocPropsApp($this->spreadSheet));
 260              $zip->addFromString('docProps/core.xml', $this->getWriterPart('DocProps')->writeDocPropsCore($this->spreadSheet));
 261              $customPropertiesPart = $this->getWriterPart('DocProps')->writeDocPropsCustom($this->spreadSheet);
 262              if ($customPropertiesPart !== null) {
 263                  $zip->addFromString('docProps/custom.xml', $customPropertiesPart);
 264              }
 265  
 266              // Add theme to ZIP file
 267              $zip->addFromString('xl/theme/theme1.xml', $this->getWriterPart('Theme')->writeTheme($this->spreadSheet));
 268  
 269              // Add string table to ZIP file
 270              $zip->addFromString('xl/sharedStrings.xml', $this->getWriterPart('StringTable')->writeStringTable($this->stringTable));
 271  
 272              // Add styles to ZIP file
 273              $zip->addFromString('xl/styles.xml', $this->getWriterPart('Style')->writeStyles($this->spreadSheet));
 274  
 275              // Add workbook to ZIP file
 276              $zip->addFromString('xl/workbook.xml', $this->getWriterPart('Workbook')->writeWorkbook($this->spreadSheet, $this->preCalculateFormulas));
 277  
 278              $chartCount = 0;
 279              // Add worksheets
 280              for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
 281                  $zip->addFromString('xl/worksheets/sheet' . ($i + 1) . '.xml', $this->getWriterPart('Worksheet')->writeWorksheet($this->spreadSheet->getSheet($i), $this->stringTable, $this->includeCharts));
 282                  if ($this->includeCharts) {
 283                      $charts = $this->spreadSheet->getSheet($i)->getChartCollection();
 284                      if (count($charts) > 0) {
 285                          foreach ($charts as $chart) {
 286                              $zip->addFromString('xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart')->writeChart($chart, $this->preCalculateFormulas));
 287                              ++$chartCount;
 288                          }
 289                      }
 290                  }
 291              }
 292  
 293              $chartRef1 = 0;
 294              // Add worksheet relationships (drawings, ...)
 295              for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
 296                  // Add relationships
 297                  $zip->addFromString('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->spreadSheet->getSheet($i), ($i + 1), $this->includeCharts));
 298  
 299                  // Add unparsedLoadedData
 300                  $sheetCodeName = $this->spreadSheet->getSheet($i)->getCodeName();
 301                  $unparsedLoadedData = $this->spreadSheet->getUnparsedLoadedData();
 302                  if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['ctrlProps'])) {
 303                      foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['ctrlProps'] as $ctrlProp) {
 304                          $zip->addFromString($ctrlProp['filePath'], $ctrlProp['content']);
 305                      }
 306                  }
 307                  if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['printerSettings'])) {
 308                      foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['printerSettings'] as $ctrlProp) {
 309                          $zip->addFromString($ctrlProp['filePath'], $ctrlProp['content']);
 310                      }
 311                  }
 312  
 313                  $drawings = $this->spreadSheet->getSheet($i)->getDrawingCollection();
 314                  $drawingCount = count($drawings);
 315                  if ($this->includeCharts) {
 316                      $chartCount = $this->spreadSheet->getSheet($i)->getChartCount();
 317                  }
 318  
 319                  // Add drawing and image relationship parts
 320                  if (($drawingCount > 0) || ($chartCount > 0)) {
 321                      // Drawing relationships
 322                      $zip->addFromString('xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeDrawingRelationships($this->spreadSheet->getSheet($i), $chartRef1, $this->includeCharts));
 323  
 324                      // Drawings
 325                      $zip->addFromString('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts));
 326                  } elseif (isset($unparsedLoadedData['sheets'][$sheetCodeName]['drawingAlternateContents'])) {
 327                      // Drawings
 328                      $zip->addFromString('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts));
 329                  }
 330  
 331                  // Add unparsed drawings
 332                  if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['Drawings'])) {
 333                      foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['Drawings'] as $relId => $drawingXml) {
 334                          $drawingFile = array_search($relId, $unparsedLoadedData['sheets'][$sheetCodeName]['drawingOriginalIds']);
 335                          if ($drawingFile !== false) {
 336                              $drawingFile = ltrim($drawingFile, '.');
 337                              $zip->addFromString('xl' . $drawingFile, $drawingXml);
 338                          }
 339                      }
 340                  }
 341  
 342                  // Add comment relationship parts
 343                  if (count($this->spreadSheet->getSheet($i)->getComments()) > 0) {
 344                      // VML Comments
 345                      $zip->addFromString('xl/drawings/vmlDrawing' . ($i + 1) . '.vml', $this->getWriterPart('Comments')->writeVMLComments($this->spreadSheet->getSheet($i)));
 346  
 347                      // Comments
 348                      $zip->addFromString('xl/comments' . ($i + 1) . '.xml', $this->getWriterPart('Comments')->writeComments($this->spreadSheet->getSheet($i)));
 349                  }
 350  
 351                  // Add unparsed relationship parts
 352                  if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['vmlDrawings'])) {
 353                      foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['vmlDrawings'] as $vmlDrawing) {
 354                          $zip->addFromString($vmlDrawing['filePath'], $vmlDrawing['content']);
 355                      }
 356                  }
 357  
 358                  // Add header/footer relationship parts
 359                  if (count($this->spreadSheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) {
 360                      // VML Drawings
 361                      $zip->addFromString('xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml', $this->getWriterPart('Drawing')->writeVMLHeaderFooterImages($this->spreadSheet->getSheet($i)));
 362  
 363                      // VML Drawing relationships
 364                      $zip->addFromString('xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels', $this->getWriterPart('Rels')->writeHeaderFooterDrawingRelationships($this->spreadSheet->getSheet($i)));
 365  
 366                      // Media
 367                      foreach ($this->spreadSheet->getSheet($i)->getHeaderFooter()->getImages() as $image) {
 368                          $zip->addFromString('xl/media/' . $image->getIndexedFilename(), file_get_contents($image->getPath()));
 369                      }
 370                  }
 371              }
 372  
 373              // Add media
 374              for ($i = 0; $i < $this->getDrawingHashTable()->count(); ++$i) {
 375                  if ($this->getDrawingHashTable()->getByIndex($i) instanceof WorksheetDrawing) {
 376                      $imageContents = null;
 377                      $imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath();
 378                      if (strpos($imagePath, 'zip://') !== false) {
 379                          $imagePath = substr($imagePath, 6);
 380                          $imagePathSplitted = explode('#', $imagePath);
 381  
 382                          $imageZip = new ZipArchive();
 383                          $imageZip->open($imagePathSplitted[0]);
 384                          $imageContents = $imageZip->getFromName($imagePathSplitted[1]);
 385                          $imageZip->close();
 386                          unset($imageZip);
 387                      } else {
 388                          $imageContents = file_get_contents($imagePath);
 389                      }
 390  
 391                      $zip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents);
 392                  } elseif ($this->getDrawingHashTable()->getByIndex($i) instanceof MemoryDrawing) {
 393                      ob_start();
 394                      call_user_func(
 395                          $this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction(),
 396                          $this->getDrawingHashTable()->getByIndex($i)->getImageResource()
 397                      );
 398                      $imageContents = ob_get_contents();
 399                      ob_end_clean();
 400  
 401                      $zip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents);
 402                  }
 403              }
 404  
 405              Functions::setReturnDateType($saveDateReturnType);
 406              Calculation::getInstance($this->spreadSheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
 407  
 408              // Close file
 409              if ($zip->close() === false) {
 410                  throw new WriterException("Could not close zip file $pFilename.");
 411              }
 412  
 413              // If a temporary file was used, copy it to the correct file stream
 414              if ($originalFilename != $pFilename) {
 415                  if (copy($pFilename, $originalFilename) === false) {
 416                      throw new WriterException("Could not copy temporary zip file $pFilename to $originalFilename.");
 417                  }
 418                  @unlink($pFilename);
 419              }
 420          } else {
 421              throw new WriterException('PhpSpreadsheet object unassigned.');
 422          }
 423      }
 424  
 425      /**
 426       * Get Spreadsheet object.
 427       *
 428       * @throws WriterException
 429       *
 430       * @return Spreadsheet
 431       */
 432      public function getSpreadsheet()
 433      {
 434          if ($this->spreadSheet !== null) {
 435              return $this->spreadSheet;
 436          }
 437  
 438          throw new WriterException('No Spreadsheet object assigned.');
 439      }
 440  
 441      /**
 442       * Set Spreadsheet object.
 443       *
 444       * @param Spreadsheet $spreadsheet PhpSpreadsheet object
 445       *
 446       * @return Xlsx
 447       */
 448      public function setSpreadsheet(Spreadsheet $spreadsheet)
 449      {
 450          $this->spreadSheet = $spreadsheet;
 451  
 452          return $this;
 453      }
 454  
 455      /**
 456       * Get string table.
 457       *
 458       * @return string[]
 459       */
 460      public function getStringTable()
 461      {
 462          return $this->stringTable;
 463      }
 464  
 465      /**
 466       * Get Style HashTable.
 467       *
 468       * @return HashTable
 469       */
 470      public function getStyleHashTable()
 471      {
 472          return $this->styleHashTable;
 473      }
 474  
 475      /**
 476       * Get Conditional HashTable.
 477       *
 478       * @return HashTable
 479       */
 480      public function getStylesConditionalHashTable()
 481      {
 482          return $this->stylesConditionalHashTable;
 483      }
 484  
 485      /**
 486       * Get Fill HashTable.
 487       *
 488       * @return HashTable
 489       */
 490      public function getFillHashTable()
 491      {
 492          return $this->fillHashTable;
 493      }
 494  
 495      /**
 496       * Get \PhpOffice\PhpSpreadsheet\Style\Font HashTable.
 497       *
 498       * @return HashTable
 499       */
 500      public function getFontHashTable()
 501      {
 502          return $this->fontHashTable;
 503      }
 504  
 505      /**
 506       * Get Borders HashTable.
 507       *
 508       * @return HashTable
 509       */
 510      public function getBordersHashTable()
 511      {
 512          return $this->bordersHashTable;
 513      }
 514  
 515      /**
 516       * Get NumberFormat HashTable.
 517       *
 518       * @return HashTable
 519       */
 520      public function getNumFmtHashTable()
 521      {
 522          return $this->numFmtHashTable;
 523      }
 524  
 525      /**
 526       * Get \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\BaseDrawing HashTable.
 527       *
 528       * @return HashTable
 529       */
 530      public function getDrawingHashTable()
 531      {
 532          return $this->drawingHashTable;
 533      }
 534  
 535      /**
 536       * Get Office2003 compatibility.
 537       *
 538       * @return bool
 539       */
 540      public function getOffice2003Compatibility()
 541      {
 542          return $this->office2003compatibility;
 543      }
 544  
 545      /**
 546       * Set Office2003 compatibility.
 547       *
 548       * @param bool $pValue Office2003 compatibility?
 549       *
 550       * @return Xlsx
 551       */
 552      public function setOffice2003Compatibility($pValue)
 553      {
 554          $this->office2003compatibility = $pValue;
 555  
 556          return $this;
 557      }
 558  }