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...