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 SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to get the selection from the BROWSE window 3

Status
Not open for further replies.

A_Radiolog_inFoxPro

IS-IT--Management
Mar 29, 2020
38
0
0
CY
Dear All ,
please bare with me , I am very very new to FoxPro (out of necessity)

to update a super old program ,
I am running FoxPro 6
So I have a DB file and at the end I am having this code

select <db>
SET ORDER TO <the field> DESCENDING
SET FILTER TO <a given expression>
**BROWSE FIELDS **<-----(this is the part I am having trouble with)

so as the window pops up and shows what my filter produced ,
I would like to know how can I grab that record and store it to pass the values to another subroutine or do something with them in general ,

I know it sounds stupid but I am a complete noob ,

I hope you can help me ,
And sorry again (if I am wasting your time) :'(

Thank you in advance
AN_Idiot_inFoxPro
 
BROWSE is a bad choice, you could create a form with a grid, but let's take that aside as enhancement for later.

When you click on a row in the browse window, this record becomes the current record. You navigate to it. The little arrow on the left indicates this, but also the highlighted current cell. Anyway, the whole row is the current record. And that stays when you close the window.

So you have the concepts of currently set datasession (SET DATASESION), currently selected workarea (SELECT aliasname/workareanumber), which can be seen as a handle to a table file DBF() or SQL query result, that is opened in that workarea, and each workarea has a current row, too. So this zooms in to what you want and the only thing you need to address is the column or field name:

As an example:
Code:
USE yourtable.dbf ALIAS mytable && or opened by the forms data environment
* To work on a specific row of a table
SELECT mytable
SET ORDER TO ...
SET FILTER TO ....
BROWSE && now pick a row
IF NOT EOF()
   yourfunction(fieldname) && or whatever list of fields the parameterization of the function needs
ENDIF

This will call your function passing in the value of the field in the picked row.

A corner case I handled here is: You browse an empty table or your SET FILTER finds no row, then you'll be at the end of the file, EOF() returns true (.T.) and while fieldname will still get a value, that's not coming from the DBF file, that's the standard value for the data type of the field and so EOF() has to be checked to see whether there is a current and relevant row at all.

What you can't cover with BROWSE is knowing whether the user interacted at all. If you don't pick a row and close the window the code after BROWSE will see the row that was active before, too, the first row fitting the FILTER or again EOF(), if there is no such row. When you use a grid instead you can observe the user's choices and even react to each picked row by using the grid controls AfterRowColChange() event.

If yourfunction is very specific to the table you even might not pass anything and let the function pick out the rows field values it needs itself. As long as it runs in the same data session it also sees the current workarea's current row without you passing anything in.

Bye, Olaf.

Olaf Doschke Software Engineering
 
As an aside: The current row or also referred to as record pointer just as current workarea is a very core concept, which enables us to address a field simply by its name in Foxpro.

The currently selected workarea concept is very widespread and many commands which have an IN clause (IN nWorkarea|cTablealias) work on the selected workarea, if that clause is not used, some even only work on the selected workarea, like LOCATE, which has no IN clause. In some functions like SEEK() the workarea number or alias also are optional parameters and the default scope is currently selected workarea.

Also, its current row of the selected workarea is the default scope regarding the fields, so you don't need something like oADODBRecordset.Fields(4).Value.

And another important aside how the simplicity of this could bite you later: Imagine you have a variable with the same name as a field: The field has precedence, you won't see the value of your variable but instead address the field's value:

Code:
LOCAL x
x= 'World'
CREATE CURSOR mycursor (x char(5))
INSERT INTO mycursor values ('Hello')
? x, m.x

x here shows 'Hello', the variables' value is shown by m.x

The other side of this is that while the read access of table fields is so simple as if a variable exists, you can't change the value of fields simply by assignments like fieldname=newvalue. And it also means field and variable names can overlap and be separate things because variables belong to an intrinsic m object (m for memory as in LIST MEMORY mainly listing defined variables).

And this actually is also a wanted concept, as even older FoxPro versions didn't have the concept of buffering of a workarea, so you would SCATTER TO MEMVAR and create variables with the same name as fields, still have priority to access the fields and not the scattered variables. But you could cancel changes by GATHER the stored values, for example.

This concept was extended in VFP9 by being able to SCATTER to an object and not create a bunch of variables but just one object variable with field names as properties, quite a good basis for ORM. Besides being able to pass a row in one single object variable you can also INSERT from such an object, you can scatter to an existing object and thus, for example, set the top, left, width, height and further properties of a form simply by having a table with these field names.

Bye, Olaf.

Olaf Doschke Software Engineering
 
You ask how you can grab "that record". Does that mean that you can only see one record (one row) in the Browse window? If so, then you don't have to do anything. The underlying table (the "<db>" in the first line of code that you show) will automatically be aligned at the record in question.

So if the table in question contains a field named, say, Address, then that field will contain the address of the record in the Browse. You can go ahead and use the address in your program.

If there is more than record showing in the Browse, then you need to click on the one that you are interested in. That will in turn align the undelying table to the record in question. In general, as you move around the Browse (highlighting different records in turn), the "record pointer" in the underlying table will move in sync. Whatever record you are on, the values from that record will be available to you in your code.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
On another point, you wrote:

I know it sounds stupid but I am a complete noob ,
And sorry again (if I am wasting your time)

No, no, no. There is nothing stupid about the question, and you are definitely not wasting our time. We all know that FoxPro can difficult for beginners. So never worry about asking what seems like an elementary question. We were all beginners once.

For the same reason, I suggest that you change your forum login name. Just because you are a beginner doesn't mean you are an idiot. In general, we prefer people to use their actual names here, so that we know how to address them and to keep things friendly. If you prefer to be anonymous, then you can use your initials or a nickname.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Dear All ,

Thank you for the response ,

I am very happy that you are so understanding ,

Although to my dismay and lack of energy ,
instead of a DB its a table , (sorry :'( )

Also another thing that the original programer builds all forms though code ... so I did the same(i don't know how much this will bite me on the bottom later .. )
so there are not real forms per-say

furthermore I am still a bit lost , and still quite confused ,

But but after reading several times your posts before posting ,
I used this
<db(table)>.<exe_no>(field) and this way I extract what the user selected ..

I would like to thank you both for all the help

I wish you to be safe and healthy in these difficult times

Thank you in advance

The Idiot :D



 
Hi, glad you got this.

Do you have SPR files or PRG? I think it would not differ anyway, but this sounds like you're dealing with a project that started as legacy FP 2.x project and was neither converted functional nor visual but was kept at screen code:
As you can see from the description of the two conversions offered by VFP none is really useful to get you started and thuis such projects usually are kept with the legacy screen logic.

Everything about workareas and access of fields still applies.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Dear Olaf Doschke , and all

yes I guess this was initially running on DOS(damn I am too young for this) .. I guess indeed the conversion was never done , not anyone bothered ( the dimensions when going higher resolutions is a pain ..)
funny thing runs without a hitch on win 10 .... ( tested it as much as I could)

the files are mix and match but in general mostly are .prg files

regarding work areas and access after a lot of googling I found out that you use the following structure for DBs or tables use:
USE <db .or. table>(1 time in a program or globally) EXCLUSIVELY
then select <db .or. table>
release <db .or. table>
and hope that the previous subroutine did not have any complicated DBs or Tables open (of course it sends an error and then you need to go down the rabbit hole of debugging ...

although I am intrigued to learn more, since I would need to do A LOT MORE ... since I've proven myself ... (haha joke's on me :D )
is there a good resource for beginners like a crash course ...

again thank you for all the help and guidance

Thank you in advance

The Idiot :D

 
EXCLUSIVE:
No, not if two users should be able to work on the data. Shared is the norm in runtime, exclusive in the IDE, as you more often need exclusive access to modify table structure or (re)index or zap (totally empty) or pack a table (remove rows marked deleted). So it's the developer mode. I personally made OFF the IDE setting, too. Because with it on it leads to writing code that only works in the IDE and not later at runtime, where you don't have that privilege anymore.

RELEASE:
No, this is for removing variables from memory, that's not for closing tables.


USE is both opening and closing a DBF file in a workarea. You can see that, if you USE two DBFs, the second USE closes the first one:

Open the data session window: SET.
Then
USE table1
USE table2

You end up with table2 opened.
USE
table2 is now closed. So you can even interpret USE as mainly meaning close whatever is open in a workarea. And then open something else, if something else is specified is secondary, not main feature. Well, of course it is, but you could always also use the visual data environment (DE) of a form and put your tables in there to have them opened. If you had forms and not screen code. Actually I prefer the code as it's clear in which order and makes everything else that could also be done in the visual DE clear to the reader including the order of processing.

For example, a script that USEs several tables sets up joins between them with SET RELATION and then opens up several BROWSE windows was a tool I used for a project manager to let him work on the data as directly as you can. But it's not really a fine UI for end-users.

And by the way, you open multiple tables via the special meaning of workarea 0. Unlike any other workarea number>0 it's not a specific workarea, just the next available unused workarea.
So you can either SELECT 0 and then USE some.dbf or you can USE some.dbf IN 0, then USE someother.dbf IN 0 and both are open.

The difference between these alternatives? If you USE something IN 0 it's opening in a workarea not used by something else before, but it doesn't become the actively selected workarea. If you SELECT 0 and USE a table you also have it selected already, as you actually select a workarea, not a dbf file. SELECT 0 already does SELECT a specific workarea and that stays the selected workarea no matter what you open in it.

Unless you SELECT something else.

It's still the only case where it's okay - in my opinion - to use a workarea number. You might find a lot of working in specific workarea numbers in your legacy code, as before VFP3 there only were 15 at max, so you organized and used them well, not randomly. The concept of names for workareas is much more convenient to write understandable somewhat self-documenting code, though, as you don't have to remember which number means which table. But be aware that you can only SELECT <db or table> as the automatic alias naming of workareas is to get the file name (without dbf extension) as workarea name. It's not the same, though!

Useful to know, too:
CLOSE TABLES ALL - closes all workareas
CLOSE DATABASES ALL - closes all DBCs and tables, too
CLEAR ALL - often thought of as an analogy of CLOSE TABLES ALL to memory variables, but indeed releases and closes a lot of things including all tables currently open.

So these create something like an empty tidy desk you can start from, again. You might find these nowhere in start code as that's the norm to start with anyway, but it's helpful if you're stuck in the IDE and want everything to go away and start fresh without exiting and restarting VFP.

Take it with a pinch of salt, though, as some helpful frameworks used for application development load themselves at VFP startup and establish some objects and hooks in memory that are removed by CLEAR ALL, too. But I don't think this affects you, your legacy project seems not to use any framework I think of. I don't even know a legacy application framework at all.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top