En esta ocasión vamos a ver el código que podemos usar para simular un Grid con casillas editables.
En el ejemplo veremos cómo usar tanto un control TextBox como un comboBox.
como verás en el código es fácil decidir si debemos mostrar el textbox o el combo... dependiendo de lo que necesitemos usar... en caso de que necesites usar diferentes combos, te recomiendo que uses un array del control combo1 para que te resulte fácil de interceptar las pulsaciones y otras acciones con dichos controles... puede que en otra ocasión amplíe este ejemplo con esto que digo, además de usar un control checkbox... pero eso será en otra ocasión... así que... paciencia.Te explico lo que el código hace... aunque puedes seguirlo sin problemas, eso espero, con los comentarios incluidos en el código de ejemplo.
En principio el Grid sólo tendrá una fila "disponible", cuando pulsamos en una de las celdas de la última fila, la cual está identificada con ">>*", se creará una nueva fila... cuando pruebes el código de ejemplo, sabrás de que estoy hablando.
Para introducir algo en cualquiera de las celdas, podemos hacerlo de varias formas:
-haciendo doble-click en la celda a editar,
-escribiendo directamente en el grid,
-pulsando la tecla F2Para aceptar lo que hemos escrito, pulsaremos Intro o simplemente haciendo Click en cualquier otra celda.
Si se pulsa ESC, se cancela la edición de la celda.En el código mostrado, uso dos procedimientos para guardar el contenido del grid en un fichero de texto y para leer de ese fichero y asignarlo al grid. Este código tendrás que adaptarlo a los campos que tengas en el grid, aunque usado tal y como lo muestro te puede ser útil al 100%.
Bueno, me dejo de "cháchara" y te muestro el código.
El formulario contiene los siguientes controles:
Un control FlexGrid llamado Grid2,
un TextBox llamado Text1,
un ComboBox llamado Combo1,
un PictureBox llamado picStatus con la propiedad Align = 2 (para que se ajuste a la parte inferior),
una etiqueta llamada lblStatus, (insertada en el picStatus),
un botón llamado cmdSalir, (insertado en el picStatus).Nota:
No tienes que preocuparte por "insertar" los dos últimos controles mencionados en el PictureBox, ya que eso se hace en el código del evento Form_LoadComo bono extra, una función para "interpretar" fechas y asignar el formato que queramos a partir de varias formas de entrada, por ejemplo, acepta fechas con y sin separadores, e incluso sin indicar el año...
Aquí tienes el código:
'------------------------------------------------------------------------------ ' Prueba de Grid con celdas editables (09/May/01) ' Revisado: 17/May/2001 ' ' Ejemplo de código con TextBox y ComboBox ' ' ©Guillermo 'guille' Som, 2001 '------------------------------------------------------------------------------ Option Explicit Private sFicDatos As String ' Fichero con los datos del grid Const cNuevaFila As String = ">>*" ' Para indicar que es una nueva fila Private ControlVisible As Boolean ' Si el control está o no visible (editándose) Private LastRow As Long ' La última fila en que se editó Private LastCol As Long ' La última columna en que se editó Private Sub cmdSalir_Click() Unload Me End Sub Private Sub Combo1_Change() If Combo1.Visible Then Grid2.TextMatrix(LastRow, LastCol) = Combo1.Text AsignarCelda End If End Sub Private Sub Combo1_Click() Combo1_Change End Sub Private Sub Combo1_KeyPress(KeyAscii As Integer) If KeyAscii = vbKeyReturn Then KeyAscii = 0 AsignarCelda SiguienteCelda ElseIf KeyAscii = vbKeyEscape Then KeyAscii = 0 Combo1.Visible = False End If End Sub Private Sub Form_Load() Dim i As Long Dim s As String ' picStatus.Height = 585 With lblStatus .Caption = " Código de ejemplo: ©Guillermo 'guille' Som, 2001 <[email protected]>" Set .Container = picStatus .Height = 285 .BorderStyle = vbFixedSingle .Left = 90 .Top = 120 .Visible = True End With With cmdSalir Set .Container = picStatus .Height = 405 .Top = 60 .Visible = True End With ' s = App.Path sFicDatos = s & IIf(Right$(s, 1) = "\", "", "\") & "PruebaGrid.txt" ' With Combo1 .Clear For i = 1 To 20 .AddItem i Next End With ' OcultarControles ' CabeceraGrid LeerDatos End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) ' Guardar los datos del grid GuardarDatos End Sub Private Sub Form_Resize() ' Reajustar el tamaño del grid al de la ventana ' Si tuviesemos otro control, por ejemplo una barra de estado, ' restarle el ancho de la misma al Grid If WindowState <> vbMinimized Then Grid2.Move 0, 0, ScaleWidth, ScaleHeight - picStatus.Height With cmdSalir .Left = picStatus.ScaleWidth - .Width - 90 lblStatus.Width = .Left - 120 - lblStatus.Left End With End If End Sub Private Sub Grid2_Click() ' Cuando se hace un sólo click en otra columna, ' asigna el valor seleccionado, (como si se pulsara intro) AsignarCelda End Sub Private Sub Grid2_DblClick() ' Editar al hacer dobleclick LastRow = Grid2.Row LastCol = Grid2.Col ' OcultarControles ' MostrarCelda End Sub Private Sub Grid2_KeyDown(KeyCode As Integer, Shift As Integer) ' Editar si se pulsa F2 If KeyCode = vbKeyF2 Then MostrarCelda ElseIf KeyCode = vbKeyDelete Then ' Borrar las filas seleccionadas (13/May/01) BorrarFilas End If End Sub Private Sub Grid2_KeyPress(KeyAscii As Integer) Select Case KeyAscii ' Si se pulsa Intro, editar la celda Case vbKeyReturn KeyAscii = 0 MostrarCelda ' Cancelar si se pulsa ESC Case vbKeyEscape KeyAscii = 0 AsignarCelda ' Si se pulsa cualquier letra, editar la celda Case 32 To 255 MostrarCelda With Text1 If .Visible Then '.Text = .Text & Chr$(KeyAscii) .Text = Chr$(KeyAscii) .SelStart = Len(.Text) + 1 End If End With End Select End Sub Private Sub Grid2_Scroll() ' Comprobar si la columna en la que está el control está visible ' si es así, ocultar los controles ' If Grid2.ColIsVisible(LastCol) = False Then OcultarControles Exit Sub End If If Grid2.RowIsVisible(LastRow) = False Then OcultarControles Exit Sub End If ' Comprobar si estaba visible antes de ocultarlo ' y posicionarlo en la misma celda If ControlVisible Then MostrarCelda End If End Sub Private Sub MostrarCelda() Static YaEstoy As Boolean ' ' Salir si es una de las celdas fijas If Grid2.Col <= Grid2.FixedCols - 1 Or Grid2.Row <= Grid2.FixedRows - 1 Then Exit Sub End If ' If YaEstoy Then Exit Sub YaEstoy = True ' OcultarControles ' LastRow = Grid2.Row LastCol = Grid2.Col ' ' Si es una nueva celda With Grid2 If .TextMatrix(LastRow, 0) = cNuevaFila Then .Rows = .Rows + 1 .TextMatrix(LastRow, 0) = LastRow .TextMatrix(.Rows - 1, 0) = cNuevaFila End If End With ' Select Case LastCol Case 2 Combo1.Text = Grid2.TextMatrix(LastRow, LastCol) Combo1.Move Grid2.CellLeft - Screen.TwipsPerPixelX, Grid2.CellTop - Screen.TwipsPerPixelY Combo1.Width = Grid2.CellWidth + Screen.TwipsPerPixelX * 2 Combo1.Visible = True Combo1.ZOrder Combo1.SetFocus Case Else Text1.Move Grid2.CellLeft - Screen.TwipsPerPixelX, Grid2.CellTop - Screen.TwipsPerPixelY, Grid2.CellWidth + Screen.TwipsPerPixelX * 2, Grid2.CellHeight + Screen.TwipsPerPixelY * 2 Text1.Text = Grid2.Text If Len(Grid2.Text) = 0 Then If LastRow > 1 Then Text1.Text = Grid2.TextMatrix(LastRow - 1, LastCol) End If End If Text1.Visible = True If Text1.Visible Then Text1.ZOrder Text1.SetFocus End If End Select ' ControlVisible = True ' YaEstoy = False End Sub Private Sub SiguienteCelda() If Grid2.Col < Grid2.Cols - 1 Then Grid2.Col = Grid2.Col + 1 Else Grid2.Col = 1 If Grid2.Row < Grid2.Rows - 1 Then Grid2.Row = Grid2.Row + 1 End If End If End Sub Private Sub Text1_GotFocus() With Text1 ' Posicionar el cursor al final .SelStart = Len(.Text) End With End Sub Private Sub Text1_KeyPress(KeyAscii As Integer) ' Si se pulsa Intro, aceptar lo que se ha escrito If KeyAscii = vbKeyReturn Then KeyAscii = 0 AsignarCelda SiguienteCelda ' Si se pulsa ESC, cancelar la edición ElseIf KeyAscii = vbKeyEscape Then KeyAscii = 0 Text1.Visible = False ControlVisible = False End If End Sub Private Sub AsignarCelda() ' Asignar al grid el texto escrito o seleccionado del combo Dim s As String ' OcultarControles ControlVisible = False ' ' Asignar el texto anterior a la celda Select Case LastCol Case 2 ' Grid2.TextMatrix(LastRow, LastCol) = Combo1.Text Case Else s = Text1.Text ' si es la columna de la fecha... If LastCol = 1 Then ' Fecha s = AjustarFecha(s) End If Grid2.TextMatrix(LastRow, LastCol) = s End Select End Sub Private Function AjustarFecha(ByVal sFecha As String) As String ' Ajustar la cadena introducida a formato de fecha (27/Abr/01) Dim i As Long Dim s As String ' If sFecha = "" Then AjustarFecha = "" Exit Function End If ' 'On Error Resume Next On Error GoTo 0 ' ' Comprobar si se usan puntos como separador ' si es así, cambiarlos por / Do i = InStr(sFecha, ".") If i Then Mid$(sFecha, i, 1) = "/" End If Loop While i ' ' Comprobar si se usan - como separador ' si es así, cambiarlos por / Do i = InStr(sFecha, "-") If i Then Mid$(sFecha, i, 1) = "/" End If Loop While i ' s = "" Do i = InStr(sFecha, "/") If i Then s = s & Right$("0" & Left$(sFecha, i - 1), 2) & "/" sFecha = Mid$(sFecha, i + 1) End If Loop While i sFecha = s & sFecha ' If InStr(sFecha, "/") Then If Len(sFecha) = 5 Then ' Si es igual a 5 caracteres, es que falta el año sFecha = sFecha & "/" ElseIf Len(sFecha) < 3 Then ' Si es menor de 3 caracteres es que falta el mes sFecha = sFecha & "/" & CStr(Month(Now)) & "/" End If ElseIf Len(sFecha) < 3 Then sFecha = sFecha & "/" & CStr(Month(Now)) & "/" Else s = "" For i = 1 To 2 s = s & "/" & Mid$(sFecha, (i - 1) * 2 + 1, 2) Next s = s & "/" & Mid$(sFecha, 5) sFecha = s End If sFecha = Trim$(sFecha) ' ' Comprobar si tiene una barra al principio, si es así, quitarla If Left$(sFecha, 1) = "/" Then sFecha = Mid$(sFecha, 2) End If ' Si tiene una barra al final, es que falta el año If Right$(sFecha, 1) = "/" Then sFecha = sFecha & CStr(Year(Now)) End If ' ' Convertir la fecha, por si no se especifican todos los caracteres ' Nota: Aquí puedes usar el formato que más te apetezca sFecha = Format$(sFecha, "dd/mm/yyyy") ' ' ' Si no es una fecha correcta... ' If IsDate(sFecha) = False Then ' AjustarFecha = sFecha ' Else ' AjustarFecha = sFecha ' End If ' Err = 0 ' AjustarFecha = sFecha End Function Private Sub CabeceraGrid() ' Asignar las cabeceras del grid y asignación de valores predeterminados Dim i As Long ' With Grid2 .FixedRows = 1 .FixedCols = 1 .ScrollBars = flexScrollBarBoth .AllowUserResizing = flexResizeColumns .Cols = 11 ' Número de columnas, contando la cabecera .Rows = 2 ' Número de filas, contando la cabecera ' el número de filas se asignará dinámicamente .ColWidth(0) = 600 ' El ancho de la columna 0 ' ' Asignar los nombres de las cabeceras y el ancho de las columnas .TextArray(1) = "Fecha" .ColWidth(1) = 1100 .TextArray(2) = "Número" .ColWidth(2) = 900 .TextArray(3) = "Nombre" .ColWidth(3) = 1500 .TextArray(4) = "Apellidos" .ColWidth(4) = 2000 .TextArray(5) = "Domicilio" .ColWidth(5) = 2500 .TextArray(6) = "Población" .ColWidth(6) = 2000 .TextArray(7) = "Provincia" .ColWidth(7) = 1600 .TextArray(8) = "Teléfonos" .ColWidth(8) = 1500 .TextArray(9) = "e-mail" .ColWidth(9) = 1200 .TextArray(10) = "Observaciones" .ColWidth(10) = 2500 ' ' Mostrar los números en las filas For i = 1 To .Rows - 1 .TextMatrix(i, 0) = i Next ' ' Esto indicará que es una nueva fila ' (asignarla a la primera columna de la última fila) .TextMatrix(.Rows - 1, 0) = cNuevaFila End With End Sub Private Sub BorrarFilas() ' Borrar las filas seleccionadas (13/May/01) Dim i As Long Dim j As Long Dim k As Long Dim n As Long ' ' Si está seleccionada la última fila, no borrarla If Grid2.RowSel = Grid2.Rows - 1 Then Beep Exit Sub End If If Grid2.Row = Grid2.Rows - 1 Then Beep Exit Sub End If ' ' Borrar siempre desde la fila mayor a la menor i = Grid2.Row j = Grid2.RowSel If i < j Then k = i i = j j = k End If For n = i To j Step -1 Grid2.RemoveItem n Next LastRow = Grid2.Rows - 1 LastCol = 1 Grid2.Col = LastCol Grid2.Row = LastRow Grid2.RowSel = LastRow Grid2.ColSel = LastCol End Sub Private Sub OcultarControles() ' Ocultar los controles de edición (17/May/01) ' (aunque son pocos, se pueden ampliar y así es más fácil saber dónde ' poner el código para ocultarlos) Text1.Visible = False Combo1.Visible = False End Sub Private Sub LeerDatos() ' Leer los datos y asignarlos al grid Dim nFic As Long Dim r As Long Dim c As Long Dim s As String ' ' Si no existe el fichero, nada que hacer... If Len(Dir$(sFicDatos)) = 0 Then Exit Sub ' r = Grid2.Rows - 2 nFic = FreeFile Open sFicDatos For Input As nFic Do While Not EOF(nFic) r = r + 1 Grid2.Rows = r + 2 Grid2.TextMatrix(r, 0) = r For c = 1 To Grid2.Cols - 1 If Not EOF(nFic) Then Line Input #nFic, s Grid2.TextMatrix(r, c) = s Else Exit For End If Next Loop Close nFic ' With Grid2 .TextMatrix(.Rows - 1, 0) = cNuevaFila LastRow = .Rows - 1 LastCol = 1 .Col = LastCol .Row = LastRow .RowSel = LastRow .ColSel = LastCol End With End Sub Private Sub GuardarDatos() ' Guardar los datos del Grid Dim nFic As Long Dim r As Long Dim c As Long ' nFic = FreeFile Open sFicDatos For Output As nFic ' No guardar la última fila, (si se usa el indicador de nueva fila) For r = 1 To Grid2.Rows - 2 For c = 1 To Grid2.Cols - 1 Print #nFic, Grid2.TextMatrix(r, c) Next Next Close nFic End SubPara bajarte el código de ejemplo, pulsa en este link. (GridEdit.zip 5.50 KB)
Nos vemos.
Guillermo