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\Xlsx;
   4  
   5  use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
   6  use PhpOffice\PhpSpreadsheet\Comment;
   7  use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
   8  
   9  class Comments extends WriterPart
  10  {
  11      /**
  12       * Write comments to XML format.
  13       *
  14       * @param \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet
  15       *
  16       * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
  17       *
  18       * @return string XML Output
  19       */
  20      public function writeComments(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet)
  21      {
  22          // Create XML writer
  23          $objWriter = null;
  24          if ($this->getParentWriter()->getUseDiskCaching()) {
  25              $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
  26          } else {
  27              $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
  28          }
  29  
  30          // XML header
  31          $objWriter->startDocument('1.0', 'UTF-8', 'yes');
  32  
  33          // Comments cache
  34          $comments = $pWorksheet->getComments();
  35  
  36          // Authors cache
  37          $authors = [];
  38          $authorId = 0;
  39          foreach ($comments as $comment) {
  40              if (!isset($authors[$comment->getAuthor()])) {
  41                  $authors[$comment->getAuthor()] = $authorId++;
  42              }
  43          }
  44  
  45          // comments
  46          $objWriter->startElement('comments');
  47          $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
  48  
  49          // Loop through authors
  50          $objWriter->startElement('authors');
  51          foreach ($authors as $author => $index) {
  52              $objWriter->writeElement('author', $author);
  53          }
  54          $objWriter->endElement();
  55  
  56          // Loop through comments
  57          $objWriter->startElement('commentList');
  58          foreach ($comments as $key => $value) {
  59              $this->writeComment($objWriter, $key, $value, $authors);
  60          }
  61          $objWriter->endElement();
  62  
  63          $objWriter->endElement();
  64  
  65          // Return
  66          return $objWriter->getData();
  67      }
  68  
  69      /**
  70       * Write comment to XML format.
  71       *
  72       * @param XMLWriter $objWriter XML Writer
  73       * @param string $pCellReference Cell reference
  74       * @param Comment $pComment Comment
  75       * @param array $pAuthors Array of authors
  76       *
  77       * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
  78       */
  79      private function writeComment(XMLWriter $objWriter, $pCellReference, Comment $pComment, array $pAuthors)
  80      {
  81          // comment
  82          $objWriter->startElement('comment');
  83          $objWriter->writeAttribute('ref', $pCellReference);
  84          $objWriter->writeAttribute('authorId', $pAuthors[$pComment->getAuthor()]);
  85  
  86          // text
  87          $objWriter->startElement('text');
  88          $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $pComment->getText());
  89          $objWriter->endElement();
  90  
  91          $objWriter->endElement();
  92      }
  93  
  94      /**
  95       * Write VML comments to XML format.
  96       *
  97       * @param \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet
  98       *
  99       * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
 100       *
 101       * @return string XML Output
 102       */
 103      public function writeVMLComments(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $pWorksheet)
 104      {
 105          // Create XML writer
 106          $objWriter = null;
 107          if ($this->getParentWriter()->getUseDiskCaching()) {
 108              $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
 109          } else {
 110              $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
 111          }
 112  
 113          // XML header
 114          $objWriter->startDocument('1.0', 'UTF-8', 'yes');
 115  
 116          // Comments cache
 117          $comments = $pWorksheet->getComments();
 118  
 119          // xml
 120          $objWriter->startElement('xml');
 121          $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml');
 122          $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office');
 123          $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel');
 124  
 125          // o:shapelayout
 126          $objWriter->startElement('o:shapelayout');
 127          $objWriter->writeAttribute('v:ext', 'edit');
 128  
 129          // o:idmap
 130          $objWriter->startElement('o:idmap');
 131          $objWriter->writeAttribute('v:ext', 'edit');
 132          $objWriter->writeAttribute('data', '1');
 133          $objWriter->endElement();
 134  
 135          $objWriter->endElement();
 136  
 137          // v:shapetype
 138          $objWriter->startElement('v:shapetype');
 139          $objWriter->writeAttribute('id', '_x0000_t202');
 140          $objWriter->writeAttribute('coordsize', '21600,21600');
 141          $objWriter->writeAttribute('o:spt', '202');
 142          $objWriter->writeAttribute('path', 'm,l,21600r21600,l21600,xe');
 143  
 144          // v:stroke
 145          $objWriter->startElement('v:stroke');
 146          $objWriter->writeAttribute('joinstyle', 'miter');
 147          $objWriter->endElement();
 148  
 149          // v:path
 150          $objWriter->startElement('v:path');
 151          $objWriter->writeAttribute('gradientshapeok', 't');
 152          $objWriter->writeAttribute('o:connecttype', 'rect');
 153          $objWriter->endElement();
 154  
 155          $objWriter->endElement();
 156  
 157          // Loop through comments
 158          foreach ($comments as $key => $value) {
 159              $this->writeVMLComment($objWriter, $key, $value);
 160          }
 161  
 162          $objWriter->endElement();
 163  
 164          // Return
 165          return $objWriter->getData();
 166      }
 167  
 168      /**
 169       * Write VML comment to XML format.
 170       *
 171       * @param XMLWriter $objWriter XML Writer
 172       * @param string $pCellReference Cell reference, eg: 'A1'
 173       * @param Comment $pComment Comment
 174       */
 175      private function writeVMLComment(XMLWriter $objWriter, $pCellReference, Comment $pComment)
 176      {
 177          // Metadata
 178          [$column, $row] = Coordinate::coordinateFromString($pCellReference);
 179          $column = Coordinate::columnIndexFromString($column);
 180          $id = 1024 + $column + $row;
 181          $id = substr($id, 0, 4);
 182  
 183          // v:shape
 184          $objWriter->startElement('v:shape');
 185          $objWriter->writeAttribute('id', '_x0000_s' . $id);
 186          $objWriter->writeAttribute('type', '#_x0000_t202');
 187          $objWriter->writeAttribute('style', 'position:absolute;margin-left:' . $pComment->getMarginLeft() . ';margin-top:' . $pComment->getMarginTop() . ';width:' . $pComment->getWidth() . ';height:' . $pComment->getHeight() . ';z-index:1;visibility:' . ($pComment->getVisible() ? 'visible' : 'hidden'));
 188          $objWriter->writeAttribute('fillcolor', '#' . $pComment->getFillColor()->getRGB());
 189          $objWriter->writeAttribute('o:insetmode', 'auto');
 190  
 191          // v:fill
 192          $objWriter->startElement('v:fill');
 193          $objWriter->writeAttribute('color2', '#' . $pComment->getFillColor()->getRGB());
 194          $objWriter->endElement();
 195  
 196          // v:shadow
 197          $objWriter->startElement('v:shadow');
 198          $objWriter->writeAttribute('on', 't');
 199          $objWriter->writeAttribute('color', 'black');
 200          $objWriter->writeAttribute('obscured', 't');
 201          $objWriter->endElement();
 202  
 203          // v:path
 204          $objWriter->startElement('v:path');
 205          $objWriter->writeAttribute('o:connecttype', 'none');
 206          $objWriter->endElement();
 207  
 208          // v:textbox
 209          $objWriter->startElement('v:textbox');
 210          $objWriter->writeAttribute('style', 'mso-direction-alt:auto');
 211  
 212          // div
 213          $objWriter->startElement('div');
 214          $objWriter->writeAttribute('style', 'text-align:left');
 215          $objWriter->endElement();
 216  
 217          $objWriter->endElement();
 218  
 219          // x:ClientData
 220          $objWriter->startElement('x:ClientData');
 221          $objWriter->writeAttribute('ObjectType', 'Note');
 222  
 223          // x:MoveWithCells
 224          $objWriter->writeElement('x:MoveWithCells', '');
 225  
 226          // x:SizeWithCells
 227          $objWriter->writeElement('x:SizeWithCells', '');
 228  
 229          // x:AutoFill
 230          $objWriter->writeElement('x:AutoFill', 'False');
 231  
 232          // x:Row
 233          $objWriter->writeElement('x:Row', ($row - 1));
 234  
 235          // x:Column
 236          $objWriter->writeElement('x:Column', ($column - 1));
 237  
 238          $objWriter->endElement();
 239  
 240          $objWriter->endElement();
 241      }
 242  }