Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
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\Reader\Xlsx\Namespaces; 8 use PhpOffice\PhpSpreadsheet\Shared\XMLWriter; 9 10 class Comments extends WriterPart 11 { 12 /** 13 * Write comments to XML format. 14 * 15 * @return string XML Output 16 */ 17 public function writeComments(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet) 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 27 // XML header 28 $objWriter->startDocument('1.0', 'UTF-8', 'yes'); 29 30 // Comments cache 31 $comments = $worksheet->getComments(); 32 33 // Authors cache 34 $authors = []; 35 $authorId = 0; 36 foreach ($comments as $comment) { 37 if (!isset($authors[$comment->getAuthor()])) { 38 $authors[$comment->getAuthor()] = $authorId++; 39 } 40 } 41 42 // comments 43 $objWriter->startElement('comments'); 44 $objWriter->writeAttribute('xmlns', Namespaces::MAIN); 45 46 // Loop through authors 47 $objWriter->startElement('authors'); 48 foreach ($authors as $author => $index) { 49 $objWriter->writeElement('author', $author); 50 } 51 $objWriter->endElement(); 52 53 // Loop through comments 54 $objWriter->startElement('commentList'); 55 foreach ($comments as $key => $value) { 56 $this->writeComment($objWriter, $key, $value, $authors); 57 } 58 $objWriter->endElement(); 59 60 $objWriter->endElement(); 61 62 // Return 63 return $objWriter->getData(); 64 } 65 66 /** 67 * Write comment to XML format. 68 * 69 * @param string $cellReference Cell reference 70 * @param Comment $comment Comment 71 * @param array $authors Array of authors 72 */ 73 private function writeComment(XMLWriter $objWriter, $cellReference, Comment $comment, array $authors): void 74 { 75 // comment 76 $objWriter->startElement('comment'); 77 $objWriter->writeAttribute('ref', $cellReference); 78 $objWriter->writeAttribute('authorId', $authors[$comment->getAuthor()]); 79 80 // text 81 $objWriter->startElement('text'); 82 $this->getParentWriter()->getWriterPartstringtable()->writeRichText($objWriter, $comment->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 $worksheet) 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 = $worksheet->getComments(); 108 109 // xml 110 $objWriter->startElement('xml'); 111 $objWriter->writeAttribute('xmlns:v', Namespaces::URN_VML); 112 $objWriter->writeAttribute('xmlns:o', Namespaces::URN_MSOFFICE); 113 $objWriter->writeAttribute('xmlns:x', Namespaces::URN_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 string $cellReference Cell reference, eg: 'A1' 162 * @param Comment $comment Comment 163 */ 164 private function writeVMLComment(XMLWriter $objWriter, $cellReference, Comment $comment): void 165 { 166 // Metadata 167 [$column, $row] = Coordinate::indexesFromString($cellReference); 168 $id = 1024 + $column + $row; 169 $id = substr("$id", 0, 4); 170 171 // v:shape 172 $objWriter->startElement('v:shape'); 173 $objWriter->writeAttribute('id', '_x0000_s' . $id); 174 $objWriter->writeAttribute('type', '#_x0000_t202'); 175 $objWriter->writeAttribute('style', 'position:absolute;margin-left:' . $comment->getMarginLeft() . ';margin-top:' . $comment->getMarginTop() . ';width:' . $comment->getWidth() . ';height:' . $comment->getHeight() . ';z-index:1;visibility:' . ($comment->getVisible() ? 'visible' : 'hidden')); 176 $objWriter->writeAttribute('fillcolor', '#' . $comment->getFillColor()->getRGB()); 177 $objWriter->writeAttribute('o:insetmode', 'auto'); 178 179 // v:fill 180 $objWriter->startElement('v:fill'); 181 $objWriter->writeAttribute('color2', '#' . $comment->getFillColor()->getRGB()); 182 if ($comment->hasBackgroundImage()) { 183 $bgImage = $comment->getBackgroundImage(); 184 $objWriter->writeAttribute('o:relid', 'rId' . $bgImage->getImageIndex()); 185 $objWriter->writeAttribute('o:title', $bgImage->getName()); 186 $objWriter->writeAttribute('type', 'frame'); 187 } 188 $objWriter->endElement(); 189 190 // v:shadow 191 $objWriter->startElement('v:shadow'); 192 $objWriter->writeAttribute('on', 't'); 193 $objWriter->writeAttribute('color', 'black'); 194 $objWriter->writeAttribute('obscured', 't'); 195 $objWriter->endElement(); 196 197 // v:path 198 $objWriter->startElement('v:path'); 199 $objWriter->writeAttribute('o:connecttype', 'none'); 200 $objWriter->endElement(); 201 202 // v:textbox 203 $objWriter->startElement('v:textbox'); 204 $objWriter->writeAttribute('style', 'mso-direction-alt:auto'); 205 206 // div 207 $objWriter->startElement('div'); 208 $objWriter->writeAttribute('style', 'text-align:left'); 209 $objWriter->endElement(); 210 211 $objWriter->endElement(); 212 213 // x:ClientData 214 $objWriter->startElement('x:ClientData'); 215 $objWriter->writeAttribute('ObjectType', 'Note'); 216 217 // x:MoveWithCells 218 $objWriter->writeElement('x:MoveWithCells', ''); 219 220 // x:SizeWithCells 221 $objWriter->writeElement('x:SizeWithCells', ''); 222 223 // x:AutoFill 224 $objWriter->writeElement('x:AutoFill', 'False'); 225 226 // x:Row 227 $objWriter->writeElement('x:Row', (string) ($row - 1)); 228 229 // x:Column 230 $objWriter->writeElement('x:Column', (string) ($column - 1)); 231 232 $objWriter->endElement(); 233 234 $objWriter->endElement(); 235 } 236 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body