Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

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

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