Formatear y resaltar valores en el control DataGridView con el evento CellFormatting (y III)

Como colofón a esta serie de artículos, en esta entrega explicamos el modo de aplicar formatos a las columnas del DataGridView en función del tipo de su dato, mediante expresiones reguladas y sobre filas completas del control.


 


Aplicar un estilo como formato según el tipo de dato


En caso de que en un mismo proceso de formato necesitemos manipular columnas de distintos tipos de datos, aplicando también diferentes características visuales a cada celda, puede resultar de utilidad crear en primer lugar un estilo para el tipo de dato a formatear, en el que configuremos cada uno de los aspectos visuales, y aplicarlo en el evento CellFormatting al detectar que la celda actual contiene dicho tipo de dato.


Basándonos en este supuesto, dentro del siguiente ejemplo creamos dos objetos de tipo DataGridViewCellStyle, que instanciamos y configuramos al cargar el formulario, para finalmente, asignar en el evento CellFormatting, cuando la celda a manipular corresponda a dicho tipo de dato y su valor cumpla cierta condición, como vemos en el siguiente código.


public partial class frmFormatoTipoDato : Form
{
// declarar dos estilos
DataGridViewCellStyle styFecha;
DataGridViewCellStyle styDecimal;
//….
public frmFormatoTipoDato()
{
InitializeComponent();
}

private void frmFormatoTipoDato_Load(object sender, EventArgs e)
{
// instanciar un estilo para mostrar los tipos fecha y decimal
styFecha = new DataGridViewCellStyle();
styFecha.BackColor = Color.Gold;
styFecha.ForeColor = Color.DarkOliveGreen;
styFecha.Format = «dd/MMM/yyyy»;
styFecha.Font = new Font(«Magneto», 10, FontStyle.Bold);

styDecimal = new DataGridViewCellStyle();
styDecimal.BackColor = Color.LightGreen;
styDecimal.ForeColor = Color.DarkOrchid;
styDecimal.Format = «C»;
styDecimal.Font = new Font(«Lucida Calligraphy», 10);

this.dataGridView1.DataSource = ConstruirDatos.ObtenerTabla();
}

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
// comprobar el tipo de dato que contiene la celda
// y aplicarle el estilo
if (e.Value.GetType() == typeof(DateTime))
{
if (((DateTime)e.Value).Year > 1970)
{
e.CellStyle = styFecha;
}
}

if (e.Value.GetType() == typeof(decimal))
{
if ((decimal)e.Value == 30000)
{
e.CellStyle = styDecimal;
}
}
}
}


El efecto puede apreciarse en esta imagen.



 


Formateando mediante expresiones reguladas


A través de la clase Regex podemos construir un formato basado en un patrón de sustitución que pasamos como cadena de caracteres al constructor de la expresión regulada.


Tomemos como base para esta demostración el campo CustomerAlternateKey, que muestra un código alfanumérico. Suponiendo que necesitemos visualizar los valores de esta columna en grupos de dígitos que sigan un patrón como este: XX-XXX-XX-XXX, el código para formatear estos valores sería similar al siguiente.


using System.Text.RegularExpressions;
//….
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (this.dataGridView1.Columns[e.ColumnIndex].Name == «CustomerAlternateKey»)
{
// crear una expresión regulada con un patrón de formato
Regex oExpRegulada = new Regex(@»(D{2})(d{3})(d{2})(d{3})»);

// sustituir las partes del valor a formatear mediante la expresión regulada
e.Value = oExpRegulada.Replace(e.Value.ToString(), «$1-$2-$3-$4»);
}
}


Mientras que los resultados serían los que vemos en esta imagen.



 


Aplicando formato a filas completas


Si el requerimiento de formato consiste en aplicarlo a la totalidad de una fila, podríamos pensar que la forma de resolver la situación pasaría por recorrer la colección Cells de cada objeto fila del DataGridView, y manipular la propiedad Style de dichas celdas individuales. Sin embargo existe un medio más fácil de lograr este objetivo, consistente en manipular, dentro del evento CellFormatting, la propiedad DefaultCellStyle del objeto DataGridViewRow actual que obtenemos de la colección Rows del control DataGridView.


private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
// si la celda corresponde a los ingresos anuales
if (this.dataGridView1.Columns[e.ColumnIndex].Name == «YearlyIncome»)
{
// y el valor cumple con cierta condición
if ((decimal)e.Value > 50000)
{
// aplicar formato a la totalidad de la fila
this.dataGridView1.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Aquamarine;
}
}
}

En la imagen mostrada a continuación podemos apreciar este efecto.



Y con este ejemplo damos por concluida esta pequeña serie de artículos dedicados a las diferentes posibilidades de formato que podemos utilizar con el control DataGridView, espero que os resulte de utilidad. Al igual que en las anteriores entregas, los ejemplos están disponibles en estos enlaces: C# y VB.


Un saludo.


 

20 Comentarios

  1. lmblanco

    Hola Enrique

    Muchas gracias por haberlos leido, espero que te puedan servir de ayuda en algún momento.

    Un saludo.
    Luismi

  2. anonymous

    Muy didactico el árticulo lo estoy implementando en un proyecto que estoy desarrolando en mi trabajo felicitaciones.
    Aprovecho para pedirte si puedes nose enviarme como trabajo los reposrtes con crystal reports del vd 2003 hace caso omiso cuando configuro el tamaño de hoja los margnes lo deja por defecto a tamaño carta. mi e-mail cglanet@hotmail.com

  3. lmblanco

    Hola Carlos

    Muchas gracias por tu opinión, y celebro que te pueda ser de utilidad.

    En cuanto a las cuestiones que me comentas sobre los márgenes de página con Crystal Reports, revisa este otro post:

    http://geeks.ms/blogs/lmblanco/archive/2008/02/02/establecer-la-orientaci-243-n-de-p-225-gina-en-un-informe-de-crystal-reports.aspx

    En el que se comenta acerca de la orientación de página del informe con este diseñador. Prueba a utilizar las opciones «Configurar página» o «Preparar impresora» del diseñador de Crystal, es posible que alguna de ellas te permita configurar los márgenes tal y como necesitas.

    Un saludo.
    Luismi

  4. anonymous

    Hola Miguel como estas … queria consultarte como puedo hacer para que mi datagrid tenga un parecido al grid del outlook y como puedo hacer un reporte configurable haciendo q el usuario seleccione los campos que quiere q vaya salr en el report.

    Gracias un abrazo desde Perú

    Carlos

  5. lmblanco

    Hola Carlos

    En el siguiente enlace tienes un ejemplo de un grid con un estilo similar al de Outlook

    http://www.codeproject.com/KB/miscctrl/CoolGrid.aspx

    Un saludo,
    Luismi

  6. anonymous

    yo al final, puesto q solo necesitaba modificar el formato de un campo lo solucione asi:

    private void dtgNotas_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
    DataGridViewCellStyle styFecha = new DataGridViewCellStyle();
    styFecha = e.CellStyle;
    styFecha.Format = «dd/MM/yyyy»;
    }

    y listo!
    asias por la info, me vino de luxe

  7. anonymous

    siento el doble post pero acabo de encontrar una forma mas directa de hacerlo en la propia entidad donde lo cargamos:
    c = new DataGridViewTextBoxColumn();
    c.DataPropertyName = º.FECHA;
    c.HeaderText = º.FECHA;
    c.Name = º.FECHA;
    c.DefaultCellStyle.Format = «dd/MM/yyyy»;
    c.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
    dtg.Columns.Add(c);
    dtg.Columns[º.FECHA].Width = 84;

    asi nos hevitamos usar el evento cellformatting
    de nuevo disculpo este post pero espero q ayude, nos vemos

  8. lmblanco

    Hola Penwin

    Celebro que el artículo te haya sido útil. Esta última forma que comentas en efecto es más adecuada si quieres aplicar un estilo a todos los valores de una columna, ya que el uso de CellFormatting resulta más conveniente si quieres formatear de forma condicional ciertas celdas de la columna que cumplan una condición.

    Un saludo.
    Luismi

  9. anonymous

    Esta muy bien el formato y el acomodo pero si quiciera unir celdas para colocar un texto en 2 o mas celdas de un determinado renglon….??

    De antemano gracias….

  10. anonymous

    Muchas gracias por el excelente artículo, era justo lo que andaba buscando, muchas gracias de verdad y sigue adelante.

  11. lmblanco

    Hola Efren

    Gracias por tu interés y opinión en el artículo. Celebro que te haya sido de utilidad.

    Un saludo.
    Luismi

  12. anonymous

    Justo lo que necesitaba, graciaaaaaaaasssssss, muy buen blog no lo habia visto, ahora me considero un aprendiz de brujo XD.

  13. anonymous

    Justo lo que necesitabaaaa, graciaaaaaaaaaaas, muy buen blog no lo había visto, ahora me considero un aprendiz de brujo XD.

  14. lmblanco

    Hola Adrián

    Gracias a tí por visitar el blog, y bienvenido al grupo de aprendices de brujo 😉

    Un saludo,
    Luismi

  15. anonymous

    Hola una pregunta cuando intento aplicar el codigo de resaltar toda la linea me señala el siguiente error en la siguiente linea:

    if ((decimal)e.Value >0)——>>>>La conversion especificada no es valida.

    No entiendo pues los valores de mi columna son numeros guardados en formato number en oracle, ya intente poner Int en lugar de decimal y marca el mismo error, me puedes ayudar? Gracias.

  16. lmblanco

    Hola Moisés

    Por lo que me comentas, e.Value almacena un valor numérico,

  17. lmblanco

    Hola Moisés

    Por lo que me comentas, e.Value contiene un valor numérico, y al hacerle un type casting a decimal te da un error.

    Dado que la fuente de datos con la que estás trabajando es Oracle, desconozco si será un problema propio del motor de datos, ya que las pruebas que yo he realizado han sido con SQL Server. Intenta, no obstante, hacer el type casting a alguno de los otros tipos numéricos disponibles, a ver si con alguno de ellos te admitiera la conversión de valores.

    Un saludo,
    Luismi

  18. anonymous

    muy buen post, aqui les dejo un link
    uyaychay.blogspot.com

  19. lmblanco

    Hola Mario

    Gracias por tu opinión y ánimo con tu blog 🙂

    Un saludo,
    Luismi

Responder a Cancelar respuesta

Tema creado por Anders Norén