Buen día a todos! Buen fin de semana!, ¿como la están pasando? espero todo bien!. bueno hace un tiempo estoy dando soporte a una amiga que en el tema de informática está como mi presidenta Dina Boluarte que no sabe en donde está parada al decirnos que “Con 10 solcitos hacemos sopa, segundo y postre” que en vez de risa me da una F@#*** COLERA! , pero bueno a lo que quería contarles, lo que pasa es que ella tiene que hacer reportes mensuales en un EXCEL con un formato ya establecido por su empresa (OJO: no voy a decir ni la empresa ni el nombre de mi amiga) y esos reportes son de miles de personas (20 mil personas aprox.) y hay que rellenar datos personales (Dni, Apellidos y Nombres, Fecha de Nacimiento, edad, Etc.) y otros datos(Tipo de actividad, Detalle de la intervención, Etc.) y ella me pedía que lo rellene yo, al principio lo hacia de forma manual, osea llenando los datos uno por uno (se imaginan llenar datos de, por ejemplo 300 personas?) y eso causaba una perdida de tiempo y energía y aunque ella me pagaba por eso, aun perdida mucho tiempo, entonces pensé en hacer una pequeña aplicación donde en una base de datos ya debería estar registrados todos los empleados de la empresa (si esos 20mil empleados) y que pida los datos más importantes y luego genere el reporte automáticamente y pues me puse manos a la Obra….
la aplicación la hice en PHP y use para la base de datos MYSQL con el paquete completo XAMPP, pero antes de mostrar el código, tenía una complicación, yo sabía que para poder generar un EXCEL desde PHP se necesita la librería PhpSpreadsheet pero me rondaba una duda: en el formato del reporte que la empresa la daba había campos repetidos los cuales son para cada tipo de actividad y dependiendo del ese tipo de actividad(Grupal o Individual) se llenaban un rango de campos la lógica es asi:
Si TipoActividad==’GRUPAL’, se llenan los campos Descripción y Día (ubicados en las celdas Q,R,S,T,UV,W,X,Y,ZAA,AB,AC,AD), Si TipoActividad==’INDIVIDUAL’, se deberían llenar los campos Sesión y Día (ubicados en las celdas AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN) y el problema radicaba en que ella a veces hacia varias actividades en la semana y no veía como llenar ese EXCEL programando en PHP para que llenen los datos respectivos, no se si me explico (comenten si no entienden xD). Pero bueno entonces para no perder el tiempo comencé por lo más básico, la base de datos (no voy a mostrar toda la estructura, solo algunos detalles):
nombre base de datos: db_reporte
CREATE TABLE `descripciones` (
`id_descripciones` int(3) NOT NULL,
`NOMBRE` varchar(30) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
CREATE TABLE `detalle_reporte_mensual` (
`id_detalle_reporte_mensual` int(8) NOT NULL,
`id_reporte_mensual` int(8) NOT NULL,
`id_empleado` int(8) NOT NULL,
`planificacion_intervencion` varchar(1) NOT NULL,
`tipo_intervencion` varchar(1) NOT NULL',
`id_grupo_especifico` int(1) NOT NULL,
`id_descripciones` int(3) NOT NULL,
`dia_actividades` int(2) DEFAULT NULL,
`id_sessiones` int(1) NOT NULL,
`id_usuariro` int(4) NOT NULL,
`tema` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `grupo_especifico`
--
CREATE TABLE `grupo_especifico` (
`id_grupo_especifico` int(1) NOT NULL,
`nombre` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `empleados`
--
CREATE TABLE `empleados` (
`id_empleado` int(8) NOT NULL,
`doc_identidad` varchar(20) NOT NULL DEFAULT 'INDOCUMENTADO',
`ape_nombres` varchar(255) NOT NULL,
`fecha_ingreso` date NOT NULL,
`fecha_nacimiento` date NOT NULL,
`cargo` varchar(20) NOT NULL,
`discapacidad` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `reportes_mensuales`
--
CREATE TABLE `reportes_mensuales` (
`id_reporte_mensual` int(8) NOT NULL,
`id_usuario` int(4) NOT NULL,
`fecha_reporte` date NOT NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `sessiones`
--
CREATE TABLE `sesiones` (
`id_sesiones` int(1) NOT NULL,
`nombre` varchar(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
--
-- Volcado de datos para la tabla `sesiones`
--
INSERT INTO `sesiones` (`id_sessiones`, `nombre`) VALUES
(1, 'ASISTIO'),
(2, 'FALTÓ'),
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `usuarios`
--
CREATE TABLE `usuarios` (
`id_usuario` int(4) NOT NULL,
`doc_identidad` varchar(12) NOT NULL,
`clave` varchar(255) CHARACTER SET armscii8 COLLATE armscii8_general_ci NOT NULL,
`nombres` varchar(255) NOT NULL,
`ape_paterno` varchar(255) NOT NULL,
`ape_materno` varchar(255) NOT NULL,
`telefono` varchar(12) NOT NULL DEFAULT 'NO TIENE',
`email` varchar(255) NOT NULL DEFAULT 'NO TIENE',
`area` varchar(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
--
-- Índices para tablas volcadas
--
--
-- Indices de la tabla `descripciones`
--
ALTER TABLE `descripciones`
ADD PRIMARY KEY (`id_descripciones`);
--
-- Indices de la tabla `detalle_reporte_mensual`
--
ALTER TABLE `detalle_reporte_mensual`
ADD PRIMARY KEY (`id_detalle_reporte_mensual`),
ADD KEY `id_grupo_especifico` (`id_grupo_especifico`),
ADD KEY `id_sesiones` (`id_sessiones`),
ADD KEY `id_reporte_mensual` (`id_reporte_mensual`),
ADD KEY `id_empleado` (`id_empleado`),
ADD KEY `id_descripciones` (`id_descripciones`) USING BTREE;
--
-- Indices de la tabla `grupo_especifico`
--
ALTER TABLE `grupo_especifico`
ADD PRIMARY KEY (`id_grupo_especifico`);
--
-- Indices de la tabla `empleados`
--
ALTER TABLE `empleados`
ADD PRIMARY KEY (`id_empleado`);
--
-- Indices de la tabla `reportes_mensuales`
--
ALTER TABLE `reportes_mensuales`
ADD PRIMARY KEY (`id_reporte_mensual`),
ADD KEY `id_usuario` (`id_usuario`);
--
-- Indices de la tabla `sesiones`
--
ALTER TABLE `sesiones`
ADD PRIMARY KEY (`id_sessiones`);
-- Indices de la tabla `usuarios`
--
ALTER TABLE `usuarios`
ADD PRIMARY KEY (`id_usuario`);
--
-- AUTO_INCREMENT de las tablas volcadas
--
--
-- AUTO_INCREMENT de la tabla `descripciones`
--
ALTER TABLE `descripciones`
MODIFY `id_descripciones` int(3) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=21;
--
-- AUTO_INCREMENT de la tabla `detalle_reporte_mensual`
--
ALTER TABLE `detalle_reporte_mensual`
MODIFY `id_detalle_reporte_mensual` int(8) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT de la tabla `grupo_especifico`
--
ALTER TABLE `grupo_especifico`
MODIFY `id_grupo_especifico` int(1) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
--
-- AUTO_INCREMENT de la tabla `empleados`
--
ALTER TABLE `empleados`
MODIFY `id_empleado` int(8) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4368;
--
-- AUTO_INCREMENT de la tabla `reportes_mensuales`
--
ALTER TABLE `reportes_mensuales`
MODIFY `id_reporte_mensual` int(8) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT de la tabla `sesiones`
--
ALTER TABLE `sesiones`
MODIFY `id_sesiones` int(1) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT de la tabla `usuarios`
--
ALTER TABLE `usuarios`
MODIFY `id_usuario` int(4) NOT NULL AUTO_INCREMENT;
--
-- Restricciones para tablas volcadas
--
--
-- Filtros para la tabla `detalle_reporte_mensual`
--
ALTER TABLE `detalle_reporte_mensual`
ADD CONSTRAINT `detalle_reporte_mensual_ibfk_1` FOREIGN KEY (`id_grupo_especifico`) REFERENCES `grupo_especifico` (`id_grupo_especifico`),
ADD CONSTRAINT `detalle_reporte_mensual_ibfk_3` FOREIGN KEY (`id_empleado`) REFERENCES `empleados` (`id_empleado`),
ADD CONSTRAINT `detalle_reporte_mensual_ibfk_4` FOREIGN KEY (`id_reporte_mensual`) REFERENCES `reportes_mensuales` (`id_reporte_mensual`),
ADD CONSTRAINT `detalle_reporte_mensual_ibfk_6` FOREIGN KEY (`id_sesiones`) REFERENCES `sesiones` (`id_sesiones`),
ADD CONSTRAINT `detalle_reporte_mensual_ibfk_7` FOREIGN KEY (`id_descripciones`) REFERENCES `descripciones` (`id_descripciones`);
--
-- Filtros para la tabla `reportes_mensuales`
--
ALTER TABLE `reportes_mensuales`
ADD CONSTRAINT `reportes_mensuales_ibfk_1` FOREIGN KEY (`id_usuario`) REFERENCES `usuarios` (`id_usuario`);
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
y para no hacer larga esta entrada en mi blog solo voy a poner el codigo de la clase donde genera el EXCEL y como se usa.
archivo: conexion.php
<?php
class Conexion{
//Atributo para la cadena de conexion
private $cn=null;
//funcion de conexion
public function getConexion(){
try{
//Script de la cadena de conexion
$cadena="mysql:host=localhost;dbname=db_reporte";
//implementando la cadena de conexion
$this->cn=new PDO($cadena,'user_reporte','123456'); //OBVIO AQUI LA CAMBIE
$this->cn->setAttribute(PDO::ATTR_CASE,PDO::CASE_LOWER);
//retornando la conexion correcta
return $this->cn;
} catch(PDOException $ex){
echo 'Error en la Conexion - '.$ex->getMessage();
}
}
}
?>
archivo: ReportGenerator.php
<?php
require 'vendor/autoload.php';
require 'conexion.php';
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use Monolog\Level;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler;
class ReportGenerator
{
private $conn;
private $spreadsheet;
private $worksheet;
private $templateFile = './reportes/formato.xlsx';
private $outputFile = './reportes/reporte_mensual.xlsx';
private $processedIds = [];
private $rowMapping = [];
private $logger;
public function __construct()
{
$database = new Conexion();
$this->conn = $database->getConexion();
$this->loadTemplate();
$this->initializeProcessedIds();
//Logs
$this->logger = new Logger('my_app');
$this->logger->pushHandler(new StreamHandler(__DIR__ . '/reportes/debug.log', Level::Debug));
// $this->logger->info('My logger is now ready');
$this->logger->pushHandler(new FirePHPHandler());
}
private function loadTemplate()
{
$this->spreadsheet = IOFactory::load($this->templateFile);
$this->worksheet = $this->spreadsheet->getActiveSheet();
}
private function initializeProcessedIds()
{
$highestRow = $this->worksheet->getHighestRow();
for ($row = 2; $row <= $highestRow; $row++) {
$documentoId = $this->worksheet->getCell('C' . $row)->getValue();
if (!empty($documentoId)) {
$this->processedIds[] = $documentoId;
$this->rowMapping[$documentoId] = $row;
}
}
}
public function generateReport($id_reporte,$tipo_actividad)
{
if($tipo_actividad==1){ //tipo_actividad = INDIVIDUAL
$query="SELECT I.doc_identidad AS 'documento_identidad',
I.ape_nombres AS 'apellidos_nombres_interno',
I.fecha_ingreso AS 'fecha_ingreso',
I.fecha_nacimiento AS 'fecha_nacimiento',
I.discapacidad AS 'discapacidad',
DET.planificacion_intervencion AS 'planificacion_intervencion',
TIPO_INTERV.nombre_tipo_intervencion AS 'tipo_intervencion',
GRUP.nombre_grupo_especifico AS 'grupo_especifico',
DET.tema AS 'tema',
DESCRIP.nombre_descripciones AS 'descripcion',
DET.dia_actividades AS 'dia',
SES.nombre_sesiones AS 'nombre_sesion',
CONCAT(U.ape_paterno,' ',U.ape_materno,' ',U.nombres) AS 'datos_profesional'
FROM reportes_mensuales REP
INNER JOIN detalle_reporte_mensual DET ON REP.id_reporte_mensual=DET.id_reporte_mensual
INNER JOIN tipo_intervencioN TIPO_INTERV ON DET.id_tipo_intervencion=TIPO_INTERV.id_tipo_intervencion
INNER JOIN grupo_especifico GRUP ON DET.id_grupo_especifico=GRUP.id_grupo_especifico
INNER JOIN empleados I ON DET.id_empleado=I.id_empleado
INNER JOIN usuarios U ON REP.id_usuario=U.id_usuario
INNER JOIN descripciones DESCRIP ON DET.id_descripciones=DESCRIP.id_descripciones
INNER JOIN sesiones SES ON DET.id_sesiones=SES.id_sesiones
WHERE REP.id_reporte_mensual=:id_reporte AND DESCRIP.nombre_descripciones!='---'
ORDER BY I.doc_identidad";
}else if($tipo_actividad==2){
$query="SELECT I.doc_identidad AS 'documento_identidad',
I.ape_nombres AS 'apellidos_nombres_interno',
I.fecha_ingreso AS 'fecha_ingreso',
I.fecha_nacimiento AS 'fecha_nacimiento',
I.discapacidad AS 'discapacidad',
DET.planificacion_intervencion AS 'planificacion_intervencion',
TIPO_INTERV.nombre_tipo_intervencion AS 'tipo_intervencion',
GRUP.nombre_grupo_especifico AS 'grupo_especifico',
DET.tema AS 'tema',
DESCRIP.nombre_descripciones AS 'descripcion',
DET.dia_actividades AS 'dia',
SES.nombre_sesiones AS 'nombre_sesion',
CONCAT(U.ape_paterno,' ',U.ape_materno,' ',U.nombres) AS 'datos_profesional'
FROM reportes_mensuales REP
INNER JOIN detalle_reporte_mensual DET ON REP.id_reporte_mensual=DET.id_reporte_mensual
INNER JOIN tipo_intervencioN TIPO_INTERV ON DET.id_tipo_intervencion=TIPO_INTERV.id_tipo_intervencion
INNER JOIN grupo_especifico GRUP ON DET.id_grupo_especifico=GRUP.id_grupo_especifico
INNER JOIN empleados I ON DET.id_empleado=I.id_empleado
INNER JOIN usuarios U ON REP.id_usuario=U.id_usuario
INNER JOIN descripciones DESCRIP ON DET.id_descripciones=DESCRIP.id_descripciones
INNER JOIN sessiones SES ON DET.id_sesiones=SES.id_sesiones
WHERE REP.id_reporte_mensual=:id_reporte AND DESCRIP.nombre_descripciones='---'
ORDER BY I.doc_identidad";
}else{
$query="SELECT I.doc_identidad AS 'documento_identidad',
I.ape_nombres AS 'apellidos_nombres_interno',
I.fecha_ingreso AS 'fecha_ingreso',
I.fecha_nacimiento AS 'fecha_nacimiento',
I.discapacidad AS 'discapacidad',
DET.planificacion_intervencion AS 'planificacion_intervencion',
TIPO_INTERV.nombre_tipo_intervencion AS 'tipo_intervencion',
GRUP.nombre_grupo_especifico AS 'grupo_especifico',
DET.tema AS 'tema',
DESCRIP.nombre_descripciones AS 'descripcion',
DET.dia_actividades AS 'dia',
SES.nombre_sesiones AS 'nombre_sesion',
CONCAT(U.ape_paterno,' ',U.ape_materno,' ',U.nombres) AS 'datos_profesional'
FROM reportes_mensuales REP
INNER JOIN detalle_reporte_mensual DET ON REP.id_reporte_mensual=DET.id_reporte_mensual
INNER JOIN tipo_intervencioN TIPO_INTERV ON DET.id_tipo_intervencion=TIPO_INTERV.id_tipo_intervencion
INNER JOIN grupo_especifico GRUP ON DET.id_grupo_especifico=GRUP.id_grupo_especifico
INNER JOIN empleados I ON DET.id_empleado=I.id_empleado
INNER JOIN usuarios U ON REP.id_usuario=U.id_usuario
INNER JOIN descripciones DESCRIP ON DET.id_descripciones=DESCRIP.id_descripciones
INNER JOIN sessiones SES ON DET.id_sesiones=SES.id_sesiones
WHERE REP.id_reporte_mensual=:id_reporte
ORDER BY I.doc_identidad";
}
$stmt = $this->conn->prepare($query);
$stmt->bindParam(':id_reporte', $id_reporte, PDO::PARAM_INT);
$stmt->execute();
$currentRow = empty($this->rowMapping) ? 2 : max($this->rowMapping) + 1;
while ($row = $stmt->fetch(PDO::FETCH_OBJ)) {
$documentoId = $row->documento_identidad;
$tipoActividad = $this->determinarTipoActividad($tipo_actividad);
if (in_array($documentoId, $this->processedIds)) {
$existingRow = $this->rowMapping[$documentoId];
$this->updateExistingRow($existingRow, $row, $tipoActividad);
} else {
$this->createNewRow($currentRow, $row, $tipoActividad);
$this->processedIds[] = $documentoId;
$this->rowMapping[$documentoId] = $currentRow;
$currentRow++;
}
}
$writer = IOFactory::createWriter($this->spreadsheet, 'Xlsx');
$writer->save($this->outputFile);
}
private function determinarTipoActividad($tipo_intervencion)
{
// Aquí defines la lógica para determinar si es tipo 1 o 2
// basado en el valor de tipo_intervencion
if($tipo_intervencion == '1'){
return 1;
}else if($tipo_intervencion == '2'){
return 2;
}else{
return 0;
}
}
private function updateExistingRow($row, $data, $tipoActividad)
{
if ($tipoActividad == 1) {
$descripcionColumns = ['Q', 'S', 'U', 'W', 'Y', 'AA', 'AC'];
$diaColumns = ['R', 'T', 'V', 'X', 'Z', 'AB', 'AD'];
for ($i = 0; $i < count($descripcionColumns); $i++) {
$currentValue = $this->worksheet->getCell($descripcionColumns[$i] . $row)->getValue();
if (empty($currentValue)) {
$this->worksheet->setCellValue($descripcionColumns[$i] . $row, $data->descripcion);
$this->worksheet->setCellValue($diaColumns[$i] . $row, $data->dia);
break;
}
}
} elseif ($tipoActividad == 2) {
$sesionColumns = ['AE', 'AG', 'AI', 'AK', 'AM'];
$diaColumns = ['AF', 'AH', 'AJ', 'AL', 'AN'];
for ($i = 0; $i < count($sesionColumns); $i++) {
$currentValue = $this->worksheet->getCell($sesionColumns[$i] . $row)->getValue();
if (empty($currentValue)) {
$this->worksheet->setCellValue($sesionColumns[$i] . $row, $data->nombre_sesion);
$this->worksheet->setCellValue($diaColumns[$i] . $row, $data->dia);
break;
}
}
}else{
}
}
private function createNewRow($row, $data, $tipoActividad)
{
// Mapear los campos de la consulta a las columnas del Excel
$sexo="MASCULINO";
$columnMapping = [
'C' => 'documento_identidad',
'D' => 'apellidos_nombres_interno',
'F' => 'fecha_ingreso',
'G' => 'fecha_nacimiento',
'I' => 'discapacidad',
'J' => 'planificacion_intervencion',
'K' => 'tipo_intervencion',
'L' => 'grupo_especifico',
'M' => 'tema',
'AO' => 'datos_profesional',
];
foreach ($columnMapping as $column => $field) {
if (property_exists($data, $field)) {
//llenar columna H (edad)
$formula = "=(NOW()-" ."G".$row . ")/365-0.5";
$this->worksheet->setCellValue("H" . $row, $formula)
->getStyle("H" . $row)->getNumberFormat()->setFormatCode('0');;
$this->logger->error("Columna H, valor: ".$formula);
//llenado columna E (sexo)
$this->worksheet->setCellValue("E" . $row, $sexo);
$this->logger->error("Columna E, valor: ".$sexo);
/*
//Llenado de Tipo_intervencion
//Llenado de Tipo_intervencion
if($column=="K"){
if ($data->$field== 1) {
$data->$field = "";
}
if ($data->$field== 2) {
$data->$field = "INTRODUCCION_AL_CAMBIO_CLIMATICO";
}
if ($data->$field== 3) {
$data->$field = "INTERVENCIÓN_GENERAL";
}
if ($data->$field== 4) {
$data->$field = "APTITUD_POSITIVA";
}
if ($data->$field== 5) {
$data->$field = "OTROS_TEMAS";
}
if ($data->$field== 6) {
$data->$field = "INTERVENCION_ESPECIALIZADA";
}
if ($data->$field== 7) {
$data->$field = "RESPONSABILIDAD_SOCIAL";
}
if ($data->$field== 8) {
$data->$field = "NO_DIFERENCIADA";
}
}
*/
$this->worksheet->setCellValue($column . $row, $data->$field);
$this->logger->error("Columna: ".$column." Fila: ".$row);
}
}
// foreach ($this->columnMapping as $column => $field) {
// if (property_exists($data, $field)) {
// $this->worksheet->setCellValue($column . $row, $data->$field);
// }
// }
if ($tipoActividad == 1) {
$this->worksheet->setCellValue('Q' . $row, $data->descripcion);
$this->worksheet->setCellValue('R' . $row, $data->dia);
} elseif ($tipoActividad == 2) {
$this->worksheet->setCellValue('AE' . $row, $data->nombre_sesion);
$this->worksheet->setCellValue('AF' . $row, $data->dia);
}
}
}
archivo: generate_report.php
<?php
require 'ReportGenerator.php';
try {
// El ID del reporte que quieres generar
$id_reporte = isset($_GET['id_reporte']) ? (int)$_GET['id_reporte'] : null;
$tipo_actividad = isset($_GET['tipo_actividad']) ? (int)$_GET['tipo_actividad'] : null;
if (!$id_reporte || !$tipo_actividad) {
throw new Exception("Es necesario proporcionar un ID de reporte.");
}
$generator = new ReportGenerator();
$generator->generateReport($id_reporte,$tipo_actividad);
echo "Reporte generado exitosamente como 'reporte_mensual.xlsx'\n";
} catch (Exception $e) {
echo "Error al generar el reporte: " . $e->getMessage() . "\n";
}
lo que hace generate_report.php es en primer lugar llamar al archivo ReportGenerator.php donde se encuentra la clase que genera el reporte en EXCEL, luego captura mediante el método GET los valores del id_reporte a generar y el tipo_actividad que vas a generar, luego genera una nueva instancia de la clase ReportGenerator() y llama a la función dentro de esa clase generateReport() con sus respectivos parámetros ($id_reporte y $tipo_actividad) luego genera el reporte y nos avisa con un «echo» que se generó el reporte y en caso de algún error (catch(Exception $e)) muestra el error que se ha producido. he modificado el codigo para que en vez de GET sea por POST y lo pida a travez de un formulario con dos SELECT tanto el id_reporte como el tipo_actividad)

y aquí muestro un video de como funciona: