Vendor/phpspreadsheet/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php
private function writeDataValidity()
    {
        // Datavalidation collection
        $dataValidationCollection = $this->phpSheet->getDataValidationCollection();

        // Write data validations?
        if (!empty($dataValidationCollection)) {
            // DATAVALIDATIONS record
            $record = 0x01B2; // Record identifier
            $length = 0x0012; // Bytes to follow

            $grbit = 0x0000; // Prompt box at cell, no cached validity data at DV records
            $horPos = 0x00000000; // Horizontal position of prompt box, if fixed position
            $verPos = 0x00000000; // Vertical position of prompt box, if fixed position
            $objId = 0xFFFFFFFF; // Object identifier of drop down arrow object, or -1 if not visible

            $header = pack('vv', $record, $length);
            $data = pack('vVVVV', $grbit, $horPos, $verPos, $objId, count($dataValidationCollection));
            $this->append($header . $data);

            // DATAVALIDATION records
            $record = 0x01BE; // Record identifier

            foreach ($dataValidationCollection as $cellCoordinate => $dataValidation) {
                // initialize record data
                $data = '';

                // options
                $options = 0x00000000;

                // data type
                $type = 0x00;
                switch ($dataValidation->getType()) {
                    case DataValidation::TYPE_NONE:
                        $type = 0x00;

                        break;
                    case DataValidation::TYPE_WHOLE:
                        $type = 0x01;

                        break;
                    case DataValidation::TYPE_DECIMAL:
                        $type = 0x02;

                        break;
                    case DataValidation::TYPE_LIST:
                        $type = 0x03;

                        break;
                    case DataValidation::TYPE_DATE:
                        $type = 0x04;

                        break;
                    case DataValidation::TYPE_TIME:
                        $type = 0x05;

                        break;
                    case DataValidation::TYPE_TEXTLENGTH:
                        $type = 0x06;

                        break;
                    case DataValidation::TYPE_CUSTOM:
                        $type = 0x07;

                        break;
                }

                $options |= $type << 0;

                // error style
                $errorStyle = 0x00;
                switch ($dataValidation->getErrorStyle()) {
                    case DataValidation::STYLE_STOP:
                        $errorStyle = 0x00;

                        break;
                    case DataValidation::STYLE_WARNING:
                        $errorStyle = 0x01;

                        break;
                    case DataValidation::STYLE_INFORMATION:
                        $errorStyle = 0x02;

                        break;
                }

                $options |= $errorStyle << 4;

                // explicit formula?
                if ($type == 0x03 && preg_match('/^\".*\"$/', $dataValidation->getFormula1())) {
                    $options |= 0x01 << 7;
                }

                // empty cells allowed
                $options |= $dataValidation->getAllowBlank() << 8;

                // show drop down
                $options |= (!$dataValidation->getShowDropDown()) << 9;

                // show input message
                $options |= $dataValidation->getShowInputMessage() << 18;

                // show error message
                $options |= $dataValidation->getShowErrorMessage() << 19;

                // condition operator
                $operator = 0x00;
                switch ($dataValidation->getOperator()) {
                    case DataValidation::OPERATOR_BETWEEN:
                        $operator = 0x00;

                        break;
                    case DataValidation::OPERATOR_NOTBETWEEN:
                        $operator = 0x01;

                        break;
                    case DataValidation::OPERATOR_EQUAL:
                        $operator = 0x02;

                        break;
                    case DataValidation::OPERATOR_NOTEQUAL:
                        $operator = 0x03;

                        break;
                    case DataValidation::OPERATOR_GREATERTHAN:
                        $operator = 0x04;

                        break;
                    case DataValidation::OPERATOR_LESSTHAN:
                        $operator = 0x05;

                        break;
                    case DataValidation::OPERATOR_GREATERTHANOREQUAL:
                        $operator = 0x06;

                        break;
                    case DataValidation::OPERATOR_LESSTHANOREQUAL:
                        $operator = 0x07;

                        break;
                }

                $options |= $operator << 20;

                $data = pack('V', $options);

                // prompt title
                $promptTitle = $dataValidation->getPromptTitle() !== '' ?
                    $dataValidation->getPromptTitle() : chr(0);
                $data .= StringHelper::UTF8toBIFF8UnicodeLong($promptTitle);

                // error title
                $errorTitle = $dataValidation->getErrorTitle() !== '' ?
                    $dataValidation->getErrorTitle() : chr(0);
                $data .= StringHelper::UTF8toBIFF8UnicodeLong($errorTitle);

                // prompt text
                $prompt = $dataValidation->getPrompt() !== '' ?
                    $dataValidation->getPrompt() : chr(0);
                $data .= StringHelper::UTF8toBIFF8UnicodeLong($prompt);

                // error text
                $error = $dataValidation->getError() !== '' ?
                    $dataValidation->getError() : chr(0);
                $data .= StringHelper::UTF8toBIFF8UnicodeLong($error);

                // formula 1
                try {
                    $formula1 = $dataValidation->getFormula1();
                    if ($type == 0x03) { // list type
                        $formula1 = str_replace(',', chr(0), $formula1);
                    }
                    $this->parser->parse($formula1);
                    $formula1 = $this->parser->toReversePolish();
                    $sz1 = strlen($formula1);
                } catch (PhpSpreadsheetException $e) {
                    $sz1 = 0;
                    $formula1 = '';
                }
                $data .= pack('vv', $sz1, 0x0000);
                $data .= $formula1;

                // formula 2
                try {
                    $formula2 = $dataValidation->getFormula2();
                    if ($formula2 === '') {
                        throw new WriterException('No formula2');
                    }
                    $this->parser->parse($formula2);
                    $formula2 = $this->parser->toReversePolish();
                    $sz2 = strlen($formula2);
                } catch (PhpSpreadsheetException $e) {
                    $sz2 = 0;
                    $formula2 = '';
                }
                $data .= pack('vv', $sz2, 0x0000);
                $data .= $formula2;

                // cell range address list
                $data .= pack('v', 0x0001);
                $data .= $this->writeBIFF8CellRangeAddressFixed($cellCoordinate);

                $length = strlen($data);
                $header = pack('vv', $record, $length);

                $this->append($header . $data);
            }
        }
    }
private function writeDataValidity()
    {
        // Datavalidation collection
        $dataValidationCollection = $this->phpSheet->getDataValidationCollection();

        // Write data validations?
        if (!empty($dataValidationCollection)) {
            // DATAVALIDATIONS record
            $record = 0x01B2; // Record identifier
            $length = 0x0012; // Bytes to follow

            $grbit = 0x0000; // Prompt box at cell, no cached validity data at DV records
            $horPos = 0x00000000; // Horizontal position of prompt box, if fixed position
            $verPos = 0x00000000; // Vertical position of prompt box, if fixed position
            $objId = 0xFFFFFFFF; // Object identifier of drop down arrow object, or -1 if not visible

            $header = pack('vv', $record, $length);
            $data = pack('vVVVV', $grbit, $horPos, $verPos, $objId, count($dataValidationCollection));
            $this->append($header . $data);

            // DATAVALIDATION records
            $record = 0x01BE; // Record identifier

            foreach ($dataValidationCollection as $cellCoordinate => $dataValidation) {
                // initialize record data
                $data = '';

                // options
                $options = 0x00000000;

                // data type
                $type = 0x00;
                switch ($dataValidation->getType()) {
                    case DataValidation::TYPE_NONE:
                        $type = 0x00;

                        break;
                    case DataValidation::TYPE_WHOLE:
                        $type = 0x01;

                        break;
                    case DataValidation::TYPE_DECIMAL:
                        $type = 0x02;

                        break;
                    case DataValidation::TYPE_LIST:
                        $type = 0x03;

                        break;
                    case DataValidation::TYPE_DATE:
                        $type = 0x04;

                        break;
                    case DataValidation::TYPE_TIME:
                        $type = 0x05;

                        break;
                    case DataValidation::TYPE_TEXTLENGTH:
                        $type = 0x06;

                        break;
                    case DataValidation::TYPE_CUSTOM:
                        $type = 0x07;

                        break;
                }

                $options |= $type << 0;

                // error style
                $errorStyle = 0x00;
                switch ($dataValidation->getErrorStyle()) {
                    case DataValidation::STYLE_STOP:
                        $errorStyle = 0x00;

                        break;
                    case DataValidation::STYLE_WARNING:
                        $errorStyle = 0x01;

                        break;
                    case DataValidation::STYLE_INFORMATION:
                        $errorStyle = 0x02;

                        break;
                }

                $options |= $errorStyle << 4;

                // explicit formula?
                if ($type == 0x03 && preg_match('/^\".*\"$/', $dataValidation->getFormula1())) {
                    $options |= 0x01 << 7;
                }

                // empty cells allowed
                $options |= $dataValidation->getAllowBlank() << 8;

                // show drop down
                $options |= (!$dataValidation->getShowDropDown()) << 9;

                // show input message
                $options |= $dataValidation->getShowInputMessage() << 18;

                // show error message
                $options |= $dataValidation->getShowErrorMessage() << 19;

                // condition operator
                $operator = 0x00;
                switch ($dataValidation->getOperator()) {
                    case DataValidation::OPERATOR_BETWEEN:
                        $operator = 0x00;

                        break;
                    case DataValidation::OPERATOR_NOTBETWEEN:
                        $operator = 0x01;

                        break;
                    case DataValidation::OPERATOR_EQUAL:
                        $operator = 0x02;

                        break;
                    case DataValidation::OPERATOR_NOTEQUAL:
                        $operator = 0x03;

                        break;
                    case DataValidation::OPERATOR_GREATERTHAN:
                        $operator = 0x04;

                        break;
                    case DataValidation::OPERATOR_LESSTHAN:
                        $operator = 0x05;

                        break;
                    case DataValidation::OPERATOR_GREATERTHANOREQUAL:
                        $operator = 0x06;

                        break;
                    case DataValidation::OPERATOR_LESSTHANOREQUAL:
                        $operator = 0x07;

                        break;
                }

                $options |= $operator << 20;

                $data = pack('V', $options);

                // prompt title
                $promptTitle = $dataValidation->getPromptTitle() !== '' ?
                    $dataValidation->getPromptTitle() : chr(0);
                $data .= StringHelper::UTF8toBIFF8UnicodeLong($promptTitle);

                // error title
                $errorTitle = $dataValidation->getErrorTitle() !== '' ?
                    $dataValidation->getErrorTitle() : chr(0);
                $data .= StringHelper::UTF8toBIFF8UnicodeLong($errorTitle);

                // prompt text
                $prompt = $dataValidation->getPrompt() !== '' ?
                    $dataValidation->getPrompt() : chr(0);
                $data .= StringHelper::UTF8toBIFF8UnicodeLong($prompt);

                // error text
                $error = $dataValidation->getError() !== '' ?
                    $dataValidation->getError() : chr(0);
                $data .= StringHelper::UTF8toBIFF8UnicodeLong($error);

                // formula 1
                try {
                    $formula1 = $dataValidation->getFormula1();
                    if ($type == 0x03) { // list type
                        $formula1 = str_replace(',', chr(0), $formula1);
                    }
                    $this->parser->parse($formula1);
                    $formula1 = $this->parser->toReversePolish();
                    $sz1 = strlen($formula1);
                } catch (PhpSpreadsheetException $e) {
                    $sz1 = 0;
                    $formula1 = '';
                }
                $data .= pack('vv', $sz1, 0x0000);
                $data .= $formula1;

                // formula 2
                try {
                    $formula2 = $dataValidation->getFormula2();
                    if ($formula2 === '') {
                        throw new WriterException('No formula2');
                    }
                    $this->parser->parse($formula2);
                    $formula2 = $this->parser->toReversePolish();
                    $sz2 = strlen($formula2);
                } catch (PhpSpreadsheetException $e) {
                    $sz2 = 0;
                    $formula2 = '';
                }
                $data .= pack('vv', $sz2, 0x0000);
                $data .= $formula2;

                // cell range address list
                $data .= pack('v', 0x0001);
                $data .= $this->writeBIFF8CellRangeAddressFixed($cellCoordinate);

                $length = strlen($data);
                $header = pack('vv', $record, $length);

                $this->append($header . $data);
            }
        }
    }
Store the DATAVALIDATIONS and DATAVALIDATION records.