diff --git a/Business/Business.csproj b/Business/Business.csproj index 40e6bc94..454fbe09 100644 --- a/Business/Business.csproj +++ b/Business/Business.csproj @@ -56,6 +56,9 @@ false + + ..\packages\EPPlus.4.5.3.3\lib\net40\EPPlus.dll + False ..\Referencias\Iesi.Collections.dll diff --git a/Business/Utility.cs b/Business/Utility.cs index 3baec8ae..5518d367 100644 --- a/Business/Utility.cs +++ b/Business/Utility.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Security.Cryptography; using System.Configuration; using System.Xml.Serialization; @@ -14,6 +14,9 @@ //using Sql.Data using System.Security.Cryptography; +using OfficeOpenXml; +using System.Drawing; +using OfficeOpenXml.Style; namespace Business { @@ -599,7 +602,7 @@ public DataTable getDataSet(String strSql, bool conColu) } return ds2.Tables[0]; } - #region " Otros Mtodos " + #region " Otros Métodos " public bool EsNumerico(string val) { @@ -681,12 +684,12 @@ public int VerificaPermisos(ArrayList lista, string m_Objeto) } - /// con - //private const string ConSignos = "u"; + /// con ñ + //private const string ConSignos = "áàäéèëíìïóòöúùuñÁÀÄÉÈËÍÌÏÓÒÖÚÙÜçÇ"; //private const string SinSignos = "aaaeeeiiiooouuunAAAEEEIIIOOOUUUcC"; - /// sin - private const string ConSignos = "uDZ"; + /// sin ñ + private const string ConSignos = "áàäéèëíìïóòöúùuÁÀÄÉÈËÍÌÏÓÒÖÚÙÜçDZ"; private const string SinSignos = "aaaeeeiiiooouuuAAAEEEIIIOOOUUUcCn"; @@ -712,11 +715,11 @@ public bool bisiesto(int anno) bool resultado; //Comprobamos la regla general. //Si anno es divisible por 4, es decir, si el - //resto de la divisin entre 4 es 0... + //resto de la división entre 4 es 0... if (anno % 4 == 0) { //Si es divisible por 4, ahora toca comprobar - //la excepcin + //la excepción if ( (anno % 100 == 0) && //Si es divisible por 100 (anno % 400 != 0) //y no por 400 @@ -726,7 +729,7 @@ public bool bisiesto(int anno) } else { - resultado = true; //No cumple la excepcin. + resultado = true; //No cumple la excepción. //Lo dejamos como bisiesto por ser divisible por 4 } } @@ -792,11 +795,11 @@ public string DiferenciaFechas(DateTime dn, DateTime fechaProtocolo) { ///calculo de fechas teniendo el cuenta los dias de los meses DateTime da = fechaProtocolo; // DateTime.Now; - int anos = da.Year - dn.Year; // calculamos aos + int anos = da.Year - dn.Year; // calculamos años int meses = da.Month - dn.Month; // calculamos meses - int dias = da.Day - dn.Day; // calculamos das + int dias = da.Day - dn.Day; // calculamos días - //ajuste de posible negativo en $das + //ajuste de posible negativo en $días if (dias < 0) { //--$meses; @@ -872,6 +875,377 @@ public void CargarRadioButton(RadioButtonList buttons, String strSql, String Cam + #endregion + + #region Excel + + public static void ExportDataTableToXlsx(DataTable dataTable, string filename) + { + //Version final 29/4/26 + // ⚠️ Si usas EPPlus v5.x o superior, descomenta esta línea: + // OfficeOpenXml.ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial; + + if (dataTable.Rows.Count > 0) + { + + HttpResponse response = HttpContext.Current.Response; + + // Color finalBackColor = ColorTranslator.FromHtml("#2b3e4c"); //azul-neuquen + // Color fontColor = Color.White + using (ExcelPackage package = new ExcelPackage()) + { + // Crear una nueva hoja de trabajo + ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(filename); + + // Cargar la DataTable en la hoja de trabajo. 'true' incluye los encabezados. + worksheet.Cells["A1"].LoadFromDataTable(dataTable, true); + + int colCount = dataTable.Columns.Count; + + // --- ENCABEZADOS --- + for (int c = 0; c < colCount; c++) + { + worksheet.Cells[1, c + 1].Value = dataTable.Columns[c].ColumnName; + } + + // --- DATOS --- + int filaExcel = 2; + + foreach (DataRow row in dataTable.Rows) + { + for (int c = 0; c < colCount; c++) + { + object valor = row[c]; + int colExcel = c + 1; + + // Null o DBNull + if (valor == null || valor == DBNull.Value) + { + worksheet.Cells[filaExcel, colExcel].Value = ""; + continue; + } + + // Detectar fechas + if (valor != null && valor.GetType() == typeof(DateTime)) + { + DateTime dt = (DateTime)valor; + worksheet.Cells[filaExcel, colExcel].Value = dt; + worksheet.Cells[filaExcel, colExcel].Style.Numberformat.Format = "dd/MM/yyyy"; + continue; + } + + // Detectar números por TryParse + double numero; + string texto = valor.ToString().Trim(); + + System.Globalization.CultureInfo cultura; + + // Si tiene coma, usar cultura con coma decimal + if (texto.Contains(",")) + { + cultura = System.Globalization.CultureInfo.GetCultureInfo("es-ES"); + } + else + { + // Si tiene punto, usar cultura con punto decimal + cultura = System.Globalization.CultureInfo.InvariantCulture; + } + + bool esNumero = double.TryParse( + texto, + System.Globalization.NumberStyles.Any, + cultura, + out numero + ); + + if (esNumero) + { + worksheet.Cells[filaExcel, colExcel].Value = numero; + } + else + { + worksheet.Cells[filaExcel, colExcel].Value = texto; + } + + //formato de numero segun cantidad de decimales + string separador = texto.Contains(",") ? "," : "."; + + int decimales = 0; + + if (texto.Contains(separador)) + { + decimales = texto.Split(separador[0])[1].Length; + } + + string formato = "0"; + + if (decimales > 0) + { + formato += "." + new string('0', decimales); + } + + worksheet.Cells[filaExcel, colExcel].Style.Numberformat.Format = formato; + } + + filaExcel++; + } + + + // --- APLICAR ESTILO AL ENCABEZADO --- + int rowCount = dataTable.Rows.Count; + //int colCount = dataTable.Columns.Count; + + // Rango del encabezado: Desde A1 hasta el final de la primera fila + using (var range = worksheet.Cells[1, 1, 1, colCount]) + { + ExcelEstilo(range); + } + + // Autoajusta las columnas + worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns(); + + //Todas las celdas + var range2 = worksheet.Cells[1, 1, rowCount+1, colCount]; //row+1 asi cuenta la fila del encabezado. + ExcelBordes(range2); + // --- CONFIGURAR RESPUESTA HTTP --- + response.Clear(); + response.Buffer = true; + response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + + string fullFilename = filename.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase) ? filename : filename + ".xlsx"; + response.AddHeader("Content-Disposition", $"attachment; filename=\"{fullFilename}\""); + + // Escribe el paquete de Excel directamente al flujo de salida + package.SaveAs(response.OutputStream); + + response.Flush(); + response.End(); + } + } + + } + + private static void ExcelEstilo(ExcelRange range, Color? backColor = null, Color? fontColor = null) + { + Color finalBackColor = backColor ?? Color.Transparent; + Color finalFontColor = fontColor ?? Color.Black; + + if (backColor == fontColor) + { + finalBackColor = Color.Transparent; + finalFontColor = Color.Black; + } + range.Style.Border.BorderAround(ExcelBorderStyle.Thin); + range.Style.Font.Bold = true; + range.Style.Fill.PatternType = ExcelFillStyle.Solid; + range.Style.Fill.BackgroundColor.SetColor(finalBackColor); + range.Style.Font.Color.SetColor(finalFontColor); + range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; + } + + private static void ExcelBordes(ExcelRange rango) + { + rango.Style.Border.Top.Style = ExcelBorderStyle.Thin; + rango.Style.Border.Bottom.Style = ExcelBorderStyle.Thin; + rango.Style.Border.Left.Style = ExcelBorderStyle.Thin; + rango.Style.Border.Right.Style = ExcelBorderStyle.Thin; + } + + public static void ExportGridViewToExcel(GridView grid, string nombreArchivo) + { + if(grid.Rows.Count > 0) + { + using (var package = new ExcelPackage()) + { + var ws = package.Workbook.Worksheets.Add(nombreArchivo); + + int fila = 1; + int col = 1; + + // ================================ + // 1) Escribir encabezados + // ================================ + + Color encabezadoColor = grid.HeaderStyle.BackColor; + Color fontColor = grid.HeaderStyle.ForeColor; + + if (encabezadoColor == fontColor) + { + encabezadoColor = Color.Transparent; + fontColor = Color.Black; + } + foreach (DataControlField column in grid.Columns) + { + ws.Cells[fila, col].Value = column.HeaderText; + ws.Cells[fila, col].Style.Font.Size = 9; + ws.Cells[fila, col].Style.Font.Bold = true; + ws.Cells[fila, col].Style.Fill.PatternType = ExcelFillStyle.Solid; + ws.Cells[fila, col].Style.Fill.BackgroundColor.SetColor(encabezadoColor); + ws.Cells[fila, col].Style.Font.Color.SetColor(fontColor); + ws.Cells[fila, col].Style.Border.BorderAround(ExcelBorderStyle.Thin); + + col++; + } + + fila++; + + // ================================ + // 2) Escribir filas + // ================================ + foreach (GridViewRow row in grid.Rows) + { + col = 1; + + foreach (TableCell cell in row.Cells) + { + ExcelCompletarFilas(ws, cell, fila, col); + col++; + } + + fila++; + } + //Todas las celdas + var range2 = ws.Cells[1, 1, grid.Rows.Count + 1, grid.Columns.Count]; + ExcelBordes(range2); + // Autoajustar columnas + ws.Cells[1, 1, fila - 1, grid.Columns.Count].AutoFitColumns(); + + // ================================ + // 2.2) Escribir filas del footer + // ================================ + + GridViewRow filaFooter = grid.FooterRow; + col = 1; + + if (tieneValores(filaFooter.Cells)) + { + foreach (TableCell cell in filaFooter.Cells) + { + ExcelCompletarFilas(ws, cell, fila, col, encabezadoColor, fontColor); + ws.Cells[fila, col].Style.Font.Bold = true; + ws.Cells[fila, col].Style.Fill.PatternType = ExcelFillStyle.Solid; + ws.Cells[fila, col].Style.Fill.BackgroundColor.SetColor(encabezadoColor); + ws.Cells[fila, col].Style.Font.Color.SetColor(fontColor); + col++; + } + ExcelBordes(ws.Cells[grid.Rows.Count + 2,1, grid.Rows.Count + 2,col-1 ]); + } + + // ================================ + // 3) Descargar archivo + // ================================ + var response = HttpContext.Current.Response; + + response.Clear(); + response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + response.AddHeader("content-disposition", $"attachment; filename={nombreArchivo}.xlsx"); + + response.BinaryWrite(package.GetAsByteArray()); + response.End(); + } + } + + } + private static bool tieneValores(TableCellCollection footer) + { + + foreach (TableCell cell in footer) + { + var texto = HttpUtility.HtmlDecode(cell.Text); + if (!string.IsNullOrEmpty(texto.Trim())) + return true; + } + + return false; + } + + private static void ExcelCompletarFilas(ExcelWorksheet ws, TableCell cell, int fila, int col, Color? encabezadoColor = null, Color? fontColor = null) + { + + // (1) Detectar si es número + // Detectar números por TryParse + double numero; + var texto = cell.Text.ToString().Trim(); + + System.Globalization.CultureInfo cultura; + + // Si tiene coma, usar cultura con coma decimal + if (texto.Contains(",")) + { + cultura = System.Globalization.CultureInfo.GetCultureInfo("es-ES"); + } + else + { + // Si tiene punto, usar cultura con punto decimal + cultura = System.Globalization.CultureInfo.InvariantCulture; + } + + bool esNumero = double.TryParse( + texto, + System.Globalization.NumberStyles.Any, + cultura, + out numero + ); + + if (esNumero) + { + ws.Cells[fila, col].Value = numero; + } + else + { + ws.Cells[fila, col].Value = HttpUtility.HtmlDecode(cell.Text); + } + + //formato de numero segun cantidad de decimales + string separador = texto.Contains(",") ? "," : "."; + + int decimales = 0; + + if (texto.Contains(separador)) + { + decimales = texto.Split(separador[0])[1].Length; + } + + string formato = "0"; + + if (decimales > 0) + { + formato += "." + new string('0', decimales); + } + + ws.Cells[fila, col].Style.Numberformat.Format = formato; + + // Aplicar colores si existen + + + if (cell.BackColor != Color.Empty) + { + ws.Cells[fila, col].Style.Fill.PatternType = ExcelFillStyle.Solid; + ws.Cells[fila, col].Style.Fill.BackgroundColor.SetColor(cell.BackColor); + } + + if (cell.ForeColor != Color.Empty) + { + ws.Cells[fila, col].Style.Font.Color.SetColor(cell.ForeColor); + } + + ws.Cells[fila, col].Style.Font.Size = 9; + + } + + public static void GenerarColumnasGrid(GridView grid, DataTable dt) + { + if(dt.Columns.Count > 0) + { + DataColumnCollection dc = dt.Columns; + foreach(DataColumn column in dc) + { + BoundField columna = new BoundField(); + columna.HeaderText = column.ColumnName; + grid.Columns.Add(columna); + } + } + } #endregion } } \ No newline at end of file diff --git a/Business/packages.config b/Business/packages.config index 6b05dd43..453e1b88 100644 --- a/Business/packages.config +++ b/Business/packages.config @@ -3,6 +3,7 @@ + diff --git a/ImprimeLocal/ImprimeLocal.csproj b/ImprimeLocal/ImprimeLocal.csproj index 83ed1e11..da49c845 100644 --- a/ImprimeLocal/ImprimeLocal.csproj +++ b/ImprimeLocal/ImprimeLocal.csproj @@ -130,12 +130,6 @@ Designer - - - {4bec40cc-9614-4e0e-8f4a-dc7c933425bc} - Business - - False @@ -148,6 +142,12 @@ false + + + {4bec40cc-9614-4e0e-8f4a-dc7c933425bc} + Business + +