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

Complete Newbie - Please check a VFP expression for currency

Status
Not open for further replies.

Bollard04

Technical User
Dec 27, 2008
21
GB
Hello Guys,

I have absolutely no experience with VFP but am trying to edit some of our reports (ie invoices, quotations etc).

The expression i am looking at pulls a price from a table (as a number) and then converts (divides by 100) to a currency. I wanted to clean up the code (as to me it seems quite ridicolous) and change the formatting to add comma separation

The old expression was (i think - i cant copy and paste!):

p_oCallingObject.dispunit(.f.,p_oCallingObject.p_currncy,p_oCallingObject.w_fcrate, it_price,"",.t.,.f.,10,.f.,"",.t.)

This is what i cobbled together:

TRANSFORM(it_price/100, '$$$,$$$,$$$.$$')

I would love to know:
a) What exactly the old code is doing?
b) If there is anything wrong / could be improved in my attempt?

I would REALLY appreciate some help

Thank you
 
Nobody can tell you what the method being called is doing. It won't be doing anything if you don't call it.

Transform() creates a string from any other data type, adding formatting if desired. If that's the operation you need, then you've found your man.

I suspect you'll find you actually need whatever that method does or it likely wouldn't be there in the first place.
 
Techically p_oCallingObject.dispunit(...) is calling a method dispunit of the p_oCallingObject object. Without that code it's impossible to tell what this did.

No idea. At least neither p_oCallingObject is a native system object of foxpro, nor is there a dispunit method or function. From the name alone I can only guess it's displaying a unit of something, maybe an all purpose display/string format function.

If you don't understand it you could simply add a breakpoint at the line (simply click at the left border before the line) and see where the debugger leads you, if you single step into the code.

Your transform is fine for transforming a value to a currency display, but if it_price is a currency field you would not divide by 100, it seems to be a int of Cents or Pence or such.

Copy & Paste: Select some code (hold down left mouse button and move the mouse), tehn right click the mouse, choose Copy, right click somewhere else, eg the Message textarea here at Tek-Tips, and choose Paste. You can do the same with keyboard: select with holding down shift while using arrow keys, copy with CTRL+C, paste with CTRL+V.

Bye, Olaf.
 
Thank you for the response.

Is there any way i can find where the method (im guessing thats dispunit?) is defined?

I see what you are saying, but the old expression certainly seems very over the top wouldnt you agree? I would really like to understand and improve it
 
It's only over the top if it doesn't do the job it needs to do, and you haven't defined that.

The code is going to be inside the class definition for whatever was instantiated as the object p_oCallingObject.

Now, going just on the name (and it appears to follow a defined naming convention), I'd guess that the object reference itself is getting passed as a parameter so there may be entirely different objects (and different code) at different times.

You may be messing with some pretty complex stuff. I'd suggest you study on it a bit before messing with it.

Simplifying things is good, but not when it means breaking things.
 
@OlafDoschke - Sorry i didnt see your reply before i posted. Thank you for the help.

Im editing the code within our ERP system (which to my knowledge, i cant introduce break points / debugg / copy or paste), should i be using some Visual Fox Pro Studio of some sorts?

What do you mean about it_price being a currency (which it is) and not dividing by 100? One cent / pence is 100th of a dollar / pound (which is how i want it displayed, no?)

@danfreeman - I agree and i may have to end up going back to the original developer. However, the existing code doesnt align properly, doesnt insert commas to separate large numbers, nor does it add currency symbols - all things i would like.

Do you know how i would go about finding the class definition? Once again, do i need to be using some sort of VFP IDE?

Thank you again for the reponses - i really appreciate the help
 
Im editing the code within our ERP system (which to my knowledge, i cant introduce break points / debugg / copy or paste), should i be using some Visual Fox Pro Studio of some sorts?


Yes in order to actually EDIT any VFP code and re-compile the results, you need to be using Visual Foxpro. It helps to have the same version which was used on your application, but typically later versions will work on applications developed under earlier versions.

With a copy of VFP, you can use the TRACE and DEBUG windows along with Breakpoints to examine how your code operates.

Do you know how i would go about finding the class definition?

You could try to use the Windows Search to see if you could find the text "dispunit" within any of the source code files. It should find all instances where that method is called, but it also might (or might not) find where that method is defined.

I agree and i may have to end up going back to the original developer.

Often it is quite a bit quicker to do just that. Plus it sounds as though there are a number of issues to be addressed and they should be able to resolve them most expeditiously.

Plus there is sometimes the question of legality involved.
Did you purchase a commercial software package which a developer was selling or did you have custom software developed specifically for you?
In one case you do not own the source code so changes would be 'illegal', in the other case you most likely will own the source code (although sometimes not).

Good Luck,
JRB-Bldr
 
Thanks for the help jrbbldr

Ive opened the FRX file with VFP 9 and it looks pretty much the same as from within the ERP (guess it has VFP editor inbuilt) - but i still cant find a way to look at the source code and find these class definitions? Am i looking at the right file (i have an FRT and an FRX)?

The software is commerical, which an authorised distributor then produced custom reports (using VFP) which is what im trying to edit

Cheers
 
but i still cant find a way to look at the source code and find these class definitions?

You may indeed be able to look into the Report Forms (FRX/FRT files), but the class or other objects which are referenced will not be resident there.

The software is commercial, which an authorized distributor then produced custom reports (using VFP) which is what I'm trying to edit

That means that it is unlikely that you will have the source code available at all to even look at, let alone modify. And that 'other' code is where the classes and/or other objects will reside.

The application being a commercial product introduces the legality issue into the equation. Yes the authorized distributor may be authorized to create custom reports using the existing classes, etc. which are resident within the application, but even they are not generally allowed to make changes to the classes themselves.

If you REALLY want to make the changes to the Report Form yourself, then you need to get the authorized distributor to provide you with FULL documentation on the various classes, etc. available to use (as is) within the application. And, with that info, you can introduce your own changes to the Report Forms only.

If you were to choose to go that route, you might want to familiarize yourself with the VFP commands & functions which could be used within the Report Form object expressions.
Some references might include:
or just do a Google search for VFP Commands Functions

But if you want to most expeditious resolution to your various issues, I'd recommend just having the authorized distributor do it for you.

Good Luck,
JRB-Bldr
 
I think we're making this much more complicated than it is.

Bollard04: If your aim is to right-align the amount, add a currency symbol, and add commas between thousands, then you're already there.

You say you used this code:

TRANSFORM(it_price/100, '$$$,$$$,$$$.$$')

As far as I can see, that should do what you want. In what way doesn't it work?

Whether or not you need to divide by 100 depends on how the amount is stored. You will see immediately if it's wrong because the amount will be 1/100th of what it should be. If that's the case, just remove the "/100".

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Perhaps Mike is correct (he really is that quite often!!!).

If all you really want to do is to change how the data appears on the single custom Report, then you can merely change the Expression in the appropriate Report Form text object Expression.

One thing I am not sure of is what is the TYPE of the value returned by the existing expression?
p_oCallingObject.dispunit(.f.,p_oCallingObject.p_currncy,p_oCallingObject.w_fcrate, it_price,"",.t.,.f.,10,.f.,"",.t.)

If the whole method call is within the Report Form text box expression as I assume from what you say above, then it is returning a single value based on the various specific parameters passed to the method.
That returned value may be IT_Price or it may be something else - we cannot tell for certain by the code above.

And we do not know what the TYPE of that returned value might be - a Numeric value or a Character value?

If the value is not known to be IT_Price and it were Numeric, then I would would just 'wrap' the whole expression within the TRANSFORM() function somewhat like suggested above and then put it all within an ALLTRIM() function to eliminate extra spaces....
"$" + ALLTRIM(TRANSFORM(p_oCallingObject.dispunit(.f.,p_oCallingObject.p_currncy,p_oCallingObject.w_fcrate, it_price,"",.t.,.f.,10,.f.,"",.t.),"999,999,999.99"))

But if the value returned was a Character value then you would need to handle it differently.

Good Luck,
JRB-Bldr
 
What do you mean about it_price being a currency (which it is) and not dividing by 100? One cent / pence is 100th of a dollar / pound (which is how i want it displayed, no?)

I don't know about you, but when I have a currency value of $95.00, I want it to display as $95.00 instead of $.9500 which is what divide-by-100 would give.

If this is a currency (as in the data type currency) value, you may not need the math. If it's something you're *calling* currency but it's actually stored in a character field, then divide by 100 is senseless anyway because you'll beget a data type mismatch error.

Since you're working with output fields in a report, is there a reason you haven't double-clicked the field and ticked the currency box in the formatting dialog?

It may sound like we're trying to confuse you, but there really are a bazillion options here and it may take some honing to find out what works best in your case.
 
Thank you for all your help - i really do appreciate it.

@MikeLewis - The problem with the code i had is that it doesnt always produce the right values when testing with old reports.

VERY oddly it seems as though the value it_value stores a price in cents (i.e. when the currency being quoted in is in USD, i need to divide by 100) but in 1/10th penny when quoting in GBP (ie i need to divide by 1000 to get to pounds).

I have no idea why on earth this would be, but it explains why some reports were printing correctly but some were out by odd factors. Also, you can see in the original code p_oCallingObject.p_currncy which looks like it checks the currency, im assuming to get this conversion correct.

@jrbbldr - Im getting in contact with the software developer we used and am asking the cost for them to complete this change.

I like your idea of simply wrapping the expression in TRANSFORM and ALLTRIM.I tried the code you provided, on clicking "verify" i get "invalid subscript reference" and when i run the report it prints something like ", 39.99" ie not right! Im guessing it may be to do with the data type that you hinted at. Could you elaborate about "handling it differently" as a character?

@danfreeman - See above about how the values are stored. Im not sure of the datatype (if its currency / character / numeric etc). I tried ticking Currency, but still have ", 39.99" when using the above code.

Thank you again for all your help. I really appreciate it
 
Could you elaborate about "handling it differently" as a character?

First, I hope you have made a copy of your original FRX & FRT files before you began introducing changes. If not, hopefully you have been making good backups so that if you need to restore things you can.

Regardless, here is another thing you could try to identify the value type that is returned by the method. In the Report Form text box expression change it to:

TYPE('p_oCallingObject.dispunit(.f.,p_oCallingObject.p_currncy,p_oCallingObject.w_fcrate, it_price,"",.t.,.f.,10,.f.,"",.t.)')

I can't guarantee that it will work, but the simplistic testing I did here suggests that the above will return either a 'C' for a Character type or an 'N' for a Numeric value or an "I" for an Integer value (also considered a Numeric). That returned value should appear in the associated Report Form text box when the report is run.

If it does work, then you will KNOW the TYPE of the value returned by your method call.

As indicated above, if it is a Numeric then the above suggestions should work. Perhaps we have small typos in our suggestions which are throwing the result off slightly, but in general it should work.

If the returned value is a Character string, then it will need to get converted into the format you desire.
You could first convert it to a numeric with VALUE() and then utilize the TRANSFORM() on it all within a single line of code - albeit a LONG one.

Something like:
TRANSFORM(VALUE(<method call goes here>),'$$$,$$$,$$$.$$'))

Lastly I'd suggest making another modification to the test copy of your Report Form for TESTING PURPOSES ONLY.
Add a new text box object to display just the IT_PRICE value with no modifications. Then compare its value to the value returned by the Method call. If they are different, then you should not try to over-simplify the original expression by using IT_Price. Instead use the entire Method call which will result in the correct value.

Good Luck,
JRB-Bldr






 
Thanks for the continued support - i appreciate you all bearing with me!

@jrbbldr - I used your code (and have backups!) and oddly it returned "U"?! What datatype is that?!

As i said above, i can look into the data environment and locate the value of it_price which is not the same as the value returned by the method call (different by a factor of 100 or 1000 dependant on currency)

I look forward to your response.

Thank you again
 
The TYPE "U" is Unknown.

I cannot say for certain, but in my simplistic testing I found that if the data were formatted such as TYPE('999,999.99') the result that I got was a "U"

NOTE - locating the value of IT_Price in the data environment (somewhere in the data table) is not necessarily the same as having that specific value returned from the Method.

But, based on the results that you got, I am guessing that the Method is locating the specific IT_Price and then, for USD it is calculating (IT_Price/100) and returning the result in a formatted Character string.

If that is correct, you could try the following:
TRANSFORM(VALUE(STRTRAN(<method>,',','')),'999,999,999.99')

Where the STRTRAN() function would remove all commas from the returned Character string value.
Then the VALUE() function would convert the string value to a Numeric value.
And finally the TRANSFORM() function would format it the way you wanted.

Give that a try.

Good Luck,
JRB-Bldr


 
PERFECT! (Well nearly!)

Thank you jrbbldr. I have ended up with:

ALLTRIM(TRANSFORM(VAL(STRTRAN(<method>,',','')),'999,999,999.99'))

Note: VALUE() was throwing an error, but googling around i found VAL() which works

The only issue is now, where before if i had inserted a blank line for spacing in a report, the previous code would stay blank, now i have 0.00

I have tried ticking "Blank if zero" but that makes no difference.

Any ideas?

Thank you again so much!
 
Use the Print When... for the text box which is displaying the 0.00

In the Print When... Expression put something like:
!EMPTY(<whatever>)

Note - the leading exclamation mark '!' means 'NOT'.

That will cause the text box to 'print' its value ONLY when the <whatever> value is NOT EMPTY (for Characters that is '' and for Numerics that is 0)

Also note that the controlling variable for the Print When expression does not necessarily need to be the value printed, it can also be some other value from the Report Form's control table/cursor such as maybe the Item_No for the specific 'blank' record.

Good Luck,
JRB-Bldr
 
others have already answered for me. Also you say yourself:

VERY oddly it seems as though the value it_value stores a price in cents (i.e. when the currency being quoted in is in USD, i need to divide by 100) but in 1/10th penny when quoting in GBP (ie i need to divide by 1000 to get to pounds).

I have no idea why on earth this would be, but it explains why some reports were printing correctly but some were out by odd factors. Also, you can see in the original code p_oCallingObject.p_currncy which looks like it checks the currency, im assuming to get this conversion correct.

So it seems you better not fiddle to much and replace this by a simpler method, as this object seems to encapsulate the knowlegde about which factor is needed in case of which currency and other influnces.

If you only have the reports at hand you don't have source code, reports are merely definitions of what is printed where, you have very limited capabilities to call functions or methods from within the expressions of report fields and no breakpoints there. I thought you were talking about a prg or other code prerunning to the reports.

You don't have many options in your situations, especially if there is no documentation of the p_oCallingObject object and what it does. As your application does offer you to create and modify reports there should be documentation available of what this object is and offers for you. I can only say it's no native foxpro object, it's very specific to your application and nobody can help you with it but the original developer.

Bye, Olaf.
 
Regarding the "blank when zero" issue, JRB wrote:

[blue]In the Print When... Expression put something like:
!EMPTY(<whatever>)[/blue]

I don't think that will work in this case. Because the expression has been converted to a string, it will appear as "0.00", which is not empty.

So I think the Print When expression needs to be something like:

<whatever> <> "0.00" AND !EMPTY(<whatever>)


Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top