Anda di halaman 1dari 9

Insertando una ProgressBar en un DataGridView

Despus de unos cuantos posts orientados hacia el terreno de la metodologas y la gestin de proyectos, con este artculo vamos a volver al campo del desarrollo puro y duro. El objetivo de este post es mostrar cmo poder insertar un control de tipo ProgressBar en una columna del control DataGridView. Este problema, a priori complicado de solucionar ya que el DataGridView no permite la insercin directa de controles en sus columnas, es relativamente sencillo de abordar si se comprende el modelo de objetos que utiliza el control DataGridView de .Net. No vamos a entrar en detalle sobre el citado modelo de objetos, nicamente explicaremos que para poder crear nuevas columnas (cmo la nuestra de ProgressBar) necesitamos crear una nueva clase que represente el tipo de columna, y una nueva que represente el tipo de celdas que pertenecen a dicha columna. Para ello basta con crear clases que deriven de DataGridViewColumn (o una de sus clases hijas) y DataGridViewCell (o una de sus clases hijas) Para crear una columna que permita aadir objetos ProgressBar vamos a crear una clase que derive de DataGridViewImageColumn (despus veremos porque concretamente de esta y no de la clase base o de alguna de las otras subclases)
public class DataGridViewProgressColumn : DataGridViewImageColumn { public DataGridViewProgressColumn() { CellTemplate = new DataGridViewProgressCell(); } }
En esta clase vemos que en el constructor se asigna una propiedad llamada CellTemplate. Esta propiedad se encarga de definir el tipo de celda que corresponde a la columna, de manera que cuando se tengan que crear nuevas celdas el DataGridView sepa cmo crearla. Cmo podemos ver se esta asignado a la propiedad una nueva instancia del tipo DataGridViewProgressCell, que es una clase que tambin tenemos que crear. Ahora vamos a ver cmo construir la clase que representar a nuestro nuevo tipo de celda:

class DataGridViewProgressCell : DataGridViewImageCell {}


Lo primero es derivar del tipo de celda correspondiente (DataGridViewImageCell, que es el tipo de celda que corresponde a la columna de la que habamos derivado nuestra ProgressColumn) Ahora vamos a explicar como funcionar esta clase para poder entender todo el cdigo que va a ir dentro de ella: La celda mostrar una barra de progreso (en el ejemplo la estndar de Windows, pero ya veris que ser muy fcil modificarla al gusto de cada uno) , que ir actualizndose en base al valor que nosotros le pasemos a la celda. Es decir nosotros asignaremos valores enteros entre 0 y 100 y la barra de progreso se ir actualizando. Parece lgico pero ya veris que si no de deja claro ahora puede ser complicado entender el siguiente cdigo:

Aadimos los siguientes constructores a la clase: static Image emptyImage; static DataGridViewProgressCell() { emptyImage = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb); } public DataGridViewProgressCell() { this.ValueType = typeof(int); } En el constructor esttico (o de clase) se inicializa una variable de tipo Image mientras que en el contructor pblico se indica el tipo de datos de la columna, que ser un entero. Este valor ser el que se utilizar para recoger el porcentaje que se debe mostrar en la barra de progreso y ahora veremos que utilidad tiene la imagen del cosntructor esttico. El siguiente paso es sobreescribir el mtodo GetFormattedValue. Este mtodo sirve para transformar el valor de entrada de la celda (que en este caso es un entero) en el objeto que espera el DataGridView, que al estar derivando de DataGridViewImageCell es una imagen (Ahora se entiende el porqu de la imagen del constructor esttico) protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context) {

return emptyImage; } Cmo veis, en lugar de formatear el valor de entrada y devolver la imagen correspondiente que pareca la opcin ms lgica segn lo expuesto arriba en este mtodo devolvemos directamente la imagen vaca, ya que en nuestro caso no se va a utilizar este mtodo para representar el valor del ProgressBar, pero se debe devolver una imagen por consistencia con el tipo de datos de la celda madre (DataGridViewImageCell).
Y finalmente vamos ver cmo tenemos que a sobreescribir el mtodo Paint de la celda. En este mtodo ser donde representemos realmente el valor del progreso. Con esto completaremos la clase:

protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) { int progressVal; if (value != null && value.GetType() == typeof(Int32)) progressVal = (int)value; else progressVal = 1; float percentage = ((float)progressVal / 100.0f); Brush backColorBrush = new SolidBrush(cellStyle.BackColor); Brush foreColorBrush = new SolidBrush(cellStyle.ForeColor); base.Paint(g, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, (paintParts & ~DataGridViewPaintParts.ContentForeground)); const int margin = 4; ProgressBar pb = new ProgressBar(); pb.Height = cellBounds.Bottom - cellBounds.Top - (margin * 2); pb.Width = cellBounds.Right - cellBounds.Left - (margin * 2); pb.Value = progressVal; Bitmap bmp = new Bitmap(pb.Width, pb.Height); pb.DrawToBitmap(bmp, pb.ClientRectangle); g.DrawImage(bmp, new Point(cellBounds.X + margin, cellBounds.Y + margin)); } Lo que estamos haciendo aqu es que cada vez que se llama al evento Paint de la celda se actualiza el estado de la variable ProgressBar interna de la misma y se "pinta" el control dentro de la celda (mediante GDI). Ahora vemos cmo a partir de un entero de entrada tenemos el control ProgressBar en pantalla. El utilizar GDI para "pintar" el control aporta mucha flexibilidad ya que permite darle la apariencia que se quiera: Por ejemplo en lugar de utilizar un control ProgressBar interno y "ver su imagen" podramos dibujar el resultado del progreso de la manera que mejor nos pareciera, con los colores que mas nos gustasen, con efectos, con texto, etc... Ahora que ya tenemos las clases preparadas vamos a ver cmo utilizarlas en un DataGridView de manera que podamos visualizar el control en las diferentes filas que se aadan al mismo. En el ejemplo vamos a suponer que creamos el DataGridView en tiempo de diseo (aunque se podra hacer en tiempo de ejecucin). Lo primero es arrastrar el control DataGridView a nuestro formulario y visualizar la pantalla de propiedades del control.

Arrastramos el DataGridView al formulario

Pantalla de propiedades

En esta pantalla definimos las columnas que tendr nuestro DataGridView. Pulsando el botn Add aparece una pantalla donde se indica entre otras cosas el tipo de la columna y aqu ya podemos ver que en la lista aparece un nuevo tipo, DataGridViewProgressBarColumn, que ser el que seleccionaremos para la columna que tiene que mostrar la barra de progreso (Para que el nuevo tipo de columna aparezca hay que tener acceso al espacio de nombres donde hemos definido la clase desde el formulario).

Aadiendo la columna de progreso

Cuando hayamos aadido las columnas necesarias (en el ejemplo aadiremos nicamente dos) volvemos al formulario y creamos un objeto BindingSource arrastrndolo hacia el mismo. Con este objeto implementaremos el enlace entre los datos y el DataGridView. En la pantalla deberamos tener algo parecido a esto:

DataGridView con las dos columnas y el objeto BindingSource

El siguiente paso es crear un DataSet que ser el que contenga los datos. Este DataSet podramos extraerlo de una base de datos, de un servicio Web o de cualquier otro origen de datos, en nuestro ejemplo lo construiremos y lo llenaremos programticamente. private void InitializeDataSet() { //Creamos el DataSet y definimos las columnas. customDataSet = new DataSet(); customDataSet.Tables.Add(new DataTable("TablaEjemplo")); customDataSet.Tables["TablaEjemplo"].Columns.Add(new DataColumn("DSNombre", typeof(string))); customDataSet.Tables["TablaEjemplo"].Columns.Add(new DataColumn("DSProgreso", typeof(int))); DataRow row1 = customDataSet.Tables[0].NewRow(); row1["DSNombre"] = "Fila 1"; row1["DSProgreso"] = 25; customDataSet.Tables[0].Rows.Add(row1); DataRow row2 = customDataSet.Tables[0].NewRow(); row2["DSNombre"] = "Fila 2";

row2["DSProgreso"] = 35; customDataSet.Tables[0].Rows.Add(row2); //Ponemos a false el valor AutoGenerateColumns para utilizar las columnas definidas en vista de diseo dataGridView1.AutoGenerateColumns = false; //Enlazamos el Dataset con el DataGrid bindingSource1.DataSource = customDataSet.Tables[0]; dataGridView1.DataSource = bindingSource1.DataSource; } Volvemos a la vista de diseo del Grid e indicamos la relacin entre las columnas del DataGrid y las del DataSet (opcin Columnas de las propiedades del control)

En la opcin DataPropertyName de cada columna ponemos el nombre de la columna del DataSet que enlazaremos. Fijaros que son las columnas definidas en customDataSet

Si ahora ejecutamos el proyecto vemos que aparecen las dos filas creadas y que la barra de progreso de cada una corresponde a los valores dados a las columnas del DataSet. Si quiseramos modificar ese valor slo tendramos que ir cambiando el valor de la celda DSProgreso del DataSet y automticamente se vera reflejado en el Grid y en la barra de progreso.

Gracias al potente modelo de objetos que .Net define para el DataGridView podemos de manera similar al ejemplo mostrado definir columnas para hospedar casi cualquier tipo de control que necesitemos. En ocasiones habr que derivar de la columna DataGridViewImageCell cmo en el ejemplo, pero podemos cualquiera de las otras clases base segn la funcionalidad que necesitemos insertar en nuestra nueva columna. Os esperamos con vuestras opiniones, sugerencias sobre el tema o crticas al artculo en los comentarios! Un saludo!!

Inicio Novatos Destacados


CIENCIA Y EDUCACIN | HACE MS DE 8 MESES

Importar y exportar datos de excel a datagridview


link: https://www.youtube.com/watch?v=Hm5TLtI3D-o&feature=plcp A continuacin les dejo el codigo fuente del programa hecho en visual basic 2010 Los nombres de los objetos y su correspondiente uso se los nombre en siguiente listado usamos DataGridView1 para ingresar y almacenar los datos a exportar o los importados Button1 para Exportar los datos a Excel lleva el nombre de Exportar Button2 para Importar los datos de Excel al DataGridView1 lleva el nombre de Importar Form1 que se usa como interfaz Bueno para finalizar la explicacin antes de porner el codigo fuente debemos importar las referencias System.Data.OleDb y crear un metodo el cual llame Exportar_Excel Imports System.Data.OleDb ----------------------------------------------------------------------------------------------------------------------------- --------------------------------------Public Class Form1 Public Sub Exportar_Excel(ByVal dgv As DataGridView, ByVal pth As String) Dim xlApp As Object = CreateObject("Excel.Application" 'crear una nueva hoja de calculo Dim xlWB As Object = xlApp.WorkBooks.add Dim xlWS As Object = xlWB.WorkSheets(1) 'exportamos los caracteres de las columnas For c As Integer = 0 To DataGridView1.Columns.Count - 1 xlWS.cells(1, c + 1).value = DataGridView1.Columns(c).HeaderText Next 'exportamos las cabeceras de columnas For r As Integer = 0 To DataGridView1.RowCount - 1 For c As Integer = 0 To DataGridView1.Columns.Count - 1 xlWS.cells(r + 2, c + 1).value = DataGridView1.Item(c, r).Value

Next Next 'guardamos la hoja de calculo en la ruta especificada xlWB.saveas(pth) xlWS = Nothing xlWB = Nothing xlApp.quit() xlApp = Nothing End Sub ----------------------------------------------------------------------------------------------------------------------------- --------------------------------------'Este es el Button1 = Exportar Private Sub Button1_Click Dim save As New SaveFileDialog save.Filter = "Archivo Excel | *.xlsx" If save.ShowDialog = Windows.Forms.DialogResult.OK Then Exportar_Excel(Me.DataGridView1, save.FileName) End If End Sub -------------------------------------------------------------------------------------------------------------------------------------------------------------------'Este es el Button2 = Importar Private Sub Button2_Click Dim stRuta As String = "" Dim openFD As New OpenFileDialog() With openFD .Title = "Seleccionar archivos" .Filter = "Archivos Excel(*.xls;*.xlsx)|*.xls;*xlsx|Todos los archivos(*.*)|*.*" .Multiselect = False .InitialDirectory = My.Computer.FileSystem.SpecialDirectories.Desktop If .ShowDialog = Windows.Forms.DialogResult.OK Then stRuta = .FileName End If End With Try Dim stConexion As String = ("Provider=Microsoft.ACE.OLEDB.12.0;" & ("Data Source=" & (stRuta & ";Extended Properties=""Excel 12.0;Xml;HDR=YES;IMEX=2"";" )) 'este es el codigo que funciona para office 2007 y 2010 Dim cnConex As New OleDbConnection(stConexion) Dim Cmd As New OleDbCommand("Select * From [Hoja1$]" Dim Ds As New DataSet Dim Da As New OleDbDataAdapter Dim Dt As New DataTable cnConex.Open() Cmd.Connection = cnConex Da.SelectCommand = Cmd Da.Fill(Ds) Dt = Ds.Tables(0) Me.DataGridView1.Columns.Clear() Me.DataGridView1.DataSource = Dt Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Critical, "Error" End Try End Sub

-------------------------------------------------------------------------------------------------------------------------------------------------------------------Bueno esto es el codigo del programa probado y sin errores. Pueden cambiar las variables por el nombre que ustedes gusten.

Anda mungkin juga menyukai