幻蓝博客 – 孤月蓝风

追寻互联网科技、Unity开发、AR/VR开发、游戏开发、Web前后端开发等技术。

【PHP】将数据导出为可以用Excel打开的一个CSV文件


在一些小型项目中,后台页面或许并不会有太多的功能。但是统计基本是所有客户必不可少的需求之一,虽然我们可以通过各种JS来实现图标效果,但个人觉得导出Excel是更加合适的方式,而最方便导出的格式莫过于CSV了。

CSV是很简单的文本格式,通过逗号 ,换行 \r\n 进行分隔,而且可以通过Excel打开,也可以很方便的转换为Excel格式。

$csv = fopen('user.csv','w');
$text = "昵称,性别,年龄\n";
foreach ($data['user'] as $row) {
    $nt = $row['name'].','.$row['sex'].','.$row['age']."\n";
    $text .= $nt;
}
//$text = utf8_encode($text);
$text = iconv('UTF-8','GBK',$text);
//echo $text;
fwrite($csv,$text);
fclose($csv);

在最开始导出CSV文件时,发现Excel打开后显示乱码,后得知必须转成GBK才能正常显示中文,所以就有了iconv转换编码类型的一行。之后保存在本地后,供用户下载。


【PHP】将Excel数据导入到MySQL数据库中


在一些项目中,经常会需要将Excel文件导入到Mysql或其他数据库中,我们这里使用PHPExcel来进行导入。

PHPExcel是一个使用PHP语言开发的Excel操作类,拥有读取、写入等强大功能。

我们可以读取服务器上的文件进行导入,也可以通过上传进行导入。

首先进行文件上传:

$file = '/tmp/excel.xlsx';
move_uploaded_file($_FILES["file"]["tmp_name"], $file);

之后我们需要进行一些设置,防止导入大文件时超时等:

ini_set("memory_limit","-1");
set_time_limit(1800);

在PHPExcel中,可以设置缓存已节省内存开始,但会影响读取与写入单元格的速度(官方文档中有此说明)。如果你的内存勾搭,获取并不需要进行缓存设置,但对于小内存的服务器,这是很有必要的。PHPExcel有多种缓存机制,我们使用gzip压缩方式来使用:

$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_in_memory_gzip;
if (!PHPExcel_Settings::setCacheStorageMethod($cacheMethod)) {
    die($cacheMethod . " caching method is not available" . EOL);
}

官方文档中介绍,在脚本执行完成之前,已初始化过的缓存设置将不能被更改,会一直使用到脚本执行结束。

设置好缓存之后,我们就可以对Excel文件进行读取了:

$reader = PHPExcel_IOFactory::createReader('Excel2007');
$reader->setReadDataOnly(true);

我们读取的是Excel2007格式的文件,PHPExcel支持多种文件格式,如果需要查看对应格式的使用方式可以去查看官方文档。

设置 setReadDataOnly 有助于提高读取性能。

加载文件,之后获取当前的sheet进行操作:

$excel = $reader->load($file);
$sheet = $excel->getActiveSheet();

你可以通过读取单元格的方式来进行操作,也可以通过数组的方式进行操作。

数组方式:

$sheet->toArray(null,true,true,true);

单元格方式:

$sheet->getCell('A6')->getFormattedValue();

可以读取单元格数据之后,我们就可以将数据写入数据库了。

但这样远没有结束,如果你的Excel文件过大的话,load操作的时间会特别特别长(超强服务器请忽略此句),所以我们需要对数据进行分块处理。

我们可以通过Filter来进行分块操作,我们这里定义一个ReadFilter的过滤类:

class ReadFilter implements PHPExcel_Reader_IReadFilter
{
    private $_startRow = 0;
    private $_endRow = 0;

    public function setRows($startRow, $chunkSize)
    {
        $this->_startRow = $startRow;
        $this->_endRow = $startRow + $chunkSize;
    }

    public function readCell($column, $row, $worksheetName = '')
    {
        if ($row >= $this->_startRow && $row < $this->_endRow) {
            return true;
        }
        return false;
    }
}

我们读取的时候通过setRows来规定要读取的起始行和结束行,在readCell中对数据进行过滤,return false则为忽略此条数据。

我们通过URL参数来规定此页面需要读取哪些数据,读取完之后刷新,进行下一批操作,这个功能可以自行尝试。

我们对Excel的操作基本就可以完成了,其实这应该是一个很简单的功能,因为在我的本地服务器上只写了一遍代码就通过了,但传到在线服务器后,发现在线服务器有各种各样的限制,而我又不能修改这些限制,于是尝试了多种读取及数据库写入方式,今天面对的最多的一句话就是Mysql has gone away,当我无比心酸,但最后筛查后发现是框架里的数据库操作类有问题。    =_=

这篇博客就到这里了。


PHP中Apache的虚拟目录设置


之前做PHP,一直用的UwAmp这种工具,傻瓜式的创建虚拟目录,一直没看过到底是怎样一回事。好久没玩PHP了,今天更换了XAMPP,于是看了一下虚拟目录的生成,发现挺简单的。

httpd.conf最后加入如下代码即可:

<VirtualHost *:81>
# Generate Virtual Host
	DocumentRoot "C:\wwwroot\"
	ServerName "localhost"
</VirtualHost>