PHP - descarga en Excel

 
Vista:
sin imagen de perfil

descarga en Excel

Publicado por Hugo (37 intervenciones) el 08/10/2022 21:24:23
Hola, buenas tardes estimados.

Estoy teniendo un problema con una emisión de reportes en Excel.
Resulta que en intento descargar una consulta en Excel la cual en mi localhost se descarga correctamente, pero cuando lo intento hacer en el Servidor, no lo descarga y me muestra la consulta realizada en HTML.
Lo cierto es que le doy vueltas y no encuentro el porqué.

Agradecería mucho si alguien me pudiese echar una mano para resolverlo.
Copio el código:

reporte_faltas.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
<?php
session_start();
?>
<html>
	<head>
		<title>Intranet</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
		<link rel="stylesheet" type="text/css" href="../../../Cabecera/cabecera.css">
		<link rel="stylesheet" type="text/css" href="../../gsa.css">
		<link rel="stylesheet" type="text/css" href="../Reclamos de Sueldo/reporte_reclamos.css">
		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
		<link rel="preconnect" href="https://fonts.googleapis.com">
		<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
		<link href="https://fonts.googleapis.com/css2?family=Kaisei+HarunoUmi:wght@500&display=swap" rel="stylesheet">
		<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.11.0/sweetalert2.css"/>
		<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.11.0/sweetalert2.js"></script>
	</head>
	<body>
		<?php
			include ("../../../Conexion/conexion.php");
		?>
		<div id="Logo">
			<img src= "../../../logo_Univ.jpg" class="soc"/>
		</div>
		<div id="Cabecera">
			<img src= "../../../gsa.png" class="gsa"/>
			<?php
				require ("../../../Login/iniciar_session.php");
			?>
		</div>
 
		<div id="Contenedor">
			<div id="formulario">
				<form action="excel_faltas.php" method="post" class="form">
					<div class="formulario">
						<h2 class="titulo">Reporte de Faltas con Aviso</h2><br><br>
						<div class="fechas">
							<span class="Desde">Desde:
							<input type="date" name="desde" class="fecha" required/></span>
							<span class="Hasta">Hasta:
							<input type="date" name="hasta" class="fecha" required/></span>
 
							<br><br><br><br><br><br>
							<div class="boton">
								<button type="submit" name="ver" class="btn btn-primary btn-lg btn-block boton">Descargar</button><br><br><br>
								<a href="../emision_reportes.php"><button type="button" class="btn btn-danger btn-lg btn-block boton">Volver</button></a>
							</div>
						</div>
					</div>
				</form>
 
			<?php
 
				//error_reporting(E_ERROR | E_WARNING | E_PARSE);
				date_default_timezone_set("America/Montevideo");
				if(isset($_POST['ver'])){
					$desde=$_POST['desde'];
					$hasta=$_POST['hasta'];
 
					$datos="SELECT * FROM faltas WHERE (fechaDesde>='$desde' && fechaDesde<='$hasta') ORDER BY fechaDesde DESC";
					$query_datos=$conexion->query($datos);
 
			?>
 
			<div class="col-md-8-sm">
				<br><table class="table table-striped table-responsive table-sm table-hover table-bordered">
                 <thead class="encabezado" >
                    <tr>
                        <th>N° Solic.</th>
						<th>N° Func.</th>
						<th>Nombre</th>
						<th>Apellido</th>
						<th>Sección</th>
                        <th>Tipo</th>
                       	<th>Desde</th>
                        <th>Hasta</th>
						<th>Cant. de Días</th>
						<th>Fecha de Solicitud</th>
						<th>Hora de Solicitud</th>
                    </tr>
                </thead>
				<tbody>
				<?php
					while($array_datos=$query_datos->fetch_assoc()){
						$fecha_desde=$array_datos['fechaDesde'];
						$desde=strtotime($fecha_desde);
						$f_desde=date('d-m-Y',$desde);
 
						$fecha_hasta=$array_datos['fechaHasta'];
						$hasta=strtotime($fecha_hasta);
						$f_hasta=date('d-m-Y',$hasta);
 
						$fecha_solicitud=$array_datos['fechaSolicitud'];
						$solic=strtotime($fecha_solicitud);
						$f_solic=date('d-m-Y',$solic);
				?>
						<tr>
                            <td><?php  echo $array_datos['idSolic']?></td>
							<td><?php  echo $array_datos['numFunc']?></td>
							<td><?php  echo $array_datos['nombre']?></td>
							<td><?php  echo $array_datos['apellido']?></td>
							<td><?php  echo $array_datos['seccion']?></td>
							<td><?php  echo $array_datos['tipo']?></td>
							<td><?php  echo $f_desde?></td>
							<td><?php  echo $f_hasta?></td>
							<td><?php  echo $array_datos['cantDias']?></td>
							<td><?php  echo $f_solic?></td>
							<td><?php  echo $array_datos['horaSolic']?></td>
						</tr>
					<?php
                       }
                     ?>
				</tbody>
            </table>
			<?php
                }
            ?>
		</div>
			<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
			<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
 
		</div>
		</div>
	</body>
</html>
 
excel_faltas.php:
 
<?php
session_start();
?>
<meta charset="utf-8">
<?php
 
header("Content-Type: application/xls");
header("Content-Disposition: attachment; filename= faltas.xls");
?>
			<table class="table table-striped table-responsive table-sm table-hover table-bordered">
                 <thead class="encabezado" >
				 <h3>Faltas con aviso</h3>
				 <tr>
				 </tr>
				    <tr>
                        <th>N° Solic.</th>
						<th>N° Func.</th>
						<th>Nombre</th>
						<th>Apellido</th>
						<th>Sección</th>
                        <th>Tipo</th>
                       	<th>Desde</th>
                        <th>Hasta</th>
						<th>Cant. de Días</th>
						<th>Fecha de Solicitud</th>
						<th>Hora de Solicitud</th>
                    </tr>
                </thead>
				<tbody>
				<?php
					include ("../../../Conexion/conexion.php");
 
					//error_reporting(E_ERROR | E_WARNING | E_PARSE);
					if(isset($_POST['ver'])){
					$desde=$_POST['desde'];
					$hasta=$_POST['hasta'];
 
					$datos="SELECT * FROM faltas WHERE (fechaDesde>='$desde' && fechaDesde<='$hasta') ORDER BY fechaDesde DESC";
					$query_datos=$conexion->query($datos);
 
				?>
				<?php
					$fec_desde=strtotime($desde);
					$fecha_des=date('d-m-Y',$fec_desde);
 
					$fec_hasta=strtotime($hasta);
					$fecha_has=date('d-m-Y',$fec_hasta);
 
					echo '<p>'.'Período: '.$fecha_des.' - '.$fecha_has.'</p>';
				?>
 
				<?php
					while($array_datos=$query_datos->fetch_assoc()){
						$fecha_desde=$array_datos['fechaDesde'];
						$desde=strtotime($fecha_desde);
						$f_desde=date('d-m-Y',$desde);
 
						$fecha_hasta=$array_datos['fechaHasta'];
						$hasta=strtotime($fecha_hasta);
						$f_hasta=date('d-m-Y',$hasta);
 
						$fecha_solicitud=$array_datos['fechaSolicitud'];
						$solic=strtotime($fecha_solicitud);
						$f_solic=date('d-m-Y',$solic);
				?>
						<tr>
                            <td><?php  echo $array_datos['idSolic']?></td>
							<td><?php  echo $array_datos['numFunc']?></td>
							<td><?php  echo $array_datos['nombre']?></td>
							<td><?php  echo $array_datos['apellido']?></td>
							<td><?php  echo $array_datos['seccion']?></td>
							<td><?php  echo $array_datos['tipo']?></td>
							<td><?php  echo $f_desde?></td>
							<td><?php  echo $f_hasta?></td>
							<td><?php  echo $array_datos['cantDias']?></td>
							<td><?php  echo $f_solic?></td>
							<td><?php  echo $array_datos['horaSolic']?></td>
						</tr>
					<?php
                       }
                     ?>
				</tbody>
            </table>
			<?php
                }
            ?>
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Ivan

descarga en Excel

Publicado por Ivan (118 intervenciones) el 09/10/2022 11:27:04
Hola,

existe la posibilidad que sea un problema de seguridad en el servidor que no permita descargar contenido dinámico.
No estoy 100% seguro pero algunos problemas son por estos motivos.

Una solución posible es que guardes la tabla en un archivo físico del servidor, lo descargues y lo borres después.

Te pongo un ejemplo basado en tu código excel_faltas.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
session_start();
$file = '<table class="table table-striped table-responsive table-sm table-hover table-bordered">
  <thead class="encabezado" >
  <h3>Faltas con aviso</h3>
  <tr>
  </tr>
  <tr>
    <th>N° Solic.</th>
    <th>N° Func.</th>
    <th>Nombre</th>
    <th>Apellido</th>
    <th>Sección</th>
    <th>Tipo</th>
    <th>Desde</th>
    <th>Hasta</th>
    <th>Cant. de Días</th>
    <th>Fecha de Solicitud</th>
    <th>Hora de Solicitud</th>
  </tr>
  </thead>
  <tbody>
  </tbody>
</table>';
$file = utf8_decode($file);
$fp = fopen('faltas.xls', 'w');
fwrite($fp, $file);
fclose($fp);
header("Content-Type: application/xls");
header("Content-Disposition: attachment; filename= faltas.xls");
readfile('faltas.xls');
unlink('faltas.xls');
?>

Una ventaja de hacerlo así es que puedes compatibilizar el texto con utf-8, en mis pruebas he visto que fallaban los acentos.

Espero que te sirva.

Un saludo!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

descarga en Excel

Publicado por Marcel Alonso (37 intervenciones) el 09/10/2022 11:49:36
Hola Ivan, buenos días.

Muchas gracias por tu ayuda, probaré hacerlo de la manera que me sugieres.

Te mando un saludo!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

descarga en Excel

Publicado por Hugo (37 intervenciones) el 11/10/2022 03:48:06
Hola Iván, cómo estás?

Probé realizarlo como me sugieres y si bien ahora sí realiza la descarga a Excel, lo hace únicamente con el encabezado, es decir, no carga los datos de la consulta.
Esto creo es porque no está incluido en <tbody> los datos de la misma. Cuando lo hice me da error, creo debe ser que algo estoy haciendo mal.
Copio el código.
Muchas gracias por tu tiempo.

excel_faltas.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?php
session_start();
 
$file = '<table class="table table-striped table-responsive table-sm table-hover table-bordered">
  <thead class="encabezado" >
  <h3>Faltas con aviso</h3>
  <tr>
  </tr>
  <tr>
    <th>N° Solic.</th>
    <th>N° Func.</th>
    <th>Nombre</th>
    <th>Apellido</th>
    <th>Sección</th>
    <th>Tipo</th>
    <th>Desde</th>
    <th>Hasta</th>
    <th>Cant. de Días</th>
    <th>Fecha de Solicitud</th>
    <th>Hora de Solicitud</th>
  </tr>
  </thead>
  <tbody>
    include ("../../../Conexion/conexion.php");
					//error_reporting(E_ERROR | E_WARNING | E_PARSE);
					if(isset($_POST['ver'])){
					$desde=$_POST['desde'];
					$hasta=$_POST['hasta'];
					$datos="SELECT * FROM faltas WHERE (fechaDesde>='$desde' && fechaDesde<='$hasta') ORDER BY fechaDesde DESC";
					$query_datos=$conexion->query($datos);
                <?php
					$fec_desde=strtotime($desde);
					$fecha_des=date('d-m-Y',$fec_desde);
					$fec_hasta=strtotime($hasta);
					$fecha_has=date('d-m-Y',$fec_hasta);
					echo '<p>'.'Período: '.$fecha_des.' - '.$fecha_has.'</p>';
				?>
				<?php
					while($array_datos=$query_datos->fetch_assoc()){
						$fecha_desde=$array_datos['fechaDesde'];
						$desde=strtotime($fecha_desde);
						$f_desde=date('d-m-Y',$desde);
						$fecha_hasta=$array_datos['fechaHasta'];
						$hasta=strtotime($fecha_hasta);
						$f_hasta=date('d-m-Y',$hasta);
						$fecha_solicitud=$array_datos['fechaSolicitud'];
						$solic=strtotime($fecha_solicitud);
						$f_solic=date('d-m-Y',$solic);
				?>
						<tr>
                            <td><?php  echo $array_datos['idSolic']?></td>
							<td><?php  echo $array_datos['numFunc']?></td>
							<td><?php  echo $array_datos['nombre']?></td>
							<td><?php  echo $array_datos['apellido']?></td>
							<td><?php  echo $array_datos['seccion']?></td>
							<td><?php  echo $array_datos['tipo']?></td>
							<td><?php  echo $f_desde?></td>
							<td><?php  echo $f_hasta?></td>
							<td><?php  echo $array_datos['cantDias']?></td>
							<td><?php  echo $f_solic?></td>
							<td><?php  echo $array_datos['horaSolic']?></td>
						</tr>
					<?php
                       }
                     ?>
				</tbody>
        </table>';
$file = utf8_decode($file);
$fp = fopen('faltas.xls', 'w');
fwrite($fp, $file);
fclose($fp);
header("Content-Type: application/xls");
header("Content-Disposition: attachment; filename= faltas.xls");
readfile('faltas.xls');
unlink('faltas.xls');
?>
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Ivan

descarga en Excel

Publicado por Ivan (118 intervenciones) el 11/10/2022 09:11:02
Hola,

me alegra que el problema de descargar archivos se haya resuelto.
El otro problema que aparece ahora es que simplemente estás incluyendo el código PHP de las consutas Mysql dentro de la tabla HTML y que es el string que debe exportarse.

En cuanto llegue a casa esta tarde te pongo cómo lo haría.

Un saludo!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Ivan

descarga en Excel

Publicado por Ivan (118 intervenciones) el 11/10/2022 15:52:15
Hola,

bueno creo que lo tengo, se trata de que $file sólo contenga una tabla HTML en forma de string.
Las clases css simplemente se ignoran en excel.

Si quieres un título
1
echo '<p>'.'Período: '.$fecha_des.' - '.$fecha_has.'</p>';
Lo guardas en una variable a parte y al final del bucle lo añades al principio del string $file = $titulo . $file;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?php
session_start();
$file = '<table class="table table-striped table-responsive table-sm table-hover table-bordered">
  <thead class="encabezado" >
  <h3>Faltas con aviso</h3>
  <tr>
  </tr>
  <tr>
    <th>N° Solic.</th>
    <th>N° Func.</th>
    <th>Nombre</th>
    <th>Apellido</th>
    <th>Sección</th>
    <th>Tipo</th>
    <th>Desde</th>
    <th>Hasta</th>
    <th>Cant. de Días</th>
    <th>Fecha de Solicitud</th>
    <th>Hora de Solicitud</th>
  </tr>
  </thead>
  <tbody>';
  include ("../../../Conexion/conexion.php");
  //error_reporting(E_ERROR | E_WARNING | E_PARSE);
  if(isset($_POST['ver'])) {
    $desde=$_POST['desde'];
    $hasta=$_POST['hasta'];
    $datos="SELECT * FROM faltas WHERE (fechaDesde>='$desde' && fechaDesde<='$hasta') ORDER BY fechaDesde DESC";
    $query_datos=$conexion->query($datos);
    $fec_desde=strtotime($desde);
    $fecha_des=date('d-m-Y',$fec_desde);
    $fec_hasta=strtotime($hasta);
    $fecha_has=date('d-m-Y',$fec_hasta);
    echo '<p>'.'Período: '.$fecha_des.' - '.$fecha_has.'</p>';
    while($array_datos=$query_datos->fetch_assoc()) {
      $fecha_desde=$array_datos['fechaDesde'];
      $desde=strtotime($fecha_desde);
      $f_desde=date('d-m-Y',$desde);
      $fecha_hasta=$array_datos['fechaHasta'];
      $hasta=strtotime($fecha_hasta);
      $f_hasta=date('d-m-Y',$hasta);
      $fecha_solicitud=$array_datos['fechaSolicitud'];
      $solic=strtotime($fecha_solicitud);
      $f_solic=date('d-m-Y',$solic);
      $file .= "<tr>
      <td>".$array_datos['idSolic']."</td>
        <td>".$array_datos['numFunc']."</td>
        <td>".$array_datos['nombre']."</td>
        <td>".$array_datos['apellido']."</td>
        <td>".$array_datos['seccion']."</td>
        <td>".$array_datos['tipo']."</td>
        <td>".$f_desde."</td>
        <td>".$f_hasta."</td>
        <td>".$array_datos['cantDias']."</td>
        <td>".$f_solic."</td>
        <td>".$array_datos['horaSolic']."</td>
      </tr>";
    }
$file .= '</tbody></table>';
  }
$file = utf8_decode($file);
$fp = fopen('faltas.xls', "w");
fwrite($fp, $file);
fclose($fp);
header("Content-Type: application/xls");
header("Content-Disposition: attachment; filename= faltas.xls");
readfile('faltas.xls');
unlink('faltas.xls');
?>

También puedes tener el nombre del archivo en un avariable para no escribirlo cada vez: $fileName = 'faltas.xls';

Un saludo!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

descarga en Excel

Publicado por Hugo (37 intervenciones) el 12/10/2022 03:49:02
Hola Iván, espero estés bien.

Probé el código y me sigue sucediendo lo mismo que al principio, carga la consulta y me la muestra en HTML, pero no la descarga en Excel.
No sé que pueda ser...

Gracias!
Un saludo!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Ivan

descarga en Excel

Publicado por Ivan (118 intervenciones) el 12/10/2022 11:25:22
Hola,

bueno pues creo que está claro ...
Si no te aparece ningún error de PHP y primero no descarga el excel, luego sí y ahora otra vez no ...

Se trata de algún error sencillo tipo unas comillas o un llaves mal colocadas, al tener que construir un string tan largo entre los resultados de Mysql es fácil equivocarse en estos detalles.

La manera que hago para hacercarme al orígen del error es ir poniendo var_dump() con alguna variable clave que quiero ver en diversas partes del código, especialmente en los inicios y finales de bucles y condicionales. Tambien puedes hacer var_dump('llega1'), var_dump('llega2'), etc.

Cuando te muestre valores incorrectos o no llegue te estarás hacercando a la linea que da el error.

Un saludo!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

descarga en Excel

Publicado por Marcel Alonso (37 intervenciones) el 12/10/2022 11:37:47
Hola Iván.

Si,es justamente lo que voy a hacer, verificar que no me haya faltado alguna comilla, llave, etiqueta de cierre.

Muchas gracias como siempre por tu tiempo y amabilidad.

Te mando un saludo!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

descarga en Excel

Publicado por Hugo (37 intervenciones) el 15/10/2022 13:36:35
Hola, buenos días.

Le encontré la solución al problema y lo comparto por si a alguien más le sucede.

El inconveniente era que estaba poniendo en el archivo "excel_faltas.php" la etiqueta <meta charset UTF-8> por delante de los encabezados de esta manera:

1
2
3
4
5
6
7
8
<?php
session_start();
?>
<meta charset="utf-8">
<?php
header("Content-Type: application/xls");
header("Content-Disposition: attachment; filename= faltas.xls");
?>
y debía ponerlo luego de ellos de esta otra manera:

1
2
3
4
5
6
7
8
9
<?php
session_start();
?>
<?php
header("Content-Type: application/xls");
header("Content-Disposition: attachment; filename= faltas.xls");
?>
          <meta charset="utf-8">
			<table class="table table-striped table-responsive table-sm table-hover table-bordered">

Espero le sirva a alguien si se encuentra con el mismo problema.

Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar