| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 | <?phpnamespace PhpOffice\PhpSpreadsheet\Chart;use PhpOffice\PhpSpreadsheet\Calculation\Calculation;use PhpOffice\PhpSpreadsheet\Calculation\Functions;use PhpOffice\PhpSpreadsheet\Cell\Coordinate;use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;class DataSeriesValues{    const DATASERIES_TYPE_STRING = 'String';    const DATASERIES_TYPE_NUMBER = 'Number';    private static $dataTypeValues = [        self::DATASERIES_TYPE_STRING,        self::DATASERIES_TYPE_NUMBER,    ];    /**     * Series Data Type.     *     * @var string     */    private $dataType;    /**     * Series Data Source.     *     * @var string     */    private $dataSource;    /**     * Format Code.     *     * @var string     */    private $formatCode;    /**     * Series Point Marker.     *     * @var string     */    private $pointMarker;    /**     * Point Count (The number of datapoints in the dataseries).     *     * @var int     */    private $pointCount = 0;    /**     * Data Values.     *     * @var array of mixed     */    private $dataValues = [];    /**     * Fill color (can be array with colors if dataseries have custom colors).     *     * @var string|string[]     */    private $fillColor;    /**     * Line Width.     *     * @var int     */    private $lineWidth = 12700;    /**     * Create a new DataSeriesValues object.     *     * @param string $dataType     * @param string $dataSource     * @param null|mixed $formatCode     * @param int $pointCount     * @param mixed $dataValues     * @param null|mixed $marker     * @param null|string|string[] $fillColor     */    public function __construct($dataType = self::DATASERIES_TYPE_NUMBER, $dataSource = null, $formatCode = null, $pointCount = 0, $dataValues = [], $marker = null, $fillColor = null)    {        $this->setDataType($dataType);        $this->dataSource = $dataSource;        $this->formatCode = $formatCode;        $this->pointCount = $pointCount;        $this->dataValues = $dataValues;        $this->pointMarker = $marker;        $this->fillColor = $fillColor;    }    /**     * Get Series Data Type.     *     * @return string     */    public function getDataType()    {        return $this->dataType;    }    /**     * Set Series Data Type.     *     * @param string $dataType Datatype of this data series     *                                Typical values are:     *                                    DataSeriesValues::DATASERIES_TYPE_STRING     *                                        Normally used for axis point values     *                                    DataSeriesValues::DATASERIES_TYPE_NUMBER     *                                        Normally used for chart data values     *     * @throws Exception     *     * @return DataSeriesValues     */    public function setDataType($dataType)    {        if (!in_array($dataType, self::$dataTypeValues)) {            throw new Exception('Invalid datatype for chart data series values');        }        $this->dataType = $dataType;        return $this;    }    /**     * Get Series Data Source (formula).     *     * @return string     */    public function getDataSource()    {        return $this->dataSource;    }    /**     * Set Series Data Source (formula).     *     * @param string $dataSource     *     * @return DataSeriesValues     */    public function setDataSource($dataSource)    {        $this->dataSource = $dataSource;        return $this;    }    /**     * Get Point Marker.     *     * @return string     */    public function getPointMarker()    {        return $this->pointMarker;    }    /**     * Set Point Marker.     *     * @param string $marker     *     * @return DataSeriesValues     */    public function setPointMarker($marker)    {        $this->pointMarker = $marker;        return $this;    }    /**     * Get Series Format Code.     *     * @return string     */    public function getFormatCode()    {        return $this->formatCode;    }    /**     * Set Series Format Code.     *     * @param string $formatCode     *     * @return DataSeriesValues     */    public function setFormatCode($formatCode)    {        $this->formatCode = $formatCode;        return $this;    }    /**     * Get Series Point Count.     *     * @return int     */    public function getPointCount()    {        return $this->pointCount;    }    /**     * Get fill color.     *     * @return string|string[] HEX color or array with HEX colors     */    public function getFillColor()    {        return $this->fillColor;    }    /**     * Set fill color for series.     *     * @param string|string[] $color HEX color or array with HEX colors     *     * @return   DataSeriesValues     */    public function setFillColor($color)    {        if (is_array($color)) {            foreach ($color as $colorValue) {                $this->validateColor($colorValue);            }        } else {            $this->validateColor($color);        }        $this->fillColor = $color;        return $this;    }    /**     * Method for validating hex color.     *     * @param string $color value for color     *     * @throws \Exception thrown if color is invalid     *     * @return bool true if validation was successful     */    private function validateColor($color)    {        if (!preg_match('/^[a-f0-9]{6}$/i', $color)) {            throw new Exception(sprintf('Invalid hex color for chart series (color: "%s")', $color));        }        return true;    }    /**     * Get line width for series.     *     * @return int     */    public function getLineWidth()    {        return $this->lineWidth;    }    /**     * Set line width for the series.     *     * @param int $width     *     * @return DataSeriesValues     */    public function setLineWidth($width)    {        $minWidth = 12700;        $this->lineWidth = max($minWidth, $width);        return $this;    }    /**     * Identify if the Data Series is a multi-level or a simple series.     *     * @return null|bool     */    public function isMultiLevelSeries()    {        if (count($this->dataValues) > 0) {            return is_array(array_values($this->dataValues)[0]);        }        return null;    }    /**     * Return the level count of a multi-level Data Series.     *     * @return int     */    public function multiLevelCount()    {        $levelCount = 0;        foreach ($this->dataValues as $dataValueSet) {            $levelCount = max($levelCount, count($dataValueSet));        }        return $levelCount;    }    /**     * Get Series Data Values.     *     * @return array of mixed     */    public function getDataValues()    {        return $this->dataValues;    }    /**     * Get the first Series Data value.     *     * @return mixed     */    public function getDataValue()    {        $count = count($this->dataValues);        if ($count == 0) {            return null;        } elseif ($count == 1) {            return $this->dataValues[0];        }        return $this->dataValues;    }    /**     * Set Series Data Values.     *     * @param array $dataValues     *     * @return DataSeriesValues     */    public function setDataValues($dataValues)    {        $this->dataValues = Functions::flattenArray($dataValues);        $this->pointCount = count($dataValues);        return $this;    }    public function refresh(Worksheet $worksheet, $flatten = true)    {        if ($this->dataSource !== null) {            $calcEngine = Calculation::getInstance($worksheet->getParent());            $newDataValues = Calculation::unwrapResult(                $calcEngine->_calculateFormulaValue(                    '=' . $this->dataSource,                    null,                    $worksheet->getCell('A1')                )            );            if ($flatten) {                $this->dataValues = Functions::flattenArray($newDataValues);                foreach ($this->dataValues as &$dataValue) {                    if ((!empty($dataValue)) && ($dataValue[0] == '#')) {                        $dataValue = 0.0;                    }                }                unset($dataValue);            } else {                list($worksheet, $cellRange) = Worksheet::extractSheetTitle($this->dataSource, true);                $dimensions = Coordinate::rangeDimension(str_replace('$', '', $cellRange));                if (($dimensions[0] == 1) || ($dimensions[1] == 1)) {                    $this->dataValues = Functions::flattenArray($newDataValues);                } else {                    $newArray = array_values(array_shift($newDataValues));                    foreach ($newArray as $i => $newDataSet) {                        $newArray[$i] = [$newDataSet];                    }                    foreach ($newDataValues as $newDataSet) {                        $i = 0;                        foreach ($newDataSet as $newDataVal) {                            array_unshift($newArray[$i++], $newDataVal);                        }                    }                    $this->dataValues = $newArray;                }            }            $this->pointCount = count($this->dataValues);        }    }}
 |