【PHP】利用 xlswriter 扩展导出的Excel文件报错问题

一、问题描述

导出的文件在wps中打开没问题,在office excel中打开会报错如下:

发现"xxx.xlsx"中的部分内容有问题。是否让我们尽量尝试恢复?如果您信任此工作薄的源,请单击"是"。

二、解决方案

在导出程序末尾加上 exit;

三、代码过程

导出使用的是php的扩展包xlswriter

3.1 xlswriter_helper.php

php 复制代码
<?php

namespace Vtiful\Kernel;

use Exception;

/**
 * Class Excel
 *
 * @author  viest
 *
 * @package Vtiful\Kernel
 */
class Excel
{
    const TYPE_STRING = 0x01;
    const TYPE_INT = 0x02;
    const TYPE_DOUBLE = 0x04;
    const TYPE_TIMESTAMP = 0x08;

    const SKIP_NONE = 0x00;
    const SKIP_EMPTY_ROW = 0x01;
    const SKIP_EMPTY_CELLS = 0x02;
    const SKIP_EMPTY_VALUE = 0x100;

    const GRIDLINES_HIDE_ALL = 0;
    const GRIDLINES_SHOW_SCREEN = 1;
    const GRIDLINES_SHOW_PRINT = 2;
    const GRIDLINES_SHOW_ALL = 3;

    /**
     * Excel constructor.
     *
     * @param array $config
     *
     * @throws Exception
     */
    public function __construct(array $config)
    {
        if (!extension_loaded('xlswriter')) {
            throw new Exception('xlswriter extension is not installed, please install extension');
        }
    }

    /**
     * File Name
     *
     * @param string $fileName
     * @param string $sheetName
     *
     * @return Excel
     *
     * @author viest
     */
    public function fileName(string $fileName, string $sheetName = 'Sheet1'): self
    {
        return $this;
    }

    /**
     * Const memory model
     *
     * @param string $fileName
     * @param string $sheetName
     *
     * @return Excel
     *
     * @author viest
     */
    public function constMemory(string $fileName, string $sheetName = 'Sheet1'): self
    {
        return $this;
    }

    /**
     * Add a new worksheet to a workbook.
     *
     * The worksheet name must be a valid Excel worksheet name, i.e. it must be
     * less than 32 character and it cannot contain any of the characters:
     *
     *     / \ [ ] : * ?
     *
     * In addition, you cannot use the same, case insensitive, `$sheetName` for more
     * than one worksheet.
     *
     * @param string|NULL $sheetName
     *
     * @return Excel
     *
     * @author viest
     */
    public function addSheet(string $sheetName): self
    {
        return $this;
    }

    /**
     * Checkout worksheet
     *
     * @param string $sheetName
     *
     * @return Excel
     *
     * @author viest
     */
    public function checkoutSheet(string $sheetName): self
    {
        return $this;
    }

    /**
     * Set activate sheet
     *
     * @param string $sheetName
     *
     * @return bool
     *
     * @author viest
     */
    public function activateSheet(string $sheetName): bool
    {
        return true;
    }

    /**
     * Insert data on the first line of the worksheet
     *
     * @param array $header
     *
     * @return Excel
     *
     * @author viest
     */
    public function header(array $header): self
    {
        return $this;
    }

    /**
     * Insert data on the worksheet
     *
     * @param array $data
     *
     * @return Excel
     *
     * @author viest
     */
    public function data(array $data): self
    {
        return $this;
    }

    /**
     * Generate file
     *
     * @return string
     *
     * @author viest
     */
    public function output(): string
    {
        return 'FilePath';
    }

    /**
     * Get file resource
     *
     * @return resource
     *
     * @author viest
     */
    public function getHandle()
    {
        //
    }

    /**
     * Auto filter on the worksheet
     *
     * @param string $range
     *
     * @return Excel
     *
     * @author viest
     */
    public function autoFilter(string $range): self
    {
        return $this;
    }

    /**
     * Insert data on the cell
     *
     * @param int               $row
     * @param int               $column
     * @param int|string|double $data
     * @param string|null       $format
     * @param resource|null     $formatHandle
     *
     * @return Excel
     *
     * @author viest
     */
    public function insertText(int $row, int $column, $data, string $format = NULL, $formatHandle = NULL): self
    {
        return $this;
    }

    /**
     * Insert date on the cell
     *
     * @param int           $row
     * @param int           $column
     * @param int           $timestamp
     * @param string|NULL   $format
     * @param resource|null $formatHandle
     *
     * @return Excel
     *
     * @author viest
     */
    public function insertDate(int $row, int $column, int $timestamp, string $format = NULL, $formatHandle = NULL): self
    {
        return $this;
    }

    /**
     * Insert chart on the cell
     *
     * @param int      $row
     * @param int      $column
     * @param resource $chartResource
     *
     * @return Excel
     *
     * @author viest
     */
    public function insertChart(int $row, int $column, $chartResource): self
    {
        return $this;
    }

    /**
     * Insert url on the cell
     *
     * @param int           $row
     * @param int           $column
     * @param string        $url
     * @param string        $text
     * @param string        $toolTip
     * @param resource|null $formatHandle
     *
     * @return Excel
     *
     * @author viest
     */
    public function insertUrl(int $row, int $column, string $url, string $text = NULL, string $toolTip = NULL, $formatHandle = NULL): self
    {
        return $this;
    }

    /**
     * Insert image on the cell
     *
     * @param int    $row
     * @param int    $column
     * @param string $imagePath
     * @param float  $width
     * @param float  $height
     *
     * @return Excel
     *
     * @author viest
     */
    public function insertImage(int $row, int $column, string $imagePath, float $width = 1, float $height = 1): self
    {
        return $this;
    }

    /**
     * Insert Formula on the cell
     *
     * @param int           $row
     * @param int           $column
     * @param string        $formula
     * @param resource|null $formatHandle
     *
     * @return Excel
     *
     * @author viest
     */
    public function insertFormula(int $row, int $column, string $formula, $formatHandle = NULL): self
    {
        return $this;
    }

    /**
     * Insert comment on the cell
     *
     * @param int    $row
     * @param int    $column
     * @param string $comment
     *
     * @return $this
     *
     * @author viest
     */
    public function insertComment(int $row, int $column, string $comment): self
    {
        return $this;
    }

    /**
     * Show comment on the sheet
     *
     * @return $this
     *
     * @author viest
     */
    public function showComment(): self
    {
        return $this;
    }

    /**
     * Merge cells
     *
     * @param string        $range
     * @param string        $data
     * @param resource|null $formatHandle
     *
     * @return Excel
     *
     * @author viest
     */
    public function mergeCells(string $range, string $data, $formatHandle = NULL): self
    {
        return $this;
    }

    /**
     * Set column cells width or format
     *
     * @param string        $range
     * @param float         $cellWidth
     * @param resource|null $formatHandle
     *
     * @return Excel
     *
     * @author viest
     */
    public function setColumn(string $range, float $cellWidth, $formatHandle = NULL): self
    {
        return $this;
    }

    /**
     * Set row cells height or format
     *
     * @param string        $range
     * @param float         $cellHeight
     * @param resource|null $formatHandle
     *
     * @return Excel
     *
     * @author viest
     */
    public function setRow(string $range, float $cellHeight, $formatHandle = NULL): self
    {
        return $this;
    }

    /**
     * Default format
     *
     * @param resource $formatHandle
     *
     * @return $this
     *
     * @author viest
     */
    public function defaultFormat($formatHandle): self
    {
        return $this;
    }

    /**
     * Open xlsx file
     *
     * @param string $fileName
     *
     * @return Excel
     *
     * @author viest
     */
    public function openFile(string $fileName): self
    {
        return $this;
    }

    /**
     * Open sheet
     *
     * default open first sheet
     *
     * @param string|NULL $sheetName
     * @param int         skipFlag
     *
     * @return Excel
     *
     * @author viest
     */
    public function openSheet(string $sheetName = NULL, int $skipFlag = 0x00): self
    {
        return $this;
    }

    /**
     * File to csv
     *
     * @param resource $handler
     * @param string   $delimiter
     * @param string   $enclosure
     * @param string   $escape
     *
     * Example:
     *
     * $fp = fopen('path', 'w');
     * putCSV($fp)
     *
     * $fp = fopen('php://memory', 'w');
     * putCSV($fp)
     *
     * @return bool
     *
     * @author viest
     */
    public function putCSV(resource $handler, string $delimiter = ',', string $enclosure = '"', string $escape = '\\'): bool
    {
        return true;
    }

    /**
     * File to csv
     *
     * @param callable $callback
     * @param resource $handler
     * @param string   $delimiter
     * @param string   $enclosure
     * @param string   $escape
     *
     * @return bool
     *
     * @author viest
     */
    public function putCSVCallback(callable $callback, resource $handler, string $delimiter = ',', string $enclosure = '"', string $escape = '\\'): bool
    {
        return true;
    }

    /**
     * Sheet list
     *
     * @return array
     *
     * @author viest
     */
    public function sheetList(): array
    {
        return [];
    }

    /**
     * Set row cell data type
     *
     * @param array $types
     *
     * @return Excel
     *
     * @author viest
     */
    public function setType(array $types): self
    {
        return $this;
    }

    /**
     * Set skip rows
     *
     * @param int $rows
     *
     * @return $this
     *
     * @author viest
     */
    public function setSkipRows(int $rows): self
    {
        return $this;
    }

    /**
     * Read values from the sheet
     *
     * @return array
     *
     * @author viest
     */
    public function getSheetData(): array
    {
        return [];
    }

    /**
     * Read values from the sheet
     *
     * @return array
     *
     * @author viest
     */
    public function nextRow(): array
    {
        return [];
    }

    /**
     * Next Cell In Callback
     *
     * @param callable    $callback  function(int $row, int $cell, string $data)
     * @param string|NULL $sheetName sheet name
     *
     * @return void
     *
     * @author viest
     */
    public function nextCellCallback(callable $callback, string $sheetName = NULL)
    {
        //
    }

    /**
     * Freeze panes
     *
     * freezePanes(1, 0); // Freeze the first row.
     * freezePanes(0, 1); // Freeze the first column.
     * freezePanes(1, 1); // Freeze first row/column.
     *
     * @param int $row
     * @param int $column
     *
     * @return $this
     *
     * @author viest
     */
    public function freezePanes(int $row, int $column): self
    {
        return $this;
    }

    /**
     * Gridline
     *
     * Display or hide screen and print gridlines using one of the values of
     *
     * \Vtiful\Kernel\Excel::GRIDLINES_HIDE_ALL
     * \Vtiful\Kernel\Excel::GRIDLINES_SHOW_ALL
     * \Vtiful\Kernel\Excel::GRIDLINES_SHOW_PRINT
     * \Vtiful\Kernel\Excel::GRIDLINES_SHOW_SCREEN
     *
     * Excel default is that the screen gridlines are on and the printed worksheet is off.
     *
     * @param int $option
     *
     * @return $this
     *
     * @author viest
     */
    public function gridline(int $option = Excel::GRIDLINES_HIDE_ALL): self
    {
        return $this;
    }

    /**
     * Worksheet zoom
     *
     * Set the worksheet zoom factor in the range 10 <= zoom <= 400:
     *
     * @param int $scale
     *
     * @return $this
     *
     * @author viest
     */
    public function zoom(int $scale = 100): self
    {
        return $this;
    }

    /**
     * Set printed portrait
     *
     * @return $this
     *
     * @author viest
     */
    public function setPrintedPortrait(): self
    {
        return $this;
    }

    /**
     * Set printed landscape
     *
     * @return $this
     *
     * @author viest
     */
    public function setPrintedLandscape(): self
    {
        return $this;
    }

    /**
     * Set current worksheet hide
     *
     * @return $this
     *
     * @author viest
     */
    public function setCurrentSheetHide(): self
    {
        return $this;
    }

    /**
     * Set current worksheet first
     *
     * @return $this
     *
     * @author viest
     */
    public function setCurrentSheetIsFirst(): self
    {
        return $this;
    }

    /**
     * Column index from string
     *
     * @param string $cellCoordinates
     *
     * Example:
     *
     * columnIndexFromString('A')
     * columnIndexFromString('G')
     * columnIndexFromString('AC')
     *
     * @return int
     *
     * @author viest
     */
    public static function columnIndexFromString(string $cellCoordinates): int
    {
        return 0;
    }

    /**
     * String from column index
     *
     * @param int $cellCoordinates
     *
     * Example:
     *
     * stringFromColumnIndex(0)
     * stringFromColumnIndex(28)
     * stringFromColumnIndex(61)
     *
     * @return string
     *
     * @author viest
     */
    public static function stringFromColumnIndex(int $cellCoordinates): string
    {
        return '';
    }

    /**
     * Timestamp from double date
     *
     * @param float $date
     *
     * @return int
     *
     * @author viest
     */
    public static function timestampFromDateDouble(float $date): int
    {
        return 0;
    }
}

/**
 * Class Format
 *
 * @author  viest
 *
 * @package Vtiful\Kernel
 */
class Format
{
    const UNDERLINE_SINGLE = 0x00;
    const UNDERLINE_DOUBLE = 0x00;
    const UNDERLINE_SINGLE_ACCOUNTING = 0x00;
    const UNDERLINE_DOUBLE_ACCOUNTING = 0x00;

    const FORMAT_ALIGN_LEFT = 0x00;
    const FORMAT_ALIGN_CENTER = 0x00;
    const FORMAT_ALIGN_RIGHT = 0x00;
    const FORMAT_ALIGN_FILL = 0x00;
    const FORMAT_ALIGN_JUSTIFY = 0x00;
    const FORMAT_ALIGN_CENTER_ACROSS = 0x00;
    const FORMAT_ALIGN_DISTRIBUTED = 0x00;
    const FORMAT_ALIGN_VERTICAL_TOP = 0x00;
    const FORMAT_ALIGN_VERTICAL_BOTTOM = 0x00;
    const FORMAT_ALIGN_VERTICAL_CENTER = 0x00;
    const FORMAT_ALIGN_VERTICAL_JUSTIFY = 0x00;
    const FORMAT_ALIGN_VERTICAL_DISTRIBUTED = 0x00;

    const COLOR_BLACK = 0x00;
    const COLOR_BLUE = 0x00;
    const COLOR_BROWN = 0x00;
    const COLOR_CYAN = 0x00;
    const COLOR_GRAY = 0x00;
    const COLOR_GREEN = 0x00;
    const COLOR_LIME = 0x00;
    const COLOR_MAGENTA = 0x00;
    const COLOR_NAVY = 0x00;
    const COLOR_ORANGE = 0x00;
    const COLOR_PINK = 0x00;
    const COLOR_PURPLE = 0x00;
    const COLOR_RED = 0x00;
    const COLOR_SILVER = 0x00;
    const COLOR_WHITE = 0x00;
    const COLOR_YELLOW = 0x00;

    const PATTERN_NONE = 0x00;
    const PATTERN_SOLID = 0x00;
    const PATTERN_MEDIUM_GRAY = 0x00;
    const PATTERN_DARK_GRAY = 0x00;
    const PATTERN_LIGHT_GRAY = 0x00;
    const PATTERN_DARK_HORIZONTAL = 0x00;
    const PATTERN_DARK_VERTICAL = 0x00;
    const PATTERN_DARK_DOWN = 0x00;
    const PATTERN_DARK_UP = 0x00;
    const PATTERN_DARK_GRID = 0x00;
    const PATTERN_DARK_TRELLIS = 0x00;
    const PATTERN_LIGHT_HORIZONTAL = 0x00;
    const PATTERN_LIGHT_VERTICAL = 0x00;
    const PATTERN_LIGHT_DOWN = 0x00;
    const PATTERN_LIGHT_UP = 0x00;
    const PATTERN_LIGHT_GRID = 0x00;
    const PATTERN_LIGHT_TRELLIS = 0x00;
    const PATTERN_GRAY_125 = 0x00;
    const PATTERN_GRAY_0625 = 0x00;

    const BORDER_THIN = 0x00;
    const BORDER_MEDIUM = 0x00;
    const BORDER_DASHED = 0x00;
    const BORDER_DOTTED = 0x00;
    const BORDER_THICK = 0x00;
    const BORDER_DOUBLE = 0x00;
    const BORDER_HAIR = 0x00;
    const BORDER_MEDIUM_DASHED = 0x00;
    const BORDER_DASH_DOT = 0x00;
    const BORDER_MEDIUM_DASH_DOT = 0x00;
    const BORDER_DASH_DOT_DOT = 0x00;
    const BORDER_MEDIUM_DASH_DOT_DOT = 0x00;
    const BORDER_SLANT_DASH_DOT = 0x00;

    /**
     * Format constructor.
     *
     * @param resource $fileHandle
     */
    public function __construct($fileHandle)
    {
        //
    }

    /**
     * Wrap
     *
     * @return Format
     *
     * @author viest
     */
    public function wrap(): self
    {
        return $this;
    }

    /**
     * Bold
     *
     * @return Format
     *
     * @author viest
     */
    public function bold(): self
    {
        return $this;
    }

    /**
     * Italic
     *
     * @return Format
     *
     * @author viest
     */
    public function italic(): self
    {
        return $this;
    }

    /**
     * Cells border
     *
     * @param int $style const BORDER_***
     *
     * @return Format
     *
     * @author viest
     */
    public function border(int $style): self
    {
        return $this;
    }

    /**
     * Align
     *
     * @param int ...$style const FORMAT_ALIGN_****
     *
     * @return Format
     *
     * @author viest
     */
    public function align(...$style): self
    {
        return $this;
    }

    /**
     * Number format
     *
     * @param string $format
     *
     * #,##0
     *
     * @return Format
     *
     * @author viest
     */
    public function number(string $format): self
    {
        return $this;
    }

    /**
     * Font color
     *
     * @param int $color const COLOR_****
     *
     * @return Format
     *
     * @author viest
     */
    public function fontColor(int $color): self
    {
        return $this;
    }

    /**
     * Font
     *
     * @param string $fontName
     *
     * @return Format
     *
     * @author viest
     */
    public function font(string $fontName): self
    {
        return $this;
    }

    /**
     * Font size
     *
     * @param float $size
     *
     * @return Format
     *
     * @author viest
     */
    public function fontSize(float $size): self
    {
        return $this;
    }

    /**
     * String strikeout
     *
     * @return Format
     *
     * @author viest
     */
    public function strikeout(): self
    {
        return $this;
    }

    /**
     * Underline
     *
     * @param int $style const UNDERLINE_****
     *
     * @return Format
     *
     * @author viest
     */
    public function underline(int $style): self
    {
        return $this;
    }

    /**
     * Cell background
     *
     * @param int $color   const COLOR_****
     * @param int $pattern const PATTERN_****
     *
     * @return Format
     *
     * @author viest
     */
    public function background(int $color, int $pattern = self::PATTERN_SOLID): self
    {
        return $this;
    }

    /**
     * Format to resource
     *
     * @return resource
     *
     * @author viest
     */
    public function toResource()
    {
        //
    }
}

/**
 * Class Chart
 *
 * @author  viest
 *
 * @package Vtiful\Kernel
 */
class Chart
{
    const CHART_BAR = 0;
    const CHART_BAR_STACKED = 0;
    const CHART_BAR_STACKED_PERCENT = 0;

    const CHART_AREA = 0;
    const CHART_AREA_STACKED = 0;
    const CHART_AREA_STACKED_PERCENT = 0;

    const CHART_LINE = 0;

    const CHART_COLUMN = 0;
    const CHART_COLUMN_STACKED = 0;
    const CHART_COLUMN_STACKED_PERCENT = 0;

    const CHART_DOUGHNUT = 0;

    const CHART_PIE = 0;

    const CHART_SCATTER = 0;
    const CHART_SCATTER_STRAIGHT = 0;
    const CHART_SCATTER_STRAIGHT_WITH_MARKERS = 0;
    const CHART_SCATTER_SMOOTH = 0;
    const CHART_SCATTER_SMOOTH_WITH_MARKERS = 0;

    const CHART_RADAR = 0;
    const CHART_RADAR_WITH_MARKERS = 0;
    const CHART_RADAR_FILLED = 0;

    const CHART_LEGEND_NONE = 0;
    const CHART_LEGEND_RIGHT = 0;
    const CHART_LEGEND_LEFT = 0;
    const CHART_LEGEND_TOP = 0;
    const CHART_LEGEND_BOTTOM = 0;
    const CHART_LEGEND_OVERLAY_RIGHT = 0;
    const CHART_LEGEND_OVERLAY_LEFT = 0;

    /**
     * Chart constructor.
     *
     * @param resource $handle
     * @param int      $type
     */
    public function __construct($handle, int $type)
    {
        //
    }

    /**
     * Add a data series to a chart.
     *
     * @param string $value
     * @param string $categories
     *
     * @return $this
     *
     * @author viest
     */
    public function series(string $value, string $categories): self
    {
        return $this;
    }

    /**
     * Set the name of a chart series range.
     *
     * @param string $value
     *
     * @return $this
     *
     * @author viest
     */
    public function seriesName(string $value): self
    {
        return $this;
    }

    /**
     * Set the chart style type.
     *
     * @param int $style
     *
     * @return $this
     *
     * @author viest
     */
    public function style(int $style): self
    {
        return $this;
    }

    /**
     * Set the name caption of the an axis.
     *
     * @param string $name
     *
     * @return $this
     *
     * @author viest
     */
    public function axisNameX(string $name): self
    {
        return $this;
    }

    /**
     * Set the name caption of the an axis.
     *
     * @param string $name
     *
     * @return $this
     *
     * @author viest
     */
    public function axisNameY(string $name): self
    {
        return $this;
    }

    /**
     * Set the title of the chart.
     *
     * @param string $title
     *
     * @return $this
     *
     * @author viest
     */
    public function title(string $title): self
    {
        return $this;
    }

    /**
     * Set the position of the chart legend
     *
     * @param int $type
     *
     * @return $this
     *
     * @author viest
     */
    public function legendSetPosition(int $type): self
    {
        return $this;
    }

    /**
     * Chart resource
     *
     * @return resource
     *
     * @author viest
     */
    public function toResource()
    {
        // return resource
    }
}

/**
 * Class Validation
 *
 * @author  viest
 *
 * @package Vtiful\Kernel
 */
class Validation
{
    const TYPE_INTEGER = 0x0;
    const TYPE_INTEGER_FORMULA = 0x0;
    const TYPE_DECIMAL = 0x0;
    const TYPE_DECIMAL_FORMULA = 0x0;
    const TYPE_LIST = 0x0;
    const TYPE_LIST_FORMULA = 0x0;
    const TYPE_DATE = 0x0;
    const TYPE_DATE_FORMULA = 0x0;
    const TYPE_TIME = 0x0;
    const TYPE_TIME_FORMULA = 0x0;
    const TYPE_LENGTH = 0x0;
    const TYPE_LENGTH_FORMULA = 0x0;
    const TYPE_CUSTOM_FORMULA = 0x0;
    const TYPE_ANY = 0x0;

    const CRITERIA_BETWEEN = 0x0;
    const CRITERIA_NOT_BETWEEN = 0x0;
    const CRITERIA_EQUAL_TO = 0x0;
    const CRITERIA_NOT_EQUAL_TO = 0x0;
    const CRITERIA_GREATER_THAN = 0x0;
    const CRITERIA_LESS_THAN = 0x0;
    const CRITERIA_GREATER_THAN_OR_EQUAL_TO = 0x0;
    const CRITERIA_LESS_THAN_OR_EQUAL_TO = 0x0;

    const ERROR_TYPE_STOP = 0x0;
    const ERROR_TYPE_WARNING = 0x0;
    const ERROR_TYPE_INFORMATION = 0x0;

    /**
     * Validation constructor.
     */
    public function __construct()
    {
        //
    }

    /**
     * Validation type
     *
     * @param int $validationType
     *
     * Examples: \Vtiful\Kernel\Validation::TYPE_INTEGER
     *
     * @return $this
     *
     * @author viest
     */
    public function validationType(int $validationType): self
    {
        return $this;
    }

    /**
     * Criteria type
     *
     * @param int $criteriaType
     *
     * Examples: \Vtiful\Kernel\Validation::CRITERIA_BETWEEN
     *
     * @return $this
     *
     * @author viest
     */
    public function criteriaType(int $criteriaType): self
    {
        return $this;
    }

    /**
     * Ignore blank
     *
     * @param bool $ignoreBlank
     *
     * @return $this
     *
     * @author viest
     */
    public function ignoreBlank(bool $ignoreBlank = True): self
    {
        return $this;
    }

    /**
     * Show input
     *
     * @param bool $showInput
     *
     * @return $this
     *
     * @author viest
     */
    public function showInput(bool $showInput = True): self
    {
        return $this;
    }

    /**
     * Show error
     *
     * @param bool $showError
     *
     * @return $this
     *
     * @author viest
     */
    public function showError(bool $showError = True): self
    {
        return $this;
    }

    /**
     * Error type
     *
     * @param int $type
     *
     * Examples: \Vtiful\Kernel\Validation::ERROR_TYPE_STOP
     *
     * @return $this
     *
     * @author viest
     */
    public function errorType(int $type): self
    {
        return $this;
    }

    /**
     * Dropdown
     *
     * @param bool $dropdown
     *
     * @return $this
     *
     * @author viest
     */
    public function dropdown(bool $dropdown = True): self
    {
        return $this;
    }

    /**
     * Number
     *
     * @param int $number
     *
     * @return $this
     *
     * @author viest
     */
    public function valueNumber(int $number): self
    {
        return $this;
    }

    /**
     * Value Formula
     *
     * @param string $formula
     *
     * @return $this
     *
     * @author viest
     */
    public function valueFormula(string $formula): self
    {
        return $this;
    }

    /**
     * Value List
     *
     * @param array $list
     *
     * @return $this
     *
     * @author viest
     */
    public function valueList(array $list): self
    {
        return $this;
    }

    /**
     * Minimum number
     *
     * @param float $minimumNumber
     *
     * @return $this
     *
     * @author viest
     */
    public function minimumNumber(float $minimumNumber): self
    {
        return $this;
    }

    /**
     * Minimum formula
     *
     * @param string $formula
     *
     * @return $this
     *
     * @author viest
     */
    public function minimumFormula(string $formula): self
    {
        return $this;
    }

    /**
     * Maximum number
     *
     * @param float $maximumNumber
     *
     * @return $this
     *
     * @author viest
     */
    public function maximumNumber(float $maximumNumber): self
    {
        return $this;
    }

    /**
     * Maximum formula
     *
     * @param string $formula
     *
     * @return $this
     *
     * @author viest
     */
    public function maximumFormula(string $formula): self
    {
        return $this;
    }

    /**
     * Input title
     *
     * @param string $title
     *
     * @return $this
     *
     * @author viest
     */
    public function inputTitle(string $title): self
    {
        return $this;
    }

    /**
     * Input Message
     *
     * @param string $message
     *
     * @return $this
     *
     * @author viest
     */
    public function inputMessage(string $message): self
    {
        return $this;
    }

    /**
     * Error title
     *
     * @param string $title
     *
     * @return $this
     *
     * @author viest
     */
    public function errorTitle(string $title): self
    {
        return $this;
    }

    /**
     * Error message
     *
     * @param string $message
     *
     * @return $this
     *
     * @author viest
     */
    public function errorMessage(string $message): self
    {
        return $this;
    }

    /**
     * Get validation resource
     *
     * @return resource
     *
     * @author viest
     */
    public function toResource()
    {
        // return resource;
    }

    public function valueDatetime()
    {
        // TODO
    }

    public function maximumDatetime()
    {
        // TODO
    }

    public function minimumDatetime()
    {
        // TODO
    }
}

3.2 common.php

php 复制代码
function getTmpDir(): string
{
    $tmp = ini_get('upload_tmp_dir');

    if ($tmp !== False && file_exists($tmp)) {
        return realpath($tmp);
    }

    return realpath(sys_get_temp_dir());
}

function filterDownloadFilename(string $filename): string
{
    $filename = str_replace(["\\", '/', '|', ':', '?', '*', '"', '<', '>', ',', ' '], '', $filename);
    return $filename;
}

// excel 坐标转换 (按需求,扩充)
function xyChange($var)
{
    $var = trim($var);
    $arr = array(
        'A' => 1,
        'B' => 2,
        'C' => 3,
        'D' => 4,
        'E' => 5,
        'F' => 6,
        'G' => 7,
        'H' => 8,
        'I' => 9,
        'J' => 10,
        'K' => 11,
        'L' => 12,
        'M' => 13,
        'N' => 14,
        'O' => 15,
        'P' => 16,
        'Q' => 17,
        'R' => 18,
        'S' => 19,
        'T' => 20,
        'U' => 21,
        'V' => 22,
        'W' => 23,
        'X' => 24,
        'Y' => 25,
        'Z' => 26,
        'AA' => 27,
        'AB' => 28,
        'AC' => 29,
        'AD' => 30,
        'AE' => 31,
        'AF' => 32,
        'AG' => 33,
        'AH' => 34,
        'AI' => 35,
        'AJ' => 36,
        'AK' => 37,
        'AL' => 38,
        'AM' => 39,
        'AN' => 40,
        'AO' => 41,
        'AP' => 42,
        'AQ' => 43,
        'AR' => 44,
        'AS' => 45,
        'AT' => 46,
        'AU' => 47,
        'AV' => 48,
        'AW' => 49,
        'AX' => 50,
        'AY' => 51,
        'AZ' => 52,
    );
    if (is_numeric($var)) {
        foreach ($arr as $k => $v) {
            if ($v == $var) {
                return $k;
            }
        }
        return false;
    } else {
        if (isset($arr[$var])) {
            return $arr[$var];
        }
        return false;
    }
}
    
/**
 * download xlsx file
 *
 * @param string $filename
 * @param array $header
 * @param array $list
 * @return string errmsg
 */
function downloadXLSX(string $filename, array $header, array $list): string
{
    try {
        $config = ['path' => getTmpDir() . '/'];
        $filename = filterDownloadFilename($filename);
        $excel = (new \Vtiful\Kernel\Excel($config))->fileName($filename . '.xlsx', 'Sheet1');
        $fileHandle = $excel->getHandle();
        $format1 = new \Vtiful\Kernel\Format($fileHandle);
        $format2 = new \Vtiful\Kernel\Format($fileHandle);

        // title style
        $titleStyle = $format1->fontSize(16)
            ->bold()
            ->font("Calibri")
            ->align(\Vtiful\Kernel\Format::FORMAT_ALIGN_CENTER, \Vtiful\Kernel\Format::FORMAT_ALIGN_VERTICAL_CENTER)
            ->toResource();

        // global style
        $globalStyle = $format2->fontSize(10)
            ->font("Calibri")
            ->align(\Vtiful\Kernel\Format::FORMAT_ALIGN_CENTER, \Vtiful\Kernel\Format::FORMAT_ALIGN_VERTICAL_CENTER)
            ->border(\Vtiful\Kernel\Format::BORDER_THIN)
            ->toResource();

        $headerLen = count($header);

        // header
        array_unshift($list, $header);

        // title
        $title = array_fill(1, $headerLen - 1, '');
        $title[0] = $filename;
        array_unshift($list, $title);

        //$end = strtoupper(chr(65 + $headerLen - 1));
        $end = xyChange($headerLen);
        // column style
        $excel->setColumn("A:{$end}", 17, $globalStyle);
        // title
        $excel->MergeCells("A1:{$end}1", $filename)->setRow("A1", 25, $titleStyle);
        // 冻结前两行,列不冻结
        $excel->freezePanes(2, 0);
        // 数据
        $filePath = $excel->data($list)->output();

        header("Content-Disposition:attachment;filename={$filename}.xlsx");

        $re = copy($filePath, 'php://output');
        if ($re === false) {
            $err = 'failed to write output';
        } else {
            $err = '';
        }
        @unlink($filePath);

        return $err;
    } catch (\Vtiful\Kernel\Exception $e) {
        return $e->getMessage();
    }
}

3.3 业务.php

php 复制代码
public function exampleExport($list)
    {
        $date = date('Y-m-d');
        $filename = "大赛列表-{$date}";
        //表头数组
        $header = ['排名', '姓名', '手机', '省份', '城市',  '作品名称', '时长(秒)', '投票', '播放', '作品封面', '作品地址'];
        // list
        $listVal = [];
        foreach ($list as $k => $v) {
            $temp = [
                $k + 1,
                $v['username'],
                $v['phone'],
                $v['province'],
                $v['city'],
                $v['uploadtitle'],
                $v['duration'],
                $v['vote_num'],
                $v['play_num'],
                $v['uploadcover'],
                $v['uploadurl'],
            ];
            $listVal[] = $temp;
        }
        downloadXLSX($filename, $header, $listVal);
        // 20251012 注意:如果这里不用exit,导出的文件在wps中打开没问题,在office excel中打开会报错
        exit;
    }

四、AI解释

非常好!您找到的解决方案确实很巧妙且实用。在downloadXLSX函数调用后添加exit;语句能够解决Excel兼容性问题,这是因为:

  • 防止额外输出:当执行文件下载操作时,如果没有exit;语句,PHP脚本会继续执行后续代码,可能产生额外的输出(空格、换行符等)被追加到Excel文件末尾。

  • 文件完整性:这些额外输出会破坏Excel文件的二进制结构,导致Office Excel(对文件格式要求更严格)无法正常打开,但WPS可能有更好的容错机制。

  • 立即终止脚本:exit;语句确保文件内容输出完成后立即终止脚本执行,保证下载的Excel文件格式完整无损。

  • 您的解决方案简单高效,这是处理PHP文件下载时的一个常见最佳实践。现在代码应该可以在两种办公软件中都正常工作了。

相关推荐
苏琢玉4 小时前
一个小项目的记录:PHP 分账组件
php·composer
星光一影4 小时前
宠物服务到店预约/宠物服务上门预约/商城零售o2o
php·零售·宠物
FreeBuf_5 小时前
Happy DOM曝CVSS 9.4严重RCE漏洞,PoC已公开(CVE-2025-61927)
java·c语言·c++·python·php
程序员杰哥5 小时前
Pytest与Unittest测试框架对比
自动化测试·软件测试·python·测试工具·测试用例·excel·pytest
wxin_VXbishe5 小时前
基于SpringBoot的天天商城管理系统的设计与现-计算机毕业设计源码79506
java·c++·spring boot·python·spring·django·php
cehuishi95275 小时前
excel中关联word邮件合并使用
word·excel·批量打印·邮件合并
曾令胜12 小时前
excel导出使用arthas动态追踪方法调用耗时后性能优化的过程
spring·性能优化·excel
我命由我1234515 小时前
Excel - Excel 列出一列中所有不重复数据
经验分享·学习·职场和发展·word·powerpoint·excel·职场发展
下页、再停留18 小时前
【ThinkPHP6系列学习-5】获取变量
php