Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Data entry into a grid via a cursor. Clearing the cursor 1

Status
Not open for further replies.

AndrewMozley

Programmer
Oct 15, 2005
621
GB


I have a form which allows data entry into a grid mygrid, which causes records to be added into a cursor tDetail (which is the RowSource of the grid). So the fields in cursor tdetail are updated as the cells of mygrid are filled, and for each new row of mygrid I APPEND a record to the cursor.

This works fine, and at the end I use the records in the cursor to add and update records in several tables.

However, still in the same form, I would like to go back and let the user enter another transaction.

I realise that I cannot ZAP the records in tDetail, so I re-create this cursor. This is not good news for the grid, so I then re-define the Rowsource for the grid and redefine the header1.caption of each column, which has also been cleared.

Unfortunately I find that the mygrid.Column2.valid() is being cleared – anyway this method is no longer being invoked.

Is there a way that I can preserve the methods of the columns of the grid, even though these columns have had to be re-defined? Or am I going about this the wrong way?

Thanks. Andrew
 
Try this:

Assuming you have a button that says "New Transaction"
button's click event()

Thisform.NewTransaction()

Add a Method call it NewTransaction()

In it, do this:

Thisform.myGrid.RecordSource = ""

Create your new cursor here
Set column attributes etc..

Thisform.myGrid.RecordSource = "Mycursor"
thisform.myGrid.refresh()
return



Ez Logic
Michigan
 
Thank you Ez (Can that really be your name?)

That does the trick; Have implemented that change and can now post multiple invoices. I will remember that : I need to dissociate a grid from its RecordSource before destroying the Record Source.

Perhaps VFP10 will stop other innocents being caught out !

regards. Andrew Mozley (Warminster, UK)
 
>I realise that I cannot ZAP the records in tDetail
Of course you can zap a cursor.

It's much easier and is a preferred method to let the grid remain untouched without the need to reset column attributes etc.

What makes you think you can't ZAP a cursor?

Bye, Olaf.
 
Thank you Olaf.

I have some kind of folk-memory that there are restrictions on what you can do with a cursor (compared with other tables). But that may be the PACK command. Thank you.

Andrew
 
No, ALTER is a problem in certain cases, PACK also is possible. It's even easier for cursors than tables, as cursors always are exclusive tables. And they are tables.
The method to ZAP a cursor as a grid data source even has a name "safe select".


Andy Kramek points out the problem you have with grids, when you recreate a cursor by requerying into cursor. The problem is not the cursor, the problem is the cursor being closed, SQL creating a new tmp file and giving it the same alias name does not preserve grid binding. That's the biggest problem of grids, but this also not differs, if you SELECT.. INTO TABLE, even though it's the same file then, VFP always has to close a workarea before it recreates it, no matter if with same alias and same file, the grid binding then already is gone, and ZAP is the solution for this. That's why grids also are stable with views, a view cursor you requery is zapped and filled newly with query result, it isn't recreated. And it's a cursor.

Do a search on Safe Select and you'll find it mentioned many times, here, too. This should be more known.

Bye, Olaf.
 
Andrew,

What might be confusing you is that, in certain cases, cursors are read-only by default. This applies to cursors created with a SELECT command. So if you do, say, [tt]SELECT * FROM MyTable INTO Cursor csrCursor[/tt], then csrCursor will be read-only, and you won't be able to zap it (the solution is to add a READWRITE clause to the command).

But that doesn't apply to cursors created with CREATE CURSOR, which is what I assume you are doing.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thanks Mike, that's a good extension of the cases, where you can't zap a cursor. In this case a cursor is used to add new data, so we cannot only assume, it's writable, it would be mysterious, if it was not and still could be used to append new records to it and be used in an editable grid.

If you tke the safe select code from Andy Kramek and delete all lines not necessary, as you start with an empty cursor and only want to clear/truncate it, what remains is:

Code:
lparameters tcsql, tcalias
local lnselect, lcsql

*** preserve work area
lnselect = select(0)

*** cursor does not exist
if not used( tcalias )
  *** create it directly
  create cursor (tcalias) (...fields....)
else
  *** cursor does exist, truncate it
  zap in (tcalias)
endif

*** restore work area and return status
select (lnselect)
return used( tcalias )

And if you create the cursor in the init or load of the form or the init of the grid you never switch current workarea, as ZAP in (tcalias) zaps the specified cursor and doesn't switch and also you don't create cursor as you did that in advance, then all which remains is

Code:
lparameters tcalias
zap in (tcalias)

You may add to SET SAFETY OFF before the ZAP and SET SAFETY ON, if you have saftey on, but that's all. And as you onyl have one alias, you can also hardcode that and not need oop or a grid class, you can do that where you want to start a new transaction.

What should be known is not all this code and the Andy Kramek article, but that a grid works well without the need to redefine column properties, if you work with a view and on top of that you should know that's because the view cursor is never destroyed but just refilled and then you can deduct how to do the same with a table or a readwrite cursor.

In case you use a view (local or remote), don't ZAP it, though, that would mean deletion of the records in it, and especially with updatable views would really delete these records in the backend table. But that's due to the updatable nature, you empty a view by setting view parameters in a way having no result and REQUERY(view) or you refresh it with current filters also by REQUERY(view). and in case of "normal" cursors you do so with ZAP and appending new data. Since VFP9 Andy Kramek could have updated his code using INSERT INTO cursor SELECT ... FROM tables, instead of using a temp alias curdummy, you can now directly insert query results into a table or cursor.

One more recommendation about using a form without restarting it: Split up code from the form load and init into portions only needed to be done once, eg creating the grid cursor, and code needed to reinitialise. The latter goes into a separate method reinit. Then init should call reinit at it's end and form reinitialisation can be done by calling reinit.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top