Comments.php 8.0 KB

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