/lib/phpspreadsheet/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php

https://github.com/abgreeve/moodle · PHP · 282 lines · 171 code · 43 blank · 68 comment · 21 complexity · b5a834d7710fb5df620db0dd52714807 MD5 · raw file

  1. <?php
  2. namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  3. use PhpOffice\PhpSpreadsheet\Cell\DataType;
  4. use PhpOffice\PhpSpreadsheet\RichText\RichText;
  5. use PhpOffice\PhpSpreadsheet\RichText\Run;
  6. use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
  7. use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
  8. use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
  9. class StringTable extends WriterPart
  10. {
  11. /**
  12. * Create worksheet stringtable.
  13. *
  14. * @param Worksheet $pSheet Worksheet
  15. * @param string[] $pExistingTable Existing table to eventually merge with
  16. *
  17. * @return string[] String table for worksheet
  18. */
  19. public function createStringTable(Worksheet $pSheet, $pExistingTable = null)
  20. {
  21. // Create string lookup table
  22. $aStringTable = [];
  23. $cellCollection = null;
  24. $aFlippedStringTable = null; // For faster lookup
  25. // Is an existing table given?
  26. if (($pExistingTable !== null) && is_array($pExistingTable)) {
  27. $aStringTable = $pExistingTable;
  28. }
  29. // Fill index array
  30. $aFlippedStringTable = $this->flipStringTable($aStringTable);
  31. // Loop through cells
  32. foreach ($pSheet->getCoordinates() as $coordinate) {
  33. $cell = $pSheet->getCell($coordinate);
  34. $cellValue = $cell->getValue();
  35. if (
  36. !is_object($cellValue) &&
  37. ($cellValue !== null) &&
  38. $cellValue !== '' &&
  39. !isset($aFlippedStringTable[$cellValue]) &&
  40. ($cell->getDataType() == DataType::TYPE_STRING || $cell->getDataType() == DataType::TYPE_STRING2 || $cell->getDataType() == DataType::TYPE_NULL)
  41. ) {
  42. $aStringTable[] = $cellValue;
  43. $aFlippedStringTable[$cellValue] = true;
  44. } elseif (
  45. $cellValue instanceof RichText &&
  46. ($cellValue !== null) &&
  47. !isset($aFlippedStringTable[$cellValue->getHashCode()])
  48. ) {
  49. $aStringTable[] = $cellValue;
  50. $aFlippedStringTable[$cellValue->getHashCode()] = true;
  51. }
  52. }
  53. return $aStringTable;
  54. }
  55. /**
  56. * Write string table to XML format.
  57. *
  58. * @param string[] $pStringTable
  59. *
  60. * @return string XML Output
  61. */
  62. public function writeStringTable(array $pStringTable)
  63. {
  64. // Create XML writer
  65. $objWriter = null;
  66. if ($this->getParentWriter()->getUseDiskCaching()) {
  67. $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
  68. } else {
  69. $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
  70. }
  71. // XML header
  72. $objWriter->startDocument('1.0', 'UTF-8', 'yes');
  73. // String table
  74. $objWriter->startElement('sst');
  75. $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
  76. $objWriter->writeAttribute('uniqueCount', count($pStringTable));
  77. // Loop through string table
  78. foreach ($pStringTable as $textElement) {
  79. $objWriter->startElement('si');
  80. if (!$textElement instanceof RichText) {
  81. $textToWrite = StringHelper::controlCharacterPHP2OOXML($textElement);
  82. $objWriter->startElement('t');
  83. if ($textToWrite !== trim($textToWrite)) {
  84. $objWriter->writeAttribute('xml:space', 'preserve');
  85. }
  86. $objWriter->writeRawData($textToWrite);
  87. $objWriter->endElement();
  88. } elseif ($textElement instanceof RichText) {
  89. $this->writeRichText($objWriter, $textElement);
  90. }
  91. $objWriter->endElement();
  92. }
  93. $objWriter->endElement();
  94. return $objWriter->getData();
  95. }
  96. /**
  97. * Write Rich Text.
  98. *
  99. * @param XMLWriter $objWriter XML Writer
  100. * @param RichText $pRichText Rich text
  101. * @param string $prefix Optional Namespace prefix
  102. */
  103. public function writeRichText(XMLWriter $objWriter, RichText $pRichText, $prefix = null): void
  104. {
  105. if ($prefix !== null) {
  106. $prefix .= ':';
  107. }
  108. // Loop through rich text elements
  109. $elements = $pRichText->getRichTextElements();
  110. foreach ($elements as $element) {
  111. // r
  112. $objWriter->startElement($prefix . 'r');
  113. // rPr
  114. if ($element instanceof Run) {
  115. // rPr
  116. $objWriter->startElement($prefix . 'rPr');
  117. // rFont
  118. $objWriter->startElement($prefix . 'rFont');
  119. $objWriter->writeAttribute('val', $element->getFont()->getName());
  120. $objWriter->endElement();
  121. // Bold
  122. $objWriter->startElement($prefix . 'b');
  123. $objWriter->writeAttribute('val', ($element->getFont()->getBold() ? 'true' : 'false'));
  124. $objWriter->endElement();
  125. // Italic
  126. $objWriter->startElement($prefix . 'i');
  127. $objWriter->writeAttribute('val', ($element->getFont()->getItalic() ? 'true' : 'false'));
  128. $objWriter->endElement();
  129. // Superscript / subscript
  130. if ($element->getFont()->getSuperscript() || $element->getFont()->getSubscript()) {
  131. $objWriter->startElement($prefix . 'vertAlign');
  132. if ($element->getFont()->getSuperscript()) {
  133. $objWriter->writeAttribute('val', 'superscript');
  134. } elseif ($element->getFont()->getSubscript()) {
  135. $objWriter->writeAttribute('val', 'subscript');
  136. }
  137. $objWriter->endElement();
  138. }
  139. // Strikethrough
  140. $objWriter->startElement($prefix . 'strike');
  141. $objWriter->writeAttribute('val', ($element->getFont()->getStrikethrough() ? 'true' : 'false'));
  142. $objWriter->endElement();
  143. // Color
  144. $objWriter->startElement($prefix . 'color');
  145. $objWriter->writeAttribute('rgb', $element->getFont()->getColor()->getARGB());
  146. $objWriter->endElement();
  147. // Size
  148. $objWriter->startElement($prefix . 'sz');
  149. $objWriter->writeAttribute('val', $element->getFont()->getSize());
  150. $objWriter->endElement();
  151. // Underline
  152. $objWriter->startElement($prefix . 'u');
  153. $objWriter->writeAttribute('val', $element->getFont()->getUnderline());
  154. $objWriter->endElement();
  155. $objWriter->endElement();
  156. }
  157. // t
  158. $objWriter->startElement($prefix . 't');
  159. $objWriter->writeAttribute('xml:space', 'preserve');
  160. $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($element->getText()));
  161. $objWriter->endElement();
  162. $objWriter->endElement();
  163. }
  164. }
  165. /**
  166. * Write Rich Text.
  167. *
  168. * @param XMLWriter $objWriter XML Writer
  169. * @param RichText|string $pRichText text string or Rich text
  170. * @param string $prefix Optional Namespace prefix
  171. */
  172. public function writeRichTextForCharts(XMLWriter $objWriter, $pRichText = null, $prefix = null): void
  173. {
  174. if (!$pRichText instanceof RichText) {
  175. $textRun = $pRichText;
  176. $pRichText = new RichText();
  177. $pRichText->createTextRun($textRun);
  178. }
  179. if ($prefix !== null) {
  180. $prefix .= ':';
  181. }
  182. // Loop through rich text elements
  183. $elements = $pRichText->getRichTextElements();
  184. foreach ($elements as $element) {
  185. // r
  186. $objWriter->startElement($prefix . 'r');
  187. // rPr
  188. $objWriter->startElement($prefix . 'rPr');
  189. // Bold
  190. $objWriter->writeAttribute('b', ($element->getFont()->getBold() ? 1 : 0));
  191. // Italic
  192. $objWriter->writeAttribute('i', ($element->getFont()->getItalic() ? 1 : 0));
  193. // Underline
  194. $underlineType = $element->getFont()->getUnderline();
  195. switch ($underlineType) {
  196. case 'single':
  197. $underlineType = 'sng';
  198. break;
  199. case 'double':
  200. $underlineType = 'dbl';
  201. break;
  202. }
  203. $objWriter->writeAttribute('u', $underlineType);
  204. // Strikethrough
  205. $objWriter->writeAttribute('strike', ($element->getFont()->getStrikethrough() ? 'sngStrike' : 'noStrike'));
  206. // rFont
  207. $objWriter->startElement($prefix . 'latin');
  208. $objWriter->writeAttribute('typeface', $element->getFont()->getName());
  209. $objWriter->endElement();
  210. $objWriter->endElement();
  211. // t
  212. $objWriter->startElement($prefix . 't');
  213. $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($element->getText()));
  214. $objWriter->endElement();
  215. $objWriter->endElement();
  216. }
  217. }
  218. /**
  219. * Flip string table (for index searching).
  220. *
  221. * @param array $stringTable Stringtable
  222. *
  223. * @return array
  224. */
  225. public function flipStringTable(array $stringTable)
  226. {
  227. // Return value
  228. $returnValue = [];
  229. // Loop through stringtable and add flipped items to $returnValue
  230. foreach ($stringTable as $key => $value) {
  231. if (!$value instanceof RichText) {
  232. $returnValue[$value] = $key;
  233. } elseif ($value instanceof RichText) {
  234. $returnValue[$value->getHashCode()] = $key;
  235. }
  236. }
  237. return $returnValue;
  238. }
  239. }