Julian Carr Posted April 29, 2018 Share Posted April 29, 2018 Sometimes when you use GetRField() to return a dimension value from a PIO, it returns the value in scientific notation, so a value of 900 (mm) becomes 9e02. You can use Str2Num('9e02') to convert this to a real number, however this does not work in python and produces this error: Type Error. Can't convert 'float' object to str implicitly. Here is a code snippet: perimValue = vs.Str2Num(vs.GetRField( h, 'Space', 'Perim' )) crit_ = "('Space'.'Perim' = "+ perimValue + ")" vs.ForEachObject(DoIt, crit_) The equivalent in Vectorscript works OK. Thanks for any ideas. Julian Quote Link to comment
Pat Stanford Posted April 29, 2018 Share Posted April 29, 2018 Julian, That error message makes me think it is already a Number (type Float) and that the problem is that Python can't convert the float into a string which is the required input of the Str2Num. Perhaps use something like If Type ( vs.GetRField(.......)) = str then PerimValue=Num2Str(GetRField(.......)) else PerimValue = GetrRField(.......) Quote Link to comment
Julian Carr Posted April 29, 2018 Author Share Posted April 29, 2018 Well I guess you are correct Pat, and thanks for your reply. It is already a number expressed in scientific notation, but that can't be used in a criteria string. This is the error it gives: Error: Unable to parse Search Criteria. Database(('Space'.'Perim' = 9e02)) so I need a way to change this: perimValue = 9e02 to this: perimValue = 900 Any ideas on that one? Quote Link to comment
Pat Stanford Posted April 29, 2018 Share Posted April 29, 2018 Maybe: format(PerimValue, 'f') https://stackoverflow.com/questions/25099626/convert-scientific-notation-to-float https://stackoverflow.com/questions/44767119/python-convert-a-number-in-scientific-format-to-string Quote Link to comment
Julian Carr Posted April 29, 2018 Author Share Posted April 29, 2018 Nice try Pat. It still produces an error. It doesn't like the 'f'. Run this snippet to see it: widthValue = '9e02' format(widthValue, 'f') vs.Message(widthValue) Quote Link to comment
Pat Stanford Posted April 29, 2018 Share Posted April 29, 2018 The quotes around the 9e02 are forcing it to a sting instead of a number. Also, the format command needs to be used in conjunction with an assignment (I think). widthValue = 9e02 widthValue = format(widthValue, '.0f') vs.Message(widthValue) the .0 forces it to zero decimal places. Leave that off and the default is 6 decimal places. OK if you are doing a greater than/less than. Not so good if you are doing an equals. Quote Link to comment
Pat Stanford Posted April 29, 2018 Share Posted April 29, 2018 PS. I really much prefer the mandatory typing of variables in Vectorscript. It makes sure you know what kind of a result you are getting. And I really hate using white space as block delimiters. Being/End are so much easier to read. Overtime i have to work in Python I feel like I am back in Fortran in 1983 and counting columns on a punch card. Quote Link to comment
Julian Carr Posted April 29, 2018 Author Share Posted April 29, 2018 I totally agree Pat. Even though Pascal is verbose compared to Python and doesn't have the same community support or external libraries, it requires special knowledge to understand the syntax. Anyway thanks to you I figured a way to do it, though it only works with files in metric units. If you draw a Space, leave it selected the run this script, you will see the desired criteria string: perimValueStr = vs.GetRField( vs.FSActLayer(), 'Space', 'Perim' ) (Flag, perimValue) = vs.ValidNumStr(perimValueStr) #convert notation string to real number perimValueStr = format(perimValue, '.4f') #convert real back to string to 4 decimal places crit_ = "('Space', 'Perim' = "+ perimValueStr + ")" vs.Message(crit_) Quote Link to comment
JBenghiat Posted April 29, 2018 Share Posted April 29, 2018 You can use float() to go straight from the string value to a decimal. repr() will convert back to a string if you need that for the criteria. It should also ignore any white space. repr(float(perimValueStr)) will do it in one go. eval() also works well to convert a string into whatever python variable type best matches. Quote Link to comment
Julian Carr Posted April 29, 2018 Author Share Posted April 29, 2018 Thanks for the suggestion Josh. Unfortunately it doesn't work as the string remains in scientific notation. If you draw a Space object in a file with units set to mm then run this script: perimValueStr = vs.GetRField( vs.FSActLayer(), 'Space', 'Perim' ) repr(float(perimValueStr)) crit_ = "('Space', 'Perim' = "+ perimValueStr + ")" vs.Message(crit_) you will get this result: ('Space', 'Perim' = 6.4e03) If the units are changed to Ft & Ins, then it doesn't work at all and produces an error (could not convert string to float) as the notation value is too long. Quote Link to comment
Pat Stanford Posted April 29, 2018 Share Posted April 29, 2018 Lots of special cases here. The GetRField returns a value. In the case of units of mm, you get something back that Python interprets as a number (but in scientific notation). If you return feet and inches, it includes the unit marks and returns something that Python considers to be a string. I have not tested it, but I would bet that if you had the unit mark turned on for mm, it would probably return something that python would consider to be a string also. So, you either need to do special case for everything, or possibly turn on show units, run the script and then turn off show units. That way you should always end up with a value returned that is a string, so at least you don't have to fight with some returns as numbers and some as strings. But if you can live with just mm, try this: perimValue = (vs.GetRField( vs.FSActLayer(), 'Space', 'Perim' )) perimValueStr = format(float(perimValue),'.4f') crit_ = "('Space', 'Perim' = "+ perimValueStr + ")" vs.Message(crit_) Quote Link to comment
JBenghiat Posted April 30, 2018 Share Posted April 30, 2018 I had forgot about units. In that case vs.ValidNumStr us the way to go, and should compensate for any units format. That should take care of Pat's concern about special cases. Using it in a function lets you easily return 0 VS can't convert the value. def Str2Num(inStr): success, outNum = vs.ValidNumStr(inStr) if success: return outNum else: return 0 eval() and repr() return values, not converting the argument, which is why repr(float(perimValueStr)) as it's own line wasn't working. If you define the above function, the one line version would be: crit_ = "('Space', 'Perim' = "+ repr(Str2Num(perimValue)) + ")" This should give you a value without units, which is I believe what you want for the criteria. If you need a dimension-formatted string, then you need to deal with escaping foot and inch marks. I haven't tested much with python yet, but with native VS, 2018 is much more finicky about quotation marks in criteria strings. Quote Link to comment
Julian Carr Posted May 1, 2018 Author Share Posted May 1, 2018 Thanks Pat and Josh. I think Josh has nailed it with his last suggestion, which seems to work with any units. The script I am working on is for a worksheet and will populate a single cell with all the door IDs that match a particular door type (and optionally width), comma separated. A door type could be an internal door, an external door, the front door of an apartment, or a patio door of a particular style. Sometimes the doors can vary in size but are otherwise the same type. Something like this: TYPE ID WIDTH ETC | Type A | D01, D04, D07 | 1000 | | | Type A | D02, D03, D05 | 900 | | | Type B | D06, D11, D12 | 1000 | | | Type B | D08, D09, D13 | 900 | | The RunScript() function is so powerful it has prompted me to dip my toes into the python pit. Quote Link to comment
Pat Stanford Posted May 2, 2018 Share Posted May 2, 2018 RunScript works fine with Vectorscript. If you want to use the extra possibilities of Python, that is great, but the dozen or so short RunScripts I have written are all VS. But I am sure you already know that. Quote Link to comment
Julian Carr Posted May 2, 2018 Author Share Posted May 2, 2018 really? I just assumed they had to be Python as all the default ones were so. That opens a lot more possibilities. Thanks Pat. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.