Ludebe
Usuario (Argentina)
![Imprimir factura desde C# [Nivel Avanzado]](https://storage.posteamelo.com/assets-adonis/assets/2018/06/19/big2v5-aDPScosNw3r.webp)
Hola gente, cómo andan? El otro día se me presentó un trabajito: Me habían dicho que necesitaban imprimir facturas desde el programa, y yo les dije que no tenía ni idea y que no sé si lo iba a poder hacer, recién estaba empezando. El tema es que al final se los terminé haciendo. Lo hice de 2 formas diferentes, la correcta y la incorrecta. La incorrecta consistió en tener un modelo de factura vacía como imágen, incrustarla en el programa y llenar de labeles todas las posiciones, entonces completabas campos y se iban llenando... al final tocabas aceptar y gracias a una función que se llama DrawToBitmap se dibujaba todo el picturebox con la imagen factura y los labeles escritos encima. Un asco, encima en su PC no tomaba la captura. La forma correcta o la más factible se las paso a explicar. Vamos a crear un proyecto windowsForms con el nombre que deseen, yo le pongo imprimirfactura: Ahora vamos a crear unos campos para llenar los datos, vamos a arrastrar desde el cuadro de herramientas 4 textBoxes, 4 labeles, 2 botones y un dataGridView: Ahora cambiamos el texto de los labeles a Cantidad, Descripción, Precio unitario, e importe. Por otro lado cambiamos los nombres de los textBoxes a textBoxCantidad, textBoxDescripcion, textBoxPrecioUnitario y textBoxImporte. Cambiamos el nombre del DataGridView a DGV, y el texto y nombre de los botones 1 y 2 Agregar, btnAgregar, Imprimir, btnImprimir respectivamente y finalmente dejamos en ReadOnly el DGV seleccionandolo, tocando la flechita que sale arriba a su derecha y destildando todo: Listo. Ya tenemos el diseño. Esta primera parte va a funcionar de la siguiente manera: -Se llenan los campos -Se presiona agregar -Se comprueba que no haya campos vacíos con la función camposCompletos() : Boolean -Se comprueba que sean dátos válidos con la función datosValidos() : Boolean -Se añade como registro o fila al DGV -Se vacían los campos con la función vaciarCampos() : void Así que procedemos tocando F7 para ir al código y creamos la primer función privada Booleana camposCompletos(): Nos va a mostrar un errorcito porque la función tiene que devolver un Boolean (true o false) y todavía no pusimos ningún return. Dentro del método lo que tenemos que hacer es algo parecido a lo que hicimos en el aporte de conectar C# con Sql que pueden ver desde mi perfil, comprobar que ningún textBox sea equivalente a "" o String.Empty. Así que dentro de la función ponemos lo siguiente: if(textBoxCantidad.Text.Equals( "" ) || textBoxDescripcion.Text.Equals("" ) || textBoxPrecioUnitario.Text.Equals("" ) || textBoxImporte.Text.Equals("" )) return false ; else return true ; (Cuando dentro de los bloques if sólo hay una línea de código, no hace falta poner las llaves, lo mismo para los else y else if) Quedaría así: Ahora podemos hacerlo de varias formas, se me vienen a la cabeza unas... 3. Una es crear un evento keyPress para esos 2 textBox y controlar si la tecla presionada es un dígito. Si no es un dígito, no lo escribe. Pero no me gusta mucho. Otra es un try-catch para controlar formatException que es la que vamos a usar pero paso a explicarles la 3ra que es la que más les puede servir en otros casos: Lo que haría es tomar el .Text y analizar char por char controlando que IsDigit devuelva un true. El ejemplo: foreach (Char c in textBoxCantidad.Text) if (!Char.IsDigit(c)) return false ; Eso iría en un método que podría llamarse... datosValidos() : Boolean y sería llamada al tocar el botón agregar. Se los muestro porque les puede servir, pero ahora vamos con la que necesitamos en este caso. Usamos esta forma ya que el importe (que es la cantidad multiplicado por el precio unitario) se calcula sólo, no hay que llenarlo. Lo que hacemos es volver al diseño para crear un evento text changed en el textBoxCantidad y en el textBoxPrecioUnitario, se hace así: En el diseño, seleccionamos primero el textBoxCantidad y tocamos el "rayito" que está a la derecha, en las propiedades del control. Observen que ya el evento TextChanged esta seleccionado por defecto, supongo yo que es porque es el que más se suele utilizar. Hacemos doble-click en el espacio a la derecha de TextChanged y se generará el evento, de forma parecida al evento click de los botones: Ahora lo que hacemos es.. si textBoxCantidad.Text y textBoxPrecioUnitario.Text no están vacíos, textBoxImporte.Text va a ser igual a textBoxCantidad.Text * textBoxPrecioUnitario.Text. Código: if(!(textBoxCantidad.Text.Equals("" ) || textBoxPrecioUnitario.Text.Equals("" )) textBoxImporte.Text = (Convert.ToInt32(textBoxCantidad.Text) * Convert.ToDouble(textBoxPrecioUnitario.Text)).ToString() ; (Cambien el && por ||, mala mía.) Quedaría así: Ahora generamos el mismo evento en el textBoxPrecioUnitario y en el bloque generado ponemos el mismo código: Lo que pasará es que al escribir en los 2 textBox se calcule sólo el importe o precio final de ese producto (Y) Ahora en ambos eventos rodeamos con un try y ponemos un catch de la siguiente manera: try { //ACA VA LA MULTIPLICACION } catch (FormatException) { MessageBox.Show( "Porfavor, ingrese sólo números" , "Advertencia" ) ; } Nos pasaría a quedar así: Como ya no hay necesidad de escribir el importe, vamos al diseño y seteamos el textBoxImporte como enabled false: Perfecto. Ahora que ya hicimos los controles de datos lo que hacemos es ir al diseño y generar el evento click del btnAgregar: Ahora... Si los campos están completos se agrega el registro a la DGV dentro del btnAgregar_Click llamamos a una función añadirRegistro() que vamos a crear a continuación: Ahora le tenemos que dar una forma o estructura inicial a la DGV, para eso creamos una private DataTable dt global y en el constructor le agregamos las columnas para estructurar el DGV: Ahora volvemos a la función añadirRegistro y dentro añadimos un registro a la dt para después pasársela al DGV: dt.Rows.Add(textBoxCantidad.Text, textBoxDescripcion.Text, textBoxPrecioUnitario.Text,textBoxImporte.Text) ; DGV.DataSource = dt ; Ahora ya funcionaría el traslado de los campos al DGV. Al presionar Agregar si todo está bien, se pasa la nueva fila y los campos deberían borrase para que quede más dinámico y rápido de usar, así que creamos una función private void vaciarCampos() con éste código dentro: textBoxCantidad.Text = String.Empty; textBoxDescripcion.Text = String.Empty; textBoxPrecioUnitario.Text = String.Empty; textBoxImporte.Text = String.Empty; y la llamamos desde btnAgregar_Click luego del añadirRegistro() Perfecto. Como la factura modelo que vamos a usar tiene 14 items, hay que controlar que el DGv no tenga más de 14 registros, por lo que en el btnAgregar_Click en el if, agregamos un && DGV.Rows.Count <14. Si supera los 14 muestra un mensaje: else { MessageBox.Show("No se pueden facturar más productos en una misma factura","Aviso";} Listo. La metodología que vamos a usar es dar uso a una función llamada DrawString que lo que hace es dibujar sobre una imagen un texto. Ya se dan una idea, no? Primero, se bajan esta imagen: Perfecto. Ahora lo que tenemos que hacer es agregar la factura modelo al proyecto como recurso. Para hacerlo vamos a Proyecto >> Propiedades de ImprimirFactura Ahora a la izquierda vamos a donde dice Recursos Tocamos la flechita de Agregar Recurso y seleccionamos Archivo existente y seleccionan la factura normalmente, cierren la pestaña y guarden. Con esto ya tenemos incrustada la imagen en el proyecto Vamos a generar el evento double-click del btnImprimir Lo que hacemos ahora es debajo de la declaración de la DataTable dt, delcaramos un private Image facturaModelo; y la cargamos en el constructor. Ahora para poder dibujar el String en la imagen (Los textBoxes.Text) lo que tenemos que tener son las coordenadas x e y de cantidad, desc, precio e importe de cada fila. Al ser una factura simétrica con lo que a filas y columnas respecta, podemos trabajar en un ciclo repetitivo for sumando valores estáticos x e y. Primero empezamos declarando las variables que necesitamos: int[] x = {27,111,143,128}; int firstY = 32; int y = 28; Image facturaActual = facturaModelo; Graphics g = Graphics.FromImage(facturaActual); StringFormat formatter = new StringFormat(); formatter.LineAlignment = StringAlignment.Center; formatter.Alignment = StringAlignment.Center; Font font = new Font("Microsoft Sans Serif", 10, FontStyle.Regular); SolidBrush brush = new SolidBrush(Color.Black); El array x de tipo int se declara así porque las columnas no están a una distancia en común, el punto central de la columna cantidad se encuentra en x 27, la columna desc se encuentra a x 111, y así con las otras 2. int firstY lo que hace es dar la altura de la primera fila, ya que verán que los items no comienzan desde arriba de todo, sino que hay un header nombrando las columnas. int y 28 va a ser el valor que se va a repetir entre fila y fila, será multiplicado por i dentro del for luego del firstY. Se iguala la factura actual a la modelo para luego ser llenada. Se crea un Graphics g basándose en facturaActual que es lo que dibujará sobre ella. Se le da un formato al string que será dibujado (Alineación). Se crea una fuente. Y por último un pincel para el dibujado o trazado del String en la imágen. Listo. Ahora el for. A continuación lo paso a explicar, no se asusten (? for (int i = 0; i < DGV.Rows.Count; i++) { for (int j = 0; j < 4; j++) { if(i==0) g.DrawString(DGV.Rows.Cells.Value.ToString(), font, brush, new Point(x, firstY), formatter); else g.DrawString(DGV.Rows.Cells.Value.ToString(), font, brush, new Point(x, y), formatter); } y += 26; } Perfecto. El primero for que tiene un índice i es el encargado de pasar de fila a fila. El segundo for con índice j se encarga de las columnas. dentro de ambos, se hace la comprobación de i == 0, para saber si es la primera fila y usar el firstY, así que es lo primero que hará al entrar por primera vez. Luego se usa el método de g para Dibujar el String, y le estamos pasándo los siguientes parámetros: El valor de la celda actual del DGV, la fuente, el pincel, las coordenadas de dibujo y finalmente el formato del String. Cuando se termina de dibujar la fila entera, osea, antes de completar el ciclo del for i se suma 'y' en 26 para dar lugar a una nueva fila indicando las coordenadas de 'y'. Listop, les quedaría así: Ahora lo que hice para testear yo es crear un nuevo Form (todo mediante código) para ver si está realmente funcionando (Oooobviamente lo hice en el transcurso del codeo de los fors para ver bien las coordenadas y demás ). Form f2 = new Form(); f2.Show(); f2.Validate(); PictureBox pbox = new PictureBox(); pbox.Image = facturaActual; pbox.SizeMode = PictureBoxSizeMode.AutoSize; f2.Width = pbox.Width + 17; f2.Height = pbox.Height + 37; f2.Controls.Add(pbox); Lo que se hace es crear un nuevo form llamado f2, mostrarlo, validarlo, crear un pictureBox, cargarle una imagen, hacer que el tamaño del pBox se adapte al tamaño de la imagen, y el tamaño del form que se adapte al tamaño del pBox más unos píxeles (Por el tema del encabezado del form, bordes y demás), y finalmente cargarlo al form. El código lo ponen debajo de los for de dibujo, les queda así: Listop, pueden ir probándolo e.e Acá les dejo una muestra: D: Nos olvidábamos (me) del total! Para incluír el total en la factura primero le indicamos las coordenadas declarándolas junto a las otras de la siguiente manera: int totalX = 493; int totalY = 435; seguido de un int total = 0; y vamos calculando el total justo debajo del y += 26; total += Convert.ToInt32(DGV.Rows.Cells[3].Value.ToString()); y abajo de los for declaramos font como new font para agrandar su fuente (Así se ve mejor el total) y agregamos el último g.DrawString() font = new Font("Microsoft Sans Serif", 14, FontStyle.Regular); g.DrawString(total.ToString(), font, brush, new Point(totalX, totalY), formatter); Quedaría todo así (Entro justito todo en la imágen) Listo, ahora sí: Ahora lo que tenemos que hacer es poder imprimirla :3 Borramos el código para crear un nuevo form con la imágen ya que sólo es testeo (O bien lo meten en un método y no lo invocan, si lo quieren usar en otro momento, recomendado) y lo que debemos hacer a continuación es crear un evento nosotros por código, que es sencillo así que tranquilos. Primero creamos un método Boolean imprimirFactura(Image facturaActual) y dentro ponemos lo siguiente: try { PrintDocument pd = new PrintDocument(); pd.PrintPage += (sender, e) => e.Graphics.DrawImage(facturaActual, 0, 0); pd.Print(); return true; } catch (Exception) { MessageBox.Show("Error al imprimir la factura. Compruebe que la impresora esté conectada y encendida", "Advertencia"; return false; } Quedaría así, detectando este error: ¿Por qué el error? Porque estamos usando partes de una librería que no tenemos en este proyecto, así que nos dirigimos arriba de todo y agregamos un using System.Drawing.Printing; Ya nos deja de marcar error. ¿Qué es lo que hace el método? Buena pregunta. No sé. ah Lo que hace es intentar (por estar en un bloque try-catch) crear un documento a imprimir, crear un evento con parámetros object sender y eventArgs e, y llamarlo automáticamente, si no me equivoco, pasándole unos parámetros, entre ellos la imagen a imprimir. Imprime y si todo salió bien, devuelve un true. Sino, muestra el mensaje y devuelve false. Así que... si tienen la impresora prendida con hojas y tinta, a probarlo ! Iniciamos: Llenamos: e imprimimos ! (Colegio técnico, mucho calitecno pero mi letra sigue siendo una m*erda jajaja) Espero que les haya servido gente, cualquier duda/problema, no duden en comentar. Si quieren el proyecto, me mandan MP Este es un aporte hecho por mí en base a mis conocimientos y experiencias de desarrollo en C#. Si quieren ver más sobre este contenido pueden pasarse por mi comunidad: Desarrollo de Software Otros aportes: C# conectado a Sql Server [Nivel Medio]
![C# conectado a Sql Server [Nivel Avanzado]](https://storage.posteamelo.com/assets-adonis/assets/2018/06/19/big2v5-aDPScosNw3r.webp)
Hola muchachada! Primer post, acá, con ganas de aportar cosas de programación :3 Hoy les muestro cómo conectar un simple programa hecho en C# con Visual Studio 2012 con una base creada en SQL Server 2008. CON IMAGENES! :B A estas alturas si estás leyendo esto es porque o sabés algo de programación, o estás moderando, ambos son bienvenidos Pero el target de gente principal es alguien que tenga conocimientos mínimos de software developing, y mejor si es en C#, pero voy a tratar de explicar todo lo mejor posible. Para los que nunca vieron nada de programación, les recomiendo pasar por otros post de Taringa! que seguro debe haber, más adelante voy a hacer algunos aportes para los que saben poco o nada Bueno, empecemos. Primero: - Visual Studio 2012 -SQL Server 2008 R2 (después linkeo, tengo que subir mi sql porque a varios que los bajan de internet no les andaba, así que después subo el mío que anda de 10 :3) Instalen todo por defecto los que no lo tenían :3 Primero arrancamos con el programa, codeando y diseñando todo. Después nos vamos a pasar a Sql y les voy a mostrar un poco como va la mano, vamos a tener una base de datos Agenda con una sola tabla llamada Persona. (PIDAN POR MP EL PROYECTO) El programa consistirá en mostrar todas las personas de la Agenda en una tablita que en VS se llama DataGridView (Vista de cuadrícula de datos o como se quiera traducir), y podremos ir agregando más personas además de editar y borrar desde la tablita. Primero arrancamos con C# porque lo digo yo (? es lo más complicado, así que si sobreviven ya pasamos a SQL y va a ser todo más fácil. :33 Agregar: Abrimos el Visual Studio '12 Archivo >> Nuevo >> Proyecto >> Aplicación de Windows Forms Aceptar Se nos genera el proyecto con la solución y quedaría así: Perfecto, ahí tenemos el form el cual podemos rediseñar agregando/modificando/quitando componentes desde el cuadro de herramientas, que es la pestaña que se encuentra a la <------ Por ahora, vamos a agregar un DataGridView al Form (ventana), agrandamos el form y nos dirigimos al cuadro de herramientas y arrastramos esos 2 componentes a la ventana. Al agregarlo nos saldrá una ventanita, dejaremos tododestildado (Quedará como ReadOnly): Ahora lo que vamos a hacer es cambiar el nombre de dataGridView a DGV, para que quede más simple. Teniendo seleccionada la dataGridView vamos a la derecha, a propiedades >> diseño >> (Name) y lo nombramos DGV Joya, ahora... qué hacemos? A codear. Vamos abajo a la derecha a la pestaña que dice "Explorador de soluciones" o simplemente tocamos F7 para el código (Shift + F7 para el diseño). Nos encontramos con lo siguiente: Ahora como vamos a usar cosas que forman parte de una librería que no estamos usando, la agregamos arriba de todo. using System.Data.SqlClient; Ahora fuera de "public Form1" creamos las siguientes variables privadas: private SqlConnection sqlCon; private SqlCommand sqlCmd; private String strCmd; private DataTable dt; private SqlDataAdapter sqlDA; ese "public Form1" es el constructor de la clase, es lo primero que se ejecuta al iniciar el programa (De lo que nos interesa) Así que agarramos y dentro de ese bloque inicializamos la conexión de la base. Cómo? De la siguiente manera: String instancia = "SQLExpress"; String bd = "Agenda"; try { sqlCon = new SqlConnection("Server=" + System.Environment.MachineName + "" + instancia + ";Database= " + bd + ";Trusted_Connection=True" ) ; sqlCon.Open(); } catch (SqlException) { MessageBox.Show("No se pudo establecer la conexión con la Base de datos." ) ; Application.Exit(); } bloque try-catch en el try: se se pasa un String por parámetro al instanciar el sqlCon como un nuevo SqlConnection Internamente al ejecutar el programa quedaría, en mi caso, así: Server=Ludebe-PCSQLExpress;Database=Agenda;Trusted_Connection= True y al final del try abre la conexión para ya dejarla abierta durante todo le uso del programa. A mí me enseñaron que lo ideal es abrir y cerrar al momento de enviar una consulta a la base de datos, pero en SQL Server, según leí, existe algo que se llama connection pooling, que es una función de Sql que se encarga de administrar las conexiones. Al ser un programita simple, lo dejamos así. El catch se ejecuta si se genera una excepción en el try, en el cual nos mostraría un mensaje y al aceptar se cerraría el programa. Quedaría así: El método InitializateComponent() lo que hace es cargar todos los componentes que cargamos visualmente en el Form en la clase Designer.cs, pero no nos vamos a meter en eso porque no hace falta Perfecto, ya inicializamos la conexión. Pero... ahora? Lo que vamos a hacer es ahora conseguir o traer todos los registros de la tabla Persona para mostrarlos en una tabla. Cómo? De la siguiente manera con las variables que declaramos antes: Vamos a crear un método privado que se va a llamar actualizarTabla() y que se va a encargar de llenar la tabla con los valores de la BDD. private void actualizarTabla() { dt = new DataTable(); strCmd = "Select * from Personas"; sqlCmd = new SqlCommand(strCmd,sqlCon); sqlDA = new SqlDataAdapter(sqlCmd); sqlDA.Fill(dt); DGV.DataSource = dt; } Se vacía la datatable, se crea la consulta (strCmd), se crea el comando pasándole el string y la conexión ya abierta, el dataAdapter lo que hace es lo que parece, es un adaptador entre una datatable y SQL. Como ven, al crearlo se le pasa el comando, por lo que al llamar su método Fill() está llenando la dt con los registros traídos desde SQL. al final, se iguala la DGV al dt. Simple, no? La lógica es fácil, capaz que cuesta aprenderse la sintáxis En VS quedaría así: Bueno, ahora invocamos el método en el constructor de la clase, justo debajo de donde instanciamos la conexíon de la base así al cargar el Form ya llena la tabla :3 like this: Listop, ahora si ejecutamos va a explotar todo a la mi*rda porque no tenemos la base creada, obviamente. Vamos a proceder a añadir unos textBoxes locos para poder agregar nuevas personas. Así que Shift + F7 o explorador de soluciones >> Form1 doble click Vamos a agregar un textBox para el nombre, otro para el apellido, uno para el DNI, otro para el teléfono y uno final para la dirección, así bien simple. Cuadro de herramientas >> TextBox Arrastran 5 al form como hicieron con el DGV o arrastran uno y copypastean el control: ahora para reconocerlos arrastramos 5 Labels a la izquierda de cada TextBox: Va quedando... ahora a cambiar las propiedades de los 10 controles que acabamos de agregar. Tenemos que cambiar de los labeles el texto que se muestra y de los textBoxs el nombre en el diseño. Vamos con los labeles... Seleccionamos uno >> propiedades >> apariencia >> text >> "Nombre" así: Y después con los demás, quedaría así: Perfecto, ahora lo mismo con los textBoxes nada más que en vez de ir a apariencia, vamos a diseño y cambiamos el (name) a txtBoxNombre, txtBoxApellido, y así con los 5, así podremos usarlos más fácil después al momento de getear o conseguir su Text (lo que está escrito). (No recomiendo poner acentos en variables, como se presenta en el caso del Teléfono y de la Dirección). Luego de esto, agregamos un botón debajo de estos controles: Jueguen con las propiedades, les pueden cambiar la apariencia a casi todo, por ejemplo, a mí en estos tipos de programa me gustan los botones así: Para ponerlo así vayan a propiedades teniendo el botón seleccionado, apariencia, FlatStyle, y elijan Flat :3 Bueno, ahora cambienle el nombre en diseño a "btnAgregar" y el texto en apariencia a Agregar, quedaría así: Por último agregen un botón igual pero que se llame en apariencia Actualizar y en diseño bntActualizar Ahora, si hacen doble click en el btnAgregar se va a generar en el código un evento click, que luego al ejecutar el programa y presionar el botón, se ejecutará lo que esté dentrode ese bloque que se auto-generó. También pueden jugar con este tipo de cosas si van al rayito teniendo el control seleccionado (sea un botón, un textBox, un label, lo que sea, cualquiera ! ) Ese "rayito" es una forma de declarar eventos muy fácilmente, en otro post hablaré de esto sino nos vamos a la mier e.e Buem, hagan doble-click en btnagregar para generar el evento y los llevará al código: Este evento lo que hará es ejecutar una consulta a SQL para que se guarde una nueva persona al tener todos los campos llenos. Una buena práctica y acá empiezan temas de ética y seguridad mínima, es hacer un método que compruebe que estén los campos llenos, así no manda un DNI vacío, o un apellido, o lo que sea que fuese que esté sin completar :3 Entoonces, debajo de actualizarTabla() creamos un método privado que devuelva un Boolean y que se llame camposCompletos() private Boolean camposCompletos() { if (textBoxNombre.Text.Equals( "" ) || textBoxApellido.Text.Equals( "" ) || textBoxDNI.Text.Equals( "" ) || textBoxTelefono.Text.Equals( "" ) || textBoxDireccion.Text.Equals( "" )) { return false; } else { return true; }} Lo que hace este método es comprobar que ningún textBox tenga un Text "", osea, esté vacío. Es similar a poner String.Empty en los parámetros del Equals. Si se cumple el if es porque hay un campo vacío y devuelve un false. camposCompletos() == false sino, devuelve un true camposCompletos() == true Quedaría así: Hermoso. Ahora... invocamos el método que acabamos de crear en un if dentro del evento del botón Agregar if (camposCompletos()) lo que hace es ver si camposCompletos devuelve un true o un false, ya que el método devuelve un Boolean. Si devuelve un true va a llamar a un método privado que devuelve un Boolean guardar() que vamos a crear a continuación, sino, muestra un mensaje por pantalla avisando que el lince no llenó los campos. debajo de camposCompletos() creamos un private void guardar() private Boolean guardar() { try { strCmd = "insert into Personas (Nombre,Apellido,DNI,Telefono,Direccion)" + "values ('" + textBoxNombre.Text + "','" + textBoxApellido.Text + "','" + textBoxDNI.Text + "','" + textBoxTelefono.Text + "','" + textBoxDireccion.Text + "')"; sqlCmd = new SqlCommand(strCmd,sqlCon); sqlCmd.ExecuteNonQuery(); MessageBox.Show( "Hecho!" , "Aviso" ) ; return true; } catch(SqlException) { MessageBox.Show("No se ha podido guardar en la base de datos","Advertencia" ) ; return false; } } Queda así: (Escriban bien Direccion no sean boludos, por dios (? Jajajaja) Ahora solo queda llamar al método guardar() en el if del evento click del botón like THIS: Un espectáculo. Ahora generen el evento del btnActualizar haciendo doble-click sobre él y dentro del bloque llamen al actualizarTabla(); :3 : Bien maquinola,creo que es hora de pasarnos a Sql. Así que sin cerrar VS abren el SQL Managment Studio, loguéan y tocan donde dice new Query: y escriben lo siguiente: create database Agenda go use Agenda go create table Personas ( Nombre varchar(30) not null, Apellido varchar(30) not null, DNI varchar(12) not null, Telefono varchar(20) not null, Direccion varchar(40) not null ) Lo que hace es crear la base Agenda, usarla y declarar la tabla con sus respectivos campos. ya con esto podríamos ejecutar el programa perfectamente y veremos que funciona. les dejo la imagen del query, igual después se las incluyo en el .rar junto al proyecto y al .exe, pidanlo por MP Perfecto rufián, a ejecutar el programa! Vuelvan al Visual Studio y Dááleh al plaàày (Compliar y ejecutar [► Iniciar]) Se muestra así: Si les llega a mostrar la ventana es porque ya conecta bien con la base de datos. De lo contrario comprueben bien el nombre de la instancia y de la base de datos en el constructor, como muestro al principio del post, es eso seguro :3 Ahora si tocamos agregar así como viene sin llenar nada, nos tira un errorcito e.é: 10 punto' Ahora llenamos normalmente y tocamos actualizar: GG WP ! Commend Ludebe.(? Fíjense que quedó un poco angostito el DGV, ensanchenlo un toque Ya tenemos la funcionalidad de agregar un registro a la base, ahora vamos con la editar! Editar: Primero cambiemos el nombre del diseño de btnAgregar por btnGuardar y su apariencia a Guardar, ya que lo usaremos tanto para un nuevo registro como para terminar de editar, ya van a ver. (Aumenté el ancho del DGV ya que estaba) Si se fijan y hacen doble-click en el botón, el método se seguirá llamando btnAgregar_Click, eso no va a generar conflictos, pero si son caprichosos como yo e.e lo pueden cambiar de la siguiente forma: Primero, simplemente donde dice btnAgregar lo cambian por btnGuardar: Luego, vuelvan al diseño tocando shift + F7, y les dirá que hay un error blablabla, esto es porque en la clase Designer.cs quedó el evento click del botón referenciando a btnAgregar, mientras que ahora es btnGuardar, lo que hacen es ir a donde dice "instancias de este error", el primre renglón celeste: y les aparecerá esto: Ahora verán que les marca una línea en rojo. Lo siguiente es muy fácil, reemplazar btnAgregar por btnGuardar como hicieron antes, así cambian la referencia del botón. Fácil, ya no tira error. Pueden cerrar la clase Designer que no la vamos a usar, y volver al diseño, ahora va a funcionar todo perfecto. Ahora para poder editar lo que vamos a hacer es configurar el DGV para que se seleccione el registro o fila completa para poder acceder al index o número de fila seleccionada y poder acceder a los datos de la misma. Primero, agregamos 2 personas más para tener un poquito más de variedad, si es que todavía no lo hicieron: Ahora configuramos el DGV. Vamos al constructor del Fom1 (donde inicializamos la conexión) y ahí abajo de todo ponemos lo siguiente: DGV.SelectionMode = DataGridViewSelectionMode.FullRowSelect ; DGV.MultiSelect = false ; Lo que se hace es que se selecicone por fila completa y sólo 1, quedaría así: ahora si ejecutamos y vamos al DGV a seleccionar algo, comprobaremos que funca e.e Ahora lo que hacemos es crear un botón btnEditar con texto Editar: Vamos al código y como variables arriba de todo declaramos un private Boolean editando, y en el constructor lo ponemos como editando = false ahora doble-click en el botón Editar para generar el método, y dentro ponemos lo siguiente: if (DGV.SelectedRows.Count > 0) { editando = true; textBoxNombre.Text = DGV.Rows[DGV.SelectedRows[0].Index].Cells["Nombre"].Value.ToString() ; textBoxApellido.Text = DGV.Rows[DGV.SelectedRows[0].Index].Cells["Apellido"].Value.ToString() ; textBoxDNI.Text = DGV.Rows[DGV.SelectedRows[0].Index].Cells["DNI"].Value.ToString() ; textBoxTelefono.Text = DGV.Rows[DGV.SelectedRows[0].Index].Cells["Telefono"].Value.ToString() ; textBoxDireccion.Text = DGV.Rows[DGV.SelectedRows[0].Index].Cells["Direccion"].Value.ToString() ; } Queda así: lo que se hace es llenar los campos con los valores del registro seleccionado de la tabla. DGV.SelectedRows[0].Index trae un int index, osea, el número del registro o fila seleccionado del DGV. textBoxNombre.Text = DGV.Rows[DGV.SelectedRows[0].Index].Cells["Nombre"].Value.ToString() ; Acá se setea o asigna al texto del textBoxNombre el valor que esté en la fila INDEX y en la celda NOMBRE del DGV. Al llenarse los textBox con los valores, los editamos a gusto y al presionar guardar editando va a ser true, por lo que en vez de insert into va a ser un update where. Vamos al método guardar y implementamos la edición de la siguiente manera. Dentro del try ponemos un if(editando) y dentro del bloque del if, ponemos lo que pasaría si se está editando: strCmd = "Update Personas set Nombre = '" + textBoxNombre.Text + "', Apellido = '" + textBoxApellido.Text + "'," + "DNI = '" + textBoxDNI.Text + "', Telefono = '" + textBoxTelefono.Text + "', Direccion = '" + textBoxDireccion.Text + "' " + "where DNI = '" + DGV.Rows[DGV.SelectedRows[0].Index].Cells["DNI"].Value.ToString()+ "'"; sqlCmd = new SqlCommand(strCmd, sqlCon) ; sqlCmd.ExecuteNonQuery() ; MessageBox.Show("Hecho!", "Aviso" ) ; editando = false; return true ; y después, en un else, lo que ya estaba puesto, el guardar o agregar normal. Queda así: Comprueben que quede igual en la foto, es difícil poner código en el post por los emoticones y el formato, se petea todo (? Bueno... otra aclaración: El DNI acá funcionaría como Primary Key, los que saben van a entender a qué me refiero, después voy a hacer un aporte en la comu explicando esto :3 Si hay 2 personas con mismo DNI, va a modificar los 2, lo cual no estaría bueno, así que cuando crean personas, que tengan diferente DNI :3 Probemos: ejecutamos: Seleccionamos al Lince y presionamos Editar: Cambiamos todos los campos para ver si funciona correctamente, guardar y actualizamos: Y eso es todo para la edición! Borrar: Agregamos un btnBorrar debajo del btnEditar: doble-click en el botón nuevo para generar el evento y adentro ponemos esto: if(MessageBox.Show( "¿Desea realmente borrar este registro?" , "Confirmación" , MessageBoxButtons.YesNo) == DialogResult.Yes) { borrar() ; } Así: obviamente borrar() nos va a tirar error porque no existe, así que vamos a crearlo. debajo del método guardar() creamos un private Boolean borrar() con lo siguiente: try { strCmd = "delete from Personas where Nombre = '" + DGV.Rows[DGV.SelectedRows[0].Index].Cells["Nombre"].Value.ToString() + "' " + " and DNI = '" + DGV.Rows[DGV.SelectedRows[0].Index].Cells["DNI"].Value.ToString() + "'"; sqlCmd = new SqlCommand(strCmd, sqlCon); sqlCmd.ExecuteNonQuery(); MessageBox.Show(DGV.Rows[DGV.SelectedRows[0].Index].Cells["Nombre"].Value.ToString() + " Borrado correctamente" , "Aviso" ) ; return true; } catch (SqlException) { MessageBox.Show("No se ha podido guardar en la base de datos" , "Advertencia" ) ; return false ; } Quedaría así: LISTO LINCE! Si, era sólo eso, una boludes Lo que hace es borrar en Personas donde el DNI sea igual al del registro o fila seleccionado en el DGV. Ejecutamos: Seleccionamos el editado de recién y tocamos borrar Ponemos que No. na mentira, que sí actualizamos y... VOILÁ: Ahí tienen, bah.. en realidad ya no lo tienen jajajaj, se borró correctamente. :3 Después obviamente pueden modificar la interfaz decorandola a gusto para que quede más organizada o fachera Así con esta base (de conocimiento) ya hasta lo pueden hacer ustedes, pueden comprobar que sea un dni válido, pueden agregar más campos, un botón cancelar para cancelar la edición/borrado de registros y que se limpien los textBox, todo lo que quieran. Lo importante y lo que quería mostrar es que tan fácil es conectar una base con mi amado C# <3 Lo he hecho en java y es mucho más manual, Microsoft al poner mucho más $$ nos facilita las cosas. Beautiful. Listo muchachada, me encantó hacer este post, lo disfruté mucho Pienso seguir pero ahora van a ser aportes en mi comunidad de desarrollo de software Los que quieran aprender/aportar son todos bienvenidos!! (No sé si este post va en Ciencias y educación o en Hazlo tu mismo, creí más correcta esta categoría) Nos vemos gente ! Felices Fiestas!! EDIT 1: Gracias a ustedes ya pude crear la comunidad ! A los que les interese, pásense. Ya estoy subiendo algunos aportes que les puede servir! Voy a empezar también a hacer tutoriales para los más iniciados! MUCHAS GRACIAS GENTE! Este es un aporte hecho por mí en base a mis conocimientos y experiencias de desarrollo en C#. Si quieren ver más sobre este contenido pueden pasarse por mi comunidad: Otros aportes: