[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/spout/src/Spout/Writer/ODS/Internal/ -> Worksheet.php (source)

   1  <?php
   2  
   3  namespace Box\Spout\Writer\ODS\Internal;
   4  
   5  use Box\Spout\Common\Exception\InvalidArgumentException;
   6  use Box\Spout\Common\Exception\IOException;
   7  use Box\Spout\Common\Helper\StringHelper;
   8  use Box\Spout\Writer\Common\Helper\CellHelper;
   9  use Box\Spout\Writer\Common\Internal\WorksheetInterface;
  10  
  11  /**
  12   * Class Worksheet
  13   * Represents a worksheet within a ODS file. The difference with the Sheet object is
  14   * that this class provides an interface to write data
  15   *
  16   * @package Box\Spout\Writer\ODS\Internal
  17   */
  18  class Worksheet implements WorksheetInterface
  19  {
  20      /** @var \Box\Spout\Writer\Common\Sheet The "external" sheet */
  21      protected $externalSheet;
  22  
  23      /** @var string Path to the XML file that will contain the sheet data */
  24      protected $worksheetFilePath;
  25  
  26      /** @var \Box\Spout\Common\Escaper\ODS Strings escaper */
  27      protected $stringsEscaper;
  28  
  29      /** @var \Box\Spout\Common\Helper\StringHelper To help with string manipulation */
  30      protected $stringHelper;
  31  
  32      /** @var Resource Pointer to the temporary sheet data file (e.g. worksheets-temp/sheet1.xml) */
  33      protected $sheetFilePointer;
  34  
  35      /** @var int Maximum number of columns among all the written rows */
  36      protected $maxNumColumns = 1;
  37  
  38      /** @var int Index of the last written row */
  39      protected $lastWrittenRowIndex = 0;
  40  
  41      /**
  42       * @param \Box\Spout\Writer\Common\Sheet $externalSheet The associated "external" sheet
  43       * @param string $worksheetFilesFolder Temporary folder where the files to create the XLSX will be stored
  44       * @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing
  45       */
  46      public function __construct($externalSheet, $worksheetFilesFolder)
  47      {
  48          $this->externalSheet = $externalSheet;
  49          /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
  50          $this->stringsEscaper = new \Box\Spout\Common\Escaper\ODS();
  51          $this->worksheetFilePath = $worksheetFilesFolder . '/sheet' . $externalSheet->getIndex() . '.xml';
  52  
  53          $this->stringHelper = new StringHelper();
  54  
  55          $this->startSheet();
  56      }
  57  
  58      /**
  59       * Prepares the worksheet to accept data
  60       * The XML file does not contain the "<table:table>" node as it contains the sheet's name
  61       * which may change during the execution of the program. It will be added at the end.
  62       *
  63       * @return void
  64       * @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing
  65       */
  66      protected function startSheet()
  67      {
  68          $this->sheetFilePointer = fopen($this->worksheetFilePath, 'w');
  69          $this->throwIfSheetFilePointerIsNotAvailable();
  70      }
  71  
  72      /**
  73       * Checks if the book has been created. Throws an exception if not created yet.
  74       *
  75       * @return void
  76       * @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing
  77       */
  78      protected function throwIfSheetFilePointerIsNotAvailable()
  79      {
  80          if (!$this->sheetFilePointer) {
  81              throw new IOException('Unable to open sheet for writing.');
  82          }
  83      }
  84  
  85      /**
  86       * @return string Path to the temporary sheet content XML file
  87       */
  88      public function getWorksheetFilePath()
  89      {
  90          return $this->worksheetFilePath;
  91      }
  92  
  93      /**
  94       * Returns the table XML root node as string.
  95       *
  96       * @return string <table> node as string
  97       */
  98      public function getTableElementStartAsString()
  99      {
 100          $escapedSheetName = $this->stringsEscaper->escape($this->externalSheet->getName());
 101          $tableStyleName = 'ta' . ($this->externalSheet->getIndex() + 1);
 102  
 103          $tableElement  = '<table:table table:style-name="' . $tableStyleName . '" table:name="' . $escapedSheetName . '">';
 104          $tableElement .= '<table:table-column table:default-cell-style-name="ce1" table:style-name="co1" table:number-columns-repeated="' . $this->maxNumColumns . '"/>';
 105  
 106          return $tableElement;
 107      }
 108  
 109      /**
 110       * @return \Box\Spout\Writer\Common\Sheet The "external" sheet
 111       */
 112      public function getExternalSheet()
 113      {
 114          return $this->externalSheet;
 115      }
 116  
 117      /**
 118       * @return int The index of the last written row
 119       */
 120      public function getLastWrittenRowIndex()
 121      {
 122          return $this->lastWrittenRowIndex;
 123      }
 124  
 125      /**
 126       * Adds data to the worksheet.
 127       *
 128       * @param array $dataRow Array containing data to be written. Cannot be empty.
 129       *          Example $dataRow = ['data1', 1234, null, '', 'data5'];
 130       * @param \Box\Spout\Writer\Style\Style $style Style to be applied to the row. NULL means use default style.
 131       * @return void
 132       * @throws \Box\Spout\Common\Exception\IOException If the data cannot be written
 133       * @throws \Box\Spout\Common\Exception\InvalidArgumentException If a cell value's type is not supported
 134       */
 135      public function addRow($dataRow, $style)
 136      {
 137          $styleIndex = ($style->getId() + 1); // 1-based
 138          $cellsCount = count($dataRow);
 139          $this->maxNumColumns = max($this->maxNumColumns, $cellsCount);
 140  
 141          $data = '<table:table-row table:style-name="ro1">';
 142  
 143          $currentCellIndex = 0;
 144          $nextCellIndex = 1;
 145  
 146          for ($i = 0; $i < $cellsCount; $i++) {
 147              $currentCellValue = $dataRow[$currentCellIndex];
 148  
 149              // Using isset here because it is way faster than array_key_exists...
 150              if (!isset($dataRow[$nextCellIndex]) || $currentCellValue !== $dataRow[$nextCellIndex]) {
 151                  $numTimesValueRepeated = ($nextCellIndex - $currentCellIndex);
 152                  $data .= $this->getCellContent($currentCellValue, $styleIndex, $numTimesValueRepeated);
 153  
 154                  $currentCellIndex = $nextCellIndex;
 155              }
 156  
 157              $nextCellIndex++;
 158          }
 159  
 160          $data .= '</table:table-row>';
 161  
 162          $wasWriteSuccessful = fwrite($this->sheetFilePointer, $data);
 163          if ($wasWriteSuccessful === false) {
 164              throw new IOException("Unable to write data in {$this->worksheetFilePath}");
 165          }
 166  
 167          // only update the count if the write worked
 168          $this->lastWrittenRowIndex++;
 169      }
 170  
 171      /**
 172       * Returns the cell XML content, given its value.
 173       *
 174       * @param mixed $cellValue The value to be written
 175       * @param int $styleIndex Index of the used style
 176       * @param int $numTimesValueRepeated Number of times the value is consecutively repeated
 177       * @return string The cell XML content
 178       * @throws \Box\Spout\Common\Exception\InvalidArgumentException If a cell value's type is not supported
 179       */
 180      protected function getCellContent($cellValue, $styleIndex, $numTimesValueRepeated)
 181      {
 182          $data = '<table:table-cell table:style-name="ce' . $styleIndex . '"';
 183  
 184          if ($numTimesValueRepeated !== 1) {
 185              $data .= ' table:number-columns-repeated="' . $numTimesValueRepeated . '"';
 186          }
 187  
 188          if (CellHelper::isNonEmptyString($cellValue)) {
 189              $data .= ' office:value-type="string" calcext:value-type="string">';
 190  
 191              $cellValueLines = explode("\n", $cellValue);
 192              foreach ($cellValueLines as $cellValueLine) {
 193                  $data .= '<text:p>' . $this->stringsEscaper->escape($cellValueLine) . '</text:p>';
 194              }
 195  
 196              $data .= '</table:table-cell>';
 197          } else if (CellHelper::isBoolean($cellValue)) {
 198              $data .= ' office:value-type="boolean" calcext:value-type="boolean" office:boolean-value="' . $cellValue . '">';
 199              $data .= '<text:p>' . $cellValue . '</text:p>';
 200              $data .= '</table:table-cell>';
 201          } else if (CellHelper::isNumeric($cellValue)) {
 202              $data .= ' office:value-type="float" calcext:value-type="float" office:value="' . $cellValue . '">';
 203              $data .= '<text:p>' . $cellValue . '</text:p>';
 204              $data .= '</table:table-cell>';
 205          } else if (empty($cellValue)) {
 206              $data .= '/>';
 207          } else {
 208              throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cellValue));
 209          }
 210  
 211          return $data;
 212      }
 213  
 214      /**
 215       * Closes the worksheet
 216       *
 217       * @return void
 218       */
 219      public function close()
 220      {
 221          fclose($this->sheetFilePointer);
 222      }
 223  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1