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

Someone please explain me the flow of this code. 4

Status
Not open for further replies.

janak vyas

Technical User
Jun 3, 2020
47
IN


Code:
CREATE CURSOR tmp (RD N(18))
INDEX ON RD TAG MAIN CANDIDATE
SET ORDER TO

RAND(-1)
LOCAL i, j
j = 29
ON ERROR ErrHand(@j)

FOR i = 1 TO 30 && Just do 100k for now
  INSERT INTO tmp (RD) VALUES (RAND()*j+1)
NEXT
ON ERROR

PROCEDURE ErrHand(j)
if j>=30

else
  j=j*1.05
endif  
RETRY
ENDPROC


what does this procedure does ? How is the loop working ? what role does CANDIDATE has? What does TAG does ?
 
No, for this to make sense as knowledgebase in the long term, we can't now go into "private mode". Because, notice, attachments are not stored forever, posted code is.

Please post problematic portions of your code and errors you encounter. Also notice your setting up of an error handler will keep VFP silent about ANY other errors, so better not use your own version of computing random number with RETRY. Just don't. You'll not get messages about errors and the handler will RETRY any line of code causing an error, which usually will cause an endless loop and render VFP unusable. This can only work, when you know the code actually is okay and like in the case of that INSERT of random numbers will eventually work, with another RAND() number.

Usual code does not differ in the next execution, it will not depend on random numbers or time, so it will error again. That's illustrating the importance of Mike's last post.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Well any ways, the things is I am just lost I know it's all concepts that i am missing in my program, but I am just giving up. With no technical guidance and no thought given into the engineering of this program, I am going no way.

Janek, if you are saying that you are planning to give up the whole application, I would be very sorry to hear that. You and your uncle have put a lot of effort into this project, and it would be a great shame not to see it through.

Could it be the application that you inherited was simply too ambitious for your level of knowledge? Would it be worth stepping back from it, and spending a little time learning the fundamentals of VFP. There are plenty of resources available to help with that.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Maybe this will help:

The functions I have designed are not to be called once to generate aq group of n records up to a max range.
So just run the code of my previous post and see what you get there.

You make ONE call and get 5 numbers. Shouldn't this clear up what the parameters mean?

In the first parameter you pass in the array the function should populate, in the second parameter you specify how many different numbers you want, and in contrast to a normal random number generated they will guaranteed to be different, non repeating. But this can also only be assured, because they are not generated separately, one per call, but all numbers are generated in a single call. That, by the way, was also done by your own function.

Thinking of a function generating 5 values, in each in 5 calls without being signalled when to start the series isn't possible, I already told you that, and that's not a question of the programming language.

Now, since VFP can't RETURN r1,r2,r3,r4,r5, as Python could, the only way to return 5 values at once is using a cursor or array. Your function used a cursor, my last one now uses an array.

So the loop determining 5 field names should be like this:

Code:
Local array laRandnumbers[5]
Local lnCounter

Randomize3(@laRandnumbers,5,30)
SELECT yourtable
For lnCounter = 1 to 5
   ? FIELD( laRandnumbers[lnCounter])
EndFor

And again, and I already repeatedly said so, when your 30 fields don't start at field number 1, then add an offset to this. I remember you have tow fields before you series of 30 or 31 fields, so add an offset of 2 to skip those two fields not belonging to the "calender" columns.

Code:
Local array laRandnumbers[5]
Local lnCounter, lnHowManyDifferentNumbers, lnNumberRandeFrom1ToThis
lnHowManyDifferentNumbers = 5
lnNumberRandeFrom1ToThis = 30

Randomize3(@laRandnumbers, lnHowManyDifferentNumbers ,lnNumberRandeFrom1ToThis )
Local lnFieldNumberOffset
lnFieldNumberOffset = 2 && add to all laRandnumbers elements to shift the range from 1...lnNumberRandeFrom1ToThis to 1+lnFieldNumberOffset...lnNumberRandeFrom1ToThis+lnFieldNumberOffset
* for example to change from 1...30 to 3..32 add 2

SELECT yourtable
For lnCounter = 1 to lnHowManyDifferentNumbers
   lnFieldnumber = laRandnumbers[lnCounter] + lnFieldNumberOffset
   ? FIELD(lnFieldnumber)
EndFor

I can't give you exactly what you need, for example, whether you want to cover the range 1..30 or whether that will depend on the number of days the current month has, that's up to you. But it's all adjustable.

Bye, Olsf.

Olaf Doschke Software Engineering
 
It surely did !!!

I simply have no words.. the explanation of what does what helped me to understand more and having that "lnFieldNumberOffset" was icing on the cake !
I had given up but not my uncle, he is stubborn in making things to work and I think that is the attitude needed because of which things have worked since 1995.

Well, a milestone in this program is reached and I whole heartedly thank Olaf and Mike for this. You guys are a blessing!

I continue with the program for new featured to be added..
 
result_zfoaqg.png


This is the result what we were working for.
According to the red marked circle we wanted to allot 'A' that much times.

and that's what we achieved with the help of you guys.

What we now are trying to figure out is, to allot 'P' on the basis of the blue marked field.
for that I searched around if I could find something and I got Olaf's answer on some previous threads
Code:
select 0
use mytable in 0 exclusive
if type("mytable.mynewfield") # cTypeexpected
   alter table mytable add mynewfield ...
endif

where to check if a specific field is empty, if not replace it with a 'P'.

I do not know if this approach is correct or not plus
Code:
 # cTypeexpected
seems to give an error that cTypeexpected is not found. I know it is just a placeholder for me to write according to my needs, but I am not able to figure out it.
Any help ?
 
The [tt]#[/tt] simply means "not equal to". It is another way of writing [tt]<>[/tt].

The TYPE() function returns the data type of the specified field (in this case, mynewfield in mytable). It returns a letter to indicate the type, such as C for character or D for date.

So you are comparing the type of the field with the letter stored in the variable, cTypeexpected, whatever that is. If it is not the same as that letter, you are adding the field to the table.

So that's what the code does. But, as before, you have to think about why you want to do it. I'm not aware of where you found this code, so I can't really comment on that.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Okay... so it checks the type of that field. I get it now.

What if I wanted If the specified field is empty or not ?
if it is replace it with something.

Is !empty would work ?
 
Code:
LOCAL Absentornot
Absentornot = 'A'
if field("ATTEST.D1") = Absentornot
  MESSAGEBOX('Contains')
ELSE
MESSAGEbox('Is empty ')
endif

I tried this and it seems to work but it shows "Is empty" even if the field contains an "A" .
Why is this happening ?
 
Code:
if  D1#'A'
REPLACE   d1  WITH 'P'
endif

This is working for me.
Code:
if  D2#'A'
REPLACE   d2  WITH 'P'
endif

But what if there is no field 'D2' it would throw an error, how to find it there is a field D2, and if there is then only replace.
 
How can this be possible, to check if from field number 3 to whatever field I want to replace all the empty records with 'P' !?
 
The FIELDS() function gives you a field name by field number, not a field number by field name.

The way you use the field function would determine if the D1 field is present at all in the DBF, you only get the input returned as output, if the field of the given name exists. This isn't ADODB.Recordsetfiel("name).value.

In no way will you get tat a field value with the field function, you a) get name of a column number by FIELD(1), for example and b) empty value for FIELD('dfhkjhdfkjdfs'( will just tell you that a field dfhkjhdfkjdfs doesn't exist, as that returns empty.

To get at the field value as you know you can write [tt]IF D2#'A'[/tt] or [tt]IF NOT EMPTY(D2)[/tt] or such, but that's not applicable to FIELD(x) no matter whether x is number or name. Use EVAL(FIELD(x)) to get the value of the field name.

Code:
? FIELD('D2')
? EVAL(FIELD('D2'))
? D2

See? The first call just gives back D2 again, output=input. FIELD is never giving you values of fields, it gives you field names only, no matter how you call it.
The last line shows you how easy it is to access fields simply by their name when you already know which name you want to address. Your situation is, that you need to be able to address a field by number, so there's a need to go the route EVAL(FIELD(randomnumber+2)), for example.

Bye, Olaf.

Olaf Doschke Software Engineering
 

Can you replradse the question, please?

As far as I understood you wanted to prevent random field numbers o address the same field twice, Randomize already guarantees you get 5 different random numbers. You don't need to check this now anymore. The Randomize function already solves that there will be no same field number twice.

You only need to ensure the records you process start out empty, then the loop over the laRandnumbers array you get from randomize already ensures you address 5 different fields.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Code:
if type("mytable.mynewfield") # cTypeexpected
   alter table mytable add mynewfield ...
endif

I recommend you don't do such table alterations in the regular process itself.
Keep database changes as administrative separate tasks, ensure your databases are in the structure needed for your software version and then process the datqa inside.

This is mixing up regular processing and administrative database upgrading.

I would also leave out any code checking for a field to exist despite the unusual situation of a software release prereleased to a database update, that can start working once the update exists, but even then ideally you'd just need to heck one database version number stored somewhere in one table of it, for example.

It's all very over the top terminology, if your database is a bunch of DBF files and your software consists of single scripts, but this still applies. The need for exclusive access then also disappears at runtime of the software, only the scripts concerned with the database structure expansion are eating with checking the existence of fields or not. And you can even spare that yourself, if you already know which alter table scripts you ran and which not. You're overcomplicating things here by wanting to do everything at once and ensure things work or mend themselves as necessary, that's a strategy leading to maintainable unclean code.

Software version X having a SELECT a,b,c from D has to be able to rely on table D existing and having fields a,b,c or your code will never get to the point of really acting.

Bye, Olaf.

Olaf Doschke Software Engineering
 
3234CA73-BBAE-43C9-8721-652DF7FFCF12_my6ob7.png


Have a look at this image.
What I am trying to achieve is that the empty records that Are left, I want them to be replaced by ‘P’.
 
The value in Present is the number of the field, the day number? This isn't self-explanatory.

If so, use it as the field number instead of the random value, the rest of the REPLACE command stays the same, doesn't it? The only thing that changes is where the number of the day comes from, isn´t it?

Olaf.

Olaf Doschke Software Engineering
 
I don't know what exactly you want, please rephrase your question, you really don't make it understandable what exactly you want. What does the blue outlined column has to do with it?

If I try to make sense of "empty records that Are left," and replace "records" with "fields". Then the simplest solution would be to start by setting all fields to 'P' before changing some to 'A', wouldn't it?

If you don't like that this puts them to the wrong letter temporarily, well, you initiate all fields empty, that's also a wrong value, isn't it? So that's not the problem as long as out end result gets right, or is it?
Why make it hard on you, just initialize all with P and you don't need to care, the non flipped fields will stay P and all D1-D30 are set.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Okay, another of my famous triple posts. Just look at the length of this thread and realize how you actually introduce the main problem of handling your data by wanting this structure of 30 fields.

One rule of data normalization is to avoid such data "arrays" inside a record. Just let that sink in and you may find much simpler ways that won't depend on field numbers to set fields. Look back to what Mike and I initially recommended as data structures in thread184-1803937.

You do repeat employee ids, yes, but you then would have combinations of employee_id, date and type (A for Ad, P for Present) and ensure you don't store double information about a date by a candidate index you do on both employeeid and date field, for example. A database only gives you tools to look at multiple rows of the same table for restricting them, or counting them, like such indexes, COUNT(), SUM(), AVG() etc. You don't have such functions for columns of a row. So you always struggle with such structures.

If you design them for easier display, that programming by wrong virtues. A visual representation of data can differ from the storage of it and usually will, the concerns for data storage are wildly different and your mental idea, human readablity or such have nothing to do with that. They are a separate issue when going for display or report of data.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top