一、问题描述
导出的文件在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文件下载时的一个常见最佳实践。现在代码应该可以在两种办公软件中都正常工作了。