王新阳

wangxinyang

生成CSV格式excel基本规则

以下为CodeIgniter中导出csv的完整示例

知识点:输出缓冲控制 http://php.net/manual/zh/book.outcontrol.php

//导出数据
public function export(){
	/*
	 * 不使用PHPExcel生成excel文件,因为太占内存
	 * 生成csv基本规则
	 * 1、列内容用逗号分隔
	 * 2、\r\n换行
	 * 3、如果当前字段内容中有回车、换行、逗号等任意内容时,字段两头要加双引号
	 * 4、如果当前字段内容中有双引号,但不包含回车、换行、逗号等任意内容时,直接输出不用处理;否则字段中的双引号要进行转义(两个双引号代替1个),且字段两头加又引号
	 * 5、超过11位的整数要写成 ="123456789012" 形式,防止因excel自动采用科学计数法而导致内容失真(如身份证)
	 */
	
	//获取表字段并删除无用项
	$arr_table_fields = array_diff_key($this->tableinfo(), array('id'=>0, 'sn'=>0, 'updatetime'=>0, 'createtime'=>0));
	//重置要查询的字段
	$select_fields = implode(',', array_keys($arr_table_fields));
	
	//清空缓冲区
	if (ob_get_level() !== 0 && @ob_end_clean() === FALSE)@ob_clean();
	//输出headers
	header('Content-Type: application/octet-stream');
	header('Content-Disposition: attachment; filename="观众数据-'. date('YmdHis') .'.csv"');
	header('Expires: 0');
	header('Content-Transfer-Encoding: binary');
	//header('Content-Length: '.$filesize);
	header('Cache-Control: private, no-transform, no-store, must-revalidate');
	
	$str = '';
	//输出表头
	foreach($arr_table_fields as $row){
		$str .= $row['comment'].',';
	}
	$str .= "\n";
	echo utf82gbk($str);
	
	//获取记录总数
	$num = $this->db->count_all('my_guanzhong');
	if(! $num)return;
	//每次获取1000条
	$pagesize = 1000;
	//循环获取数据并输入
	//如果数据记录很多而直接全部读取到内存会导致内存溢出
	ob_start();
	for($i=0; $idb->select($select_fields)->order_by('id DESC')->limit($pagesize, $i*$pagesize)->get('my_guanzhong');
		while($row=$res->unbuffered_row()){
			foreach($row as $item){
				if(is_numeric($item)){ //数值型
					if(preg_match("/^-?\d{1,11}$/", (string)$item)){ //不超过11位的整数
						echo $item, ',';
					}else{
						echo '="', $item, '",';
					}
				}else{
					if(strpos($item, ',') !== FALSE || strpos($item, "\r") !== FALSE || strpos($item, "\n") !== FALSE){ //逗号、回车、换行
						if(strpos($item, '"') !== FALSE){ //有双引号
							echo '"', str_replace('"', '""', $item), '",';
						}else{
							echo '"', $item, '",';
						}
					}else{
						echo $item, ',';
					}
				}
			}
			echo "\n";
		}
		//echo format_bytes(memory_get_peak_usage()), ', ', microtime(1)-NOW_TIME, "\n";
		//获取缓冲区内容并转为gbk编码
		$str = utf82gbk(ob_get_contents());
		//清空缓冲区
		ob_clean();
		//重新输出转码后的内容
		echo $str;
		//发送至浏览器
		ob_flush();
	}
	flush();
}
2017-09-20
2024-05-03 星期五 农历三月二十五