Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Articles
Search: 

VFP for Beginners - Part VII
Claudio Lassala, July 1, 2002
Enhancing the Data-entry form class a little bit In the previous articles of this series, we learned how we could create a simple Data-entry form class, which we can re-use very easily in all of our data-entry forms. Now, in this article, we'll enhance a little bit our class. The "Salv...

Enhancing the Data-entry form class a little bit

In the previous articles of this series, we learned how we could create a simple Data-entry form class, which we can re-use very easily in all of our data-entry forms. Now, in this article, we'll enhance a little bit our class.

The "SalvarRegistro()" method

Do you remember our SalvarRegistro() Method? It contains some code that runs to save data in the table. If you open that method from our "CadastroBasico" class, you will see something like this:

*-- SalvarRegistro() Method
=Tableupdate()
Thisform.Refresh
thisform.nStatus = 0
Messagebox("Registro salvo!")

This way, when this method is executed, all it will do is try to save the record. But, what happens if you need to validate the data before saving it? And what happens if some errors occur on the save attempt?

Forcing an error

For example, let's force a situation that will fire an error:

  • Run our form CadFornece.scx twice (you will see two windows with this form).

  • Click on the Add button in one form, fill all the data, and pay attention to the ID generated for the record (do not save the data yet!).

  • Go to the other form, and click on the Add button. Pay attention to the ID generated, and you'll notice that the ID is the same for the first form.

  • Fill the form with data, and try to save. The record will be saved.

  • Now click on the save button in the first form. An error will occur, because you are violating a uniqueness of the index on the primary key.

This is a sort of error which occurs very often, depending on how you generate your primary-keys.

Validating data and handling errors

Let's change the SalvarRegistro() method in order to address those issues:

*-- Try to validate the data
If This.Validardados()

   *-- if the data is valid, try to save it.
   If Tableupdate()

      Thisform.Refresh
      Thisform.nStatus = 0
      Messagebox("Registro salvo!")
      Return .T.

   Else
      *-- If an error has occurred when saving, try to handle the error.
      Local laErro(1,5), lnErro
      Aerror(laErro)
      lnErro = laErro(1,1)

      Do Case

         Case lnErro = 1884  && Uniqueness of index violated

            If laErro(1,3) = "PRIMARY"  && Primary-key
               Replace (Field(1)) with (Evaluate(Field(1)) + 1)
            Else && Candidate key
               Messagebox("Candidate-key violation!")
            Endif

      EndCase
		
      Return .F.

   Endif

Else

   Return .F.

Endif

As you can see, the code now starts invoking the ValidarDados() method and testing the value returned from it. You must create this method in the class. The big gotcha here is that you do not have to fill this method in the class. That's it. The method must be empty. But, why is this like that? Well, this class will be used for a lot of forms and for each form we'll validate different data. So, we cannot foresee all the validations we'll be doing. But we do KNOW that we'll validate data before saving and that's enough for a while.

If the ValidarDados() method returns .T., we can try to save the data. Otherwise, the SalvarRegistro() method must return .F.

Then, we will try to save the data using the TableUpdate() function. If this function returns .T., that means our data was saved and we can let the user know that the record has been saved. But, if TableUpdate() returns .F., that means an error occurred. So, we must handle it.

We can obtain information about the error using the AError() function. This function will create (or use an already created) array variable (in this example, named laErro), containing details about the last error which occurred.

Please, refer to AERROR() function in the VFP help to obtain more information about the array generated by Aerror().

Now, we just need to do a DO CASE structure and test the number of the error. By that, we can decide what sort of treatment we'll apply on this error.

On this example, if the error which occurred has the error number 1884 (Uniqueness of index "name" violated.) - as this was the case when we generated two records with the same ID - we'll test what sort of index was violated. If the index violated was a "PRIMARY" one, we'll increment the value on the first field of the table (by convention, I'll always put my primary key as the first field on any table). Otherwise, if the index violated was a "CANDIDATE" one, we'll just show a message box. Of course, this is a very simple process, you will implement a more detailed handling for this sort of error.

Don't forget to create a fresh new method called ValidarDados(), with no code inside it!

It's now time to save the class. You may go in our CadFornece.scx form as we will change it a little bit.

Don't forget to validate the data

Let's suppose we need to apply some validations on the data of this form. For example, lets assume the "Estado" field cannot be left empty and that the "Data Cadastro" field must not have a date less than 20/03/1980. Well, in order to achieve this, we will put some code inside the ValidarDados() method. Just open this method on the form and put the following code:

With Thisform

   If Empty(Alltrim(.txtc_UF.Value))
      Messagebox("O campo Estado deve ser preenchido!")
      .txtc_UF.SetFocus()
      Return .F.
   Endif

   If .txtd_Cadastro.Value < {^1980-03-20}
      Messagebox("A Data de Cadastro deve ser Maior que 20/03/1980!")
      .txtd_Cadastro.SetFocus()
      Return .F.
   EndIf
	
Endwith

This doesn't represent a big problem. If any of the defined conditions failed, the method will return .F. Remember that the SalvarRegistro() method is testing the success of the operation. So, if this method returns .F., the SalvarRegistro() method will not even try to save the data on the table.

Hooks, Hooks and more Hooks!

In a lot of cases, we need to "extend" the functionalities of our classes, because it's impossible to cover all the possibilities when we're creating them. For example, in some cases you might want to send an email just before a record is saved (in order to inform someone about the changes). In another case, you might want to upload some file to a server after a record has been deleted. In order to provide such extensibility, we need to create "hooks" on our classes.

For example, first, you must create two new methods on our "CadastroBasico" form class: a method called AntesDeSalvar() (aka BeforeSave()), and another called DepoisDeSalvar() (aka, AfterSave()). This method must not include any code.

Then, let's change again our SalvarRegistro() method. Now, it will look like this:

If This.AntesDeSalvar()

   If This.Validardados()
      If Tableupdate()
         Thisform.Refresh
         Thisform.nStatus = 0
	 		
         This.DepoisDeSalvar()
			
         Messagebox("Registro salvo!")
         Return .T.
      Else
         Local laErro(1,5), lnErro
         Aerror(laErro)
         lnErro = laErro(1,1)

         Do Case
            Case lnErro = 1884  && Violação da unicidade de índice
                If laErro(1,3) = "PRIMARY"  && Chave-primária
                   Replace (Field(1)) With (Evaluate(Field(1)) + 1)
                Else && Chave-candidata
                   Messagebox("Violação de chave-candidata!")
                Endif
         Endcase

         Return .F.
      Endif
   Else
      Return .F.
   Endif
Endif

As you can see, on the first line we're invoking the AntesDeSalvar() method. This way, before trying to save or even validating the data, this method will be called. Typically, you'll fill this method with some data prepared for the upcoming validations and save actions.

Then, you can see the implementation of the DepoisDeSalvar() method. This method is called right after the save was successful. Typically, you'll fill this method with code to send an email, or any other process that must be executed after a saving.

Let's test it. Open the CadFornece.scx form and then open the AntesDeSalvar() method. Put the following code into it:

MessageBox("We are preparing some data which are required for the save process...")
Then, open the DepoisDeSalvar() method, and put the following code in it:
MessageBox("We just saved the data. Now, we can send an email for someone.")

Run the form and try to edit or add a record. Finally, click on the save button. You should now see the results.

Conclusion

So, when you create your classes, keep in mind to benefit of a hook approach. That will give you some wonderful possibilities of extensibility! I think you got the idea.

Ok, that's all folks! See you on the next article of this series.

Source-code for this article.

Claudio Lassala, Improving
Claudio Lassala is an independent Software Developer who currently works mostly building Ruby on Rails applications. Previously, he has worked for several years developing .NET applications, presented several lectures at Microsoft events such as PDC Brazil, TechEd Europe, and various other Microsoft seminars, as well as several conferences and user groups across North America, Europe and Brazil. He is a multiple winner of the Microsoft MVP Award since 2001 (for Visual FoxPro in 2001-2002, and for C# ever since). He has articles published on several magazines, such as MSDN Brazil Magazine and CoDe Magazine. He started the Virtual Brown Bag meetings (www.virtualbrownbag.com) in 2009 and have been hosting it weekly since then. When not writing code, Claudio is probably rocking out with his band, Descent Into Madness (http://www.descentintomadness.com). In a previous life, Claudio authored and presented several training videos that can be found on the Universal Thread.
More articles from this author
Claudio Lassala, October 1, 2004
Claudio Lassala is a well-known member of the Visual FoxPro and .NET communities, has been involved with Brazilian and American user groups, and has been part of the Universal Thread Magazine in the past, when the publication merged with his RapoZine magazine, until the moment in which he reallocate...
Claudio Lassala, December 1, 2002
West Wind Technologies has presented a one of a kind 3 day conference on WWC prior to the GLGDW conference in Milwaukee. This conference was geared towards existing WWC and general VFP Web developers with specialized topics presented by several speakers in this session style conference. Speakers inc...
Claudio Lassala, June 1, 2002
PDC 2002 - Brazil - On the vision of Claudio Lassala For the first time, Brazil hosted the Personal Developers’ Conference (PDC), the major Microsoft technologies developers’ conference. The event took place on May 6th and 7th, at the Meliá Hotel in São Paulo. Over 700 professionals attended ...
Claudio Lassala, October 1, 2002
Author: Fábio Vazquez Publisher: Axcel Books ISBN: 8573231777 Retail Price: R$ 54,00 Publication Date: 2002 Pages: 268 Fonte: http://www.axcel.com.br It has b...
Claudio Lassala, April 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez Claudio Rola José Cavalcanti Moacyr Zalcman Ricardo Soares Fábio Vieira ...
Claudio Lassala, July 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Claudio Lassala, August 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Claudio Lassala, June 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Claudio Lassala, January 1, 2002
The Universal Thread Magazine has the honor to include in this month's issue two interviews which appeared in the RapoZine magazine recently. Those interviews have been conducted by Claudio Lassala. We would like to thank the RapoZine team and Claudio Lassala for allowing us to include those in th...
Claudio Lassala, September 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Claudio Lassala, August 1, 2002
In an appreciation to Microsoft for the 10th year anniversary since the purchase of "Fox Software", Hugh Winters initiated, in June 2002, a 10th year anniversary event which involved the participation of one of the greatest, if not the greatest, developers community - the Visual FoxPro developers c...
Claudio Lassala, May 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira Martín Salías Antonio Castañ...
Claudio Lassala, January 1, 2002
The Universal Thread Magazine has the honor to include in this month's issue two interviews which appeared in the RapoZine magazine recently. Those interviews have been conducted by Claudio Lassala. We would like to thank the RapoZine team and Claudio Lassala for allowing us to include those in th...
Claudio Lassala, October 1, 2002
Introduction - by Claudio Lassala The life for those who work with Visual FoxPro in Brazil is not that easy. There is a lack of content in Portuguese, just a few courses, books, just the UTMag/RapoZine magazine in Portuguese, and there is no localized version of VFP in Portuguese. ...
Claudio Lassala, February 1, 2002
On January 15th, 2002, an important joint took place for our magazine. The Universal Thread Magazine and RapoZine magazine, an online magazine available for the Portuguese developers community, joined to create UTMag/RapoZine. Effective from this issue, both magazines will offer the same technical c...
Claudio Lassala, October 1, 2002
My users can't see this stuff, but I can, and I love it As usually happens with every new version of Visual FoxPro, we have plenty of new "non-visual" enhancements. These enhancements are not noticed by o...
Claudio Lassala, March 1, 2002
Following our course (which began on the 8th Issue of RapoZine), we will learn to create Forms. Visual FoxPro give us tools that make Form creation very simple. Let's start. Creating an "About..." Form. A very common Form, and also one of the simplest to create, is an "Abo...
Claudio Lassala, May 1, 2002
In the previous chapter of our course for beginners, we saw how it is possible to create forms in Visual FoxPro. In this chapter, we will learn how to create classes, converting our recently created database into a class that can be reused in all of our applications. Classes Very often ou...
Claudio Lassala, February 1, 2002
FoxPro Report Designer has always been a great tool, very easy and efficient. However, developers must very often design reports in a format that can be easily viewed by third parties, specially the ones that must be visualized from a non-VFP application. The only native format the rep...
Claudio Lassala, March 1, 2002
In the last month, we received dozens of emails from satisfied persons in regards for our initiative of opening the magazine and the Universal Thread in general for additional communities such as the Portuguese and Spanish communities. Regulars members of the Universal Thread, new members, Microsoft...