我编写了一个类,用于为传递给它的每个查询导出excel文件和工作表。
由于某些原因,我的工作表缺少第一行结果。标题显示正确,但标题下的第一行缺失。
如果我不调用SetHeaderCells()函数,那么第一行就在那里,所以我知道它是我班上的东西。
但是如果我调用SetHeaderCells()那么第一行就会丢失。
用以下方式调用此类:
if(gfQSGetGetVar('Export')=='xls') {
$ex2 = new ExportToExcel2('Somefile');
$ex2->AddSheet('Sheet1', 'Select * from Division;');
$ex2->AddSheet('Sheet2', 'Select * from Zone');
$ex2->ExportMultiSheet();
}
类别:
require_once 'PhpExcel.php';
class ExportToExcel2 {
public $AllSheetData = [];
protected $SheetData = [];
protected $PHPExcel = '';
protected $FileName = '';
function __construct($_filename) {
$this->FileName = $_filename;
$this->PHPExcel = new PHPExcel;
//clean the output buffer before download
ob_clean();
}
public function AddSheet($_WorkSheetName, $_Query) {
$this->SheetData['Sheet_Name'] = $_WorkSheetName;
$this->SheetData['Query'] = $_Query;
$this->AllSheetData[] = $this->SheetData;
unset($this->SheetData);
}
public function ExportMultiSheet($_ExportType='xls') {
if(!empty($this->AllSheetData)) {
$count=0;$Result='';
$this->PHPExcel->setActiveSheetIndex(0);
foreach($this->AllSheetData as $subarray) {
if($count>0){
$this->PHPExcel->createSheet(null);
$this->PHPExcel->setActiveSheetIndex($count);
}
$count++;
foreach($subarray as $key => $value) {
if($key == 'Query') {
$Result = dbQuery($value);
$this->SetHeaderCells($Result);
$this->SetbodyCells($Result);
}
if($key =='Sheet_Name') {
$this->PHPExcel->getActiveSheet()->setTitle($value);
}
}
}
$this->ExportType($_ExportType);
}
}
public function ExportSingleSheet($_Query, $_ExportType='xls') {
$Result = dbQuery($_Query);
$this->SetHeaderCells($Result);
$this->SetBodyCells($Result);
$this->SetProperties();
$this->ExportType($_ExportType);
}
private function ExportType($_ExportType) {
if($_ExportType=='xls') {
$this->DownloadXLS();
}
else if($_ExportType=='csv') {
$this->DownloadCSV();
}
}
private function SetProperties() {
//set all columns to align left
$this->PHPExcel->getDefaultStyle()->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
//show gridlines?
$this->PHPExcel->getActiveSheet()->setShowGridlines(true);
//set columns a through z to auto width
for($col = 'A'; $col !== 'Z'; $col++) {
$this->PHPExcel->getActiveSheet()
->getColumnDimension($col)
->setAutoSize(true);
}
//set the first sheet to open first
$this->PHPExcel->setActiveSheetIndex(0);
}
private function DownloadXLS() {
$this->SetProperties();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="'.$this->FileName.'-'.date("y.m.d").'.xls"');
header('Cache-Control: max-age=0');
$objWriter = PHPExcel_IOFactory::createWriter($this->PHPExcel, 'Excel2007');
$objWriter->save('php://output');
exit;
}
private function DownloadCSV() {
$this->SetProperties();
header('Content-Type: text/csv');
header('Content-Disposition: attachment;filename="'.$this->FileName.'-'.date("y.m.d").'.csv"');
header('Cache-Control: max-age=0');
$objWriter = new PHPExcel_Writer_CSV($this->PHPExcel);
$objWriter->save("php://output");
exit;
}
private function SetHeaderCells($Result) {
$row = 1; // 1-based index
$row_data = sqlsrv_fetch_array($Result, SQLSRV_FETCH_ASSOC);
$col = 0;
foreach(array_keys($row_data) as $key) {
$this->PHPExcel->getActiveSheet()->setCellValueByColumnAndRow($col, $row, $key);
$col++;
}
}
private function SetBodyCells($Result) {
$row2 = 2;
while($row_data = sqlsrv_fetch_array($Result, SQLSRV_FETCH_ASSOC)) {
$col2 = 0;
foreach($row_data as $key=>$value) {
$this->PHPExcel->getActiveSheet()->setCellValueByColumnAndRow($col2, $row2, $value);
$col2++;
}
$row2++;
}
}
}
解决!
我解决这个问题的方法是使用推荐的元数据功能。
将SetHeaderCells函数更改为:
private function SetHeaderCells($Result) {
$row = 1; // 1-based index
$col = 0;
foreach( sqlsrv_field_metadata($Result) as $fieldMetadata ) {
foreach( $fieldMetadata as $name => $value) {
if($name=='Name') {
$this->PHPExcel->getActiveSheet()->setCellValueByColumnAndRow($col, $row, $value);
$col++;
}
}
}
}
答案 0 :(得分:1)
您正在获取第一条记录并使用$row_data
键设置标题;但是那个记录已经被提取了,所以当你转到数据时,你会立即进入一个以结果集中的第二个记录开头的提取循环
我不相信sqlsrv支持倒带功能,但您可以使用sqlsrv_field_metadata()来获取标头信息,而不是获取第一条记录。
或者,例如:
private function SetHeaderCells($Result) {
$row = 1; // 1-based index
$row_data = sqlsrv_fetch_array($Result, SQLSRV_FETCH_ASSOC);
$col = 0;
foreach(array_keys($row_data) as $key) {
$this->PHPExcel->getActiveSheet()->setCellValueByColumnAndRow($col, $row, $key);
$col++;
}
return $row_data;
}
private function SetBodyCells($Result, $row_data) {
$row2 = 2;
do {
$col2 = 0;
foreach($row_data as $key=>$value) {
$this->PHPExcel->getActiveSheet()->setCellValueByColumnAndRow($col2, $row2, $value);
$col2++;
}
$row2++;
} while($row_data = sqlsrv_fetch_array($Result, SQLSRV_FETCH_ASSOC));
}
$Result = dbQuery($_Query);
$firstRow = $this->SetHeaderCells($Result);
$this->SetBodyCells($Result, $firstRow);
但使用标题的元数据将是一种更好的方法