Un Gran Proyecto, Paso a Paso
Quinta Entrega (7/Abr/97)
Entregas anteriores: Primera,
Segunda, Tercera, Cuarta
Lo dicho en otras ocasiones, es recomendable que les eches una visual para seguir el
hilo del proyecto.
Bajate las p�ginas HTML y los gr�ficos de
las 5 primeras entregas. (gsnotas_htm.zip 55.2 KB)
Bajate los
listados del proyecto. (gsnotas.zip 20.9 KB)
(Estos tama�os variar�n seg�n el n�mero de entregas; para saber el tama�o actual,
deber�as ver la �ltima entrega)
Hoy no voy a abordar todav�a el tema de las consultas, lo
siento. Ese ser� el tema de la pr�xima entrega.
No es que quiera ponerme "intrigante", pero es que en ese apartado se van a
tener que hecer una serie de "replanteamientos" del programa y habr� que
a�adir algunas estructuras de datos y eso voy a dejarlo despu�s de los peque�os cambios
que hoy tengo pensado. A estas alturas sabr�s que no tengo este "cursillo"
planeado ni planificado, va saliendo poco a poco y como no soy una persona de ideas fijas,
pues me permito "cambiar" de parecer y espero que no sea a costa de tu
aburrimiento.
Ah!, por cierto, en cuanto a la gente que
"apuesta" por que sea un proyecto de 16 bits, decirte que a�n no hay NI UNA.
Espero que esto siga as�, la verdad es que no me hace mucha ilusi�n tener que hacer el
planteamiento para los 16 bits, no ser�a bueno, creo. S� que a�n hay gente que
"tiene" que trabajar con Win 3.x, pero ya va siendo hora de que cambien...
De todas formas, si hubiese alguna persona interesada en convertirlo a VB3, me podr�a
tomar la molestia de hacer una versi�n "paralela", aunque eso s�, con menos
"actualizaciones". (el plazo termina el pr�ximo Mi�rcoles dia 9 de Abril)
Una vez hecha estas aclaraciones, vamos al tema que nos
interesa. Hoy tengo pensado estas cosas:
(Antes de pasar a estos puntos, debemos
hacer unos cambios al form gsNotas)
Los cambios a realizar en el form gsNotas, son los
siguientes:
---Al Picture1, cambiale el Nombre para que se llame ToolBar
---A�adir un pictureBox y asignarle las siguientes propiedades:
Name = StatusBar (hay que ir prepar�ndose para los 32 bits!)
Height = 270
Align = 2-Align Botton
BorderStile = 0-None
---A�adir un Label dentro del Picture que acabas de insertar y asigna las siguientes
propiedades:
Name = LblStatus
BorderStile = 0-None
Ahora a�ade el siguiente c�digo:
En las declaraciones, despu�s del Option Explicit, deber�s poner esto otro, para que la
rutina de b�squeda "no falle"
Option Compare Text
De esta forma, al comparar cadenas (incluso con el Instr),
no se tendr�n en cuenta las may�sculas/min�sculas.
Estas declaraciones, tambi�n en la parte general del form, para "recordar" el
tama�o inicial de la ventana, despu�s se usar� cuando cambiemos el tama�o.
Dim iH As Integer 'Tama�o m�nimo de la ventana Dim iW As Integer
Ahora si, estas son las cosillas para hoy:
1.- A�adir unos men�s.
Los vamos a necesitar, ya que se a�adir�n m�s opciones
de las que en principio van a "coger" en la barra de herramientas.
Para ello, muestra el form gsNotas. Pulsa en Tools/Menu Editor...
A�ade los siguientes "men�s"
&Archivo mnuArc
--&Nuevo mnuNuevo
--G&uardar mnuGuardar
--&Borrar mnuBorrar
-- - mnuArcSep1
--&Salir mnuSalir
&Edici�n mnuEd
--C&ortar mnuCortar Shortcut = ^X
--&Copiar mnuCopiar Shortcut = ^C
--&Pegar mnuPegar Shortcut = ^V
-- - mnuEdSep1
--S&eleccionar Todo mnuSelecTodo Shortcut = ^E
-- - mnuEdSep2
--&Buscar... mnuBuscar Shortcut = ^B
--Buscar Si&guiente mnuBuscSig Shortcut = {F3}
--&Reemplazar mnuReemplazar Shortcut = ^R
Ya tenemos unos cuantos men�s creados, ahora vamos a asignarles los comandos a realizar. El tema de la Edici�n (cortar, copiar, etc., lo dejaremos para otra ocasi�n)
A�ade la siguiente declaraci�n en la parte general del Form:
Const CMD_Reemplazar = 5
Y este es el c�digo para los men�s que ahora estan operativos: (fijate que la opci�n de Reemplazar, se efectuar� en el interior del procedimiento del cmdAccion, aunque ese bot�n no exista, el VB s�lo procesa la orden que le digamos y no comprueba si el valor Index recibido en el procedimiento est� dentro del rango de botones creados)
Private Sub mnuBorrar_Click()
cmdAccion_Click CMD_BORRAR
End Sub
Private Sub mnuBuscar_Click()
cmdAccion_Click CMD_BUSCAR
End Sub
Private Sub mnuBuscSig_Click()
cmdAccion_Click CMD_BuscarSiguiente
End Sub
Private Sub mnuGuardar_Click()
cmdAccion_Click CMD_ACTUALIZAR
End Sub
Private Sub mnuNuevo_Click()
cmdAccion_Click CMD_NUEVO
End Sub
Private Sub mnuReemplazar_Click()
cmdAccion_Click CMD_Reemplazar
End Sub
Private Sub mnuSalir_Click()
cmdSalir_Click
End Sub
2.- Ajustar los controles al redimensionar la ventana
Para ajustar el tama�o de los controles, usaremos el
procedimiento Form_Resize. En esta rutina, se comprueba de que no se haga ning�n cambio,
si est� minimizada y que no se pueda hacer el form m�s peque�o del tama�o inicial.
Veamos el c�digo: (el Form_Load tambi�n se ha modificado)
Private Sub Form_Load()
'El tama�o por defecto
iH = Height
iW = Width
'El archivo de configuraci�n
sFFIni = ficIni
Show
DoEvents
'Cargar la tabla
CargarTabla
End Sub
Private Sub Form_Resize()
Dim i As Integer
'No hacer nada si se minimiza
If WindowState = vbMinimized Then Exit Sub
'No permitir un tama�o menor que el inicial
If Width < iW Then
Width = iW
Exit Sub
End If
If Height < iH Then
Height = iH
Exit Sub
End If
Data1.Width = ScaleWidth - 180
Text2.Left = ScaleWidth - Text2.Width - 90
Label1(0).Left = Text2.Left - 450
'Los textBox de Asunto y descripci�n
For i = 2 To 3
With Text1(i)
.Width = ScaleWidth - .Left - 90
End With
Next
'Los texts y labels del final
For i = 4 To 5
With Text1(i)
.Top = ScaleHeight - 750
Label1(i).Top = .Top + 30
End With
Next
Check1.Top = Label1(4).Top
'El alto del text de la descripci�n
With Text1(3)
.Height = Text1(4).Top - .Top - 75
End With
'Move es m�s r�pido que efectuar los 3 cambios
LblStatus.Move 60, 30, ScaleWidth - 120
End Sub
3.- Nuevo Form para Buscar/Reemplazar
Para la tarea de Reemplazar, vamos a necesitar otro form,
el cual nos va a servir tanto para pedir los datos a Reemplazar como para la rutina de
Buscar, con lo cual no necesitaremos, al menos por ahora, el m�dulo y el form gsInput,
as� que puedes "quitarlos" del proyecto y a�adir los siguientes:
gsDBR.Frm y gsDBR.Bas

Esta es una "foto" del form gsDBR
El c�digo de estos dos nuevos m�dulos es el siguiente:
'----------------------------------------------------
'Form gen�rico para di�logo Buscar/Reemplazar
'
'�Guillermo Som Cerezo, 1996-97
'----------------------------------------------------
Option Explicit
Const NumeroMaximoDeItems = 100
Dim bBuscandoEnCombo As Boolean
Private Sub cmdCancel_Click()
ActualizarCombo
iFFAccion = cFFAc_Cancelar
Unload Me
End Sub
Private Sub cmdFindNext_Click()
ActualizarCombo
sFFBuscar = txtFind.Text
sFFPoner = ""
iFFAccion = cFFAc_BuscarSiguiente
Unload Me
End Sub
Private Sub cmdReplace_Click()
ActualizarCombo
sFFBuscar = txtFind.Text
sFFPoner = txtReplace.Text
If Len(sFFPoner) = 0 Then
iFFAccion = cFFAc_Buscar
Else
iFFAccion = cFFAc_Reemplazar
End If
Unload Me
End Sub
Private Sub cmdReplaceAll_Click()
ActualizarCombo
sFFBuscar = txtFind.Text
sFFPoner = txtReplace.Text
If Len(sFFPoner) = 0 Then
iFFAccion = cFFAc_Buscar
Else
iFFAccion = cFFAc_ReemplazarTodo
End If
Unload Me
End Sub
Private Sub Combo1_Change(Index As Integer)
If bBuscandoEnCombo Then Exit Sub
If Index = 0 Then
txtFind = Combo1(0).Text
Else
txtReplace = Combo1(1).Text
End If
End Sub
Private Sub Combo1_Click(Index As Integer)
If bBuscandoEnCombo Then Exit Sub
If Combo1(Index).ListIndex Then
Combo1(Index).Text = Combo1(Index).List(Combo1(Index).ListIndex)
End If
If Index = 0 Then
txtFind = Combo1(Index).Text
Else
txtReplace = Combo1(Index).Text
End If
End Sub
Private Sub Form_Load()
Dim j As Integer
Dim i As Integer
Dim n As Integer
Dim vTmp As String
Dim sTmp As String
Dim sTag As String
If sFFIni = "" Then
sFFIni = "BuscReemp.ini"
End If
'Posicionar en el centro de la ventana principal
Move (Screen.Width - Width) \ 2, (Screen.Height - Height) \ 2
'asignar los valores anteriores del combo
For i = 0 To 1
sTag = Trim$(Combo1(i).Tag)
n = 0
n = LeerIni(sFFIni, sTag, "NumEntradas", n)
If n > NumeroMaximoDeItems Then n = NumeroMaximoDeItems
'For j = n - 1 To 0 Step -1
For j = 0 To n - 1
vTmp = "Entrada" & CStr(j)
sTmp = LeerIni(sFFIni, sTag, vTmp, "")
If Len(sTmp) Then
Combo1(i).AddItem sTmp
End If
Next
Next
Combo1(0).Text = ""
Combo1(1).Text = ""
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
'Si se cierra por el controlbox, o cualquier forma distinta del propio c�digo,
'asumir que se ha cancelado.
If UnloadMode <> vbFormCode Then
iFFAccion = cFFAc_Cancelar
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
Dim n As Integer
Dim vTmp As String
Dim sTmp As String
Dim i As Integer
Dim j As Integer
Dim sTag As String
If iFFAccion <> cFFAc_Cancelar Then
ActualizarCombo
For i = 0 To 1
n = Combo1(i).ListCount
sTag = Trim$(Combo1(i).Tag)
If n > NumeroMaximoDeItems Then n = NumeroMaximoDeItems
GuardarIni sFFIni, sTag, "NumEntradas", CStr(n)
For j = 0 To n - 1
vTmp = "Entrada" & CStr(j)
sTmp = Combo1(i).List(j)
GuardarIni sFFIni, sTag, vTmp, sTmp
Next
Next
End If
Set gsDBR = Nothing
End Sub
Private Sub ActualizarCombo()
'-----------------------------------------------------
'Esta rutina actualiza el contenido de los dos combos,
'si la entrada en el Combo.Text no est�, la incluye.
'Se podr�a usar la llamada al API de Windows.
'-----------------------------------------------------
'Actualizar el contenido del Combo
Dim sTmp As String
'Para m�s rapidez...
Static i As Integer
Static j As Integer
Static hallado As Boolean
Static k As Integer
'
bBuscandoEnCombo = True
For k = 0 To 1
hallado = False
sTmp = Combo1(k).Text
If Len(Trim$(sTmp)) Then
j = Combo1(k).ListCount - 1
For i = 0 To j
If StrComp(Trim$(sTmp), Trim$(Combo1(k).List(i))) = 0 Then
hallado = True
Exit For
End If
Next
If Not hallado Then
Combo1(k).AddItem sTmp, 0
End If
End If
Next
bBuscandoEnCombo = False
End Sub
Este es el listado del m�dulo con las rutinas de petici�n de los datos
'---------------------------------------------------------------
'gsDBR.bas M�dulo para el di�logo de Buscar y Reemplazar
'
'(c)Guillermo Som, 1996-97
'---------------------------------------------------------------
Option Explicit
'Variables y constantes para buscar/reemplazar
Global sFFBuscar As String
Global sFFPoner As String
Global iFFAccion As Integer
'Constantes para la acci�n a realizar
Global Const cFFAc_Cancelar = True
Global Const cFFAc_IDLE = 0
Global Const cFFAc_Buscar = 1
Global Const cFFAc_BuscarSiguiente = 2
Global Const cFFAc_Reemplazar = 3
Global Const cFFAc_ReemplazarTodo = 4
Global Const cFFAc_Aceptar = 5
'
Global sFFIni As String 'Archivo de configuraci�n
Public Function gsReemplazar(sBuscar As String, sPoner As String, Optional vModo, Optional vCaption) As Integer
'Prepara el di�logo de Reemplazar
Dim iModo As Integer
Dim sCaption As String
If IsMissing(vModo) Then
iModo = cFFAc_Reemplazar
Else
iModo = vModo
End If
If IsMissing(vCaption) Then
sCaption = "Reemplazar"
Else
sCaption = CStr(vCaption)
End If
iFFAccion = cFFAc_IDLE
With gsDBR
.Caption = sCaption
.cmdFindNext.Default = False
.cmdFindNext.Visible = False
.cmdReplaceAll.Default = True
.Combo1(0).Text = sBuscar
.Combo1(1).Text = sPoner
'Mostrar el form y esperar a que se tome una acci�n
.Show vbModal
'Do
' .Show
' DoEvents
'Loop Until iFFAccion
End With
'Devolver la cadena a reemplazar y buscar
sBuscar = sFFBuscar
sPoner = sFFPoner
'Si tanto buscar como poner est�n en blanco, devolver cancelar
If Len(Trim$(sBuscar)) = 0 Then
If Len(Trim$(sPoner)) = 0 Then
iFFAccion = cFFAc_Cancelar
End If
End If
'Devolver la acci�n
gsReemplazar = iFFAccion
End Function
Public Function gsBuscar(sBuscar As String, Optional vModo, Optional vCaption) As Integer
'Prepara el di�logo para buscar
Dim iModo As Integer
Dim sCaption As String
If IsMissing(vModo) Then
iModo = cFFAc_Buscar
Else
iModo = vModo
End If
'S�lo permitir buscar y buscar-siguiente
Select Case iModo
Case cFFAc_Buscar, cFFAc_BuscarSiguiente
'est� bien, no hay nada que hacer
Case Else
iModo = cFFAc_Buscar
End Select
If IsMissing(vCaption) Then
sCaption = "Buscar"
Else
sCaption = CStr(vCaption)
End If
iFFAccion = cFFAc_IDLE
With gsDBR
.Caption = sCaption
.cmdReplace.Visible = False
.lblReplace.Visible = False
.cmdReplaceAll.Visible = False
.Combo1(1).Visible = False
.cmdFindNext.Left = .cmdReplaceAll.Left
If iModo = cFFAc_BuscarSiguiente Then
.cmdFindNext.Caption = "Siguiente"
DoEvents
End If
.Combo1(0).Text = sBuscar
'Mostrar el form y esperar a que se tome una acci�n
.Show vbModal
'Do
' .Show
' DoEvents
'Loop Until iFFAccion
End With
'Devolver la cadena seleccionada/introducida
sBuscar = sFFBuscar
'Devolver la acci�n
gsBuscar = iFFAccion
End Function
Public Sub gsPedirUnValor(spuvTitulo As String, spuvMensaje As String, spuvPregunta As String, spuvValor As String, spuvBoton As String)
'Rutina de prop�sito general para pedir un valor (00.22 23/May/96)
With gsDBR
.Caption = spuvTitulo
.Combo1(0).Visible = False
.lblBuscar.Width = .ScaleWidth - 120
.lblBuscar = spuvMensaje
.Combo1(0).Visible = False
.cmdReplace.Visible = False
.cmdFindNext.Default = False
.cmdFindNext.Visible = False
.lblReplace = spuvPregunta
.cmdReplaceAll.Default = True
.cmdReplaceAll.Caption = spuvBoton
If Len(Trim$(spuvValor)) Then
.Combo1(1).Text = spuvValor
Else
If .Combo1(1).ListCount Then
.Combo1(1).ListIndex = 0
End If
End If
.Show vbModal
End With
spuvValor = sFFPoner
End Sub
Ahora la rutina de b�squeda quedar�a as�, (he puesto tambi�n que si hay texto seleccionado, se ponga ese para buscar)
Case CMD_BUSCAR 'Buscar registros
'Si no estamos en un Text de b�squeda, salir
If ControlActual = 0 Then Exit Sub
'Si hay texto seleccionado...
With Text1(ControlActual)
If .SelLength > 0 Then
sBuscar = "*" & Trim$(.SelText)
End If
End With
If gsBuscar(sBuscar, , "Buscar datos") > cFFAc_IDLE Then
sBuscar = Trim$(sBuscar)
If Len(sBuscar) Then
YaEstoyAqui = True
Data1.Recordset.FindFirst Text1(ControlActual).DataField & " LIKE '" & sBuscar & "*'"
If Data1.Recordset.NoMatch Then
Beep
MsgBox "No se ha hallado el dato buscado en el campo: " & Text1(ControlActual).DataField, vbOK + vbInformation, "Buscar"
Text1(ControlActual).SetFocus
Else
sTmp = sBuscar
If Left(sTmp, 1) = "*" Then
sTmp = Mid$(sTmp, 2)
End If
'Seleccionar el texto hallado
With Text1(ControlActual)
i = InStr(.Text, sTmp)
.SelStart = i - 1
.SelLength = Len(sTmp)
'posicionarse en ese control
.SetFocus
End With
End If
YaEstoyAqui = False
End If
End If
Ahora el tema de Reemplazar, (ya era hora t�o!)
4.- Una rutina para Reemplazar datos
Deber�s tener estas declaraciones de variables al principio del procedimiento (no es necesario que est�n al principio, pero queda como m�s "mono"):
Dim BusquedaNoHallada As Boolean
Dim j As Integer
Este es el c�digo de la rutina de "Reemplazo"
Case CMD_Reemplazar
'Si no estamos en un Text de b�squeda, salir
If ControlActual = 0 Then Exit Sub
'Si hay texto seleccionado...
With Text1(ControlActual)
If .SelLength > 0 Then
sBuscar = "*" & Trim$(.SelText)
End If
End With
sFFBuscar = sBuscar
sFFPoner = ""
iFFAccion = gsReemplazar(sFFBuscar, sFFPoner)
If iFFAccion <> cFFAc_Cancelar Then
MousePointer = vbHourglass
DoEvents
sBuscar = Trim$(sFFBuscar)
'Quitar de los caracteres de aster�scos
Do While InStr(sFFBuscar, "*")
i = InStr(sFFBuscar, "*")
sFFBuscar = Left$(sFFBuscar, i - 1) & Mid$(sFFBuscar, i + 1)
Loop
If Len(sFFBuscar) <> 0 And Len(sFFPoner) <> 0 Then
If iFFAccion = cFFAc_Reemplazar Or iFFAccion = cFFAc_ReemplazarTodo Then
LblStatus = "Buscando " & sBuscar & "..."
DoEvents
YaEstoyAqui = True
Data1.Recordset.FindFirst Text1(ControlActual).DataField & " LIKE '" & sBuscar & "*'"
If Data1.Recordset.NoMatch Then
Beep
MsgBox "No se ha hallado el dato buscado en el campo: " & Text1(ControlActual).DataField, vbOK + vbInformation, "Reemplazar"
Text1(ControlActual).SetFocus
BusquedaNoHallada = True
End If
YaEstoyAqui = False
Do Until BusquedaNoHallada
sTmp = Text1(ControlActual).Text
'cambiar... (comprobar si es palabra completa)
If Left$(sBuscar, 1) = "*" Then
i = InStr(sTmp, sFFBuscar)
Else
If Left$(sTmp, Len(sFFBuscar)) = sFFBuscar Then
i = 1
Else
i = 0
End If
End If
If i Then
sTmp = Left$(sTmp, i - 1) & sFFPoner & Mid$(sTmp, i + Len(sFFBuscar))
Text1(ControlActual).Text = sTmp
End If
If iFFAccion = cFFAc_Reemplazar Then Exit Do
'Cambiar todas las coincidencias en el m�smo text
j = 1
Do
If Left$(sBuscar, 1) = "*" Then
i = InStr(j, sTmp, sFFBuscar)
Else
If Left$(sTmp, Len(sFFBuscar)) = sFFBuscar Then
i = 1
Else
i = 0
End If
End If
If i Then
j = i + 1
sTmp = Left$(sTmp, i - 1) & sFFPoner & Mid$(sTmp, i + Len(sFFBuscar))
Text1(ControlActual).Text = sTmp
End If
Loop While i
DoEvents
YaEstoyAqui = True
Data1.Recordset.FindNext Text1(ControlActual).DataField & " LIKE '" & sBuscar & "*'"
If Data1.Recordset.NoMatch Then
BusquedaNoHallada = True
Else
BusquedaNoHallada = False
End If
YaEstoyAqui = False
Loop
End If
End If
MousePointer = vbDefault
DoEvents
End If
5.- Informar en que posici�n del TextBox estamos.
Esto es para "rematar" el tema por hoy. Ya que
tenemos el LblStatus, vamos a darle una utilidad.
A mi particularmente me gusta saber en que posici�n se encuentra el cursor cuando estoy
editando un campo, sobre todo cuantos caracteres me quedan a�n. �? Suponte que est�s en
el campo de Asunto y quieres saber cuantos caracteres puedes utilizar, ya sabes que son
255 el m�ximo, as� que lo que viene a continuaci�n, es para indicarnos eso
precisamente, la posici�n dentro del Text y cuantos caracteres son en total.
Mejor ver el c�digo, que ya no controlo demasiado...
Private Sub Text1_Click(Index As Integer)
LblStatus = "Pos: " & Text1(Index).SelStart + 1 & "/" & Text1(Index).MaxLength
End Sub
Private Sub Text1_KeyUp(Index As Integer, KeyCode As Integer, Shift As Integer)
LblStatus = "Pos: " & Text1(Index).SelStart + 1 & "/" & Text1(Index).MaxLength
End Sub
Ahora si que hemos terminado. Espero que saques algunas
cosillas de provecho de todo lo de hoy.
Hasta la pr�xima entrega, esta vez no digo para cuando que despu�s me
dices que no cumplo mi palabra...