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

array reference treated as program call -- but only in exe version 3

Status
Not open for further replies.

CJMK

Programmer
Jul 2, 2014
30
US
Code below
The procedure is in a proc library, and has run fine for 15 years or more. It gets a filedate and time from an ADIR array from which it creates timestamps of various sorts.

The opperant code is
m.timestamp = DTOC(downloaded(1,3)) + downloaded(1,4)

Running the exe directly, or doing the install on my own machine there is no problem.
But I get a file not found error when it runs in the executable installed on another machine
I realize I can probably get the job done using fdate and ftime, but am worried that something will go wrong with another array sometime. Its is not a constant issue. I created a test array reference earlier in the program, and that ran ok. But I am wondering. In another case, I might not have a good way around using the array.

The installer was created with inno setup

PROCEDURE datatime
&& Provides a timestamp tag for export filenames
&& to indicate the time the data was obtained.

PARAMETERS filespec

filespec = IIF(EMPTY(filespec),ALIAS() + ".dbf",filespec)

curdateset = SET("Date")
curcenturyset = SET("Century")

dnlddata = ADIR(downloaded,filespec)

SET DATE YMD
SET CENTURY on

m.timestamp = DTOC(downloaded(1,3)) + downloaded(1,4)

SET DATE (curdateset)
SET CENTURY &curcenturyset

m.timenote = DTOC(downloaded(1,3)) + " at " + downloaded(1,4)
m.datatime = CTOT(DTOC(downloaded(1,3)) + " " + downloaded(1,4) )

m.timestamp = STRTRAN(m.timestamp,":","")
m.timestamp = STRTRAN(m.timestamp,"-","")
m.timestamp = STRTRAN(m.timestamp,"/","")
m.timestamp = STRTRAN(m.timestamp,".","")
m.timestamp = STRTRAN(m.timestamp," ","")

IF file("datadate.dbf")
SELECT 0
USE datadate

ELSE
CREATE TABLE datadate (timestamp c(12),datadate c(30),datatime t)
ENDIF

REPLACE timestamp WITH m.timestamp
REPLACE datadate WITH m.timenote
replace datatime WITH m.datatime

USE IN datadate

RETURN
 
I thnk the problem is with this line:

[tt]dnlddata = ADIR(downloaded,filespec)[/tt]

If the filespec is not found, then the array will not be created. When that happens, any line containing a reference to the array will cause an error.

The solution is to test for [tt]dnlddata = 0[/tt]. If that's true, don't proceed with the rest of the code (use a default value, or whatever makes sense in your application).

I'd also question the use of Datetime() as a procedure name, since that it is a keyword in VFP. In this case, it won't do any harm, but it would be good practice to avoid it.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I second mike,

ALIS()+".dbf" will not always be the DBF file, only if you restrict yourself to the norm of opening DBFs as their table name.

Cursors or Views don't fit that scheme, but the solution is simple, you have the DBF() function for that:

Code:
PARAMETERS filespec

filespec = IIF(EMPTY(filespec),DBF(),filespec)

Besides that, when filespec is poassed in, you rely on it to be a file name, you should also double check after doing [tt]dnlddata = ADIR(downloaded,filespec)[/tt], that dnlddata >0.

Just by the way: This also regularly is a problem of the compiler figuring out whether you mean array elements of function calls (ultimately some PRG file). It does neither help the compiler nor the runtime to distinguish arrays from function calls using round and square brackets, but it helps a developer seeing what you mean. It's less known, but also function calls can be made with square brackets, eg ? STR[42], so you always have that ambiguity just like you have the ambiguity of names being constant names, field names, constant names or even alias or file names. You always better be precise in what you mean and yes, that can mean such an error only hits you after many years. Happened to me not knowing about filter cursors.

Bye, Olaf.

Olaf Doschke Software Engineering
 
... besides you could use EVL() and PCOUNT() and besides filespec still could be empty when this is called with no parameter and no active workarea. After SELECT 0 both ALIAS() and DBF() give you empty results but ADIR(arrayname,'') results in 0, which comes to your rescue again, if you only act when dnlddata >0.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Finally, a suspicion: This is used to scan through some downloaded files, eg after an FTP routine gets some affiliate data? Don't know, but you might lately have file names with spaces in them, using them you get underlines in the ALIAS() name. So even for a simple USE (dbffile) you can't rely on ALIAS()==JUSTSTEM(DBF(). Use the DBF() function to determine the file name behind a workarea. That's not a new function, either.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Good points all
I will implement and let you know the results
However, the name is DATATIME NOT DATETIME (referring to the time the data was downloaded from another system. It appears on any report so the viewer knows when the source was tapped.

The file does exist, as the form cannot run without it. and if I just ignore the error, the system seems to work fine. Just can't ask a user to put up with the fuss.
Now you have me thinking better, I will check path issues, which may not have been set yet.
 
the name is DATATIME NOT DATETIME

Ok. My mistake.

if I just ignore the error, the system seems to work fine.

That might be OK when you are running it in the development environment. But it is a bad idea to let the end user ignore an error. The fact that an error has been triggered means that there is something wrong in the environment, and you should not allow the execution to continue*. Better to have an error-handler which logs the error, gives the user a friendly message, and closes the application.

(* There are one or two exceptions to this, such as disk full, no printer installed, no permission to write to a certain drive, and a few other issues that are within the user's control. But they are an exception.)

Mike
__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thanks loads. Yes, never let an error be ignored and continue -- but am still in development. As usual finding the answer, while necessary, was not the big benefit of learning more searching for it. The path setting was not the same in the exe environment -- my error. Along with not having written the routine to notify me directly if the file was absent. The silent 'file not found' bit me.
 
Glad this was useful, CJMK.

Before we leave this thread, could I make a suggestion.

When you post a lengthy piece of code (as in your first post in this thread), you should wrap the code in [ignore]
Code:
 ...
[/ignore] tags. That way it will all be properly indended and aligned, and the "small" characters like dots and commas will be more visible.

You can either type the above tags manually, or highlight the code and click on the "Code" button in the toolbar.

Just a suggestion.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
>The silent 'file not found' bit me.

Well, you used ADIR, that has no error happening for "file (skeleton) not found", but it has a very obvious and "loud" result number of 0, if no file matches the file skeleton and then the array isn't generated. And when no array downloaded exists downloaded(1,3) is interpreted as a call to a function/procedure named downloaded or downloaded.prg with parameters 1 and 3. The thing to always evaluate and rect to is the count of elements if its 0 no array exists.

Bye, Olaf.

Olaf Doschke Software Engineering
 
As I said elsewhere and many other times, the real value in solving these problems is the associated learning. You guys are great teachers. NO array of mine will fail to get checked again.
 
Fine, thank you.

If I get on your nerves simply skip this. But another thing to make this complete: Foxpro also has an error for addressing a non-existing array element, simply test this:

Code:
Dimension test[2]
? test[1]
? test[2]
? test[3]

Memorize the term "Subscript", this only refers to array element indexes. Also, notice arrays are 1-based in VFP and initially all elements are .F. just like all variables are initialized with .F..

So if array exists, that's smaller than expected, you get such an error, but not when it doesn't exist at all and there is no way to have a zero sized array.

But ADIR won't release a preexisting array when it has no results, it will redimension it, but only if it has a result.
So another way to ensure you always have an array element downloaded[1,3] would be dimensioning an array before calling ADIR and initializing it with dummy values that later hint on file not found:

Code:
Dimension downloaded[1,5]
downloaded[1,1]=""
downloaded[1,2]=-1
downloaded[1,3]=CTOD('')
downloaded[1,4]="24:00:00"
downloaded[1,5]="%"

dnlddata = ADIR(downloaded,"nonsense dfjkldsjlfj.dbf")

Now downloaded(1,3) always will exist, in case nothing is found the hint is this is predefined as empty date, something no real file would have, besides of course an empty file name or size<0 or time 24:00:00 or a file attribute "%". So all these values can't come from a real file.

Aside from that, it should always be possible to exit before executing further code depending on the existence of some array elements simply with
Code:
IF dnlddata=0 
   RETURN 
ENDIF

You might live by rules such as having no RETURN somewhere in the middle of some code, then you'll need to nest the rest of code in [tt]IF dnlddata>0[/tt], of course. Too many nesting levels can make the code as unreadable as too many exit points before the usual at the end.

Anyway, while it's more cumbersome if you have a lot of code and that even depends on a PUBLIC or PRIVATE array and it's tedious to change all that code a strategy of predefining values can be far less work than to change all preexisting code.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top