tags:

views:

698

answers:

4

Hi all,

Having an issue with type conversion in ASP classic.

heres my code:

     Set trainingCost = Server.CreateObject("ADODB.Recordset")
 strSQL3 = "SELECT cost1 FROM tblMain WHERE (Booked = 'Booked') AND (Paid IS NULL) AND (PaidDate BETWEEN '01/04/" & startyear & "' AND '31/03/" & endyear & "')"
 trainingCost.Open strSQL3, Connection
 trainingCost.movefirst
 totalTrainCost = 0
 do while not trainingCost.eof
  trainCost = trainingCost("cost1")
  If NOT isNull(trainCost) then
   trainCostStr = CStr(trainCost)
   trainCostStr = Replace(trainCostStr, "£", "")
   trainCostStr = Replace(trainCostStr, ",", "")
   totalTrainCost = totalTrainCost + CInt(trainCostStr)
  end if
  trainingCost.movenext
 loop 

 trainingCost.close

when I run this I get the following error:

Microsoft VBScript runtime (0x800A000D) Type mismatch: 'CInt' /systems/RFT/v1.2/Extract.asp, line 43

which is "totalTrainCost = totalTrainCost + CInt(trainCostStr)"

Im guessing that the problem is to do with the String value being uncastable to Int in which case is there any way to catch this error? I havent worked with asp classic much so any help would be usefull

cheers

-EDIT-

the type of column cost1 is String as it may contain a number or a sequence of chars eg £10.00 or TBC

A: 

Heh heh. Classic ASP. You have my pity :) Anyway,

On error resume next

And then on the next line, check that it worked.

Though maybe you want CDouble. Is that a function? I can't remember.

Noon Silk
I would argue that it's a really bad idea to just swallow and ignore all exceptions. You're better to prevent the exception from coming up in the first place.
Phil.Wheeler
There are still developers working on it ;-) I am one too
Shoban
Yes phil, that's pretty obvious; but I am showing how you can _detect_ an error, as asked. I quote 'is there any way to catch this error'. Please read the question before downvoting.
Noon Silk
-1. On Error Resume Next is a last resort, that shouldn't be needed in this case. Even if it were you should detail how to use it safely.
AnthonyWJones
Yes, Anthony, I agree. Please see the response above yours. It's in response to his question.
Noon Silk
Easy tiger! I didn't downvote you, I just commented. Anyone else want to own up?
Phil.Wheeler
Haha, Okay, all cool, we're all friends here ... *backs away from the keyboard*
Noon Silk
@Silky, a) I can see you are trying to answer the specific question however its not good advice. b) Good answers do not always answer the specific question but lead to better practices altogether. Storing currency values as strings in the DB is the real root of the problem.
AnthonyWJones
@Anthony, while true, the 'real' root of the problem is also using ASP. Anyway, this argument is subjective; but I'd suggest that downvoting someone for providing an answer to an asked question is odd. Regardless; each to his own. It's a free world, for the most part :)
Noon Silk
Guys, weather its good practice or not dosnt matter. In certain cases (like this one) we dont get to choose what type of DB structure we have, yes I agree that this may seem like a needless problem, but this is a legacy system which is now unchangeable. so take a chill pill dudes
Jambobond
+2  A: 

Rather than casting to a string, why not use CCur (Cast as Currency) so that your commas and any currency symbols (I think) are effectively ignored while doing arithmetic operations?

Phil.Wheeler
Note that VBScript is quite happy converting numerical strings containing . and , and even prefixed currencty symbols to Int using CInt.
AnthonyWJones
+1  A: 

Potentially solving the wrong problem, depends on the type of Cost1 within the database but the code is looping through the records to generate a total.

strSQL3 = "SELECT sum(cost1) FROM tblMain WHERE (Booked = 'Booked') AND (Paid IS NULL) AND (PaidDate BETWEEN '01/04/" & startyear & "' AND '31/03/" & endyear & "')"        
trainingCost.Open strSQL3, Connection

etc and just read off the value as a total.

I don't see why the RS is being looped to generate a sum when the database can do that work for you. All the conversion work it has generated just looks artifical.

Andrew
This is actually a good point. You could even go one step further and ask, "Wouldn't it be better to place this in a stored procedure and call that rather than having inline SQL?".
Phil.Wheeler
Yes, and avoid potentially dodgy string concatenation allowing SQL injection, I nearly added a comment to that effect before.
Andrew
the column is not of numeric type, its a string. dont ask me why its a legacy project.
Jambobond
+2  A: 

You have a couple of choices. You can be proactive by checking ahead of time whether the value is numeric using the IsNumeric function:

 If IsNumeric(trainCostStr) Then
    totalTrainCost = totalTrainCost + CInt(trainCostStr)
 Else
    ' Do something appropriate
 End If

...or you can be reactive by using error catching; in Classic ASP probably easiest to define a function and use On Error Resume Next:

Function ConvertToInt(val)
    On Error Resume Next
    ConvertToInt = CInt(val)
    If Err.Number <> 0 Then
        ConvertToInt = Empty
        Err.Clear
    End If
End Function

Or return 0 or Null or whatever suits you, then use it in your trainCost code.

Note that CInt expects an integer and will stop at the first non-digit, so "123.45" comes back as 123. Look at the other conversions, CDouble, CCur, etc.

T.J. Crowder
Actually CInt uses the same parsing used in CDouble or CSingle then converts the resulting value to an Int. Hence CInt("123.6") results in 124.
AnthonyWJones
Doh! I work with so many slightly different languages. Of course you're right, it rounds. Cheers, Anthony.
T.J. Crowder
Thanks If IsNumeric worked great! cheers!
Jambobond