暫無描述

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. <?php
  2. /**
  3. * This file is part of PHPWord - A pure PHP library for reading and writing
  4. * word processing documents.
  5. *
  6. * PHPWord is free software distributed under the terms of the GNU Lesser
  7. * General Public License version 3 as published by the Free Software Foundation.
  8. *
  9. * For the full copyright and license information, please read the LICENSE
  10. * file that was distributed with this source code. For the full list of
  11. * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
  12. *
  13. * @link https://github.com/PHPOffice/PHPWord
  14. * @copyright 2010-2014 PHPWord contributors
  15. * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
  16. */
  17. namespace PhpOffice\PhpWord\Writer\Word2007\Part;
  18. use PhpOffice\PhpWord\Element\Chart as ChartElement;
  19. use PhpOffice\PhpWord\Shared\XMLWriter;
  20. /**
  21. * Word2007 chart part writer: word/charts/chartx.xml
  22. *
  23. * @since 0.12.0
  24. * @link http://www.datypic.com/sc/ooxml/e-draw-chart_chartSpace.html
  25. */
  26. class Chart extends AbstractPart
  27. {
  28. /**
  29. * Chart element
  30. *
  31. * @var \PhpOffice\PhpWord\Element\Chart $element
  32. */
  33. private $element;
  34. /**
  35. * Type definition
  36. *
  37. * @var array
  38. */
  39. private $types = array(
  40. 'pie' => array('type' => 'pie', 'colors' => 1),
  41. 'doughnut' => array('type' => 'doughnut', 'colors' => 1, 'hole' => 75, 'no3d' => true),
  42. 'bar' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'bar'),
  43. 'column' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'col'),
  44. 'line' => array('type' => 'line', 'colors' => 0, 'axes' => true),
  45. 'area' => array('type' => 'area', 'colors' => 0, 'axes' => true),
  46. 'radar' => array('type' => 'radar', 'colors' => 0, 'axes' => true, 'radar' => 'standard', 'no3d' => true),
  47. 'scatter' => array('type' => 'scatter', 'colors' => 0, 'axes' => true, 'scatter' => 'marker', 'no3d' => true),
  48. );
  49. /**
  50. * Chart options
  51. *
  52. * @var array
  53. */
  54. private $options = array();
  55. /**
  56. * Set chart element.
  57. *
  58. * @param \PhpOffice\PhpWord\Element\Chart $element
  59. * @return void
  60. */
  61. public function setElement(ChartElement $element)
  62. {
  63. $this->element = $element;
  64. }
  65. /**
  66. * Write part
  67. *
  68. * @return string
  69. */
  70. public function write()
  71. {
  72. $xmlWriter = $this->getXmlWriter();
  73. $xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
  74. $xmlWriter->startElement('c:chartSpace');
  75. $xmlWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
  76. $xmlWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main');
  77. $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
  78. $this->writeChart($xmlWriter);
  79. $this->writeShape($xmlWriter);
  80. $xmlWriter->endElement(); // c:chartSpace
  81. return $xmlWriter->getData();
  82. }
  83. /**
  84. * Write chart
  85. *
  86. * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_Chart.html
  87. * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
  88. * @return void
  89. */
  90. private function writeChart(XMLWriter $xmlWriter)
  91. {
  92. $xmlWriter->startElement('c:chart');
  93. $xmlWriter->writeElementBlock('c:autoTitleDeleted', 'val', 1);
  94. $this->writePlotArea($xmlWriter);
  95. $xmlWriter->endElement(); // c:chart
  96. }
  97. /**
  98. * Write plot area.
  99. *
  100. * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_PlotArea.html
  101. * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_PieChart.html
  102. * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_DoughnutChart.html
  103. * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_BarChart.html
  104. * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_LineChart.html
  105. * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_AreaChart.html
  106. * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_RadarChart.html
  107. * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_ScatterChart.html
  108. * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
  109. * @return void
  110. */
  111. private function writePlotArea(XMLWriter $xmlWriter)
  112. {
  113. $type = $this->element->getType();
  114. $style = $this->element->getStyle();
  115. $this->options = $this->types[$type];
  116. $xmlWriter->startElement('c:plotArea');
  117. $xmlWriter->writeElement('c:layout');
  118. // Chart
  119. $chartType = $this->options['type'];
  120. $chartType .= $style->is3d() && !isset($this->options['no3d'])? '3D' : '';
  121. $chartType .= 'Chart';
  122. $xmlWriter->startElement("c:{$chartType}");
  123. $xmlWriter->writeElementBlock('c:varyColors', 'val', $this->options['colors']);
  124. if ($type == 'area') {
  125. $xmlWriter->writeElementBlock('c:grouping', 'val', 'standard');
  126. }
  127. if (isset($this->options['hole'])) {
  128. $xmlWriter->writeElementBlock('c:holeSize', 'val', $this->options['hole']);
  129. }
  130. if (isset($this->options['bar'])) {
  131. $xmlWriter->writeElementBlock('c:barDir', 'val', $this->options['bar']); // bar|col
  132. $xmlWriter->writeElementBlock('c:grouping', 'val', 'clustered'); // 3d; standard = percentStacked
  133. }
  134. if (isset($this->options['radar'])) {
  135. $xmlWriter->writeElementBlock('c:radarStyle', 'val', $this->options['radar']);
  136. }
  137. if (isset($this->options['scatter'])) {
  138. $xmlWriter->writeElementBlock('c:scatterStyle', 'val', $this->options['scatter']);
  139. }
  140. // Series
  141. $this->writeSeries($xmlWriter, isset($this->options['scatter']));
  142. // Axes
  143. if (isset($this->options['axes'])) {
  144. $xmlWriter->writeElementBlock('c:axId', 'val', 1);
  145. $xmlWriter->writeElementBlock('c:axId', 'val', 2);
  146. }
  147. $xmlWriter->endElement(); // chart type
  148. // Axes
  149. if (isset($this->options['axes'])) {
  150. $this->writeAxis($xmlWriter, 'cat');
  151. $this->writeAxis($xmlWriter, 'val');
  152. }
  153. $xmlWriter->endElement(); // c:plotArea
  154. }
  155. /**
  156. * Write series.
  157. *
  158. * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
  159. * @param bool $scatter
  160. * @return void
  161. */
  162. private function writeSeries(XMLWriter $xmlWriter, $scatter = false)
  163. {
  164. $series = $this->element->getSeries();
  165. $index = 0;
  166. foreach ($series as $seriesItem) {
  167. $categories = $seriesItem['categories'];
  168. $values = $seriesItem['values'];
  169. $xmlWriter->startElement('c:ser');
  170. $xmlWriter->writeElementBlock('c:idx', 'val', $index);
  171. $xmlWriter->writeElementBlock('c:order', 'val', $index);
  172. if (isset($this->options['scatter'])) {
  173. $this->writeShape($xmlWriter);
  174. }
  175. if ($scatter === true) {
  176. $this->writeSeriesItem($xmlWriter, 'xVal', $categories);
  177. $this->writeSeriesItem($xmlWriter, 'yVal', $values);
  178. } else {
  179. $this->writeSeriesItem($xmlWriter, 'cat', $categories);
  180. $this->writeSeriesItem($xmlWriter, 'val', $values);
  181. }
  182. $xmlWriter->endElement(); // c:ser
  183. $index++;
  184. }
  185. }
  186. /**
  187. * Write series items.
  188. *
  189. * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
  190. * @param string $type
  191. * @param array $values
  192. * @return void
  193. */
  194. private function writeSeriesItem(XMLWriter $xmlWriter, $type, $values)
  195. {
  196. $types = array(
  197. 'cat' => array('c:cat', 'c:strLit'),
  198. 'val' => array('c:val', 'c:numLit'),
  199. 'xVal' => array('c:xVal', 'c:strLit'),
  200. 'yVal' => array('c:yVal', 'c:numLit'),
  201. );
  202. list($itemType, $itemLit) = $types[$type];
  203. $xmlWriter->startElement($itemType);
  204. $xmlWriter->startElement($itemLit);
  205. $index = 0;
  206. foreach ($values as $value) {
  207. $xmlWriter->startElement('c:pt');
  208. $xmlWriter->writeAttribute('idx', $index);
  209. $xmlWriter->startElement('c:v');
  210. $xmlWriter->writeRaw($value);
  211. $xmlWriter->endElement(); // c:v
  212. $xmlWriter->endElement(); // c:pt
  213. $index++;
  214. }
  215. $xmlWriter->endElement(); // $itemLit
  216. $xmlWriter->endElement(); // $itemType
  217. }
  218. /**
  219. * Write axis
  220. *
  221. * @link http://www.datypic.com/sc/ooxml/t-draw-chart_CT_CatAx.html
  222. * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
  223. * @param string $type
  224. * @return void
  225. */
  226. private function writeAxis(XMLWriter $xmlWriter, $type)
  227. {
  228. $types = array(
  229. 'cat' => array('c:catAx', 1, 'b', 2),
  230. 'val' => array('c:valAx', 2, 'l', 1),
  231. );
  232. list($axisType, $axisId, $axisPos, $axisCross) = $types[$type];
  233. $xmlWriter->startElement($axisType);
  234. $xmlWriter->writeElementBlock('c:axId', 'val', $axisId);
  235. $xmlWriter->writeElementBlock('c:axPos', 'val', $axisPos);
  236. $xmlWriter->writeElementBlock('c:crossAx', 'val', $axisCross);
  237. $xmlWriter->writeElementBlock('c:auto', 'val', 1);
  238. if (isset($this->options['axes'])) {
  239. $xmlWriter->writeElementBlock('c:delete', 'val', 0);
  240. $xmlWriter->writeElementBlock('c:majorTickMark', 'val', 'none');
  241. $xmlWriter->writeElementBlock('c:minorTickMark', 'val', 'none');
  242. $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'none'); // nextTo
  243. $xmlWriter->writeElementBlock('c:crosses', 'val', 'autoZero');
  244. }
  245. if (isset($this->options['radar'])) {
  246. $xmlWriter->writeElement('c:majorGridlines');
  247. }
  248. $xmlWriter->startElement('c:scaling');
  249. $xmlWriter->writeElementBlock('c:orientation', 'val', 'minMax');
  250. $xmlWriter->endElement(); // c:scaling
  251. $this->writeShape($xmlWriter, true);
  252. $xmlWriter->endElement(); // $axisType
  253. }
  254. /**
  255. * Write shape
  256. *
  257. * @link http://www.datypic.com/sc/ooxml/t-a_CT_ShapeProperties.html
  258. * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter
  259. * @param bool $line
  260. * @return void
  261. */
  262. private function writeShape(XMLWriter $xmlWriter, $line = false)
  263. {
  264. $xmlWriter->startElement('c:spPr');
  265. $xmlWriter->startElement('a:ln');
  266. if ($line === true) {
  267. $xmlWriter->writeElement('a:solidFill');
  268. } else {
  269. $xmlWriter->writeElement('a:noFill');
  270. }
  271. $xmlWriter->endElement(); // a:ln
  272. $xmlWriter->endElement(); // c:spPr
  273. }
  274. }