c5_labsci/zciyphp/excel.php
2026-01-27 00:52:00 +08:00

386 lines
18 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/* =================================================================================
* License: GPL-2.0 license
* Author: 众产® https://ciy.cn/code
* Version: 0.1.3
====================================================================================*/
/*
* excel.php Excel导入导出扩展库
*
* ciy_ImportCSV 导入Excel CSV格式解析
* ciy_runExcelCSV 导出到Excel CSV格式
* ciy_runExcelxml 导出到Excel xml格式样式可控
* ciy_runExcelxlsx 导出到Excel xlsx格式不建议实现
*
*/
namespace ciy;
class excel {
public static function ciy_ImportCSV($file) {
$fh = file_get_contents($file);
$dot = ',';
if (ord($fh[0]) == 255) {
$line = mb_convert_encoding(substr($fh, 2), 'UTF-8', 'UTF-16LE');
$dot = "\t";
} else
$line = mb_convert_encoding($fh, 'UTF-8', 'GBK');
$csvlines = array();
$csvfields = array();
$csvdata = '';
$bcontent = false;
$linecnt = strlen($line) - 1;
if ($line[$linecnt] != "\n") {
$line .= "\n\n";
$linecnt += 2;
} else {
$line .= "\n";
$linecnt++;
}
for ($i = 0; $i < $linecnt; $i++) {
if ($line[$i] == "\"") {
if ($line[$i + 1] == "\"")
$csvdata .= $line[$i];
else
$bcontent = !$bcontent;
} else if ($bcontent) {
$csvdata .= $line[$i];
} else if ($line[$i] == $dot) {
$csvfields[] = $csvdata;
$csvdata = '';
} else if ($line[$i] == "\n") {
$csvfields[] = str_replace("\r", '', $csvdata);
$csvdata = '';
$csvlines[] = $csvfields;
$csvfields = array();
} else
$csvdata .= $line[$i];
}
return $csvlines;
}
/**
* CSV函数调用组件用于数据导出到Excel操作
* ?func=函数名
* 将调用csv_函数名(){}
* 函数返回array数组。第一行包含.csv则为CSV文件名。
*/
public static function ciy_runExcelCSV($csql) {
if (!isset($_GET['excel']) || $_GET['excel'] != 'csv')
return;
$funcname = 'excel_' . get('func');
if (!function_exists($funcname)) {
clog('Excel CSV导出失败' . $funcname . '函数未定义');
exit;
}
$retarr = call_user_func($funcname, $csql);
if (!is_array($retarr)) {
clog('Excel CSV导出失败' . $retarr);
exit;
}
$filename = $retarr[0];
if (empty($filename))
$filename = date('Y-m-d_H-i-s') . rand(1000, 9999);
$filename .= '.csv';
$fields = $retarr[1];
$datas = $retarr[2];
header("Cache-Control: public");
header("Pragma: public");
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=" . $filename);
echo (chr(255) . chr(254));
$bline = false;
foreach ($fields as $field) {
if (is_array($field))
$d = $field['name'];
else
$d = $field;
if ($bline)
echo mb_convert_encoding("\t", "UTF-16LE", "UTF-8");
echo mb_convert_encoding('"' . $d . '"', "UTF-16LE", "UTF-8");
$bline = true;
}
echo mb_convert_encoding("\r\n", "UTF-16LE", "UTF-8");
foreach ($datas as $data) {
$bline = false;
foreach ($data as $d) {
if ($bline)
echo mb_convert_encoding("\t", "UTF-16LE", "UTF-8");
echo mb_convert_encoding('"' . $d . '"', "UTF-16LE", "UTF-8");
$bline = true;
}
echo mb_convert_encoding("\r\n", "UTF-16LE", "UTF-8");
}
exit;
}
public static function ciy_runExcelxml($csql) {
if (!isset($_GET['excel']) || $_GET['excel'] != 'xml')
return;
$funcname = 'excel_' . get('func');
if (!function_exists($funcname)) {
clog('Excel xml导出失败' . $funcname . '函数未定义');
exit;
}
$retarr = call_user_func($funcname, $csql);
if (!is_array($retarr)) {
clog('Excel xml导出失败:' . $retarr);
exit;
}
$filename = $retarr[0];
if (empty($filename))
$filename = date('Y-m-d_H-i-s') . rand(1000, 9999);
$filename .= '.xls';
$fields = $retarr[1];
$datas = $retarr[2];
$styles = @$retarr[3];
if (!is_array($styles))
$styles = array();
$exts = @$retarr[4];
if (!is_array($exts))
$exts = array();
$sheetname = 'sheetCIY';
if (isset($exts['sheetname']))
$sheetname = $exts['sheetname'];
$DefaultColumnWidth = 60; //默认宽度
$DefaultRowHeight = 16; //默认高度
$dat = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>CIY</Author>
<Version>15.00</Version>
</DocumentProperties>
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"><AllowPNG/></OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><WindowTopX>0</WindowTopX><WindowTopY>0</WindowTopY> <ProtectStructure>False</ProtectStructure><ProtectWindows>False</ProtectWindows></ExcelWorkbook>
<Styles>';
foreach ($styles as $id => $style)
$dat .= '<Style ss:ID="' . $id . '">' . $style . '</Style>';
$dat .= '</Styles><Worksheet ss:Name="' . $sheetname . '"><Table ss:ExpandedColumnCount="' . (count($fields) + 10) . '" ss:ExpandedRowCount="' . (count($datas) + 20) . '" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="' . $DefaultColumnWidth . '" ss:DefaultRowHeight="' . $DefaultRowHeight . '">';
foreach ($fields as $field) {
if (!is_array($field) || !isset($field['width']))
$dat .= '<Column ss:Width="' . $DefaultColumnWidth . '"/>';
else
$dat .= '<Column ss:Width="' . $field['width'] . '"/>';
}
$dat .= @$exts['rowstop']; //自定义表格头
if (isset($exts['titleheight']))
$dat .= '<Row ss:Height="' . $exts['titleheight'] . '">';
else
$dat .= '<Row>';
$cellpre = '<Cell';
if (isset($styles['ts']))
$cellpre .= '<Cell ss:StyleID="ts"';
foreach ($fields as $field) {
if (is_array($field)) {
$dat .= $cellpre . '><Data ss:Type="String">' . @$field['name'] . '</Data></Cell>';
} else
$dat .= $cellpre . '><Data ss:Type="String">' . $field . '</Data></Cell>';
}
$dat .= '</Row>';
foreach ($datas as $data) {
$dat .= '<Row>';
foreach ($data as $ind => $d) {
$dat .= '<Cell';
$type = 'String';
if (is_array($fields[$ind])) {
if (isset($fields[$ind]['style']))
$dat .= ' ss:StyleID="' . $fields[$ind]['style'] . '"';
if (isset($fields[$ind]['type']))
$type = $fields[$ind]['type'];
}
$dat .= '><Data ss:Type="' . $type . '">' . $d . '</Data></Cell>';
}
$dat .= '</Row>';
}
$dat .= @$exts['rowsfooter']; //自定义表格尾
$dat .= '</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>';
$dat .= @$exts['pagesetup'];
$dat .= '<Header x:Margin="0.3"/>
<Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
</PageSetup>
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>1</PaperSizeIndex>
<HorizontalResolution>600</HorizontalResolution>
<VerticalResolution>0</VerticalResolution>
</Print>
<Selected/>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
</Workbook>';
header("Cache-Control: public");
header("Pragma: public");
header("Content-type: text/xml");
header("Content-Disposition: attachment; filename=" . $filename);
echo $dat;
exit;
}
public static function general_excel_xml($param) {
$fields = $param['field'];
$datas = $param['data'];
$styles = @$param['style'];
if (!is_array($styles)) {
$styles = array();
$styles['l'] = '<Alignment ss:Horizontal="Left"/><Font ss:Color="#000000"/><Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>';
$styles['c'] = '<Alignment ss:Horizontal="Center"/><Font ss:Color="#000000"/><Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>';
$styles['r'] = '<Alignment ss:Horizontal="Right"/><Font ss:Color="#000000"/><Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>';
$styles['dd'] = '<Alignment ss:Horizontal="Center"/><Font ss:Color="#000000"/><Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders><NumberFormat ss:Format="yyyy\-mm\-dd"/>';
$styles['dt'] = '<Alignment ss:Horizontal="Center"/><Font ss:Color="#000000"/><Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders><NumberFormat ss:Format="yyyy\-mm\-dd\ hh:mm"/>';
$styles['ts'] = '<Alignment ss:Horizontal="Center"/><Interior ss:Color="#bdd7ee" ss:Pattern="Solid"/><Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>';
$styles['cap'] = '<Alignment ss:Horizontal="Left" ss:Vertical="Center"/>
<Font ss:Size="16" ss:Color="#1f4e78" ss:Bold="1"/>
<Interior ss:Color="#ffffff" ss:Pattern="Solid"/>';
}
$sheetname = 'sheetCIY';
if (isset($param['sheetname']))
$sheetname = $param['sheetname'];
$DefaultColumnWidth = 60; //默认宽度
$DefaultRowHeight = 20; //默认高度
$dat = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>CIY</Author>
<Version>15.00</Version>
</DocumentProperties>
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"><AllowPNG/></OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><WindowTopX>0</WindowTopX><WindowTopY>0</WindowTopY> <ProtectStructure>False</ProtectStructure><ProtectWindows>False</ProtectWindows></ExcelWorkbook>
<Styles>';
foreach ($styles as $id => $style)
$dat .= '<Style ss:ID="' . $id . '">' . $style . '</Style>';
$dat .= '</Styles><Worksheet ss:Name="' . $sheetname . '"><Table ss:ExpandedColumnCount="' . (count($fields) + 10) . '" ss:ExpandedRowCount="' . (count($datas) + 20) . '" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="' . $DefaultColumnWidth . '" ss:DefaultRowHeight="' . $DefaultRowHeight . '">';
foreach ($fields as $field) {
if (isset($field['width']))
$dat .= '<Column ss:Width="' . $field['width'] . '"/>';
else
$dat .= '<Column ss:Width="' . $DefaultColumnWidth . '"/>';
}
if (isset($param['toptitle'])) { //头部标题
$dat .= '<Row ss:Height="30"><Cell ss:StyleID="cap"><Data ss:Type="String"></Data></Cell><Cell ss:StyleID="cap"><Data ss:Type="String">' . $param['toptitle'] . '</Data></Cell></Row>';
//$dat .= '<Row ss:Height="30"><Cell ss:MergeAcross="' . (count($fields) - 1) . '" ss:StyleID="cap"><Data ss:Type="String">' . $param['toptitle'] . '</Data></Cell></Row>';
}
if (isset($param['rowstop'])) //自定义表格头
$dat .= $param['rowstop'];
if (isset($param['titleheight']))
$dat .= '<Row ss:Height="' . $param['titleheight'] . '">';
else
$dat .= '<Row>';
$cellpre = '<Cell';
if (isset($styles['ts']))
$cellpre .= ' ss:StyleID="ts"';
foreach ($fields as $field) {
$dat .= $cellpre . '><Data ss:Type="String">' . $field['name'] . '</Data></Cell>';
}
$dat .= '</Row>';
foreach ($datas as $data) {
$dat .= '<Row>';
foreach ($data as $ind => $d) {
$dat .= '<Cell';
$type = 'String';
if (is_array($fields[$ind])) {
if (isset($fields[$ind]['style']))
$dat .= ' ss:StyleID="' . $fields[$ind]['style'] . '"';
if (isset($fields[$ind]['type'])) {
$type = $fields[$ind]['type'];
if (!is_numeric($d) && $type == 'Number')
$type = 'String';
} else {
if (strlen($d) < 11 && is_numeric($d) && (!empty($dd) && $d[0] == '0'))
$type = 'Number';
else
$type = 'String';
}
}
$dat .= '><Data ss:Type="' . $type . '">' . $d . '</Data></Cell>';
}
$dat .= '</Row>';
}
if (isset($param['total'])) {
$dat .= '<Row>';
foreach ($param['total'] as $total) {
$dat .= '<Cell';
if (isset($total['merge']))
$dat .= ' ss:MergeAcross="' . $total['merge'] . '"';
if (isset($total['style']))
$dat .= ' ss:StyleID="' . $total['style'] . '"';
if ($total['name'][0] == '=') {
$dat .= ' ss:Formula="' . $total['name'] . '"><Data ss:Type="Number"></Data></Cell>';
} else {
$dat .= '><Data ss:Type="String">' . $total['name'] . '</Data></Cell>';
}
}
$dat .= '</Row>';
// $param['total'][] = array('name'=>'合计','merge'=>2,'style'=>'l');
// $param['total'][] = array('name'=>'=SUM(R[-2]C:R[-1]C)','style'=>'r');
}
if (isset($param['rowsfooter']))
$dat .= $param['rowsfooter']; //自定义表格尾
$dat .= '</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>';
if (isset($param['pagesetup']))
$dat .= $param['pagesetup'];
else {
if (isset($param['landscape']))
$dat .= '<Layout x:Orientation="Landscape"/>'; //横向打印
$dat .= '<Header x:Margin="0.3"/><Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.3" x:Left="0.3" x:Right="0.3" x:Top="0.3"/>';
}
$dat .= '</PageSetup>';
if (isset($param['fixtopage']))
$dat .= '<FitToPage/>';
$dat .= '<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>1</PaperSizeIndex>
<HorizontalResolution>600</HorizontalResolution>
<VerticalResolution>0</VerticalResolution>
</Print>
<Selected/>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
</Workbook>';
return $dat;
}
//直接导出xls/xlsx格式。
//分析具体格式将xlsx修改为zip解压后研究sheet1.xml/styles.xml。
//使用PHPExcel后端导出服务器压力较大可以自定义样式或导入样式
//建议使用js-xlsx前端导出服务器压力小前端JS控制数据样式
public static function ciy_runExcelxlsx($csql) {
if (!isset($_GET['excel']) || $_GET['excel'] != 'xlsx')
return;
}
}