getActiveSheet(); // Set worksheet title $sheet->setTitle('Sheet 1'); // A1 Start here... should be compnay name .... $sheet->setCellValue('A1', $company); // Get last column letter based on headers count // $lastColumnLetter = getExcelColumnName(count($headers) - 1); $colCount = count($headersMain); // Calculate end column by character math (works up to 'ZZ') $lastColumnLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($colCount); $sheet->mergeCells("A1:{$lastColumnLetter}1"); // Style A1 $sheet->getStyle("A1")->getFill() ->setFillType(Fill::FILL_SOLID) ->getStartColor()->setRGB('ADD8E6'); // Light blue $sheet->getStyle("A1")->getAlignment() ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER) ->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER); $sheet->getStyle("A1")->getFont()->setBold(true)->setSize(14); $sheet->getStyle("A1")->getFont() ->getColor() ->setRGB(Color::COLOR_WHITE); // /. A1 ends here $currentRow = 2; // Start at row 2 if($type == 1){ $startCell = 'A' . $currentRow; $lastcolrow = callHeader($sheet, $headersMain, $startCell,$headersSub); $lastcolrow2 = callSkipRow($lastcolrow); $lastcolrow3 = callData($sheet,$headersMain,$xldata,$lastcolrow2,$mergeEndCol); $lastcolrow4 = callSkipRow($lastcolrow3); if($footer){ $lastcolrow5 = callFooter($sheet, $headersMain, $xldata, $lastcolrow4,'','',$mergeEndCol); } }else if($type == 2){ // $final_Footer=[]; // foreach($xldata as $i => $xl){ // echo $i; // echo "
";
                //     print_r($xl[$i]);
                //     echo "
"; // // echo count($xl[$i])."**"; // // $forFinalFooter // } // foreach ($xldata as $i => $xl) { // $forFinalFooter[] = $xl[$i]; // } $final_Footer = isset($headlines['final_Footer']) && !empty($headlines['final_Footer']) ? $headlines['final_Footer'] : []; foreach ($xldata as $index => $data) { if (!empty($data)) { $startCell = 'A' . $currentRow; $lastcolrow = callHeader($sheet, $headersMain, $startCell,$headersSub); $lastcolrow2 = callSkipRow($lastcolrow); $lastcolrow3 = callData($sheet, $headersMain, $data, $lastcolrow2); $lastcolrow4 = callSkipRow($lastcolrow3); $lastcolrow5 = callFooter($sheet, $headersMain, $data, $lastcolrow4,'Total Amount Rs','228B22',$mergeEndCol); $lastcolrow6 = callSkipRow($lastcolrow5); // Update currentRow for next iteration $currentRow = (int) filter_var($lastcolrow6, FILTER_SANITIZE_NUMBER_INT); } else { $startCell = 'A' . $currentRow; $lastcolrow = callHeader($sheet, $headersMain, $startCell,$headersSub); $lastcolrow2 = callSkipRow($lastcolrow); $currentRow = (int) filter_var($lastcolrow2, FILTER_SANITIZE_NUMBER_INT); } } if(!empty($final_Footer)){ $startCell = 'A' . $currentRow; callFooter($sheet, $headersMain, $final_Footer[0], $startCell,'Final Net Salary Amount Rs','DC143C',$mergeEndCol); // echo "cr".$currentRow;die; } // $final_Footer } // Create Excel writer $writer = new Xlsx($spreadsheet); $columnCount = count($headersMain); for ($col = 1; $col <= $columnCount; $col++) { $columnLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col); $sheet->getColumnDimension($columnLetter)->setAutoSize(true); } $highestColumn = $sheet->getHighestColumn(); // e.g., 'E' $highestRow = $sheet->getHighestRow(); // e.g., 10 // Build the full range (e.g., 'A1:E10') $range = 'A1:' . $highestColumn . $highestRow; // Apply border to that range $sheet->getStyle($range)->applyFromArray([ 'borders' => [ 'allBorders' => [ 'borderStyle' => Border::BORDER_THIN, 'color' => ['argb' => 'FF000000'], ], ], ]); try { // Save Excel file to the specified path ob_clean(); header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header("Content-Disposition: attachment; filename=\"$filename\""); header('Cache-Control: max-age=0'); $writer->save('php://output'); // stream to browser exit; // Return true if file was successfully saved } catch (\Exception $e) { // Log or handle the exception return false; // Return false if there was an error saving the file } } } function callHeader($sheet, $headersMain, $startCell, $headersSub = []) { $rowNumber = (int) filter_var($startCell, FILTER_SANITIZE_NUMBER_INT); $startCol = 'A'; $colCount = count($headersMain); // Calculate end column by character math (works up to 'ZZ') $endCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($colCount); // Check if sub-header has any non-empty value $hasSubHeader = !empty(array_filter($headersSub, function ($val) { return trim($val) !== ''; })); // 1. Write Main Header $sheet->fromArray([$headersMain], null, $startCell); $mainHeaderRange = "{$startCol}{$rowNumber}:{$endCol}{$rowNumber}"; // Style Main Header $sheet->getStyle($mainHeaderRange)->applyFromArray([ 'font' => [ 'bold' => true, 'color' => ['rgb' => 'FF0000'], 'size' => 12, ], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ] ]); if ($hasSubHeader) { // 2. Write Sub Header $subHeaderRow = $rowNumber + 1; $sheet->fromArray([$headersSub], null, "A{$subHeaderRow}"); $subHeaderRange = "{$startCol}{$subHeaderRow}:{$endCol}{$subHeaderRow}"; $sheet->getStyle($subHeaderRange)->applyFromArray([ 'font' => [ 'bold' => true, 'color' => ['rgb' => 'FF0000'], 'size' => 12, ], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER, ] ]); return 'A' . ($subHeaderRow + 1); } else { return 'A' . ($rowNumber + 1); } } function callData($sheet, $headers, $data, $startCell) { $startRow = (int) filter_var($startCell, FILTER_SANITIZE_NUMBER_INT); $startCol = 'A'; $sheet->fromArray($data, null, $startCell); $dataRowCount = count($data); $lastDataRow = $startRow + $dataRowCount; // $dataColCount = count($headers); // $lastDataColumn = getExcelColumnName($dataColCount - 1); // $dataRange = "{$startCol}{$startRow}:{$lastDataColumn}{$lastDataRow}"; // Set font color to black // $sheet->getStyle($dataRange)->getFont()->getColor()->setRGB('000000'); return 'A' . ($lastDataRow + 1); // return next row } function callSkipRow($startCell){ $row = (int) filter_var($startCell, FILTER_SANITIZE_NUMBER_INT); return 'A' . ($row + 1); // just skip a line } // function callFooter($sheet, $headers, $data, $startCell,$mergeEndindex) { // $row = (int) filter_var($startCell, FILTER_SANITIZE_NUMBER_INT); // $startCol = preg_replace('/[0-9]/', '', $startCell); // // Determine numeric columns dynamically // // $numericIndexes = []; // // foreach ($data as $index => $val) { // // foreach ($data as $rowData) { // // if (isset($rowData[$index]) && is_numeric($rowData[$index])) { // // $numericIndexes[] = $index; // // break; // // } // // } // // } // if (!empty($data)) { // // Look at the first row // $firstRow = $data[0]; // foreach ($firstRow as $key => $value) { // foreach ($data as $row) { // if (isset($row[$key]) && is_numeric($row[$key])) { // $numericIndexes[] = $key; // use the key (could be column name) // break; // } // } // } // } // // Get first numeric column index for placing totals // if (empty($numericIndexes)) return 'A' . ($row + 1); // Nothing to total // sort($numericIndexes); // $firstNumericIndex = $numericIndexes[0]; // $colCount = count($headers); // // Calculate end column by character math (works up to 'ZZ') // if($mergeEndindex == ''){ // $mergeEndCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($colCount - 1); // }else{ // $mergeEndCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex((int)$mergeEndindex); // } // // echo gettype($row);die; // // Merge from A to column before first numeric column (for "TOTAL" label) // $sheet->mergeCells("A{$row}:{$mergeEndCol}{$row}"); // $sheet->setCellValue("A{$row}", 'TOTAL'); // // Style for TOTAL label // $sheet->getStyle("A{$row}:{$mergeEndCol}{$row}")->applyFromArray([ // 'font' => [ // 'bold' => true, // 'size' => 14, // 'color' => ['rgb' => '228B22'] // ], // 'alignment' => [ // 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, // 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER // ] // ]); // // Total each numeric column and write to corresponding cell // foreach ($numericIndexes as $index) { // $total = 0; // foreach ($data as $rowData) { // $value = $rowData[$index] ?? 0; // if (is_numeric($value)) { // $total += $value; // } // } // $colLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex((int)$index); // $sheet->setCellValue("{$colLetter}{$row}", $total); // } // return 'A' . ($row + 1); // Return next available row // } function callFooter($sheet, $headers, $data, $startCell,$label,$code,$mergeEndIndex = null) { $row = (int) filter_var($startCell, FILTER_SANITIZE_NUMBER_INT); $startCol = preg_replace('/[0-9]/', '', $startCell); $numericKeys = []; $columnKeys = array_keys($data[0] ?? []); $columnKeyToIndex = array_flip($columnKeys); // key => index // Detect numeric columns foreach ($columnKeys as $key) { foreach ($data as $rowData) { if (isset($rowData[$key]) && is_numeric($rowData[$key])) { $numericKeys[] = $key; break; } } } // If no numeric columns, skip total row if (empty($numericKeys)) { return $startCol . ($row + 1); } // Determine where to end the merge for the TOTAL label if ($mergeEndIndex === null || $mergeEndIndex === '') { $firstNumericKey = $numericKeys[0]; $firstNumericIndex = $columnKeyToIndex[$firstNumericKey]; $mergeEndIndex = $firstNumericIndex > 0 ? $firstNumericIndex - 1 : 0; } // Write totals for each numeric column foreach ($numericKeys as $colKey) { $total = 0; foreach ($data as $rowData) { $val = $rowData[$colKey] ?? 0; if (is_numeric($val)) { $total += $val; } } $colIndex = $columnKeyToIndex[$colKey]; $colLetter = Coordinate::stringFromColumnIndex($colIndex + 1); $sheet->setCellValue("{$colLetter}{$row}", $total); $sheet->getStyle("{$colLetter}{$row}")->getNumberFormat()->setFormatCode('#,##0.00'); $sheet->getStyle("{$colLetter}{$row}")->applyFromArray([ 'font' => [ 'bold' => true, 'size' => 12 ], 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER ] ]); } $mergeEndCol = Coordinate::stringFromColumnIndex((int)$mergeEndIndex + 1); $mergeRange = "{$startCol}{$row}:{$mergeEndCol}{$row}"; // Merge cells and write $label name = "TOTAL" $sheet->mergeCells($mergeRange); $sheet->setCellValue("{$startCol}{$row}", $label); // Style "TOTAL" label $sheet->getStyle($mergeRange)->applyFromArray([ 'font' => [ 'bold' => true, 'size' => 14, 'color' => ['rgb' => $code] ], 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER ] ]); // Return next row cell reference return $startCol . ($row + 1); }