<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5908847836728425526</id><updated>2011-12-18T07:05:13.828-05:00</updated><category term='Labor Control'/><category term='MTConnect'/><category term='QUEST'/><category term='BCL'/><category term='Excel'/><title type='text'>DELMIA QUEST and Manufacturing Simulation</title><subtitle type='html'>DELMIA QUEST and Other Simulation Tools Blog</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>60</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-3813528501786944773</id><published>2011-07-13T10:12:00.010-04:00</published><updated>2011-07-14T16:09:12.437-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MTConnect'/><title type='text'>HTML5/JavaScript MT Connect Viewer</title><content type='html'>In my &lt;a href="http://delmiaquest.blogspot.com/2011/07/mt-connect-and-ccat.html"&gt;last &lt;/a&gt;&lt;a href="http://delmiaquest.blogspot.com/2011/07/mt-connect-basics.html"&gt;few&lt;/a&gt; &lt;a href="http://www.blogger.com/publish-confirmation.g?blogID=5908847836728425526&amp;amp;postID=6712044388669503250&amp;amp;timestamp=1310670955009&amp;amp;javascriptEnabled=true"&gt;posts&lt;/a&gt;, I've talked about what MT Connect is, how it works, and why CCAT is excited about it.  Now I want to talk about a proof-of-concept web-based viewer I've created for viewing the real time status of our machine lab.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As I said before, an MT Connect agent provides the current status of the devices talking to it, by returning an XML string with all the details in it.  Since the advent of &lt;a href="http://en.wikipedia.org/wiki/Ajax_(programming)"&gt;AJAX&lt;/a&gt; it's been very common for developers to create web-based applications that hit a server for XML data, and on loading it, modify what's being shown on a web page (using &lt;a href="http://en.wikipedia.org/wiki/Document_Object_Model"&gt;DOM&lt;/a&gt; manipulation).  This is basically the strategy I wanted to take, with the added feature of using the HTML &lt;a href="http://en.wikipedia.org/wiki/Canvas_element"&gt;canvas &lt;/a&gt;element included in modern HTML5-compliant web browsers.  The canvas basically allows you to draw in 2D on a portion of a web page.  The great thing about using HTML and JavaScript is, it works on any platform that supports HTML5 features (including iPad/iPhone/Android browsers).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One reason I chose the canvas element was because we had built a flash-based viewer a few years ago for a single machine, which just listed out some of the MT Connect data we were getting in real time (spindle speed, etc...).  But now we have three machines (and maybe more in the future) that we'll want to be able to view at the same time, so I thought having an overhead view of our layout would be a cool way to get heads-up info on what's happening in our lab.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Luckily I had built a basic JavaScript library for creating and drawing 2D shapes on a canvas when learning JavaScript.  So all I really had to do was write some code to interrogate the Agent, extract data on the machines I wanted to know about, update the 2D shape objects with the right information, and let my graphics library handle the graphics.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So to start, I used a VBA macro in Visio to export my 2D layout to JavaScript code that would create 2D shape objects in my graphics library format.  So at this point I had a canvas element that would draw our machine lab layout, which was a great start.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I then added a JavaScript function that uses &lt;a href="http://jquery.com/"&gt;JQuery&lt;/a&gt; to get an XML string from my MT Connect Agent detailing the current status of my machines.  I also used JQuery to convert the XML output into the &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt; format, which converts the XML data into native JavaScript objects, and step through the XML tree to find what I need.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All that was required now was a function that would get the current status information as JSON data, and map that data to my 2D shape objects, and then call itself after some interval (using setTimeout).  So I wrote that function, and it works pretty well, just turning machines different colors depending on their current state.  You can click on a machine, and see some more detailed information pop up on the side.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've also played with storing the last 150 spindle locations and drawing that on top of the machine, but the problem there is converting the spindle locations into relative locations within the bounds of its machine, otherwise the toolpath usually leaves the bounds of the machine.  But if you watch long enough you see it follows the shape I set in my MT Connect machine simulator.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've also started playing with pulling in other information, like temperature, and displaying that.  Right now my simulator doesn't modify the temperature but that should be easy enough.  I can see it working where there's a little thermometer shape next to the machine that changes color with increasing temperature.  Or even a spindle shape that moves around drawing the toolpath line and changing color with temperature.  There's also a power consumption aspect to this all, where maybe I draw bar gadgets next to the machines so you can see at a glance which machines are using the most electricity.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Regardless, MT Connect can provide some very interesting data, but there's a lot of it.  At some point the really hard part will be in gleaning out what a user wants to see and only showing them that.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;One issue I ran into while building this tool had to do with &lt;a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;cross site request&lt;/a&gt; issues. An MT Connect agent is basically a webserver, except that it only serves XML strings based on what URL you go to. You can't serve arbitrary files (like JavaScript/HTML files). This isn't an issue if you're writing an application in VB/A, for instance, because the XMLHTTPRequest object provided by Microsoft doesn't care where the request is going to. However, the XMLHTTPRequest does care when it's being called in a web browser. Basically, any AJAX request you send has to be served by the same server that gave you the HTML document your JavaScript is running in. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So to get past this issue (which is a showstopper, if you can't actually get anything out of the agent) I used a PHP script that when called, retrieves /current from the agent, and returns that to the caller, keeping the request on the same domain, as far as the browser knows.  So that works well enough, it seems, but it now means anyone who wants to do something similar in the browser has to also have php running (or some server side scripting that can do the same thing).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One other issue I'd like to mention is that I have to use a JQuery library for converting the XML output string of the agent into the JSON format, for creating native JavaScript objects.  It'd be very cool if JSON was an option for output on the agent.  Maybe that should be something I work on building, and if successful, contribute it to the project and try to get it included in a release.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For now, you can see the veiwer at &lt;a href="http://ccat.us/mtconnect"&gt;ccat.us/mtconnect&lt;/a&gt;.  At some point, I hope the simulated data goes away, and we can start showing the real status of our machines.  I'd also like to work at automating the creation of these HTML pages so that other MT Connect users can view their shops using the same code I've written.  We'll see where this all goes.  In the meantime, I cobbled together another version of the viewer that shows the status of the&lt;a href="http://www.amit-deshpande.com/2008/06/mtconnect-live.html"&gt; simulated machine&lt;/a&gt; at &lt;a href="http://agent.mtconnect.org"&gt;agent.mtconnect.org&lt;/a&gt; as well as the toolpath the spindle is following (right now it only keeps about 20 points, and kinda looks like the game "snake", but I might up that value to show more points.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Contact me at jfournier@ccat.us if you have any questions about this.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-3813528501786944773?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/3813528501786944773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=3813528501786944773' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/3813528501786944773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/3813528501786944773'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2011/07/html5javascript-mt-connect-viewer.html' title='HTML5/JavaScript MT Connect Viewer'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-6712044388669503250</id><published>2011-07-13T09:53:00.007-04:00</published><updated>2011-07-14T15:15:55.009-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MTConnect'/><title type='text'>Machine Simulator for MT Connect</title><content type='html'>In my &lt;a href="http://delmiaquest.blogspot.com/2011/07/mt-connect-basics.html"&gt;last post&lt;/a&gt;, I talked about how &lt;a href="http://delmiaquest.blogspot.com/2011/07/mt-connect-and-ccat.html"&gt;MT Connect&lt;/a&gt; works, and how our machine lab isn't yet hooked up to an MT Connect agent (though we're working on it).  While I'm waiting for the machines to be connected (and to provide some more lively data) I've created a very basic machine simulator with a fake MT Connect adapter built into the simulation, to provide some action to an agent, ultimately letting me view that action in a web-based tool.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I built the simulator using Microsoft Visio.  Basically, I created a fake tool path for a spindle to follow, by just drawing a bunch of node shapes, and connecting them using splines.  Then, I created a circle representing the spindle of a machine.  The device/spindle shape also holds custom shapesheet attributes mapping device attributes to the device/data item ID's for the machines defined on my agent.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The spindle shape just follows the path of the lines (using a Visio animation routine I built a while back), and at each animation update (set to 2 seconds) it sends our MT Connect agent the current location of the spindle, as well as the current status of the virtual machine (working or broken down).  You can see a screen shot of the simulator in action below:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/-eI4TiUuSBmE/Th2kjDYcu0I/AAAAAAAAAoc/zSobFUhXQ94/s1600/mtsimulator.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 233px;" src="http://4.bp.blogspot.com/-eI4TiUuSBmE/Th2kjDYcu0I/AAAAAAAAAoc/zSobFUhXQ94/s320/mtsimulator.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5628836031393217346" /&gt;&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To handle reporting the state of the machine, I just hold a "Next State Change" time on each device object, and on every update see if that time has elapsed.  If it has, I flip states (from working to broken or vice versa) and then schedule the next state change event for that machine.  Very basic stuff.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I mentioned in my last post that the two agents I've used (available at &lt;a href="https://github.com/mtconnect"&gt;https://github.com/mtconnect&lt;/a&gt;) both allow you to use an HTTP "PUT" request to store information about a machine.  So, every time I want to update my MT Connect agent, I just create an XMLHTTPRequest object in VBA (from the Microsoft XML library reference) and open a URL that basically looks like this: http://mtagent/storeSample?timeStamp=(current time)&amp;amp;dataItemID=(data item id for x location, or whatever)&amp;amp;value=(whatever value to store)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With the simulator created, I just set up three device shapes in Visio; one for our Haas machine, one for our Hurco, and one for our Yasda.  These machines were already defined in our Devices.xml file on our MTAgent server, which is where our MT Connect Agent gets run from.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By using the simulator to populate data for our real machines, I was able to build a viewer that would dynamically update and show the latest status of all our machines (even though the status was fake).  Now, when we get the machines hooked up for real, the same viewer will be able to show the actual status of our machines, which will include a lot more than just spindle X/Y location and if the machine is running or not.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my next and final post on MT Connect (for the next few weeks at least) I will talk about the HTML/JavaScript viewer I wrote for viewing the current state of our machine lab.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-6712044388669503250?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/6712044388669503250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=6712044388669503250' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/6712044388669503250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/6712044388669503250'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2011/07/machine-simulator-for-mt-connect.html' title='Machine Simulator for MT Connect'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-eI4TiUuSBmE/Th2kjDYcu0I/AAAAAAAAAoc/zSobFUhXQ94/s72-c/mtsimulator.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7946679368282309465</id><published>2011-07-13T09:32:00.010-04:00</published><updated>2011-07-13T11:06:48.703-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MTConnect'/><title type='text'>MT Connect Basics</title><content type='html'>So &lt;a href="http://delmiaquest.blogspot.com/2011/07/mt-connect-and-ccat.html"&gt;CCAT has been tracking this&lt;/a&gt; standard/protocol called MT Connect for a while.  I've been very interested in it, especially from the standpoint of consuming all this great data that machine shops with MT Connect can generate.  I think we're still a long way from having this tool be as ubiquitous as general CNC machining, but I'm hoping CCAT is there with some incredible tools when that does happen (and I think it's inevitable).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So in this post I'd like to talk about how I constructed a web-based viewer for MT Connect data.  But first, I'd like to talk briefly about how MT Connect works, as well as how I'm generating data for this proof-of-concept.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;MT Connect has been created as a data protocol, and really nothing else.  My understanding is that it exists to standardize/define things like: for a milling machine the spindle is where the tool is, and the spindle turns at a rate called SpindleSpeed, and there are certain units that can be measured in, etc...  The protocol also defines several key terms: agents, adapters, and devices.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A device is just a discrete unit that can be connected to MT Connect.  The most important devices typically are the machines/controllers themselves, but I know the standard involves more than that, including bar stock feeders, tool holders, all kinds of stuff.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An agent is basically a software executable that sits somewhere and listens to things that devices want to tell it.  The agent also is able to be interrogated by client software that wants to know things about devices.  The agents I've dealt with so far (both are open source and free to use: &lt;a href="https://github.com/mtconnect"&gt;https://github.com/mtconnect&lt;/a&gt;) are implemented using TCP/IP, meaning they work over the internet/web.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The two agents implement HTTP web servers, which allow you to interrogate them using regular web technologies (i.e. the "GET" XMLHTTPRequest).  When you interrogate an agent, it spits back your data in an XML file, which is very easy to program for.  The two agents I've used also allow you to use HTTP "PUT" requests to store information about devices, meaning you can update an agent even by visiting a URL in your web browser.  Very cool, and easy to do.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, probably the most difficult item here is the adapter.  The adapter is what allows a device to talk to the agent.  Machine tools typically use their own proprietary protocols and data formats and terminologies within their controllers.  A Fanuc controller can put out completely different data streams than a Haas controller, even if they're saying basically the same things.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So an adapter has to be made for converting from one controller "language" (proprietary format/protocol) into the standard MT Connect protocol, and then sent to the agent.  So that's the adapter's job.  The adapter can live on the controller as a separate piece of software (if the controller allows that) or it can live on a computer that sits near the machine and communicates with it over a parallel or serial cable.  Either way, the adapter provides a stream of data about its machine in a standard format.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So CCAT has this &lt;a href="https://portal.ccat.us/newsletter/article.php?action=READ_MORE&amp;amp;lid=29&amp;amp;aid=146&amp;amp;e="&gt;Advanced Manufacturing Center&lt;/a&gt; where we have a few machines on consignment from &lt;a href="http://www.yasda.com/"&gt;Yasda &lt;/a&gt;and &lt;a href="http://www.hurco.com/"&gt;Hurco&lt;/a&gt;, as well as housing our &lt;a href="http://laser.ccat.us/"&gt;Laser Applications Lab&lt;/a&gt;.  We want to have these machines hooked up through MT Connect, but we're still working to install the correct adapters for these machines.  In the next post, I'll talk about how I built a machine simulator that also acts as an adapter, sending the status of a simulated machine to an MT Connect agent.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7946679368282309465?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7946679368282309465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7946679368282309465' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7946679368282309465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7946679368282309465'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2011/07/mt-connect-basics.html' title='MT Connect Basics'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-1784971559330513580</id><published>2011-07-12T16:56:00.005-04:00</published><updated>2011-07-13T10:36:16.390-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MTConnect'/><title type='text'>MT Connect and CCAT</title><content type='html'>&lt;a href="http://mtconnect.org/"&gt;MT Connect&lt;/a&gt; is a protocol/standard developed for the purpose of allowing machine tools to communicate information about themselves to other computer systems.  For instance, this allows a machine to report its current status - whether it's broken down, working, or idle.  It can also report its current spindle speed, feed rate, location, and even the current line of g-code that it's running.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All in all, it's a pretty great way to be able to collect activation/utilization data on any machine, regardless of the brand or make or model of controller running it.  The obvious upside for simulation users is that you can process the data from a machine and get a list of state-change events and what times they happened at.  This data can be run through a distribution-fitting tool, and spit out mean time between failure and mean time to repair distributions.  There's a very good paper on this topic &lt;a href="http://www.informs-sim.org/wsc10papers/155.pdf"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The standard is still evolving.  Right now it really only covers the machine resources on a shop floor, but at some point I hope it will include labor resources, and part/process tracking.  This would allow us to get accurate cycle time/setup time observations on a part-process-machine level, and get us to the point where simulation models can be initialized to the current state of the system being modeled, and then run to predict the next few hours or days or weeks worth of production.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;MT Connect can help turn simulation users into basically a weather man, though instead of predicting the weather they're predicting when jobs will be completed and planning contingencies in case a machine goes down.  Powerful stuff.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And CCAT is hoping to help make this a reality.  We have been attending the MT Connect standards meetings, and I just finished developing a proof-of-concept JavaScript/HTML-based viewer for MT Connect, which I'll detail more in a post to come.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-1784971559330513580?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/1784971559330513580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=1784971559330513580' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1784971559330513580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1784971559330513580'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2011/07/mt-connect-and-ccat.html' title='MT Connect and CCAT'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-4437339772361344001</id><published>2011-06-23T11:08:00.004-04:00</published><updated>2011-06-23T11:22:21.485-04:00</updated><title type='text'>SCL Time Measureme</title><content type='html'>&lt;div&gt;Lately I've been working on some models that are pretty involved, in terms of the scale of what's going on as well as making some calls that seem to run slow (creating new parts, packing parts, messing with allocating lists and structures into memory).  I wasn't sure what was taking so long, and it's very hard to say with SCL the way it is.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I could have instrumented my code with some subroutine call to store the start time of every subroutine in a logic file, and then another call at the end of the subroutine (before the End line or any Return lines) that logs the time it took to run that subroutine.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Doing so manually would take quite a bit of effort, so I tried my hand at writing something in VB6 that would do the trick, and I think I've succeeded.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I created a standalone executable you can call from any command shell (on Windows) and pass in the full path to the SCL file to instrument, and optionally you can pass a second argument that is the name of the init logic in your model, and an optional 3rd argument specifying a string pattern for commenting out any existing instrumentation you've added to the logic.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's an example call I've used:&lt;/div&gt;&lt;div&gt;scltimeinstrument.exe "C:/Delmia/Questlib/LOGICS/CMSD/CMSD.scl" cmsd_model_init_logic *writer(*,*)*&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So the first argument again is just the path to the SCL file to instrument.  The second argument is cmsd_model_init_logic, so the instrumenter program will find the cmsd_model_init_logic subroutine as it's defined in the file, and the first line after Begin in that subroutine will be a call to a subroutine we include that will initialize the time log file (hardcoded as C:/Tmp/scl_times_log.txt"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The third argument "*writer(*,*)*" specifies to the program to find any line that contains the text "writer(" followed by anything, then a comma, then anything, and closed with a close paren, and finally allow anything outside the paren (to allow comments).  This string pattern works well for me because I have one routine called writer where I pass some string message in as the first argument, and the second argument tells what the call means (i.e. error message, or standard debug, or starting/ending some subroutine).  So this pattern matches my usage well, because my code is instrumented with this single call, and I can easily wipe out those calls now.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The output file is just a flat text file (saved to C:/Tmp/scl_times_log.txt) that shows the time (in milliseconds) every subroutine call took every time it was called (so long as that time was more than 1 millisecond).  It's up to you to analyze the data (I use averageif, etc... in Excel to summarize the data)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyways, enough of my blabbing, &lt;a href="http://dl.dropbox.com/u/141605/SCLTimeInstrument.exe"&gt;here's a link to the tool&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-4437339772361344001?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/4437339772361344001/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=4437339772361344001' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4437339772361344001'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4437339772361344001'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2011/06/scl-time-measureme.html' title='SCL Time Measureme'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-4768109763310374257</id><published>2011-06-09T16:16:00.009-04:00</published><updated>2011-06-09T16:35:21.947-04:00</updated><title type='text'>Web-based QUEST modeling (using CMSD)</title><content type='html'>&lt;div&gt;The form below is a sneak preview of a web-based simulation service I'm trying to develop at the &lt;a href="http://clientportal.ccat.us/modsim/value_stream_mapping_macros"&gt;CT Center for Advanced Technology&lt;/a&gt; where I work.  This form will let you upload an Excel file (example data &lt;a href="http://dl.dropbox.com/u/141605/DemoFiles/ExcelPFA.xls"&gt;here&lt;/a&gt;) and get a QUEST .mdl file in your email.  Just upload the example file and type "ExcelPFA2QUEST" in the "Translation To Do" box below, and you'll get the mdl file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can also try &lt;a href="http://dl.dropbox.com/u/141605/DemoFiles/CMSD.xml"&gt;this&lt;/a&gt; &lt;a href="http://delmiaquest.blogspot.com/2010/04/core-manufacturing-simulation-data.html"&gt;CMSD&lt;/a&gt; file.  You can specify CMSD2QUEST or CMSD2Results as the translation to do.  CMSD2Results will actually run the model and let you view a statistics report online.  Or try CMSD2eVSM and you'll get a value stream map showing the data.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To use the example files, you must first download them, and then submit them through the form.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you use it, please give me feedback using the &lt;a href="http://www.jotform.com/form/11592451172?"&gt;contact form&lt;/a&gt; below.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Due to the formatting issues on this blog, it may be easier to try the form &lt;a href="http://www.jotform.com/jfournier/11372745193"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;iframe allowtransparency="true" src="http://form.jotform.com/form/11372745193" frameborder="0" style="width:100%; height:465px; border:none;" scrolling="no"&gt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;br&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;iframe allowtransparency="true" src="http://form.jotform.com/form/11592451172" frameborder="0" style="width:100%; height:507px; border:none;" scrolling="no"&gt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;br&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&lt;/iframe&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-4768109763310374257?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/4768109763310374257/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=4768109763310374257' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4768109763310374257'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4768109763310374257'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2011/06/web-based-quest-modeling-using-cmsd.html' title='Web-based QUEST modeling (using CMSD)'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-1380700807146417256</id><published>2011-04-11T13:38:00.004-04:00</published><updated>2011-04-11T14:05:14.195-04:00</updated><title type='text'>Associative Arrays / Hash Tables / Collections in SCL</title><content type='html'>&lt;div&gt;I've been using QUEST for just over five years now, and over time I've become more and more bothered by its lack of a hash table data structure, like I get out of the box in VBA (I know, VBA is pretty ancient stuff itself, but compared to SCL, VBA is a dream, in my opinion.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A &lt;a href="http://en.wikipedia.org/wiki/Hash_table"&gt;hash table&lt;/a&gt; is a data structure is basically a string array that instead of being indexed by numbers, is essentially indexed by strings.  In VBA, a hash table is called a Collection, and provides methods for adding, removing, and iterating over its contents.  Most implementations of hash tables allow you to put anything in the "bucket" of stuff, keyed by a string.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The purpose of a hash table, as far as I can tell, is to provide a somewhat faster mechanism for finding items in an array than by just looking at every item one by one.  Call this the slowest possible case.  The fastest possible case would be to just convert a string into a big long binary number, and have a gigantic string array with enough indexes to hold any length string we can throw at it.  This is probably the fastest case (I think fetching an item from an array is done in constant time), but it's not really feasible, especially with QUEST SCL, because we don't have all the memory in the world to hold this huge array, which, by the way, would be pretty much empty.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So enter the hash table.  According to the &lt;a href="http://www.amazon.com/Algorithms-C-Robert-Sedgewick/dp/0201510596"&gt;Algorithms in C++&lt;/a&gt; book I picked up at the library book sale for 75 cents, we can instead create a small array, with each array space holding a linked list of items with a specific hash value.  The linked lists are there because we know that by limiting the size of our array, we can have different keys with the same hash.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The idea then, for searching for a key value, is that you hash the key and get a number between 1 and 111, and get the base node in the linked list at that array index.  Then, we just search through each of the nodes in that linked list until we find our exact key value, and return the original string.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This kind of thing seems pretty easy to pull off with SCL, as it's just a matter of providing the hashing function (nicely included in the book), and a way to hold an array of linked lists for each of our 111 possible hash values.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've put together a hash table utility in SCL, though I called it a collection.  It's available for download &lt;a href="http://dl.dropbox.com/u/141605/hash_table.scl"&gt;here&lt;/a&gt; with an example for using it &lt;a href="http://dl.dropbox.com/u/141605/try_hash_table.scl"&gt;here&lt;/a&gt;.  I put the hash_table.scl file into my directory of &lt;a href="http://delmiaquest.blogspot.com/2009/05/precompiled-always-there-scl-routines.html"&gt;always compiled utility routines&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To use the hash table, you have to include the SCL file (I had to specify the full path to the file, so you'll have to modify that to accommodate your system.  To create a collection, call the new_collection routine, which initializes a collection structure.  Use col_add to add an item, remove_item_from_collection to remove an item, and col_item_exists to check if there is an item in the collection already.  The kill_collection procedure will deallocate all the memory for the collection, so make sure to call that when you're done with it, or you could end up eating a lot of memory, depending on how you use this.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another note, you can loop through every item in the collection, starting (assuming you call your collection col) and looping through a linked list of every item in the collection.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I haven't tested it terribly well, but the example file seems to work as I intend, so unless I start using it and find it broken, this is how it'll stay.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm not sure how much faster this is, computationally, than just looping through each item in an array and checking it.  It's probably a little slower for small collections, but I imagine as the thing grows the hash table becomes faster than just looping, but I don't know.  I do think it'll make some lookups a bit easier, at least from a programmer's productivity perspective, but then again, what do I know?  Either way, I'll have to try and implement more of these algorithms, especially the section on regular expressions.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-1380700807146417256?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/1380700807146417256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=1380700807146417256' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1380700807146417256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1380700807146417256'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2011/04/associative-arrays-hash-tables.html' title='Associative Arrays / Hash Tables / Collections in SCL'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-5704972320417749023</id><published>2011-03-10T09:12:00.005-05:00</published><updated>2011-03-10T09:35:14.892-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QUEST'/><category scheme='http://www.blogger.com/atom/ns#' term='Labor Control'/><title type='text'>Labor Popups (or, Demystifying the Labor System in QUEST)</title><content type='html'>Labor logic can be really difficult to understand without first getting the proper grounding in just what's going on.  I was lucky enough to get some training from Martin Barnes at DELMIA, who stepped me through the entire process, including how popups play into things.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Basically, the labor system uses a controller to select a labor to fulfill some request, then it passes information about the request through a command.  The labor then picks up the command and acts on it.  This seems simple enough, but reading through the code it doesn't seem so straightforward, as you can't see the labor actually doing anything.  This is because of popups.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Popups in QUEST allow a user to write incredibly flexible (reusable) logics at the expense of readability.  In the default labor process logic, you can see the labor just constantly sits there getting the next pending command to work on, and then does a switch block to see what kind of command it is.  It then gets a handle to the popup it should use to execute the command, and runs that popup.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So in the case of laborers, a popup is simply an object that lets us run some SCL code without knowing ahead of time precisely which SCL routine/procedure to run.  You just query the popup that a user has selected, and run it, and assume that logic is taking care of business.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;When we apply this thinking to the labor system, it demystifies things a little bit (at least for me).  The regular labor process logic then becomes fairly simplistic...do a switch against the command type, and based on command type, get a handle to the logic to run, then run that logic.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The real meat of the labor logics, and the thing that kept me from understanding how they work, is in the default popup implementations.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the labor Logics window in QUEST, you'll see a few options beyond the regular process and init logics.  These are all popups, just a way of selecting a procedure/routine that's going to get called in the default labor logics.  So to see what these default selections look like, we can just look at a labor's properties and see the routine names and file paths for the selected popups.  The default labor load popup is notify_after_all_loads and can be found in QUESTlib\SYSDEF\LOGICS\agv_load.scl.src.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you load that file up in an SCL editory, you can see the notify_after_all_loads is a procedure that takes an agv_cmd handle (agv's and labors are pretty similar, you can see, by digging into their logics.  My understanding is laborers were essentially copied and pasted from agv's, back in the day at Deneb.  Old/ex Deneb people can be dangerously misleading, but interesting nonetheless).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The flow of this logic is much much more readable than the labor process logic, again, because this is where we actually DO stuff.  So here we can see that we do load processes if necessary and all that, but eventually we just do a REQUIRE PART EXACT the_part, where the_part is just a handle passed in as cmd-&gt;part_handle.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The interesting thing about this line of code is that it's the same thing a machine element uses to get parts (or buffers, whatever).  If you look at the unload popups, you see it's just transferring a part to whatever element it's at.  There is nothing the least bit magical or mystifying here.  In fact, this makes the labor system seem to make a lot of sense.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This may have been obvious to you, but I was never able to get a handle on this until someone walked through the whole thing with me.  I know I can't do as good a job as Martin did, but I hope this gives newer QUEST users who don't know the labor system the ability to go in and see just what's going on.  Ever since I "saw the light" on how this all works, I've been able to write my own labor controllers and labor logics.  With that understanding comes the ability to get very detailed control of your labors, as well as the ability to write some really really bad code.  Be careful.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's a quick example of a custom labor load popup I recently had to write.  The labor would load a part and immediately destroy it, with the controller having already gotten what it needs from the part.  Keep in mind I'm using a custom controller, so I don't need to notify the controller that the labor destroyed the part.  Your mileage may vary.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;procedure custom_labor_load_popup( cmd : Agv_Cmd )&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   the_part : Part&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;   the_part = cmd-&gt;part_handle&lt;/div&gt;&lt;div&gt;   require part exact the_part&lt;/div&gt;&lt;div&gt;   destroy( the_part )&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-5704972320417749023?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/5704972320417749023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=5704972320417749023' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5704972320417749023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5704972320417749023'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2011/03/labor-popups-or-demystifying-labor.html' title='Labor Popups (or, Demystifying the Labor System in QUEST)'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-5171128052594017571</id><published>2010-12-21T14:28:00.005-05:00</published><updated>2010-12-21T14:46:58.564-05:00</updated><title type='text'>Hand-Drawn Value Stream Map</title><content type='html'>Sometimes I get ideas where I can't really let go of them, until they're realized.  These ideas tend to be stupid, useless, or impractical, or any combination of the three.  I probably would do better to just let these things go, but to this point I've only been able to just implement the idea and move on (&lt;a href="http://delmiaquest.blogspot.com/2010/01/labor-shirt-colors.html"&gt;case in point&lt;/a&gt;).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's another stupid idea I couldn't let go of: making computer-drawn value stream maps look hand-drawn.  It was a concatenation of circumstances that made me implement this; namely, I saw a post on a &lt;a href="http://www.visguy.com/2008/08/20/indexed-shapes-for-that-hand-drawn-look/"&gt;Visio blog&lt;/a&gt; on making shapes look hand drawn.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I wrote a VBA macro in Visio that takes an &lt;a href="http://www.evsm.com/"&gt;eVSM&lt;/a&gt; map and makes it look hand drawn.  I implemented this and moved on, like I feel I should.  But recently, I saw a post somewhere linking to a &lt;a href="http://callsignkatejones.deviantart.com/art/House-Whiteboard-font-64929545"&gt;whiteboard font&lt;/a&gt; based on the t.v. show House, and decided I couldn't live without seeing how it my "hand-drawn" maps would look with a "hand-drawn" font to go with it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's a regular eVSM map:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_gjBYffQqIUY/TRECE8sdfqI/AAAAAAAAAmM/_s6GXJZvkiI/s1600/vsm.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 183px;" src="http://4.bp.blogspot.com/_gjBYffQqIUY/TRECE8sdfqI/AAAAAAAAAmM/_s6GXJZvkiI/s320/vsm.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5553222099559874210" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And here is one of my "incredible" hand-drawn maps, rendered like on a whiteboard (minus any smudges one might expect):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gjBYffQqIUY/TREB1aD9bII/AAAAAAAAAmE/vHF6hI5VG3g/s1600/hvsm.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 162px;" src="http://2.bp.blogspot.com/_gjBYffQqIUY/TREB1aD9bII/AAAAAAAAAmE/vHF6hI5VG3g/s320/hvsm.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5553221832565156994" /&gt;&lt;/a&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I guess my point for sharing this was just to, 1, show off a really stupid little trick I somehow couldn't live without, and 2, to say that sometimes you have to just give up and give in to that part of your brain that thinks "wouldn't it be cool if...".  Who knows, it may come in handy some day (and I mean the experience of working through that problem).&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-5171128052594017571?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/5171128052594017571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=5171128052594017571' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5171128052594017571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5171128052594017571'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/12/hand-drawn-value-stream-map.html' title='Hand-Drawn Value Stream Map'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_gjBYffQqIUY/TRECE8sdfqI/AAAAAAAAAmM/_s6GXJZvkiI/s72-c/vsm.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-193516721079255065</id><published>2010-12-09T13:14:00.003-05:00</published><updated>2010-12-09T13:15:36.291-05:00</updated><title type='text'>Winter Sim Presentation (2010)</title><content type='html'>&lt;div&gt;I saw some cool presentations at Winter Sim this year.  One vendor presentation that stood out for me was from &lt;a href="http://forio.com"&gt;forio.com&lt;/a&gt;, which lets you upload simulation models and run them in the cloud. Very cool.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I also gave a presentation with Swee Leong from NIST:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;iframe src="https://docs.google.com/present/embed?id=dgww9c7m_356f8wpk5d5&amp;amp;interval=5" frameborder="0" width="410" height="342"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-193516721079255065?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/193516721079255065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=193516721079255065' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/193516721079255065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/193516721079255065'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/12/winter-sim-presentation-2010.html' title='Winter Sim Presentation (2010)'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-627649742073357728</id><published>2010-11-08T14:09:00.005-05:00</published><updated>2010-11-08T15:07:31.906-05:00</updated><title type='text'>Bitwise Comparison</title><content type='html'>Say you want to have a routine in QUEST SCL that may have to do some things and not others, or vice versa.  One way you can specify what sections of code to do is have a series of "flag" that tells the routine what to do and not do.  Each flag controls one aspect of the code.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One place I can use this kind of control is in a routine for writing debugging messages to a text file, and optionally to the screen.  So for one of these routines, I'd probably want a flag saying whether or not to write to the screen, and another to specify if it's an error message (in which case write to the screen and ignore the other flag), and maybe two more for telling the routine when I'm entering a routine and exiting a routine (to keep track of the call stack, so to speak).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So in this case, I'd need to have four flags I'm setting to true or false every time I call this writing routine.  And, if I want to add another flag, I have to change all the calls I've made to this routine to match up with the new flag, since SCL doesn't give you the ability to add optional arguments.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, rather than deal with this issue of having a flag variable for each option I want to add in a routine, I can instead take advantage of the nature of binary numbers in the computer.  Before I continue, keep in mind that I didn't major in computer science or computer anything, so my explanation will probably sound hokey and not quite right.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A computer deals with numbers using binary, where we have a set of numerals that can have a value of zero or one.  Each numeral you add on adds a power of two (rather than 10 like in our base-10 system).  So, for instance, 1 in binary comes out to 2 to the power of 0, or 1.  10 in binary comes out to 0 to the power of 0 (0) plus 2 to the power of 1 (2) = 2.  100 comes out to 0^0 + 0^1 + 2 ^2 = 4. 1010 comes out to 0^0 + 1^1 + 0^2 + 2^3 = 10&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hopefully, if I did that right, you'll see a pattern where each digit we add onto the left adds another power of 2.  1 = 1, 10 =2 , 100=4, 1000=8, 10000=16, and so on.  By seeing this pattern, we can also see that we could use a binary integer to store a series of yes/no flags using 1 for yes and 0 for no (or whatever you want).  For instance, 2 + 8 in base 10 equals 10 + 1000 in binary or 1010.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The practical upshot of all this so far is, we can now create a series of flags, each unique flag being a power of two value (1,2,4,8,16,32, and so on), and we can store all the flag values we want to activate by adding the ones we're using together.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, to define our constants for our message logger:&lt;/div&gt;&lt;div&gt;WriteToScreen 1&lt;/div&gt;&lt;div&gt;ErrorMsg 2&lt;/div&gt;&lt;div&gt;EnteringRoutine 4&lt;/div&gt;&lt;div&gt;ExitingRoutine 8&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If we want to write that we're entering a routine we'd just pass in WriteToScreen + EnteringRoutine, which would calculate to 9 in base-10, and our routine could then know which flags to activate based on that number 9.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, to break that 9 back up into its parts, we need to go backwards and turn a decimal number back into binary 1's and 0's.  Following is a routine that'll do that for us.  I'm not sure it's the most efficient, but it seems to work.  It works by reading left to right in the powers of two (starting at power 8 - you could increase it if you have more flags to handle).  So it starts and sees if 2^8 (256) is less than the num we're trying to break apart.  If it is, we turn that flag to true, and subtract 256 from the number until we get down to the last power.  In this routine we pass in the flag we want to check against, and return true if the bit we're looking at is true.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hopefully I didn't bungle the explanation too much, but I really just wanted to have this routine up for future reference, and hopefully it gets you thinking of ways it can help you write more concise or powerful code in SCL.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Consolas; font-size: 13px; white-space: pre; "&gt;routine bitwise_or( num : Integer ; against : Integer ) : Integer&lt;/span&gt;&lt;/div&gt;&lt;pre style="font-family: Consolas;font-size: 10 pt;"&gt;Var&lt;br /&gt; i : Integer&lt;br /&gt; pow : Integer&lt;br /&gt; sum : Integer&lt;br /&gt; result : Integer&lt;br /&gt;Begin&lt;br /&gt; sum = num&lt;br /&gt; for i = 8 to 0 by -1 do&lt;br /&gt;    pow = 2 ^ i&lt;br /&gt;    if( sum &gt;= pow ) then&lt;br /&gt;       sum = sum - pow&lt;br /&gt;       if( pow == against ) then&lt;br /&gt;          result = true&lt;br /&gt;          break&lt;br /&gt;       endif&lt;br /&gt;    endif&lt;br /&gt; endfor&lt;br /&gt; return result&lt;br /&gt;End&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-627649742073357728?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/627649742073357728/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=627649742073357728' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/627649742073357728'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/627649742073357728'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/11/bitwise-comparison.html' title='Bitwise Comparison'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-8665149231913932227</id><published>2010-10-25T22:04:00.005-04:00</published><updated>2010-10-25T22:08:43.430-04:00</updated><title type='text'>GetTickCount</title><content type='html'>Tonight I was trying to debug some slow SCL code, and wanted to pinpoint exactly which routines were taking the longest to execute.  QUEST has a systime() routine that returns the number of seconds since midnight.  However, I wanted more accuracy, so I needed to use the GetTickCount routine provided by the Windows API.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I can call this routine using &lt;a href="http://delmiaquest.blogspot.com/2009/09/examples-of-using-cexec-in-scl.html"&gt;C_EXEC&lt;/a&gt; in SCL, and the final routine comes out like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;routine get_tick_count() : Integer&lt;/div&gt;&lt;div&gt;Const&lt;/div&gt;&lt;div&gt;   THE_DLL 'kernel32.dll'&lt;/div&gt;&lt;div&gt;   THE_CMD 'GetTickCount'&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   func_return : Integer&lt;/div&gt;&lt;div&gt;   Begin&lt;/div&gt;&lt;div&gt;   func_return = c_exec( THE_DLL + ":" + THE_CMD )&lt;/div&gt;&lt;div&gt;   return func_return&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, I can get a bit more visibility into what's taking my logics so long to run (though be sure to disable any calls to this routine once you're ready to just run the model)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-8665149231913932227?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/8665149231913932227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=8665149231913932227' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8665149231913932227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8665149231913932227'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/10/gettickcount.html' title='GetTickCount'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7614087025355750810</id><published>2010-10-15T09:49:00.004-04:00</published><updated>2010-10-15T09:51:38.636-04:00</updated><title type='text'>Select a Part</title><content type='html'>The other day I was working on a project where I wanted some stats on a part in a model that don't show up in the Trace Entity window.  So, I went to write a macro that would let me select a part and show the information I needed.  I then realized that I didn't have a routine available that would let me easily select a part, so I went about writing one.  Now, it's available for download &lt;a href="https://my.syncplicity.com/share/biismtcdb1/select_a_part.scl"&gt;here&lt;/a&gt;, because it was a pain to write and now you don't have to write it too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7614087025355750810?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7614087025355750810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7614087025355750810' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7614087025355750810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7614087025355750810'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/10/select-part.html' title='Select a Part'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7477829651429636203</id><published>2010-09-09T14:46:00.003-04:00</published><updated>2010-09-09T14:51:11.428-04:00</updated><title type='text'>eVSM and QUEST User Groups</title><content type='html'>If you read back to past posts on this blog, you'll see I do a bit of work with eVSM.  Up until now, there hasn't been any organized group of eVSM users that I know of, but that's now changed.  An eVSM user has started a LinkedIn group geared toward discussing eVSM, as well as how to do various things in eVSM.  You have to be a LinkedIn member to join, and then you have to search for the eVSM user group.  Honestly, it would be nice if we could get enough eVSM users on board to build an eVSM &lt;a href="http://stackexchange.com/"&gt;Stack Exhange&lt;/a&gt; site.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm hoping this community gets enough power users and casual users to build and sustain some decent conversation.  Luckily, the &lt;a href="http://groups.google.com/group/delmia_quest"&gt;QUEST group&lt;/a&gt; I set up seems to have a great core of power QUEST users (including past &amp;amp; current Deneb/DELMIA employees) who are able to give advice and tips on how to tackle specific problems in QUEST.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hopefully we can say the same for the eVSM group, soon.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7477829651429636203?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7477829651429636203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7477829651429636203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7477829651429636203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7477829651429636203'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/09/evsm-and-quest-user-groups.html' title='eVSM and QUEST User Groups'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-2841872343530205694</id><published>2010-08-18T16:26:00.004-04:00</published><updated>2010-08-18T16:30:54.124-04:00</updated><title type='text'>eVSM to QUEST Beta Version Now Available</title><content type='html'>Any QUEST users interested in trying our (CCAT's) eVSM to QUEST converter may now do so, if they'd like to participate in beta testing (meaning we're not sure how well it works yet on lots of different computers).  So if you'd like to try it out, email me at &lt;a href="mailto:jfournier@ccat.us"&gt;jfournier@ccat.us&lt;/a&gt; and let me know.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This requires you at least have access to QUEST and Visio (you'll have to get a trial version of &lt;a href="http://evsm.com"&gt;eVSM&lt;/a&gt;)&lt;br /&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, more information &lt;a href="http://clientportal.ccat.us/modsim/value_stream_mapping_macros"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/GhigvOszgMc?fs=1&amp;amp;hl=en_US"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/GhigvOszgMc?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-2841872343530205694?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/2841872343530205694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=2841872343530205694' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/2841872343530205694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/2841872343530205694'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/08/evsm-to-quest-beta-version-now.html' title='eVSM to QUEST Beta Version Now Available'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-8822928448787139340</id><published>2010-06-18T08:56:00.002-04:00</published><updated>2010-06-18T09:01:27.655-04:00</updated><title type='text'>IE Stack Exchange Site</title><content type='html'>I recently advocated anyone reading this blog check out &lt;a href="http://delmiaquest.blogspot.com/2010/04/or-exchange.html"&gt;OR-Exchange&lt;/a&gt;.  Basically, the case is/was that if OR-Exchange didn't get to a certain amount of web traffic it would be shut down, as the people behind it (&lt;a href="http://area51.stackexchange.com/"&gt;Stack Exchange&lt;/a&gt;) have a new model where they want to create nice, high volume question and answer sites on any topic people are willing to discuss.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've been thinking about it, and it's my opinion that OR-Exchange may be a bit too niche to be able to attract enough users to keep alive.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I am proposing we create a Stack Exchange site on Industrial Engineering/Continuous Improvement/Systems Analysis, whatever you want to call it.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you're interested in seeing this site come to fruition, visit:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://area51.stackexchange.com/proposals/6949/continuous-improvement"&gt;http://area51.stackexchange.com/proposals/6949/continuous-improvement&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;and follow the site, and if we can get enough followers and example questions, we can move on and get a centralized, modern community started for discussing anything IE/OR/CI.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-8822928448787139340?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/8822928448787139340/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=8822928448787139340' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8822928448787139340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8822928448787139340'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/06/ie-stack-exchange-site.html' title='IE Stack Exchange Site'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-8657507882747327568</id><published>2010-06-01T16:24:00.002-04:00</published><updated>2010-06-01T16:29:19.513-04:00</updated><title type='text'>Number Rounding in SCL</title><content type='html'>&lt;div&gt;I recently found the need to do some simple number rounding in SCL, and was able to dig these two routines out using my &lt;a href="http://delmiaquest.blogspot.com/2008/10/scl-subroutine-indexer.html"&gt;SCL Subroutine Indexer&lt;/a&gt; though the index was from a previous computer I used, and hadn't copied over to my current machine.  Thankfully, Google Desktop was able to find a backup copy I had made who knows when.  So, to prevent me from losing these simple functions forever, here they are.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Nothing fancy; I round a number down by converting it to an integer string, then reading it back to a number using VAL.  I guess SCL will truncate a number at the decimal point when converting to an integer string (%g), rather than do any real rounding.  So to round up I just round down and add one.  Like I said, nothing fancy, and apparently nothing worth searching for 20 minutes over.  Anyways, these would be good to keep &lt;a href="http://delmiaquest.blogspot.com/2009/05/precompiled-always-there-scl-routines.html"&gt;compiled all the time&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;routine round_down_to_int( num_value : Real ) : Integer&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;int_string : String&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;result : Integer&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;result = 1&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;int_string = str( '%g' , num_value )&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;result = VAL( int_string )&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;return result&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;div&gt;routine round_up_to_int( num_value : Real ) : Integer&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;result : Integer&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;rounded_down : Integer&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;return round_down_to_int( num_value ) + 1&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-8657507882747327568?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/8657507882747327568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=8657507882747327568' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8657507882747327568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8657507882747327568'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/06/number-rounding-in-scl.html' title='Number Rounding in SCL'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-734898994184818486</id><published>2010-04-22T14:56:00.001-04:00</published><updated>2010-04-22T14:58:08.634-04:00</updated><title type='text'>eVSM, CMSD, and ProModel</title><content type='html'>So here's a video showing the new ProModel translator I wrote for CMSD.  It also shows a little bit of the CMSD Viewer program I've been working on.  Best watched in HD so you can read the text and follow along...&lt;br /&gt;&lt;br /&gt;&lt;object width="960" height="745"&gt;&lt;param name="movie" value="http://www.youtube.com/v/7Yuvtf7bRbs&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;color1=0x3a3a3a&amp;amp;color2=0x999999&amp;amp;hd=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/7Yuvtf7bRbs&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;color1=0x3a3a3a&amp;amp;color2=0x999999&amp;amp;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="960" height="745"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-734898994184818486?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/734898994184818486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=734898994184818486' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/734898994184818486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/734898994184818486'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/04/evsm-cmsd-and-promodel.html' title='eVSM, CMSD, and ProModel'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7617875156166323832</id><published>2010-04-22T11:19:00.003-04:00</published><updated>2010-04-22T12:00:56.368-04:00</updated><title type='text'>Core Manufacturing Simulation Data</title><content type='html'>I'm not sure if I've mentioned this yet, but I'm pretty sure I haven't.  A little over 3 years ago I attended Winter Sim 2006 in Monterey, CA (nice place by the way) and got introduced to the Core Manufacturing Simulation Data (CMSD) specification from &lt;a href="http://www.nist.gov"&gt;NIST&lt;/a&gt;.  This spec was supposed to act as a neutral data format for holding manufacturing simulation.&lt;br /&gt;&lt;br /&gt;I watched its progress over the years, hoping at some point to be able to apply some of my past work &lt;a href="http://delmiaquest.blogspot.com/2010/03/how-to-populate-value-stream-map-with.html"&gt;translating Value Stream Maps&lt;/a&gt; &lt;a href="http://delmiaquest.blogspot.com/2010/02/winter-sim-presentation.html"&gt;into QUEST models&lt;/a&gt; to be generically available to any simulation package.&lt;br /&gt;&lt;br /&gt;Cut to March of 2009, and it seemed like the spec was getting pretty close to being a standard.  NIST had the spec in to &lt;a href="http://www.sisostds.org/"&gt;SISO&lt;/a&gt; for review and eventual vote, and my boss saw a presentation by Swee Leong from NIST, and was impressed enough by it to allow me to start working on a CMSD translator for Value Stream Mapping.&lt;br /&gt;&lt;br /&gt;So I got started right away, first stepping back and looking at what this translator should be.  I should mention that the CMSD format is technically set to be a &lt;a href="http://en.wikipedia.org/wiki/Unified_Modeling_Language"&gt;UML&lt;/a&gt; standard, but along with that will come an XML schema.  So anyways, long story short, I hadn't done much work with parsing XML files, and had some experience kludging together solutions to build XML files, and didn't like the idea of implementing a parser/writer for each translator I might write.&lt;br /&gt;&lt;br /&gt;So I decided to build a centralized CMSD XML parser/generator, utilizing Microsoft's built-in DOM libraries to do the actual file I/O from/to XML files, and I would write the code to translate XML elements into instances of CMSD classes.  So I built that central tool as a COM/ActiveX class, using VB6 (I know, could I possibly use something older?).  So to read a CMSD file I just have to create a new CMSD object and tell it to read the file, and I get all the CMSD data in a nice, easy to program against object model.  And, I only have to write and maintain one XML I/O code base, which makes me happy.&lt;br /&gt;&lt;br /&gt;So I called this class the CMSD API (very original, I know) and started writing translators.  To cut my teeth on the standard, I started off just building something to build a QUEST model from a CMSD API object, just using a simple XML file that NIST had provided to me to demonstrate the XML format.  That one translator has turned into about a dozen different translators, some proofs of concept, and some potentially useful tools.&lt;br /&gt;&lt;br /&gt;So here, after six paragraphs, is where I get to my point.  We're reaching the stage where these translators are ready for some public consumption.  They're hopefully useful enough that people can use them, though because the CMSD standard isn't really set in stone yet, I'll refrain from calling them CMSD-based tools; rather they're just tools that utilize a custom XML format.&lt;br /&gt;&lt;br /&gt;Okay, so seven paragraphs in, and my point is that I'm looking for simulation users interested in trying this software out.  I can't guarantee I can take everyone, and ideally you should be a user of more than one of the following tools:&lt;br /&gt;1. DELMIA QUEST&lt;br /&gt;2. eVSM&lt;br /&gt;3. ProModel&lt;br /&gt;4. Arena&lt;br /&gt;5. Excel&lt;br /&gt;6. Simio&lt;br /&gt;7. FlexSim&lt;br /&gt;&lt;br /&gt;Now, if you only use one of the above-listed simulation packages, that's okay. I've also been working on a standalone CMSD editor, that hopefully in the future can take the place of a simulation package builder interface (and just use the simulation package as a solver).  Also, if you're good at programming in VBA and would like to be able to build your own translators with my CMSD API, let me know, as I'd like to get feedback on the quality of the methods in the API.&lt;br /&gt;&lt;br /&gt;So if you're interested in joining a beta test, &lt;a href="http://spreadsheets.google.com/viewform?hl=en&amp;formkey=dElQbGJaeF9qWFZVazBZeEx1d3NYYmc6MA.."&gt;contact me&lt;/a&gt;.  In the meantime you can see the documentation for these tools grow as I write it (thank you, Google Docs):&lt;br /&gt;&lt;a href="http://docs.google.com/View?id=dgww9c7m_235cwq9c5ff"&gt;Documentation&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7617875156166323832?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7617875156166323832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7617875156166323832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7617875156166323832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7617875156166323832'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/04/core-manufacturing-simulation-data.html' title='Core Manufacturing Simulation Data'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-2781463115199116583</id><published>2010-04-15T16:27:00.004-04:00</published><updated>2010-04-15T16:37:56.176-04:00</updated><title type='text'>OR Exchange</title><content type='html'>I've been a member at &lt;a href="http://www.StackOverflow.com"&gt;StackOverflow&lt;/a&gt; since it launched to the public.  For those who don't know what it is, it's basically a question and answer site built the way a question-answer site should be built; namely, every page deals with questions, and answers (rather than traditional forum type sites, which are more for threaded discussion, but get question-answer sits shoehorned in).  They've built a fantastic community, which means you can go on there and ask a programming question and get an answer in a pretty respectable amount of time.&lt;br /&gt;&lt;br /&gt;About 6 months ago they launched StackExchange, which was a service that let people set up their own question-answer sites, with the same look and feel as StackOverflow, but you were responsible for getting your community in order.  Apparently a lot of the sites that were created never really got going very well, and that's led the StackExchange people to change the rules a bit.  From now on, if you want to start a StackExchange site, you have to put together a proposal convincing them why they should build it, and then you have to rally enough users to initialize the site with questions and answers, and hopefully get enough momentum going that they can launch your site and you end up with a community where you can get answers to your niche questions.&lt;br /&gt;&lt;br /&gt;The point of this post, then, is to talk about &lt;a href="http://www.or-exchange.com"&gt;OR-Exchange&lt;/a&gt;.  OR-Exchange is a StackExchange site built for answering Operations Research problems, which involves a lot of math programming, but simulation is definitely a part of that.  Unfortunately, the StackExchange people don't seem to think there's enough participation in the site, so it's got 3 months left before it's shut down (we'll call it early July is the termination date).&lt;br /&gt;&lt;br /&gt;So I encourage you, if you're a simulation user (and why wouldn't you be if you're reading this, unless you're my mom (who doesn't read this, by the way)) to visit &lt;a href="http://www.or-exchange.com"&gt;OR-Exchange.com&lt;/a&gt; and join the community, and maybe ask some general purpose simulation questions (if you know the answer, you're allowed to answer your own questions, too).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-2781463115199116583?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/2781463115199116583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=2781463115199116583' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/2781463115199116583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/2781463115199116583'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/04/or-exchange.html' title='OR Exchange'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-6476768553997001712</id><published>2010-03-31T10:12:00.003-04:00</published><updated>2010-03-31T10:20:23.618-04:00</updated><title type='text'>Interpreting BCL Error Codes</title><content type='html'>From time to time I'll have to write an SCL macro that executes some BCL statements.  It's usually pretty straightforward, just issue the command using the BCL() function in an SCL macro, and it'll return a numeric error code, including 0 for a normal return.&lt;br /&gt;&lt;br /&gt;Sometimes though, especially when working with user-provided data, these commands can fail (often due to invalid characters or some such thing).  When a BCL command fails, the BCL() function returns a non-zero number and an error message gets printed to the screen for the user to see.&lt;br /&gt;&lt;br /&gt;However, a lot of the SCL macros I write are run pretty much autonomously, so anything printed to the screen gets lost to me.  That's why I usually have a function for logging messages to a text file, for analysis after the fact, to see why some macro failed.&lt;br /&gt;&lt;br /&gt;So, getting to my point, finally, when I am using the BCL statement, I like to have my own routine (named exec_bcl_cmd or something) that wraps all this stuff together: executing the BCL statement, evaluating any error code return, and logging that to a text file.  I've created an example SCL file that shows most of this, just a procedure named exec_bcl_cmd, that executes a bcl statement string, then converts the bcl return code integer into a more descriptive error message (pulled from the bclerr.inc file).&lt;br /&gt;&lt;br /&gt;You can download it &lt;a href="https://docs.google.com/leaf?id=0B3iGaoQCwunoZWJhMDI5ZTgtNzMyOC00OWQwLTkxZjAtNTA5NDA3NGEyY2E4&amp;hl=en"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-6476768553997001712?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/6476768553997001712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=6476768553997001712' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/6476768553997001712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/6476768553997001712'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/03/interpreting-bcl-error-codes.html' title='Interpreting BCL Error Codes'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-8095734939384206248</id><published>2010-03-24T15:30:00.002-04:00</published><updated>2010-03-24T15:34:18.347-04:00</updated><title type='text'>Name Change</title><content type='html'>If anyone even reads this to notice, I've changed the name of this blog from just DELMIA QUEST to DELMIA QUEST and Manufacturing Simulation.  I did this because, for the last year or so, I've been dedicating a lot less time to QUEST than I previously did, and a lot more time on using Value Stream Mapping for building simulation models, as well as some other production design/analysis tools.&lt;br /&gt;&lt;br /&gt;I'm going to continue focusing a lot of content ("a lot" is used loosely here meaning there's not much content to this blog anyway) on QUEST, but I also want to be able to talk a bit more about the other stuff I do, and a lot of that applies in some way to QUEST, ultimately.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-8095734939384206248?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/8095734939384206248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=8095734939384206248' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8095734939384206248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8095734939384206248'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/03/name-change.html' title='Name Change'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-761259718815489323</id><published>2010-03-24T14:26:00.010-04:00</published><updated>2010-03-24T15:27:09.633-04:00</updated><title type='text'>How to Populate a Value Stream Map with Simulation Data</title><content type='html'>So if you look back in the archives of this blog you might see I've done some work taking data from Value Stream Maps (VSM's) and using it to build QUEST models semi-automatically.  With pretty much any simulation package, a user is presented with an interface that exposes pretty much every option imaginable.  With VSM, a user only tacks on the data they have available.  Some people get overwhelmed by too many dialog options at once.  In essence, when you're building a VSM with the intent of using it for simulation, you're only sticking in the data you have, and ignoring all the other options you don't have information for, with a much simplified interface (the VSM software).&lt;br /&gt;&lt;br /&gt;It's also important to note that there are two different world views for manufacturing simulation packages, really, that I've seen: resource-based, and process-based.  In a resource-based world view, you see all your machines on a virtual floor with some labor objects, maybe.  Parts or whatever you call them enter at a source and jump around machines and modeling elements corresponding to, for the most part, physical objects.  A process-based view is different, in that you basically get a flow chart where each block usually represents a process or a decision or something.  The part item arrives at a source, again, but now moves between processes in sequence through the flow chart.  A process can require different resources, so that parts end up getting blocked like in real life.  Essentially both world views contain the same information and provide the same outputs, but just go about getting the outputs in different ways.&lt;br /&gt;&lt;br /&gt;I'll tell you right now that a VSM pretty much takes on a process-based world view, except that people usually name their process boxes after the resource where the process is done.  So there's sort of an implicit definition there, saying that we're doing a process, and that this process requires a resource based on the name of the process.&lt;br /&gt;&lt;br /&gt;You may or may not know about QUEST's world view, so I'll go over that quickly: it's a resource-based view, with a construct called a "process" that holds attributes on the process, like what labor resources it requires and what the cycle time is and all that.  There is also a "part class" construct that holds some attributes, including the sequence of processes the part needs to be "completed".  A machine in QUEST can be told what processes it's able to perform, so that when a part arrives at it, it decides what process to do on that part, and we can then route the part on to its next process (whatever machine that may be at).&lt;br /&gt;&lt;br /&gt;So a few years ago a client presented us with a VSM they had created that detailed the process flow for a line they wanted to simulate.  It contained some cycle times, but it was, otherwise, pretty much just a process sequence.  &lt;br /&gt;&lt;br /&gt;So I had to figure out, how can I take this information in an &lt;a href="http://evsm.com"&gt;eVSM&lt;/a&gt; file (which has an automatic export to Excel) and turn it into a QUEST model.  It was pretty easy to just do a one-to-one build of processes in QUEST; one process for each process block in the VSM.  But the missing component of data, then, was how to tie a process to one or more machines in a QUEST model?&lt;br /&gt;&lt;br /&gt;To tie a VSM process to a QUEST machine resource, I simply had to add a tag onto a process with the ID of the machine to attach it to (a many processes to one machine relationship).  So the actual SCL code to do this consisted of reading through the Workstation column in the Excel file, and for each unique value in that column, just build a machine with that name.  Then read through every process (row) and create a process in QUEST with that name.  Then, look at the Workstation column for that process row, and assign the process to that machine (the Workstation value can actually be a comma-delimited list to specify that multiple machines can handle the process).&lt;br /&gt;&lt;br /&gt;The next challenge was process sequencing.  I could have assumed that the Excel output from eVSM was in order of the process sequence, but that'd be pretty limiting to a simulation user.  eVSM requires that you provide a tag shape to each process shape, and the tag value must be unique for each process.  So, I required that the sequence be encoded through just specifying a process' next operation in the sequence (using that next operations' tag text) as a process attribute.  Then, the SCL to build the QUEST model just has to set the process sequence for a part class to the sequence of operations in that Excel file.  This way of creating the sequence also allowed me to look at each individual process, and find whatever processes were feeding into it.  So if I found two or more processes that both output to a single process, that single process must be an assembly operation, and require a part from each of them before running the process.&lt;br /&gt;&lt;br /&gt;That brings me to my next, and final data requirement: the part type.  Like I said, QUEST likes to have a part class for each unique part type in a system (there are exceptions of course, but I won't get into them).  Each part type (in the type of model we're building here) should then have a sequence of operations for the purpose of routing and process execution.  So to specify the part type for a process, I just required there be a Product attribute on each process, and the SCL chunks through the data and identifies the sequence of operations and assembly points and all that automatically.&lt;br /&gt;&lt;br /&gt;But, to close out, we really need three pieces of information to successfully build a (however basic) QUEST model: what are our part types, what are their process sequences, and where do those processes get done.  And a VSM is perfectly adequate at providing that information.  I meant to be a lot more succinct in my explanation of how the conversion works, but I'm not sure it's possible.  I'll give it a shot again some other time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-761259718815489323?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/761259718815489323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=761259718815489323' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/761259718815489323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/761259718815489323'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/03/how-to-populate-value-stream-map-with.html' title='How to Populate a Value Stream Map with Simulation Data'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-5974285588393011782</id><published>2010-02-18T12:57:00.001-05:00</published><updated>2010-02-18T13:29:56.542-05:00</updated><title type='text'>Winter Sim Presentation</title><content type='html'>&lt;div&gt;This past December, I was fortunate enough to be able to present some of the work I've been doing with extracting data from Value Stream Maps and turning it into simulation data.  I started off using QUEST as the simulation tool for the data, and last March (2009) I got the green light to start working on implementing the &lt;a href="http://www.sisostds.org/index.php?tg=articles&amp;amp;idx=More&amp;amp;topics=20&amp;amp;article=42"&gt;Core Manufacturing Simulation Data (CMSD)&lt;/a&gt; format.  The CMSD is meant to be a generic simulation data interchange format, sort of like STEP is for CAD.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, here's the presentation I made at Winter Sim.  If you want to talk about it, you can &lt;a href="http://spreadsheets.google.com/viewform?hl=en&amp;amp;formkey=dElQbGJaeF9qWFZVazBZeEx1d3NYYmc6MA.."&gt;contact me here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;iframe src="http://docs.google.com/present/embed?id=dgww9c7m_126cn5vbssm" frameborder="0" width="410" height="342"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-5974285588393011782?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/5974285588393011782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=5974285588393011782' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5974285588393011782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5974285588393011782'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/02/winter-sim-presentation.html' title='Winter Sim Presentation'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7934790827750043311</id><published>2010-01-20T15:16:00.006-05:00</published><updated>2010-01-20T15:26:27.673-05:00</updated><title type='text'>Labor shirt colors</title><content type='html'>This is a stupid, however somewhat useful SCL macro. Sometimes I end up with a model with lots of laborers who all have the same color shirt. Call me crazy, but I think the model presents a little better if the labors don't all look the same.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So here it is, a stupid SCL macro you can use to change all your labors' shirt colors (note it won't let the color be the same as his pants or skin color (at least with the default laborer I'm using))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So &lt;a href="http://docs.google.com/leaf?id=0B3iGaoQCwunoY2ZjM2JmNDYtYzUzYi00YWRhLTg1ZTktZmMxMzZkNjQ2OTE0&amp;amp;hl=en"&gt;here&lt;/a&gt; it is&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"    style="font-family:monospace;font-size:100%;color:#0000FF;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px; white-space: pre;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7934790827750043311?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7934790827750043311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7934790827750043311' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7934790827750043311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7934790827750043311'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/01/labor-shirt-colors.html' title='Labor shirt colors'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-6998780193237543734</id><published>2010-01-20T14:57:00.002-05:00</published><updated>2010-01-20T15:03:51.029-05:00</updated><title type='text'>SCL Examples</title><content type='html'>I recently received an email from a student using QUEST who was looking for examples of SCL.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I told him to first look at the default QUEST logics at QUESTlib\Sysdef\Logics, to see how QUEST uses SCL.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But I can't think of any good examples of how to write SCL macros. So I found an old macro I wrote that dumps all the process assignments for each laborer in a model to a tab-delimited text file. I figured it would be a good example of how to use SCL to get information out of a model, and shows some examples of different SCL syntax.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can download it &lt;a href="http://docs.google.com/leaf?id=0B3iGaoQCwunoYmQ0N2MwZTItYTE4Ny00Yjk4LTk3YjMtMWNlODFmOGZmMWVk&amp;amp;hl=en"&gt;here&lt;/a&gt;, hopefully; I put it on Google Docs as just a file, so you should be able to go download it there.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-6998780193237543734?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/6998780193237543734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=6998780193237543734' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/6998780193237543734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/6998780193237543734'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2010/01/scl-examples.html' title='SCL Examples'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-786593426574046275</id><published>2009-09-01T09:03:00.003-04:00</published><updated>2009-09-01T09:49:38.569-04:00</updated><title type='text'>Examples of using C_EXEC in SCL</title><content type='html'>SCL provides a function called C_EXEC which will allow you to execute functions in Windows DLL files.  If you have used the Declare Function ... functionality in VBA then you'll see this is the same kind of functionality.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Basically, to use C_EXEC you need to know the name of the function in the DLL file, as well as its argument list.  For example, the Sleep function resides in the kernel32.dll file that comes with Windows.  It takes one argument, which is the sleep time in milliseconds.  This function simply delays for the specified period of time, then returns control of the program back to whatever called it.  This allows you to put a pause of whatever length you want in your program.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since there is no built-in sleep function in SCL, this is a good function to have handy, &lt;a href="http://delmiaquest.blogspot.com/2009/05/precompiled-always-there-scl-routines.html"&gt;always compiled and ready to use&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The syntax for the C_EXEC function is simple:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;C_EXEC( routine_name_and_location , arg1 , arg...)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;where routine_name_and_location is the dll filename and function name separated by a colon (:).  Any extra arguments to C_EXEC should correspond to arguments in the DLL function.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;So for the Sleep function, a C_EXEC call would look like this:&lt;/div&gt;&lt;div&gt;C_EXEC( 'kernel32.dll:Sleep' , 1000 )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Calling this in SCL would make your SCL code delay for 1 second.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We can wrap this in a nice routine that you can leave compiled all the time:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;routine sleep( milliseconds : Integer ) : Integer&lt;/div&gt;&lt;div&gt;Const&lt;/div&gt;&lt;div&gt;   THE_DLL 'kernel32.dll'&lt;/div&gt;&lt;div&gt;   THE_CMD 'Sleep'&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   func_return : Integer&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;/*&lt;/div&gt;&lt;div&gt;Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)&lt;/div&gt;&lt;div&gt;*/&lt;/div&gt;&lt;div&gt;func_return = c_exec( THE_DLL + ":" + THE_CMD , \&lt;/div&gt;&lt;div&gt;               milliseconds )&lt;/div&gt;&lt;div&gt;return true&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's another example using the mciSendStringA function in winmm.dll to open your CD drive door (I know, very useful):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;procedure open_cd_drive()&lt;/div&gt;&lt;div&gt;Const&lt;/div&gt;&lt;div&gt;   THE_DLL 'winmm.dll'&lt;/div&gt;&lt;div&gt;   THE_CMD 'mciSendStringA'&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   func_return : Integer&lt;/div&gt;&lt;div&gt;   lpstrCommand : String&lt;/div&gt;&lt;div&gt;   lpstrReturnString : String&lt;/div&gt;&lt;div&gt;   uReturnLength : Integer&lt;/div&gt;&lt;div&gt;   hwndCallback : Integer&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;/*&lt;/div&gt;&lt;div&gt;Public Declare Function SendCDcmd Lib "winmm.dll" \&lt;/div&gt;&lt;div&gt;    Alias "mciSendStringA" ( \&lt;/div&gt;&lt;div&gt;    ByVal lpstrCommand As String, \&lt;/div&gt;&lt;div&gt;    ByVal lpstrReturnString As String, \&lt;/div&gt;&lt;div&gt;    ByVal uReturnLength As Long, \&lt;/div&gt;&lt;div&gt;    ByVal hwndCallback As Long) As Long&lt;/div&gt;&lt;div&gt;*/&lt;/div&gt;&lt;div&gt;lpstrCommand = 'set CDAudio door open'&lt;/div&gt;&lt;div&gt;lpstrReturnString = ''&lt;/div&gt;&lt;div&gt;uReturnLength = 127&lt;/div&gt;&lt;div&gt;hwndCallback = 0&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;func_return = c_exec( THE_DLL + ":" + THE_CMD , \&lt;/div&gt;&lt;div&gt;               lpstrCommand , \&lt;/div&gt;&lt;div&gt;               lpstrReturnString , \&lt;/div&gt;&lt;div&gt;               uReturnLength , \&lt;/div&gt;&lt;div&gt;               hwndCallback )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hopefully this gives you a good taste of what is possible with using C_EXEC to extend some of the functionality of SCL beyond what's currently available.  If you want to see how you can create your own Windows DLL (and thereby provide your own custom functions in a compiled form) you can look at &lt;a href="http://windowsdevcenter.com/pub/a/windows/2005/04/26/create_dll.html"&gt;this web site&lt;/a&gt;.  At some point in the future I hope to release a DLL library of functions to help add some functionality to SCL.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-786593426574046275?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/786593426574046275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=786593426574046275' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/786593426574046275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/786593426574046275'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/09/examples-of-using-cexec-in-scl.html' title='Examples of using C_EXEC in SCL'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-23404341192421172</id><published>2009-08-31T08:19:00.004-04:00</published><updated>2009-08-31T08:44:41.806-04:00</updated><title type='text'>Converting SketchUp models to QUEST pdb files</title><content type='html'>&lt;a href="http://sketchup.google.com/"&gt;SketchUp&lt;/a&gt; is a 3D modeling tool which was originally developed by @Last Software, which was purchased by Google.  Google now provides the SketchUp tool for free, to encourage modelers to create real-life geometry for its Google Earth tool, as well as populating their &lt;a href="http://sketchup.google.com/3dwarehouse/"&gt;3D Warehouse&lt;/a&gt;, which is a huge repository of 3D models.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SketchUp is very easy to use, easy to learn, and very powerful for being a free tool.  It's much easier to use than the QUEST CAD world, though the free version of SketchUp has some limitations which make it difficult to get SketchUp models into a format that QUEST will recognize.  The free version will only export to the Collada format, which is not supported by QUEST.  This means you have to use some intermediary program that can read Collada files and export to something QUEST understands (i.e. VRML 1.0, DXF, OpenFlight Obj).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Until now, the easiest way to get from SketchUp into QUEST was to shell out $495 for a license of SketchUp Pro, which includes a DXF exporter.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I say until now, because luckily the &lt;a href="http://www.guitar-list.com/download-software/convert-sketchup-skp-files-dxf-or-stl"&gt;Guitar-List.com&lt;/a&gt; website has put together a Ruby &lt;a href="http://www.guitar-list.com/download-software/convert-sketchup-skp-files-dxf-or-stl"&gt;plugin&lt;/a&gt; for SketchUp that exports from SketchUp to DXF, for free.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That's only half the battle, so with permission from Guitar-List.com I was able to modify their script to use QUEST's built-in DXF to PDB conversion tool so you can automatically export from QUEST to DXF to PDB.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can download the ruby script &lt;a href="http://fournier.jonathan.googlepages.com/skp_to_pdb.rb"&gt;here&lt;/a&gt;.  Download it to your Program Files/Google/Google Sketchup/Plugins folder.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One pre-requisite for this script to work, however, is that you must have your dwg2pdb.bat file configured so that DENEB_PATH is set to whatever your Deneb or Delmia path is.  You also must set the DENEB_PROD_DIR to point to the quest folder (default was vmap for me) and make sure LM_LICENSE_FILE is pointing to the right place.  These settings should more or less mimic some of the settings from your quest.bat file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next copy the dwg_cmd file from your quest folder to the bin folder, and set your default units to inches.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The last thing you'll have to do is edit line 64 of the skp_to_pdb.rb file to point to your dwg2pdb.bat and dwg_cmd files.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It may take a bit of work to get set up, but I've been using it for a few weeks and it's nice to be able to use a modern 3D drawing tool and easily load the geometry in QUEST.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A few notes on usage, make sure you draw to the proper scale in SketchUp, and be mindful of the origin.  If your geometry is far from the origin in SketchUp it'll be far from the origin in QUEST, too.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Again if you want to contact me directly just hit me up &lt;a href="http://spreadsheets.google.com/viewform?hl=en&amp;amp;formkey=dElQbGJaeF9qWFZVazBZeEx1d3NYYmc6MA.."&gt;here&lt;/a&gt; or leave a comment.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-23404341192421172?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/23404341192421172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=23404341192421172' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/23404341192421172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/23404341192421172'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/08/converting-sketchup-models-to-quest-pdb.html' title='Converting SketchUp models to QUEST pdb files'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-4808714098309317465</id><published>2009-08-25T15:09:00.004-04:00</published><updated>2009-08-25T15:29:13.240-04:00</updated><title type='text'>How to run QUEST from Excel VBA and wait for QUEST to finish</title><content type='html'>This post is not meant to show you how you can use VBA to run BCL commands in QUEST.  It's just a small tweak to how we run QUEST in &lt;a href="http://delmiaquest.blogspot.com/2009/02/how-to-run-bcl-from-excel-simple-way.html"&gt;this previous post&lt;/a&gt;.  In that previous VBA solution, I used the baked-in Shell command to run a QUEST.bat file in BCL mode.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One reason I can think of for using this functionality is being able to automatically run some experimentation in QUEST, without having to mess with sockets (until we can get an easy to use library for QUEST sockets).  This way we can have some Excel worksheet with accompanying VBA code that will run QUEST, wait for QUEST to exit, then check some output file from QUEST before advancing in the experiment.  I am working on a project where this is pretty much exactly what I'll be doing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To make this work, we just need to use a different Shell command, that will effectively halt execution of our VBA code while QUEST runs, and resume execution once the QUEST process we started ends.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Basically, we will re-use the code found &lt;a href="http://www.freevbcode.com/ShowCode.Asp?ID=99"&gt;here&lt;/a&gt; to replace our basic Shell call.  All the linked code does is start QUEST using the Shell command, and uses a few Windows API calls to monitor the QUEST.exe process we started, looping until that process ends.  Once the process ends, we exit the loop and VBA continues executing code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've updated the QUEST_BCL_Addin.xla file which can be downloaded &lt;a href="http://fournier.jonathan.googlepages.com/QUEST_BCL_Addin.xla"&gt;here&lt;/a&gt; to include this new ShellAndWait functionality.  If you call the SaveABCL function with LaunchQUEST = True and TransferToMenu = False then your code will wait for QUEST to exit before resuming.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'd like to start adding some QUEST BCL User Defined Functions to this addin in the near future.  I have some written already, but would like to get them properly formatted for release.  If you have any you'd like to donate drop me a line using &lt;a href="http://spreadsheets.google.com/viewform?hl=en&amp;amp;formkey=dElQbGJaeF9qWFZVazBZeEx1d3NYYmc6MA.."&gt;this contact form&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-4808714098309317465?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/4808714098309317465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=4808714098309317465' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4808714098309317465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4808714098309317465'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/08/how-to-run-quest-from-excel-vba-and.html' title='How to run QUEST from Excel VBA and wait for QUEST to finish'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-4169550787216718329</id><published>2009-08-25T09:56:00.009-04:00</published><updated>2009-08-25T10:19:39.373-04:00</updated><title type='text'>Split function in SCL</title><content type='html'>&lt;pre  style="font-family:Consolas;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;VBA has a function called Split that is handy for parsing strings to an array based on some delimiter.  All you have to do is dim out an array variable and say:&lt;/span&gt;&lt;/pre&gt;&lt;pre  style="font-family:Consolas;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;ArrayVar = Split( "the,split,string" , "," ) and your ArrayVar will contain three strings, "the" , "split", and "string".&lt;/span&gt;&lt;/pre&gt;&lt;pre  style="font-family:Consolas;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;There is no in-built function in SCL to do this, so I have put together something that should work in a similar fashion.  I have named the function the same, though the difference here is because SCL's arrays are fixed in size, where with VBA you can dynamically size arrays.&lt;/span&gt;&lt;/pre&gt;&lt;pre   style="font-family:Consolas;font-size:10 pt;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;To get around this, you must first declare a String array in the Var section of your calling procedure (or globally), and pass that into the Split function as the last argument.  You must also provide the upper bound of the array to the function.  This upper bound is not the highest index of the array (which is one minus the size of the array), but just the size of the array.  One easy way to use this information is to declare your arrays using Const's denoting the size of the array.  For example:&lt;/span&gt;&lt;/pre&gt;&lt;pre   style="font-family:Consolas;font-size:10 pt;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;procedure some_proc()&lt;br /&gt;Const&lt;br /&gt;arr_size 10&lt;br /&gt;Var&lt;br /&gt;my_array : Array[ arr_size ] of String&lt;/span&gt;&lt;/pre&gt;&lt;pre   style="font-family:Consolas;font-size:10 pt;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;........&lt;/span&gt;&lt;/pre&gt;&lt;pre   style="font-family:Consolas;font-size:10 pt;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;So, in this case, if you wanted to split a string into my_array, you would do this:&lt;/span&gt;&lt;/pre&gt;&lt;pre   style="font-family:Consolas;font-size:10 pt;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;num_elems = split( 'some delimited line' , ' ' , arr_size , my_array )&lt;/span&gt;&lt;/pre&gt;&lt;pre   style="font-family:Consolas;font-size:10 pt;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;where num_elems is the number of chunks of text split into the array.  If there are more chunks than there are bins in your array, any trailing chunks will be ignored, and no error will be raised.&lt;/span&gt;&lt;/pre&gt;&lt;pre   style="font-family:Consolas;font-size:10 pt;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;I have tested this routine a bit, so it should work fairly well, even with multi-character delimiters.  On a side note, you should put this routine into your &lt;a href="http://delmiaquest.blogspot.com/2009/05/precompiled-always-there-scl-routines.html"&gt;always available routines in QUEST&lt;/a&gt;.&lt;/span&gt;&lt;/pre&gt;&lt;pre   style="font-family:Consolas;font-size:10 pt;"&gt;&lt;br /&gt;&lt;span class="bold"  style="background-color: #FFFFFF;color:#0000FF;"&gt;routine&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; split&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;(&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_line : &lt;/span&gt;&lt;span class="bold italic"  style="background-color: #FFFFFF;color:#0000FF;"&gt;String&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_delim : &lt;/span&gt;&lt;span class="bold italic"  style="background-color: #FFFFFF;color:#0000FF;"&gt;String&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; max_elements : &lt;/span&gt;&lt;span class="bold italic"  style="background-color: #FFFFFF;color:#0000FF;"&gt;Integer&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span class="bold"  style="background-color: #FFFFFF;color:#0000FF;"&gt;Var&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_array : &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#000080;"&gt;Array&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;[]&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;of&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span class="bold italic"  style="background-color: #FFFFFF;color:#0000FF;"&gt;String&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;)&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; : &lt;/span&gt;&lt;span class="bold italic"  style="background-color: #FFFFFF;color:#0000FF;"&gt;Integer&lt;br /&gt;&lt;/span&gt;&lt;span class="bold"  style="background-color: #FFFFFF;color:#0000FF;"&gt;Var&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;   write_idx &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;,&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; delim_idx : &lt;/span&gt;&lt;span class="bold italic"  style="background-color: #FFFFFF;color:#0000FF;"&gt;Integer&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;   check_char : &lt;/span&gt;&lt;span class="bold italic"  style="background-color: #FFFFFF;color:#0000FF;"&gt;String&lt;br /&gt;&lt;/span&gt;&lt;span class="bold"  style="background-color: #FFFFFF;color:#0000FF;"&gt;Begin&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;   &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;while&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;(&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;len&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;(&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_line &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;)&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;0&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;)&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;do&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;&lt;span class="Apple-style-span"  style="color:#008000;"&gt;&lt;span class="Apple-style-span" style="background-color: rgb(255, 255, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;      &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;(&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; write_idx &lt;samp&gt;&lt;&lt;/samp&gt; max_elements &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;)&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;then&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;         delim_idx &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;index&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;(&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_line &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;,&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_delim &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;,&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;1&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;         &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;--write( 'delim_idx=' , delim_idx , cr )&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;         &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;(&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; delim_idx &gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;0&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;)&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;then&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;            the_array&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; write_idx &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;leftstr&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;(&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_line &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;,&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; delim_idx - &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;1&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;            the_line &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;rightstr&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;(&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_line &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;,&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;len&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;(&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_line &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;)&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; - delim_idx - &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;len&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;(&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_delim &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;)&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;+&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;1&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;         &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;else&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;            &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;-- no more delimeters left - write the last of the_line to the array&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;            the_array&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; write_idx &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; the_line&lt;br /&gt;     the_line &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#000080;"&gt;''&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;-- empty the_line so we break from the while loop&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;         &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;endif&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;         write_idx &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; write_idx &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;+&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;1&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;      &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;else&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;         the_line &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#000080;"&gt;''&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;-- empty the_line so we break from the while loop&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;      &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;endif&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;   &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;endwhile&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt;   &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#008000;"&gt; write_idx &lt;/span&gt;&lt;span style="background-color: #FFFFFF;color:#FF0000;"&gt;-- return number of pieces written to array&lt;br /&gt;&lt;/span&gt;&lt;span class="bold"  style="background-color: #FFFFFF;color:#0000FF;"&gt;End&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-4169550787216718329?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/4169550787216718329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=4169550787216718329' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4169550787216718329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4169550787216718329'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/08/split-function-in-scl.html' title='Split function in SCL'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7370097700228253650</id><published>2009-08-18T15:06:00.005-04:00</published><updated>2009-08-25T15:36:32.852-04:00</updated><title type='text'>Evaluating string expressions in SCL</title><content type='html'>&lt;div&gt;I have found a few cases where it would be better to allow a user to enter not just numbers, but some expression that can be evaluated to a number.  An simple example of this is just evaluating calculations, like "10+2*(8/5)".  Ordinarily, if someone entered this and you were expecting a number, you may have a real problem.  But luckily QUEST provides a means for evaluating strings to Real values, or even to String values.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The method involves calling out to BCL to evaluate an SCL expression, returning either a String or Real value.  The associated BCL commands are SCL_NUMERIC_EXPR and SCL_STRING.  You just pass in the SCL expression and read the resulting BCL_MSG variable as the result.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here are two SCL routines that make these BCL commands a bit easier to use:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;BCL_VAR&lt;/div&gt;&lt;div&gt;   bcl_msg : String&lt;/div&gt;&lt;div&gt;routine evaluate_scl_expr( the_string : String ) : Real&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   bcl_err : Integer&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;   bcl_err = bcl( "SCL_NUMERIC_EXPR('" + the_string + "')" )&lt;/div&gt;&lt;div&gt;   return val( bcl_msg )&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;routine eval_scl_string( the_expr : String ) : String&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   bcl_err : Integer&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;   bcl_err = bcl( "SCL_STRING_EXPR('" + the_expr + "')" )&lt;/div&gt;&lt;div&gt;   return bcl_msg&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7370097700228253650?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7370097700228253650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7370097700228253650' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7370097700228253650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7370097700228253650'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/08/evaluating-string-expressions-in-scl.html' title='Evaluating string expressions in SCL'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-8576206016332889609</id><published>2009-08-04T11:54:00.001-04:00</published><updated>2009-08-04T11:54:53.070-04:00</updated><title type='text'>Quest_Geom</title><content type='html'>&lt;div class="Section1"&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;I've used the same solution Martin described, and clumsy is an understatement, but it has worked fairly well for me in the past.&amp;nbsp; From what I've seen of the format, it's similar to the &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;wavefront&lt;/font&gt;&lt;/span&gt; &lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;obj&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt; format, if that helps...&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;Here's an overview of how a basic QUEST geometry file is laid out, just from my messing around with these files...I have no expertise in how the format works, this is all based on observation and guesses.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;All these observations are based on a basic rectangular block I created in QUEST D5R18.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;Basically the file starts with the number 12, probably a version number or something, then some vector transformation information, probably for locating and rotating the geometry, though I've never messed around with that.&amp;nbsp; After all this information there is an asterisk indicating the geometry section is beginning.&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;&amp;nbsp; I've found that older geometry files don't have this asterisk to delineate between geometry sections.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;For a basic rectangular box, there are 8 points, for each of the 8 corners on the box.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;img src="http://docs.google.com/File?id=dgww9c7m_119g4tsdrc2_b" width="434" height="327" alt="" border="0"&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;After the first asterisk, there is a number indicating the number of points in the geometry.&amp;nbsp; Points serve as vertices for lines.&amp;nbsp; After listing the number of vertices, you list out the xyz location of each vertex.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;After the vertices you list out something, and I either never knew or forgot what it is, but the geometry I'm looking at now has a zero.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;Next we indicate the number of and list out all the lines in the geometry.&amp;nbsp; So if we have a rectangular box we have a total of 12 lines&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;, as you can see in the diagram below.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;To describe a line, we have to provide the index of each of the two vertices in the line.&amp;nbsp; QUEST basically reads the initial list of points in as a zero-indexed array, which means the first entry is point number zero in the array.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;img src="http://docs.google.com/File?id=dgww9c7m_120fwknwfc4_b" width="624" height="751" alt="" border="0"&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;In this case, line 1 is composed of points 1 and 2, so our first line &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;is represented as "1 2"&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;Next we indicate the number of and list out all the polygon faces in the geometry.&amp;nbsp; So if we have a rectangular box we have a total of 6 faces, as you can see in the diagram below.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;img src="http://docs.google.com/File?id=dgww9c7m_121c6fh4jd7_b" width="624" height="285" alt="" border="0"&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;The definition of a polygon is simply a list of the line indices composing that face&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt; preceded by the number of lines composing the face&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;.&amp;nbsp; The direction of the line makes a difference, here.&amp;nbsp; The lines of a polygon must all go in the same direction - either clockwise around the face or counter-clockwise.&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;So, if a line is defined backwards from the direction of the other lines in the polygon, you must place a minus sign before that line number, and QUEST will interpret that and represent the polygon properly.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;The last section we'll discuss is text.&amp;nbsp; I'm not entirely sure where the text section goes, but with the simple polygon block example, it seems we can just put the text section after the polygon face section.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;To define the text, you must first provide the number of text objects to place on the geometry.&amp;nbsp; Next, start listing out the text values.&amp;nbsp; The first line of a text definition is the text string value.&amp;nbsp; The next four lines after that represent the location/rotation transform for the text placement.&amp;nbsp; To be honest, I'm not really sure how to interpret this.&amp;nbsp; At some point I'll try to post some routines I built for reading and writing these rotation matrices, but in the mean time, to work with text, there is an easier way.&amp;nbsp; Basically, just build your basic geometry, and manually place the text, save that out, and copy the transform matrix and use that.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;So what we end up with &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;with&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt; all this information should be a simple plain text file that we can feed into QUEST to build some simple rectangular box.&amp;nbsp; Here it is:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;&amp;nbsp;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;I hope this has helped give some basic idea of how to build simple geometry files without using QUEST. &amp;nbsp;Leave a comment&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:'Times New Roman'"&gt;&lt;font size="3"&gt;&amp;nbsp;if you have any questions about QUEST geometry that you'd like to discuss.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-8576206016332889609?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/8576206016332889609/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=8576206016332889609' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8576206016332889609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8576206016332889609'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/08/questgeom.html' title='Quest_Geom'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7845495786484224079</id><published>2009-07-23T16:35:00.002-04:00</published><updated>2009-07-23T16:35:01.032-04:00</updated><title type='text'>eVSM to QUEST demo video</title><content type='html'>Here's a youtube video showing the eVSM to QUEST tool I've been developing at the Connecticut Center for Advanced Technology (&lt;a href="http://www.ccat.us/"&gt;CCAT&lt;/a&gt;).&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;If you're a QUEST user and have the &lt;a href="http://www.evsm.com/"&gt;eVSM software&lt;/a&gt;, and would like to try this functionality out, visit &lt;a href="http://modsim.ccat.us/eVSM_Utilities"&gt;http://modsim.ccat.us/eVSM_Utilities&lt;/a&gt; and let us know you're interested.  I'll be in contact when the time comes.&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/QjakW29CQps&amp;amp;hl=en&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/QjakW29CQps&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7845495786484224079?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7845495786484224079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7845495786484224079' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7845495786484224079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7845495786484224079'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/07/evsm-to-quest-demo-video.html' title='eVSM to QUEST demo video'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-3959618220415004123</id><published>2009-07-10T09:34:00.002-04:00</published><updated>2009-07-10T09:35:56.939-04:00</updated><title type='text'>IIE Annual Conference 2009 - Applied Solutions presentation</title><content type='html'>&lt;div&gt;Here are the slides I presented this year at the IIE Annual Conference - Applied Solutions session.  It shows some of the work I've been doing with bridging the &lt;a href="http://www.evsm.com"&gt;eVSM Value Stream Mapping&lt;/a&gt; software with QUEST.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;More to come later...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;iframe src="http://docs.google.com/present/embed?id=dgww9c7m_57cc5r7dcf" frameborder="0" width="410" height="342"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-3959618220415004123?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/3959618220415004123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=3959618220415004123' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/3959618220415004123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/3959618220415004123'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/07/iie-annual-conference-2009-applied.html' title='IIE Annual Conference 2009 - Applied Solutions presentation'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-4400270773766904829</id><published>2009-07-01T14:03:00.001-04:00</published><updated>2009-07-01T14:03:00.488-04:00</updated><title type='text'>eVSM to QUEST Interface</title><content type='html'>&lt;div class="Section1"&gt;&lt;h1 style=" margin-left:0pt; margin-right:0pt; text-align:center"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="5"&gt;eVSM to QUEST Interface&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h1&gt;&lt;p style=" margin-left:0pt; margin-right:0pt; text-align:center"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;h2 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;i&gt;&lt;font size="4"&gt;Overview&lt;/font&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The CCAT eVSM Utilities tool with the DELMIA QUEST (http://3ds.com) option allows you to export Value Stream Map information to the DELMIA QUEST (QUeuing Event Simulation Tool).&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;CCAT has developed a set of Simulation Control Logic (SCL) macros in QUEST for importing plain text files in tab-delimited format, and transforming that data into QUEST modeling constructs.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The CCAT eVSM Utilities makes it very easy to generate the plain text files and automates the subsequent import within QUEST.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;h2 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;i&gt;&lt;font size="4"&gt;Terminology&lt;/font&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;&lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;QUEST - QUeuing Event Simulation Tool.  This is Discrete Event Simulation Software provided by Dassault Systemes, and is used for the modeling and simulation of stochastic manufacturing systems&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;eVSM - electronic Value Stream Mapping software (http://evsm.com).&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;NVU - Name-Value-Unit.  An NVU is a construct within eVSM for holding process data.  The Name portion describes the name of the data, the Value is simply the data value, and Unit is the name of the unit the Value is measured in&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;i&gt;&lt;font size="4"&gt;Format Overview&lt;/font&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p style=" margin-left:0pt; margin-right:0pt; text-align:center"&gt;&lt;img src="http://docs.google.com/File?id=dgww9c7m_35gv4fkwhr_b" width="308" height="475" alt="" border="0"&gt;&lt;/img&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The overall format for importing to QUEST is as such:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Two rows of column header information&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;One row delineating units in columns&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Process information in rows&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Each row of simulation data represents a process&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; in QUEST.  Each column holds different data about the process.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;There are three pieces of required data for each process in eVSM:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Cycle Time&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The processing time of the process&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Workstation&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The name of the machine resource where the process is completed&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;.  This may also be a comma-delimited list of machines, each machine being capable of running the same process&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Product&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The name of the product part class of the process&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;i&gt;&lt;font size="4"&gt;Configuration Files&lt;/font&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; The eVSM-&amp;gt;QUEST SCL macros were built to be flexible enough to import VSM data from eVSM using whatever standardized NVU names&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; you want.  An eVSM-&amp;gt;QUEST configuration file has a .esm file extension, and is simply a list of setting names and values, similar to a QUEST .inc file.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The CCAT eVSM Utilities come with a pre-configured configuration file called QUEST_DIRECT.esm, and is stored in the DATA folder of the QUEST library you install the macros to.  This file is used as the default configuration file for exporting directly from eVSM.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Aside from mapping NVU names to data fields the SCL builder macros need, there are also several high-level settings that can be used to control how the SCL builder macros run.  The following are descriptions of several of these settings:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;CELL_DELIM&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The delimiting character between columns in the input text file.  By default this is tab, but a comma can be used (and can be generated by MS Excel)&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;COMMENT_LINE&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - This character tells the SCL builder macros that a line is not to be read as a process.  The default value is the # character&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Geo&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - These settings allow you to specify the default geometry for buffers and machines&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Workcell spacing options&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - These settings allow you to specify the spacing from a machine where the input and output buffers are to be placed.  You may also offset the location of the machine labor point in the y-axis using the LABOR_Y_SPACING setting&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Logic&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - These settings allow you to specify the logics to assign to various elements by default (in-buffer routing logic, process logic, etc...).  The SCL file in which the logics are located must be compiled before the build.  This can be done by listing your logic files in your configuration file with the variable name as SCL_FILE#, where # is a number between 1 and 5, and where no two listed logic files share the same number.  These files will be compiled before the SCL builder macros execute&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;i&gt;&lt;font size="4"&gt;Data Overview&lt;/font&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;As previously mentioned, there are three required pieces of information you must provide for a process in eVSM.  In reality, there are six pieces of data the SCL builder macros need in order to build a model&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;; however, the following three pieces of data are automatically populated for you within eVSM &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Operation&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;- &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The name of the process&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Tag&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;A unique identifier for the process (no other process can have the same tag, but may have the same name)&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Next Op&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The Tag of the process downstream of the current process.  This is used for identifying process sequences and routings&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;In addition to this required information, there is a set of optional NVUs you may provide to the SCL builder macros:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Changeover Time&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The time required to change a machine from one process to another - modeled as a setup process in QUEST, betw&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;een each process on the machine&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Load Time&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The time required to load a part onto a machine before the cycle process begins.  This is modeled as a setup process and is executed when the same process is &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;performed twice in a row.  This means the load time must be included in changeover time, as the first load time is not run&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Operator&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The name of the laborer class to be required on a process.  If a process has a changeover and/or load time assigned to it, the operator is assigned to the load/changeover process(es).  Otherwise the operator i&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;s assigned to the cycle process&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Operators&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - Depending on the assign_all_operators_to_process setting in the configuration file used.  If the setting is 0, then the operators value represents the number of laborers in the labor class.  If the setting is 1, then that number of operators is assigned to the pro&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;cess the laborer is assigned to&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Num Elements&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The number of elements in the machine class&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;MTTR/MTBF/Uptime&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - This is machine reliability dat&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;a commonly used in simulation. &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Two of the three listed NVUs must be present to properly assign QUEST failures to the machines.  If Uptime is provided, the NVU not present (MTTR or MTBF) is calculated based on the Uptime value &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;and whatever value is present&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Scrap &lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;- The rejection rate of the process.  The rejection rate tells QUEST what percentage of parts to scrap, which means the parts are destroyed, and not repaired.  The SCL builder macros do not currently support p&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;art repair&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Geometry&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; -  &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The display geometry file name for the listed Workstation&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;.  This will override the configuration file level setting&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;TimeToNext&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The time for the part to get to its next operation.  The time delay is executed on the output buffer of the machine which the process is run on, and is not resource-constrained.  The part enters the buffer, and after the TimeToNext is elapsed it moves on to the next process.  This may be used for modeling outside operations which are not being modeled&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;.  This value may be provided as an SCL expression (meaning you may use build-in distribution functions)&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="3"&gt;Shifts&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; - The number of shifts the listed Workstation of the process works.&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;i&gt;&lt;font size="4"&gt;Units&lt;/font&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The builder assumes that the data file coming in was created using eVSM.&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; As of eVSM version 4, units are placed in the third row, and so the builder assumes row 3 of the data file it reads contains the units for all the NVU's.&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; The builder will look to these units to determine the units for: cycle time, setup time, load time, IAT, time to next operation, and Mean Time To Repair (MTTR).&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; If no units are found for a specific variable, default values are assumed (minutes for cycle, setup, and load times; hours for IAT &amp;amp; MTTR)&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;h2 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;i&gt;&lt;font size="4"&gt;Location/Layout Information&lt;/font&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The SCL builder macros need to know where to put the machines listed in the Workstation NVU of a process.  This can be provided multiple ways:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul type="disc"&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Shape of the Value Stream Map&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Locations from an eVSM Spaghetti Chart&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Manual location&lt;/font&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;When building from eVSM, you only have a choice between laying out machines in the shape of the VSM, or getting locations from an eVSM Spaghetti Chart.  &lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;If you choose the shape of the VSM, the SCL builder macros will place a machine in the location of the first process that uses that machine in its Workstation NVU.  To locate based off an eVSM Spaghetti Chart, you must provide the name of the page the Spaghetti Chart is on, and the column from Excel corresponding to the place names set in the eVSM Spaghetti Chart.  For example, if you name all your Spaghetti Places based on the values from your Workstation NVUs, you would tell the builder interface in eVSM to use the Workstation column for locating machines.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;h2 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;i&gt;&lt;font size="4"&gt;CCAT eVSM Utilities interface to SCL Builder Macros&lt;/font&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p style=" margin-left:0pt; margin-right:0pt; text-align:center"&gt;&lt;img src="http://docs.google.com/File?id=dgww9c7m_36cgqzfvhm_b" width="329" height="513" alt="" border="0"&gt;&lt;/img&gt;&lt;/p&gt;&lt;h3 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="4"&gt;Layout Options&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Select a radio button to tell the builder how to locate machines in QUEST.  Using "No layout" or "Layout file" will locate machines in the shape of the VSM.  Using "Layout from page" requires that you specify the name of the eVSM Spaghetti Chart page, and the name of the column in the eVSM Excel Calculator spreadsheet which matches up processes with the location names in your eVSM Spaghetti Chart&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;h3 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="4"&gt;esm File&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;You may specify an esm configuration file, if you have a customized file you need to use for the export.  If left blank, the default QUEST_DIRECT.esm is used.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;h3 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;font size="4"&gt;Pre- and Post-Build BCL Commands&lt;/font&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;You may specify a list of BCL commands to be executed before and after the SCL builder macros are executed.  You may wish to compile logic files before the build, or to run different SCL macros after the builder execution.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;These commands should be stored in the eVSM Excel Calculator spreadsheet.  The worksheet the BCL commands are stored in should be named the same as the page your VSM is in, with "_BCL" appended on the end of the name.  The easiest way to set this up is to click the "Import BCL from Excel" button, and the worksheet will be created, if necessary.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;You must specify which columns contain which commands, where Pre-build BCL commands must have "&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; *--PRE_BUILD_BCL*&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;" in the first row cell of the pre-build commands column.  "&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; *--POST_BUILD_BCL*&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;" must be in the first row cell of the post-build commands column.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;h2 style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;b&gt;&lt;i&gt;&lt;font size="4"&gt;Build Process&lt;/font&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Once you have your settings complete in the CCAT eVSM Utilities, click the "Build" button.  This will execute the eVSM Calculator, after which the CCAT eVSM Utilities will export the machine locations to Excel, as well as the Next Op data for each process (based on the connections between processes in your VSM).  Finally, the CCAT eVSM Utilities will export your Excel data to a tab-delimited text file, and start QUEST and tell it to execute a BCL script generated with your pre- and post-build BCL commands, as well as commands to run the SCL builder macros.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The SCL builder macros begin by reading the spreadsheet data to an internal string array, and identifying all the column names, as well as reading units for different NVUs.  Next, the builder copies data it has mapped to specific fields to a different string array, and begins the build process.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The build process begins with building part classes based on the Product column, then it builds a process for each row in the data array.  Next, the process products and requirements are set based on the links between processes and their products.  For instance, if two processes both have a process with tag "B10", the builder will interpret the process as an assembly process, and will require one of each of the Product part classes from the feeding processes.  Then, based on the Product of the process, the process will be set to either pack one of the requirements into the other, or it will create a new part (if the product is not one of the requirements).&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Next, shifts are added to machines based on the Shift data, if provided.  If a machine is listed as having more than three shifts, then each shift is set as a time of 24 hours divided by the highest shift number found.  If the maximum shift number is 3 or less, then each shift is set as 8 hours.  Later on in the build, these shifts will be assigned to your machines.  If the shift times need to be changed this can easily be done either manually or through BCL.  &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The hardest part is done for you, which is creating and assigning the shifts to machines.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Next, workstations are created.  A workstation is just a machine, an input buffer, and an output buffer.  An input buffer receives and holds work until its machine can take it.  An output buffer holds finished work until it can be moved to the next workstation.  &lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;As noted above, if TimeToNext is provided for a process, the workstation's output buffer will hold the part for whatever that TimeToNext value is.&lt;/font&gt;&lt;/span&gt; &lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Each workstation gets added to its own group so you may easily move a workstation around within a model.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Next, the builder will build connections between workstations.  This is done based on the requirements of the processes on different machines.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Next, laborers are assigned to processes.  If a process has loading or changeover associated with it then the laborer is assigned only to the loading/changeover process(es).  Otherwise the laborer is assigned to the cycle process.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Next, loading and changeover machines are assigned to machines.  After that, the builder assigns a process sequence to each part class, based on the chain of requirements and products of all the processes previously built.  One noted problem with this is that the BCL statement to build a process sequence must contain the names of all the processes in the sequence, rather than simply adding one process to the sequence.  This means that you may run against a string size limit when building a model with many long-named processes.  To fix this, modify the BIG_STRING_SIZE constant in the build_from_vsm_generic.scl file to something larger.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The builder then assigns action logics, if applicable, as listed in the configuration file.  Next comes machine failures, which are created and assigned if a process lists a machine's&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt; reliability as detailed above.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;Lastly, the builder goes back to the original input array and finds any data columns that were not mapped to known constructs, and creates user attributes on the processes holding that data.  This means you can very easily pass data between eVSM and QUEST without customizing the build_from_vsm_generic.scl file.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;&amp;#xa0;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=" margin-left:0pt; margin-right:0pt"&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;The builder then cleans up any build errors and data arrays, and saves the model to QUESTLib\Last_Build_Model.mdl.  Also, the builder creates a BCL script of all BCL commands &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Times New Roman&amp;#39;"&gt;&lt;font size="3"&gt;that get executed throughout the build process, and a log file is kept at QUESTlib\Output\writer_log.txt.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-4400270773766904829?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/4400270773766904829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=4400270773766904829' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4400270773766904829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4400270773766904829'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/07/evsm-to-quest-interface.html' title='eVSM to QUEST Interface'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-538918589900406916</id><published>2009-06-29T08:44:00.002-04:00</published><updated>2009-06-29T09:14:00.441-04:00</updated><title type='text'>Automating DXF import to QUEST</title><content type='html'>QUEST doesn't come with a BCL command for easily importing geometry, and although that would be very convenient, it's still possible to convert various CAD geometry to QUEST's PDB format.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;QUEST doesn't have CAD converts baked into the QUEST.exe application file, but rather uses standalone executables located in the quest\bin folder in your QUEST installation.  QUEST simply calls these executables using command line arguments to pass in information about what the user is trying to do through the QUEST UI.  The converter then performs the conversion, and dumps out a temporary pdb file into your temp directory (default is C:\Tmp).  QUEST has been waiting for the converter exe file to terminate, after which it just does a "retrieve" of the temp file the converter created.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, in a nutshell, to automate this ourselves, we simply have to call the appropriate converter with the right command line arguments, and we can go around the relatively clunky QUEST UI for dealing with our CAD importing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My use case will be generating dxf/dwg layouts from vector drawings in MS Visio, and generating a pdb file for QUEST.  This means I'll be using VBA in Visio, but the same thing could easily be done using SCL (although there might be a few snags, such as making your SCL code wait until the conversion is complete)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Before I start into laying out the arguments for converting a dwg to pdb, I should mention that DELMIA/Deneb have made it a little easier on us in running these converters.  They have provided some DOS batch files for setting environment variables, which the converters basically need to be sure you are a licensed QUEST user.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So to convert dwg to pdb, we use the dwg2pdb.bat and corresponding dwg2pdb.exe files.  If you look at dwg2pdb.bat, you can see there's about 5 lines for telling Windows where dwg2pdb.exe is.  You can get away with deleting all that junk, and finding the line that says:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;%DENEB_BIN_DIR%\dwg2pdb.exe $1 ...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;and replacing the %DENEB_BIN_DIR% with the full path to your QUEST installations bin dir (mine is C:\delmia\quest\bin)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The only environment variable you need to make sure is set is the LM_LICENSE_FILE, which you should have set already in your quest.bat file, and if your installation of QUEST works, you shouldn't even need to change this.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, on to the command line arguments.  To see what the arguments are, &lt;a href="http://fournier.jonathan.googlepages.com/ShowCommmandArgs.exe"&gt;I quickly built an exe in VB6 &lt;/a&gt;that just echos out the command line arguments in a message box.  So I renamed my dwg2pdb.exe to something else, and renamed my command line echo exe to dwg2pdb.exe.  Then I went into QUEST and ran an import, at which time I was shown that there are four arguments you need to pass to run a dwg conversion:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;The full path to the dwg/dxf input file&lt;/li&gt;&lt;li&gt;The full path to the output pdb file location &lt;/li&gt;&lt;li&gt;The full path to a configuration file called dwg_cmd (more on that later)&lt;/li&gt;&lt;li&gt;The full path to an output text callout file location&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;The first two arguments are fairly straightforward.  You just need to get the full path to the input file, and decide where to send the output file.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The third argument is for the full path to a file called "dwg_cmd", which is automatically generated by the QUEST UI when you tell QUEST some of the parameters of the input geometry, such as the default length units, point tolerance, etc... On my system, at least, this file was stored in the quest directory.  So I modified it to a default length unit of Inches, and copied the file to quest\bin.  This will serve as my default dwg import profile.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The fourth and final argument was the full path to where you'd like the converter to build a plain text file containing all the text from the dwg/dxf file.  You'll notice when imporing a file with text, you get the floating annotations containing your drawing text.  I guess this is where that text comes from.  The format is somewhat easy to understand.  Basically, the first line details the number of text annotations there are.  Then the annotations start.  The first three lines of an annotation are the x, y, and z locations of the text callout, respectively.  I'm not entirely certain what the next four lines are, though they could be rotation angles and font sizes.  The next line is the number of characters in the callout, and the final line of a callout is the callout text.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Okay, so now we know all the arguments we'll need to pass to dwg2pdb.exe or .bat, to get things translated.  When I tried this though, I got an error saying the executable could not find lmgr8b.dll, which is some runtime that QUEST needs in order to operate (and I'm assuming it's for the FlexLM license manager QUEST uses)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To fix this problem, I simply copied the lmgr8b.dll file from my quest dir into my quest\bin dir, and everything seemed to work.  I could pass in my arguments and get a pdb file out.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So now anywhere I can generate command line arguments, I can also convert dwg/dxf files into the QUEST format automatically.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-538918589900406916?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/538918589900406916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=538918589900406916' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/538918589900406916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/538918589900406916'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/06/automating-dxf-import-to-quest.html' title='Automating DXF import to QUEST'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-1117454162762237959</id><published>2009-05-20T13:20:00.005-04:00</published><updated>2009-05-20T13:59:32.034-04:00</updated><title type='text'>Selecting a file from a QUEST library (using SCL)</title><content type='html'>QUEST SCL provides a means for an SCL programmer to call the standard file selection dialog box, where the user can pick a file from a specific folder from a specific set of libraries.  This function is called FILE_POP_UP.  You pass in a string or string array containing the directory (or directories) to be shown in the dialog box.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;The way I use FILE_POP_UP, I use the inquire_config_path to populate a string array with all the libraries containing a specified folder name, and pass that array to FILE_POP_UP.  I've encapsulated this functionality into a single SCL routine you can use:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;routine get_filename( folder_name : String ) : String&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;cpaths : array [50] of String&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;numpths : Integer&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;result : String&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;        inquire_config_path( folder_name + '$LIB',cpaths, numpths)&lt;/div&gt;&lt;div&gt;        FILE_POP_UP(cpaths, result)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;return result&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now rather than havign to remember how to use inquire_config_path along with FILE_POP_UP, I can simply call a routine like so:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;sel_file_path = get_filename( 'DATA' )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And of course, when you want the user to be able to select an SCL logic file, you'll want to be able to provide the option of selecting from the LOGICS and SCLMACROS folders from your libraries, so I've created a routine that takes two folder names, and combines their inquire_config_path results into a single array that gets passed to the FILE_POP_UP.  Here it is:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;routine get_filename_multiple( folder_name1 : String ; folder_name2 : String ) : String&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;cpaths , cpaths2 : array [50] of String&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;the_paths : Array[ 100 ] of String&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;numpths , numpths2 , i , write_idx : Integer&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;result : String&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;        inquire_config_path( folder_name1 + '$LIB',cpaths, numpths)&lt;/div&gt;&lt;div&gt;        inquire_config_path( folder_name2 + '$LIB',cpaths2, numpths2)&lt;/div&gt;&lt;div&gt;        write_idx = 0&lt;/div&gt;&lt;div&gt;        for i = 0 to numpths - 1 do&lt;/div&gt;&lt;div&gt;            if( cpaths[ i ] &lt;&gt; '' ) then&lt;/div&gt;&lt;div&gt;               the_paths[ write_idx ] = cpaths[ write_idx ]&lt;/div&gt;&lt;div&gt;               write_idx = write_idx + 1&lt;/div&gt;&lt;div&gt;            endif&lt;/div&gt;&lt;div&gt;        endfor&lt;/div&gt;&lt;div&gt;        for i = 0 to numpths2 - 1 do&lt;/div&gt;&lt;div&gt;            if( cpaths2[ i ] &lt;&gt; '' ) then&lt;/div&gt;&lt;div&gt;               the_paths[ write_idx ] = cpaths2[ i ]&lt;/div&gt;&lt;div&gt;               write_idx = write_idx + 1&lt;/div&gt;&lt;div&gt;            endif&lt;/div&gt;&lt;div&gt;        endfor&lt;/div&gt;&lt;div&gt;        FILE_POP_UP(the_paths, result)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;return result&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can use it like so:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;sel_file_path = get_filename_multiple( 'LOGIC' , 'SCLMACRO' )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-1117454162762237959?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/1117454162762237959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=1117454162762237959' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1117454162762237959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1117454162762237959'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/05/selecting-file-from-quest-library-using.html' title='Selecting a file from a QUEST library (using SCL)'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-319910826417364199</id><published>2009-05-20T13:17:00.008-04:00</published><updated>2009-05-20T13:39:46.424-04:00</updated><title type='text'>Executing shell calls in SCL and BCL</title><content type='html'>&lt;span class="Apple-style-span" style="font-size: medium;"&gt;The combination of QUEST &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;BCL and SCL is extremely powerful not only for building and runnign simulation models, but also for providing a better experience for you to &lt;/span&gt;&lt;/span&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;use&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; QUEST models.  BCL and SCL can allow you to &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;greatly simplify modeling tasks, at the tradeoff of lowering QUEST's flexibility from infinite, to match with some set of assumptions you've come up with.&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;One powe&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;rfu&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;l&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; t&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;ool &lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;here, is the ability to generate system shell calls, and here I'll talk about this on Windows mac&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;hines, only.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;QUEST BCL has a call&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; named "SYSTEM" which takes a single string argument, enclosed in single quotes.  Th&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;e QUEST BCL documentation gives an example of copying a file:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;  SYSTEM 'copy  thisfile thatfile' &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'Courier New';"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;where thisfile is the path to the file to copy, and thatfile is the path to the file&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt; you want to copy to.  This is useful enough, and pretty self explanatory, especially if you've used the Windows command line enough.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;The example I'd like to provide lays in launching applications, and in this case, Microsoft Excel.  To simply launch a file from the command line, all you need to do is feed the command shell the path to the file to open.  Windows knows how to handle pretty much any file type you throw at it, and in the traditional GUI use of Windows you're prompted if Windows doesn't know what to do with the file.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;This works fine for files where there's only one program for viewing or editing a particular file type.  But what happens if you want to chose what program to use?  Using the command line shell, we can specify the program file to use to open a file by passing the path of our file as an argument in starting the application.  Most major applications support this.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;So if you have Open Office set as the default editor of Excel files, passing an Excel file to the command shell will open it in Open Office.  But if for some reason you want to open this file in Excel (without changing the default behavior) we just have to start Excel with our file as a command line argument.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;So here's an SCL routine you can use to launch an Excel file:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'Courier New';"&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;routine launch_excel( file_name : String ) : Integer&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;Const&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;EXCEL_LOCATION 'C:/Program Files (x86)/Microsoft Office/Office12/excel.exe'&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;Var&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;        bclerr : Integer&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;        bclmsg : String&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;Begin&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;        bclmsg = "SYSTEM '" + EXCEL_LOCATION + " "&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;        bclmsg = bclmsg + file_name&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;        bclmsg = bclmsg + " &amp;amp;'"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;        if( EXCEL_LOCATION &lt;&gt; '' ) then&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;            bclerr = bcl(bclmsg)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;        endif&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;        return bclerr&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;End&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;All we're doing is using the SYSTEM BCL call with the file_name argument as a commmand line argument.  Pretty simple, eh?&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-319910826417364199?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/319910826417364199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=319910826417364199' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/319910826417364199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/319910826417364199'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/05/executing-shell-calls-in-scl-and-bcl.html' title='Executing shell calls in SCL and BCL'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-1510311627387300051</id><published>2009-05-20T13:08:00.006-04:00</published><updated>2009-05-20T13:52:19.425-04:00</updated><title type='text'>Precompiled (always there) SCL routines</title><content type='html'>Over the course of the last few years, I have developed some SCL utility logics that I use quite often and don't like having to copy over and over again.  For example, a routine for &lt;a href="http://delmiaquest.blogspot.com/2008/10/string-replace_01.html"&gt;replacing strings&lt;/a&gt;, or converting text to &lt;a href="http://delmiaquest.blogspot.com/2008/09/upper-lower-case.html"&gt;upper or lower case&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's nice to have these logics, but normally, if you wanted to use them, you'd have to find a copy of the routines declared somewhere on your computer (possibly using my &lt;a href="http://delmiaquest.blogspot.com/2008/10/scl-subroutine-indexer.html"&gt;subroutine indexer&lt;/a&gt;).  However, QUEST provides a directory within your QUESTlib folder called USERDEF, with a folder for logics that, if present there, will compile every time QUEST starts up.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This means that any procedures and routines within one of those USERDEF files will be available to you without having to copy them to the logic you're working on.  They're always there.  If you're trying to use a precompiled routine, however, you'll have to remember to declare the routine in the Extern section of your logic file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What I usually do to cover this is to put in the extern definition for all my routines along with the definition of the routine in the USERDEF library.  This way I can just go in and grab the extern def rather than the actual SCL definition.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In fact, to make it even easier to set up the extern definitions for all my routines, I've actually written an SCL macro that will do this, more or less, for me.  You can download it at:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://fournier.jonathan.googlepages.com/get_extern_names_from_scl.scl"&gt;http://fournier.jonathan.googlepages.com/get_extern_names_from_scl.scl&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Just load this into an SCL macro button, and when executed it will prompt you to select an SCL file.  It will then search through the file you selected and export the extern representation for all your routines to a text file.  It will then launch notepad and open this file for you.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then all you have to do is copy the extern definitions.  Hopefully that makes life a little easier for you.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-1510311627387300051?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/1510311627387300051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=1510311627387300051' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1510311627387300051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1510311627387300051'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/05/precompiled-always-there-scl-routines.html' title='Precompiled (always there) SCL routines'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7334783471357876882</id><published>2009-05-06T09:02:00.007-04:00</published><updated>2009-05-06T09:37:08.635-04:00</updated><title type='text'>Excel VBA UDFs for QUEST BCL (wow, enough acronyms?)</title><content type='html'>If you have any familiarity with Excel VBA, you've probably made at least one User Defined Function (UDF) for use in an Excel spreadsheet.  If you're not familiar with it, you basically just create a function within an Excel VBA standard module that may or may not take arguments, and returns something that can be displayed in Excel.  For example, here is a simple function that just returns the sum of two arguments.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;    Function MySum(arg1 As Variant, arg2 As Variant)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;MySum = arg1 + arg2&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;    End Function&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In this function, arg1 and arg2 are of Variant types, meaning the user is able to pass in a literal number or a selected Excel cell (called a Range).  By defining variables as Variants, we can assume that whatever the user passes into the function can be cast into the variable type required by the operators we are using (in this case the addition/concatentation operator +).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What some people don't necessarily think of though, is to use VBA to create string concatenating UDFs.  Here's an example that just puts two pieces of text together:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;    Function MyConcat(arg1 As Variant, arg2 As Variant)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;MyConcat = CStr(arg1) &amp;amp; CStr(arg2)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;    End Function&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can see it's similar to MySum, except that we are using the &amp;amp; operator which is just for string concatenation in this use (where the + operator can be addition or concatenation).  Also, we are making use of the built-in VBA function CStr to cast our variant data into strings.  This is because the &amp;amp; operator requires strings as operands.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now to the BCL part.  We can use something similar to MyConcat to make it so we can easily create BCL commands by simply passing one or more arguments into specially created UDFs.  Here's an example for creating a cycle process:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;    Public Function create_cycle_process(process_name As Variant) As String&lt;/div&gt;&lt;div&gt;        create_cycle_process = "CREATE CYCLE PROCESS '" &amp;amp; process_name &amp;amp; "'"&lt;/div&gt;&lt;div&gt;    End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So a user only has to pass in the name of the process they want to create, and VBA returns a properly formatted BCL command to execute in QUEST.  This can be pretty handy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Even better though, is that VBA allows optional arguments in UDFs, so we can easily account for the optional arguments in many BCL commands.  A good example of this is the CREATE ELEMENT CLASS command, which requires that you provide the element class type and the element class name, but allows you to also specify the number of elements and the geometry file path to use for the class display.  Without optional arguments you would have to write four different UDFs to be able to build a CREATE ELEMENT CLASS command with all the possible arguments.  But with VBA we can do it one.  Here's how:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;    Public Function create_element_class(class_name, elem_type, Optional num_elem, Optional geo_name)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Dim Result&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Result = "CREATE " &amp;amp; elem_type &amp;amp; " CLASS '" &amp;amp; class_name &amp;amp; "'"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;If Not IsMissing(num_elem) Then&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Result = Result &amp;amp; " NUMBER OF ELEMENTS " &amp;amp; CStr(num_elem)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;End If&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;If Not IsMissing(geo_name) Then&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Result = Result &amp;amp; " GEO '" &amp;amp; geo_name &amp;amp; "'"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;End If&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;create_element_class = Result&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;    End Function&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:85%;"&gt;&lt;span class="Apple-style-span" style="font-size: 10px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;This function starts by creating the base BCL command using the required arguments, class_name and elem_type.  Then, it uses the VBA function IsMissing to see if our optional arguments were omitted in the function call.  If not, they are used to add to the BCL command.  Finally, the BCL command is returned to the user.  Now the user no longer needs to remember the proper syntax for creating an element class BCL command.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To make it even easier on the user, we can provide higher level functions that provide the proper elem_type for them, so they don't have to remember those either:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:85%;"&gt;&lt;span class="Apple-style-span" style="font-size: 10px;"&gt;&lt;div&gt;Function create_mach_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_mach_class = create_element_class(class_name, "MACHINE", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_source_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_source_class = create_element_class(class_name, "SOURCE", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_sink_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_sink_class = create_element_class(class_name, "SINK", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_buffer_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_buffer_class = create_element_class(class_name, "BUFFER", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_conveyor_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_conveyor_class = create_element_class(class_name, "CONVEYOR", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_accessory_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_accessory_class = create_element_class(class_name, "ACCESSORY", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_agv_controller_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_agv_controller_class = create_element_class(class_name, "AGV_CONTROLLER", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_labor_controller_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_labor_controller_class = create_element_class(class_name, "LABOR_CONTROLLER", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_carrier_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_carrier_class = create_element_class(class_name, "CARRIER", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_agv_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_agv_class = create_element_class(class_name, "AGV", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_labor_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_labor_class = create_element_class(class_name, "LABOR", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Function create_path_system_class(class_name , Optional num_elem , Optional geo_name ) &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;create_path_system_class = create_element_class(class_name, "PATH SYSTEM", num_elem, geo_name)&lt;/div&gt;&lt;div&gt;End Function&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;H&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;o&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;p&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;e&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;f&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;u&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;l&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;l&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;y&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; &lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;t&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;h&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;i&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;s&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; &lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;h&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;a&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;s&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; &lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;given you a good primer on using VBA UDFs to create QUEST BCL commands in Excel, so you can smarter BCL scripts that will be easier to modify and to execute in QUEST.&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7334783471357876882?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7334783471357876882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7334783471357876882' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7334783471357876882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7334783471357876882'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/05/excel-vba-udfs-for-quest-bcl-wow-enough.html' title='Excel VBA UDFs for QUEST BCL (wow, enough acronyms?)'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-1225958919651416769</id><published>2009-03-13T09:02:00.001-04:00</published><updated>2009-05-08T09:18:57.087-04:00</updated><title type='text'>Wait Until Event</title><content type='html'>A lot of times in modeling a system in QUEST there comes a need for some synchronization between different elements.  For instance, one model I made had a large piece removed from the main assembly part, which was stored until the main assembly part arrived at a specified machine.  Once that assembly part leaves for the machine, the large part should start being delivered to the machine (while the machine is running a process to prepare the assembly part for installation of the big part).&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;When I first started with QUEST, I probably would have written some logic on the storage buffer holding my part to look at the machine at a specified time interval to see if the main assembly part had arrived yet.  You can set the time interval to whatever you want, and there are drawbacks no matter what.  If you specify a small interval (like 5 seconds), your model will slow down to a crawl because your logic is running more or less constantly.  Add multiple elements running this logic and you can kiss model performance goodbye.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;So what if you specify a larger interval?  Again, you're still going to be running your logic a lot more than you need to, and with the larger interval you run the risk of not noticing the main assembly part arriving until too late.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;There are a few ways we can address this problem without using a time interval to constantly keep checking our machine.  Some would suggest using signals, where our machine would send a signal to our buffer saying the part is there, and it's time to route the part on to the machine.  This will have good performance in the model, as the logic in the buffer just uses a WAIT UNTIL SIGNAL SCL command to wait.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;What I don't like about this is the need to write logic for the machine to use to send the signal to the buffer.  And what if we can't be sure what buffer is holding our part?  Then our logic has to search for the part and alert that buffer using a signal.  This is all doable, but I prefer to use (what I think is) a simpler approach: the WAIT UNTIL EVENT SCL command.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;The WAIT UNTIL EVENT command would be used similar to how we would use the WAIT UNTIL SIGNAL command, except that QUEST is raising the event for us, so no logic needed anywhere except on the buffer routing the part.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;To use the WAIT UNTIL EVENT command, you simply provide an event constant, and optionally a pointer to the element/element class you want to watch, as well as whether you want your logic to run right before the event, or right after.  There are some other options (you can look for events on a part/part class, or segment).&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;So for the example above with the assembly part and the part that needs to move to the machine, our buffer would just have a loop that goes something like this:&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="white-space: pre;"&gt; &lt;/span&gt;while( true ) do&lt;/div&gt;&lt;div&gt;&lt;span style="white-space: pre;"&gt;  &lt;/span&gt;WAIT UNTIL EVENT PART_XFER FOR ELEMENT_CLASS the_elem_handle&lt;/div&gt;&lt;div&gt;&lt;span style="white-space: pre;"&gt;  &lt;/span&gt;-- look at the_elem_handle's inparts to see if our assembly part is there...&lt;/div&gt;&lt;div&gt;&lt;span style="white-space: pre;"&gt; &lt;/span&gt;endwhile&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;and then our logic can continue, and route the part out of the buffer to the waiting machine.  One thing to note here, too, is that to use the PART_XFER constant you must have #include &lt;events.inc&gt; at the top of your SCL file or your logics won't know what PART_XFER is and it won't compile.  You could just look up the numeric codes for the event constants if you'd prefer, but the code is easier to read (especially after a year without looking at or thinking about that particular logic) and more future proof if you use the constant names.&lt;/events.inc&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;This is just one example where we can use the WAIT UNTIL EVENT SCL command in place of using signals.  Your mileage may vary, in that the events we want may not be exposed for use in the WAIT UNTIL EVENT command (for instance, when a part actually arrives at an element).  In these cases you may need to use signals, but hopefully you'll be able to use WAIT UNTIL EVENT just as effectively.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-1225958919651416769?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/1225958919651416769/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=1225958919651416769' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1225958919651416769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1225958919651416769'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/03/wait-until-event.html' title='Wait Until Event'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total><georss:featurename>East Hartford, Connecticut, USA</georss:featurename><georss:point>41.76431783949641 -72.65730857849121</georss:point><georss:box>41.760316339496406 -72.66460407849121 41.76831933949641 -72.65001307849121</georss:box></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-6519527921308037262</id><published>2009-03-02T16:23:00.003-05:00</published><updated>2009-03-02T16:45:42.151-05:00</updated><title type='text'>How to run BCL from Excel (the simple way) Part 2</title><content type='html'>In the &lt;a href="http://delmiaquest.blogspot.com/2009/02/how-to-run-bcl-from-excel-simple-way.html"&gt;previous post&lt;/a&gt;, I showed you how to set up a batch file that launches QUEST with the path to a BCL file passed as the command line parameter.  This post will bring us the rest of the way to being able to save out a series of BCL commands generated in Excel out to a BCL file.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The easiest way to create the Excel portion of this setup is using a VBA-based Excel Addin (.xla file).  The XLA, once activated by the user, is available whenever Excel is running, and we can build toolbar buttons to execute the macros we're using.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The macros themselves are pretty straightforward if you're accustomed to writing VBA in Excel.  The VBA Project is unlocked and unprotected, so you can go in and start editing/hacking away as you'd like to.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Download the XLA file &lt;a href="http://fournier.jonathan.googlepages.com/QUEST_BCL_Addin.xla"&gt;here&lt;/a&gt;.  Understand that it's intended just for demonstration purposes and comes with no warranty.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To install the Addin, save the XLA file to your computer and note its location.  Then start Excel and go to Tools-&gt;Add-Ins.  Select the "Browse" button and navigate to the XLA file, wherever you saved it, and that's it.  The Addin will open and you'll see a new toolbar (named BCL_Launcher_Toolbar) with a pair of buttons on it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To use the buttons, first select the cells containing the commands you want to save/execute.  The button on the left will just save the commands to a text file, while the button on the right saves the commands and then launches QUEST and executes those commands.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The first time you use the Addin, you'll be prompted for the location of the BCL file where you want your commands saved to, as well as the location of your QUEST BCL BAT file that you created in the &lt;a href="http://delmiaquest.blogspot.com/2009/02/how-to-run-bcl-from-excel-simple-way.html"&gt;previous post&lt;/a&gt;.  After that you should be good to go.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://fournier.jonathan.googlepages.com/QUEST_BCL_Addin.xla"&gt;Download Addin&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-6519527921308037262?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/6519527921308037262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=6519527921308037262' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/6519527921308037262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/6519527921308037262'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/03/how-to-run-bcl-from-excel-simple-way.html' title='How to run BCL from Excel (the simple way) Part 2'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7871903485764838841</id><published>2009-03-02T15:34:00.000-05:00</published><updated>2009-03-02T15:33:36.283-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QUEST'/><category scheme='http://www.blogger.com/atom/ns#' term='Excel'/><category scheme='http://www.blogger.com/atom/ns#' term='BCL'/><title type='text'>How to run BCL from Excel (the simple way) Part 1</title><content type='html'>For some time now I've been building QUEST models by using BCL script rather than the traditional User Interface.  I do this because it provides me with a very detailed (and procedural) look at what I've done to a model, and helps to glean out what assumptions I've made along the way.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It also lets me rebuild a model from scratch whenever I want, so I can (somewhat) easily modify some model parameter and have that change made in my model.  To make changing parameters easier I build my BCL scripts in Excel using formulas.  When I need to rebuild my model I can just click a user button in Excel and up pops QUEST to execute my script.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;The following posts will tell you how to set up the same thing in your version of Excel.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since we're basically just going to build a text (.bcl) file in Excel and execute it in QUEST, we need to first set up a QUEST .bat file that will open QUEST and execute the commands in a BCL file.  Looking at the online documentation, all we have to do is append "-b" on to the call to QUEST.exe with the BCL file name.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To set up a quest_bcl.bat file just make a copy of your quest.bat file (or whatever .bat file you use to initialize environment variables before starting QUEST, usually Deneb\Quest\Quest.bat) and find the line where QUEST is being started (I believe it's something like "start/max %DENEB_PRODUCT%.exe %1 %2..."), and replace it with this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;quest -b &lt; %1&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The "&lt; %1" just tells the command line to take the first command line argument passed in and pass it on to "quest -b".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To test this, try creating a simple BCL file that creates a machine and places it at some location, then transfers control of the program to the user (otherwise QUEST will just close out having completed its task):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    CREATE MACHINE CLASS 'Machine1'&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    LOCATE ELEMENT 'Machine1_1' AT 100, 100, 100&lt;/div&gt;&lt;div&gt;    TRANSFER TO MENU&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Save this into a plain text file and name it what you'd like (preferably with a .bcl extension, but it doesn't matter much).  Note the full path to the file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next, open a command prompt and navigate it to the directory where you saved your quest_bcl.bat file.  In the command prompt type: &lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    quest_bcl.bat "bcl_file_path.bcl"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;where bcl_file_path is the full path to the BCL file you saved (unless it's in the same directory as your quest_bcl.bat).  You don't have to enclose the BCL file path in double quotes unless there is a space in the path.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;If everything is working right, QUEST should launch and create a machine at the specified coordinates.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the next post, I'll show you how to set up a simple Excel Addin (.xla file) that will let you build a BCL file from a set of Excel cells and launch it in QUEST.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7871903485764838841?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7871903485764838841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7871903485764838841' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7871903485764838841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7871903485764838841'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/02/how-to-run-bcl-from-excel-simple-way.html' title='How to run BCL from Excel (the simple way) Part 1'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-3872079420087728825</id><published>2009-02-20T13:36:00.002-05:00</published><updated>2009-02-20T13:40:43.523-05:00</updated><title type='text'>Select a part class</title><content type='html'>Since I've already posted how to select an element and a process using SCL, and because there was recently a question regarding this in the QUEST Google Group, I figured I'd post code for selecting a part class.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All this code does is populate an array wtih the names of all the part classes in the current model, then passes that to a list_pop_up, which returns the index in the array of the selected item.  The list_pop_up routine returns a boolean integer telling whether or not something was actually selected (eg the user didn't hit cancel).  So if this return value is true then just return the part class referenced in the array...&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;routine select_a_pclass() : Part_Class&lt;/div&gt;&lt;div&gt;Const&lt;/div&gt;&lt;div&gt;   max_pclass 250&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;   result , the_pclass : Part_Class&lt;/div&gt;&lt;div&gt;   num_pclasses_found , pick_process , list_picked : Integer&lt;/div&gt;&lt;div&gt;   the_pclasses : Array[ max_pclass ] of String&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;   num_pclasses_found = 0&lt;/div&gt;&lt;div&gt;   the_pclass = first_pclass&lt;/div&gt;&lt;div&gt;   while( the_pclass &lt;&gt; NULL ) do&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;      the_pclasses[ num_pclasses_found ] = the_pclass-&gt;name&lt;/div&gt;&lt;div&gt;      num_pclasses_found = num_pclasses_found + 1&lt;/div&gt;&lt;div&gt;         &lt;/div&gt;&lt;div&gt;      the_pclass = the_pclass-&gt;next_pclass&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;   endwhile&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;   --do a list popup using the_pclasses&lt;/div&gt;&lt;div&gt;   list_picked = list_pop_up( 'Select a part class' , the_pclasses , pick_process , true )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;   if( list_picked ) then&lt;/div&gt;&lt;div&gt;      return get_part_class( the_pclasses[ pick_process ] )&lt;/div&gt;&lt;div&gt;   endif&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-3872079420087728825?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/3872079420087728825/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=3872079420087728825' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/3872079420087728825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/3872079420087728825'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/02/select-part-class.html' title='Select a part class'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-5806875183704836752</id><published>2009-01-16T15:00:00.005-05:00</published><updated>2009-01-16T15:24:45.799-05:00</updated><title type='text'>How Filehamster Saved My Life</title><content type='html'>I don't know about you, but in the course of developing SCL macros and logics I sometimes tend to make bad choices, and undoing those changes can be pretty painful, especially if I went and modified something on a large scale (i.e. adding a &lt;a href="http://delmiaquest.blogspot.com/2009/01/scl-call-stack.html"&gt;call stack&lt;/a&gt; on 328 subroutines in an SCL file and finding out that my implementation gets extremely slow as the stack grows).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Thankfully, for the past couple years I've used a tool called &lt;a href="http://mogware.com/FileHamster/"&gt;FileHamster&lt;/a&gt; from &lt;a href="http://mogware.com/"&gt;MOGWare&lt;/a&gt;, which is a free and extremely easy to use backup program that basically sits and watches any files you want it to, and when you change it it snags a copy and stores it for you.  You can add comments to a revision as it's copied or later on (like "Last backup before adding call stack") so you can easily identify the point where you made a change you need to reverse, and restore your file to that version.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Filehamster just takes a copy of what's changed and saves it out for you to a backup directory. But there's very little overhead in setting up a file watch, and with SCL files we're dealing with text files in the size range of 1-300K, so it would take a while to use up an appreciable amount of hard disk space.  If you're that concerned there's a plugin for sale that'll compress each revision for you.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There's actually a set of plugins for sale on their site for extending FileHamster into something more like a full-on source control package, but I'm going to hold out until they come up with a plugin that can hear that voice in the back of my head asking "does he really think this is going to work?"&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-5806875183704836752?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/5806875183704836752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=5806875183704836752' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5806875183704836752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5806875183704836752'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/01/how-filehamster-saved-my-life.html' title='How Filehamster Saved My Life'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7610601788841883090</id><published>2009-01-13T16:02:00.004-05:00</published><updated>2009-01-13T16:28:47.895-05:00</updated><title type='text'>SCL Call Stack</title><content type='html'>If you saw my last post on &lt;a href="http://delmiaquest.blogspot.com/2008/12/compiling-scl-from-scl-ish.html"&gt;compiling SCL files from SCL&lt;/a&gt;, you may have seen that there are some array utility routines I've written that allow you to insert and remove array elements through a simple call providing the array and the number of elements in it.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After creating these routines, I thought they'd be perfect for implementing a &lt;a href="http://en.wikipedia.org/wiki/Call_stack"&gt;call stack&lt;/a&gt; in SCL.  Having a call stack available in SCL would mean we can more easily track down the source of bugs in our scl subroutines, especially if they're more generic utilities that may be called from any number of different routines.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So the way I'll be using this is in a very large (8,000+ line) SCL utility where many routines are simply wrappers around BCL commands that make it so I don't have to write out BCL statements again and again.  Basically any time a subroutine starts or ends I just write the stack out to a text file; and if the macro crashes, I just check the latest stack text file and see what subroutines were in the stack, so I can track the problem down.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://fournier.jonathan.googlepages.com/call_stack.scl"&gt;call_stack.scl&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'd suggest you save the call_stack.scl file into QUESTlib/UserDef/Logics so it's always compiled and ready to go when you need it...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Basically there are three procedures in the call_stack.scl file you need to worry about: start_procedure, end_procedure, and print_stack.  Just call start_procedure and end_procedure with the name of your subroutine as an argument, and the stack will reflect all subroutines you've got running.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, like I said earlier, I have 8000 lines of SCL code with over 300 subroutines.  So how am I supposed to put in a call to start_procedure and end_procedure for all those subroutines?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The answer is using SCL, what else?  So I went and wrote an SCL macro that lets me select an SCL file, and it then goes through and identifies each subroutine in the file, and adds a call to start_procedure at the beginning and end_procedure at the end of each subroutine, with the name of the sub as the argument.  The file gets saved out as the original filename with "_cs" appended on, so you can go and copy it over if you want, or just run that for debugging purposes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://fournier.jonathan.googlepages.com/add_call_stack_to_scl_file.scl"&gt;add_call_stack_to_scl_file.scl&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7610601788841883090?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7610601788841883090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7610601788841883090' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7610601788841883090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7610601788841883090'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/01/scl-call-stack.html' title='SCL Call Stack'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-23456361540329840</id><published>2009-01-05T16:33:00.005-05:00</published><updated>2009-01-06T10:35:36.594-05:00</updated><title type='text'>Model Scaling</title><content type='html'>I recently built a QUEST model on a CAD layout and it turned out the layout wasn't properly scaled.  This is easy enough to fix, just a matter of either modifying the CAD part in the QUEST drawing world, or just scaling it in the dimensions section of the layout accessory.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But what about the elements?  I had to scale the layout to about 120% of its original size and didn't feel like moving all the machines and buffers and everything to their new locations on the layout.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So what would I do other than write an SCL macro that lets me move all elements in a model relative to some new scale.  &lt;a href="http://fournier.jonathan.googlepages.com/scale_model.scl"&gt;Here's the code&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Basically what it does is populates a &lt;a href="http://delmiaquest.blogspot.com/2008/09/inquire-element-location.html"&gt;spot structure&lt;/a&gt;, multiplies the location coordinates by the scale input by the user, and locates the element on the spot's new coordinates.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The best part about writing this macro was that it took about 5 minutes, just by copying in SCL subroutines I've previously written and was able to find using my &lt;a href="http://delmiaquest.blogspot.com/2008/10/scl-subroutine-indexer.html"&gt;SCL Subroutine Indexer&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Update: When using this macro I found it might be better to be able to scale the model differently along various axes.  So I went and modified the macro to scale each axis to different values as input by the user using a var_pop_up.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-23456361540329840?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/23456361540329840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=23456361540329840' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/23456361540329840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/23456361540329840'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2009/01/model-scaling.html' title='Model Scaling'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7830142928864874773</id><published>2008-12-18T15:14:00.007-05:00</published><updated>2008-12-18T15:32:35.046-05:00</updated><title type='text'>Compiling SCL from SCL (ish)</title><content type='html'>I don't know about you, but in the past I've developed QUEST solutions where it would have been nice to be able to use SCL code to identify a set of other SCL files to compile.  However, there is no straightforward way to do this as using the SCL_COMPILE BCL command from an SCL script will generate an error and not compile the SCL file.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is a workaround, however, and that is to use BCL to execute an SCL subroutine which returns the path of an SCL file to the bcl_msg BCL variable.  You can then use the SCL_COMPILE command passing bcl_msg as an argument to compile an SCL file selected using SCL code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The downside is that if the routine doesn't return a file path the BCL code still tries to compile the blank string file path, and shows an error in the message window.  Unfortunately (as far as I can tell) you can't use conditional statements in a BCL script, so there's not much we can do about this.  I'd say if you need to be able to compile SCL from SCL, it's worth the small inconvenience of seeing the error message when you don't specify a file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've used this technique to compile SCL files listed in a configuration file (not the QUEST kind) that could only be parsed using SCL (rather than straight BCL), so that users can specify different SCL logics in building a QUEST model from an eVSM file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This may not be of any use to anyone reading this, so I've provided an example which hopefully will make using QUEST just a little bit easier to use.  I don't know about you, but I often debug my SCL code by writing a little, then compiling it in QUEST, until it's all done and working.  However, if you're working on multiple SCL files it can be a pain to go to the Run-&gt;Simulate-&gt;Compile button and pick files in various folders.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So what I've done is created a BCL macro that calls an SCL routine that keeps track of (up to) the last 49 or so SCL files that I've compiled (in the current session) and gives me the option of selecting another file to compile.  So I've basically duplicated the Run-&gt;Simulate-&gt;Compile functionality, and added a list of the most recently compiled files for you to chose from.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can get the &lt;a href="http://fournier.jonathan.googlepages.com/compile_recent.bcl"&gt;BCL script here&lt;/a&gt; and the corresponding &lt;a href="http://fournier.jonathan.googlepages.com/get_scl_file_path_for_compile.scl"&gt;SCL file here&lt;/a&gt;.  Keep in mind that you need to modify the BCL script to compile the SCL file wherever it is saved on your computer.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7830142928864874773?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7830142928864874773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7830142928864874773' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7830142928864874773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7830142928864874773'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/12/compiling-scl-from-scl-ish.html' title='Compiling SCL from SCL (ish)'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-3801625390136202157</id><published>2008-11-11T11:01:00.004-05:00</published><updated>2008-11-11T11:07:30.581-05:00</updated><title type='text'>Select an Element</title><content type='html'>&lt;span style="font-size: 12pt;font-size:100%;" &gt;&lt;div&gt;QUEST SCL provides a function for selecting items (including elements) from the QUEST world, aptly named Select.   Basically, you tell the function what you want to pick (elements, cad_parts, etc...), the selection mode (mouse pick, pick from a list, or key in the name), and you pass in a string variable that will be set by the routine to the selected item's name (You also have to specify a text prompt, and whether or not you want the selected item to be highlighted).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I usually don't need to use all the available options in the Select function, so I've put together a routine I use often that I can drop into an SCL macro or call with an Extern reference, so here it is:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;div&gt;   routine select_an_element( prompt : String ) : Element&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;   Var&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;elem_name : String&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;picked_elem : Element&lt;/div&gt;&lt;div&gt;   Begin&lt;/div&gt;&lt;div&gt;      while( select( prompt , ELEMENT , PICK_MODE , TRUE , elem_name ) ) do&lt;/div&gt;&lt;div&gt;         picked_elem = get_element( elem_name )&lt;/div&gt;&lt;div&gt;      endwhile&lt;/div&gt;&lt;div&gt;      return picked_elem&lt;/div&gt;&lt;div&gt;   End&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Like I said, this is just an easy to implement routine you can drop into your code without worrying too much about it, which is how I like to program...&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-3801625390136202157?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/3801625390136202157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=3801625390136202157' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/3801625390136202157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/3801625390136202157'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/11/select-element_11.html' title='Select an Element'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-4577498526397010669</id><published>2008-10-21T14:34:00.003-04:00</published><updated>2008-10-21T14:40:01.554-04:00</updated><title type='text'>Set part class dimensions</title><content type='html'>As far as the QUEST online documentation shows, there is no BCL command for setting a part class' dimensions.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I thought it would be possible to do this by exporting a part class to a text file, modifying the text file with the new dimensions, and then re-importing the text file to overwrite our part class with the new dimensions.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://fournier.jonathan.googlepages.com/set_pclass_dimensions.scl"&gt;Here&lt;/a&gt; is the resulting SCL macro.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can use it from within SCL by calling set_pclass_dimensions with a handle to the part class, then the 3 arguments to set the part class dimensions to.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can call it from a BCL script using the following commands, setting the full path to the set_pclass_dimensions.scl file, substituting Part1 with the name of the part class you want, and setting the dimensions to the sizes you want:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;SCL_COMPILE 'set_pclass_dimensions.scl' 0&lt;/div&gt;&lt;div&gt;SCL_EXEC set_pclass_dimensions_by_name WITH ARGUMENTS 'Part1' , 100 , 200 , 300&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-4577498526397010669?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/4577498526397010669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=4577498526397010669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4577498526397010669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4577498526397010669'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/10/set-part-class-dimensions.html' title='Set part class dimensions'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-3646508893033131056</id><published>2008-10-21T13:15:00.006-04:00</published><updated>2008-10-21T16:01:56.684-04:00</updated><title type='text'>SCL Subroutine Indexer</title><content type='html'>If you're anything like me, you've written a large variety of SCL logics and have tons of procedures and routines buried in files which are in turn buried in different QUEST LOGICS and SCLMACROS libraries.  Sometimes I need a logic that I know I've already written, but can't remember where it is.  I use Google Desktop to find files, but it is unable to search within the text of a plain text file unless it has an extension it recognizes (i.e. not .scl).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Rather than write a plugin for Google Desktop to enable SCL search, I went the quicker, dirtier, and easier path (for me, anyway) and wrote a couple macros in Excel to index a set of SCL files (extracting all procedure and routine declarations) into an Excel worksheet.  A while back I wrote an interface for Excel's AutoFilter that makes setting filters on large datasets a little easier than without.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One thing to note is I haven't set it up to read any subroutine declarations that span multiple lines (using the line continuation character "\") so at the moment it won't pick up the full declaration.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Updated:  10/21/08 - Modified the auto-filter helper to run faster in populating the result list box for large data sets&lt;/div&gt;&lt;div&gt;&lt;a href="http://fournier.jonathan.googlepages.com/SCL_Indexer.xls"&gt;Click here to download the SCL Indexer&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To use this indexer, simply copy the SCL_Indexer.xls file to your computer, and open it in Excel.  I signed the VBA project with a digital certificate created on my own computer, so you should be able to import the certificate, but to be honest I'm not sure how that will work, and you may be stuck hitting "enable macros" every time you open the file.  If nothing else, you can try saving the file to a trusted location.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When you open the file (with macros enabled) the indexer will create a toolbar called "AutoFilterHelper".  This toolbar contains the buttons for running the indexer and searching the index (In Excel 2007 a section will be added to the Addins ribbon with the buttons).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To use the indexer just click on the binocular button.  This will open a form that allows you to select a directory or file, and to index it.  You may select to index any subdirectories from a directory.  Hit cancel while it's indexing if you want it to stop.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once the index is built you will see that the worksheet is populated with all procedure and routines indexed, with the return type (Null means it's a procedure) and arguments listed.  The file name for each subroutine is listed as well.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To use the auto filter helper, click on the magnifying glass, and select the column header you want to search.  It may take some time to populate the result box, but you will see a list of all subroutine names in the bottom right box.  To search the list, start typing in the text box and the results in the result box will reflect what you've typed in the search box.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Select an item in the result box and click "Apply Filter" and that filter will be applied in the index worksheet.  For more information on auto filter: &lt;a href="http://www.contextures.com/xlautofilter01.html"&gt;http://www.contextures.com/xlautofilter01.html&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-3646508893033131056?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/3646508893033131056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=3646508893033131056' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/3646508893033131056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/3646508893033131056'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/10/scl-subroutine-indexer.html' title='SCL Subroutine Indexer'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-1041868031878720513</id><published>2008-10-06T11:57:00.003-04:00</published><updated>2008-10-06T12:17:14.380-04:00</updated><title type='text'>SCL Code "Profiler"</title><content type='html'>I've written a fairly large SCL macro, which you'll be able to get soon &lt;a href="http://www.ccat.us/modsim/eVSM_Utilities"&gt;here&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In order to keep tabs on how much of this 8000+ line macro is real code, I decided to write an SCL logic "profiler", which really just goes through and counts the number of comment lines, blank lines, and everything else, and reports it out for you.  So really in my (currently) 8195 lines of code there's really 5978 lines of code, 1061 blank lines, and 1156 lines commented out.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The line counter code can be downloaded &lt;a href="http://fournier.jonathan.googlepages.com/scl_code_profiler.scl"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-1041868031878720513?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/1041868031878720513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=1041868031878720513' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1041868031878720513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/1041868031878720513'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/10/scl-code-profiler.html' title='SCL Code &quot;Profiler&quot;'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-4803254354555347876</id><published>2008-10-01T13:09:00.002-04:00</published><updated>2008-12-18T15:40:38.885-05:00</updated><title type='text'>String Replace</title><content type='html'>&lt;div&gt;This routine gives you similar functionality to the replace function in VBA. Basically, the routine just reads through a string argument and replaces any instance of to_replace with replace_with.&lt;/div&gt;&lt;div&gt;As far as I can tell there is no built-in function in SCL for doing this...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;routine replace_string( full_string : String ; to_replace : String ; replace_with : String ) : String&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   result : String&lt;/div&gt;&lt;div&gt;   start_idx : Integer&lt;/div&gt;&lt;div&gt;   rep_idx : Integer&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;   start_idx = 11&lt;/div&gt;&lt;div&gt;   result = full_string&lt;/div&gt;&lt;div&gt;   while( index( result , to_replace , start_idx ) &gt; 0 ) do&lt;/div&gt;&lt;div&gt;      rep_idx = index( result , to_replace , start_idx )&lt;/div&gt;&lt;div&gt;      result = leftstr( result , index( result , to_replace , start_idx ) - 1 ) + replace_with + rightstr( result , len( result ) - index( result , to_replace , start_idx ) - len( to_replace ) + 1 )&lt;/div&gt;&lt;div&gt;      start_idx = rep_idx + len( replace_with )&lt;/div&gt;&lt;div&gt;   endwhile&lt;/div&gt;&lt;div&gt;   return result&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-4803254354555347876?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/4803254354555347876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=4803254354555347876' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4803254354555347876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/4803254354555347876'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/10/string-replace_01.html' title='String Replace'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7232341001965886603</id><published>2008-09-19T14:24:00.022-04:00</published><updated>2009-05-08T08:52:25.593-04:00</updated><title type='text'>Batch Control Language (BCL)</title><content type='html'>&lt;div&gt;QUST has two macro/scripting languages, &lt;a href="http://delmiaquest.blogspot.com/2008/06/simulation-control-language-scl.html"&gt;SCL&lt;/a&gt; and BCL.  BCL is short for Batch Control Language, and it is basically there to let you automate almost everything you can do through the QUEST User Interface.  This automation can be done through straight-up BCL scripts, which are plain-text files containing a series of BCL formatted commands.  An example of such a command is:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;CREATE SOURCE CLASS 'Source1'&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;which will create a new source class named Source1.  This will also create one element in the Source1 class.   You can locate this element using the follwing command:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;LOCATE ELEMENT 'Source1_1' AT 100 , 100 , 0&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This kind of scripting can be tedious and error-prone.  The good thing is, almost all BCL commands are supported for use through SCL programming.  This means you can write an SCL script to read a list of element names and locations, and execute BCL calls to create and locate those elements.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To use BCL within an SCL script, you use the BCL( command_text : String ) : Integer function.  All you do is provide a string argument that contains your BCL command, and SCL will have QUEST execute it.  The BCL function returns an integer containing the error code, so you can know whether or not the command executed properly.  A list of error code numbers and their corresponding descriptions can be found in the bclerr.inc file in your QUESTlib\Include folder.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's also possible to have QUEST execute a BCL script as soon as the QUEST.exe program starts.   Details for setting up QUEST to run this way from Excel can be found &lt;a href="http://delmiaquest.blogspot.com/2009/02/how-to-run-bcl-from-excel-simple-way.html"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, assuming you've set up QUEST to run a BCL script generated in Excel, you may now be wondering how to generate BCL scripts in Excel.  I have set up a number of Excel VBA User Defined Functions (UDFs) that can be used to generate a subset of all the BCL commands.  I'm currently working on building a version of this that I can release for everyone to use, but until then why not start &lt;a href="http://delmiaquest.blogspot.com/2009/05/excel-vba-udfs-for-quest-bcl-wow-enough.html"&gt;building your own BCL UDFs&lt;/a&gt;?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7232341001965886603?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7232341001965886603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7232341001965886603' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7232341001965886603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7232341001965886603'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/09/batch-control-language-bcl.html' title='Batch Control Language (BCL)'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-8319076774715083066</id><published>2008-09-19T14:24:00.019-04:00</published><updated>2008-09-19T15:36:26.084-04:00</updated><title type='text'>upper &amp; lower case</title><content type='html'>Sometimes in writing QUEST logics, especially those that deal with user input or reading from text files, I've had to compare two pieces of text for equality where the case of the text wasn't an issue.  The thing with SCL is that text comparisons are case sensitive, which meant I needed a way to convert a text string to either all caps or all lower case characters.  I never found anything for this in QUEST's SCL docs, so I made my own, and here they are.  The routines work by reading each character in a string individually, and seeing if it's already in the desired case.  If not, we just add or subtract 32 to/from its ASCII value to convert between upper and lower case characters in ASCII text.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://fournier.jonathan.googlepages.com/UpperLower.scl"&gt;Here's a download if you don't want to copy the text&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;routine is_lower( the_string : String ) : Integer&lt;/div&gt;&lt;div&gt;Const&lt;/div&gt;&lt;div&gt;   first_lower 97&lt;/div&gt;&lt;div&gt;   last_lower 122&lt;/div&gt;&lt;div&gt;   upper_to_lower 32&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   the_char : String  &lt;/div&gt;&lt;div&gt;   result : Integer&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;   the_char = leftstr( the_string , 1 )&lt;/div&gt;&lt;div&gt;   if( asc( the_char ) &lt;= last_lower AND asc( the_char ) &gt;= first_lower ) then&lt;/div&gt;&lt;div&gt;      result = true&lt;/div&gt;&lt;div&gt;   else&lt;/div&gt;&lt;div&gt;      result = false&lt;/div&gt;&lt;div&gt;   endif&lt;/div&gt;&lt;div&gt;   return result&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;routine is_upper( the_string : String ) : Integer&lt;/div&gt;&lt;div&gt;Const&lt;/div&gt;&lt;div&gt;   first_upper 65&lt;/div&gt;&lt;div&gt;   last_upper 90&lt;/div&gt;&lt;div&gt;   upper_to_lower 32&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   the_char : String  &lt;/div&gt;&lt;div&gt;   result : Integer&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;   the_char = leftstr( the_string , 1 )&lt;/div&gt;&lt;div&gt;   if( asc( the_char ) &lt;= last_upper AND asc( the_char ) &gt;= first_upper ) then&lt;/div&gt;&lt;div&gt;      result = true&lt;/div&gt;&lt;div&gt;   else&lt;/div&gt;&lt;div&gt;      result = false&lt;/div&gt;&lt;div&gt;   endif&lt;/div&gt;&lt;div&gt;   return result&lt;/div&gt;&lt;div&gt;End          &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;routine upper( the_string : String ) : String  &lt;/div&gt;&lt;div&gt;--Return upper case version of the_string&lt;/div&gt;&lt;div&gt;Const&lt;/div&gt;&lt;div&gt;   first_lower 97&lt;/div&gt;&lt;div&gt;   last_lower 122&lt;/div&gt;&lt;div&gt;   upper_to_lower 32&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   i : Integer&lt;/div&gt;&lt;div&gt;   result , check_char : String  &lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;result = ''&lt;/div&gt;&lt;div&gt;for i = 1 to len( the_string ) do&lt;/div&gt;&lt;div&gt;   check_char = substr( the_string , i , 1 )&lt;/div&gt;&lt;div&gt;   if( is_lower( check_char ) ) then&lt;/div&gt;&lt;div&gt;      check_char = chr( asc( check_char ) - 32 )&lt;/div&gt;&lt;div&gt;   endif&lt;/div&gt;&lt;div&gt;   result = result + check_char&lt;/div&gt;&lt;div&gt;endfor&lt;/div&gt;&lt;div&gt;return result&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;routine lower( the_string : String ) : String  &lt;/div&gt;&lt;div&gt;--Return upper case version of the_string&lt;/div&gt;&lt;div&gt;Const&lt;/div&gt;&lt;div&gt;   first_lower 97&lt;/div&gt;&lt;div&gt;   last_lower 122&lt;/div&gt;&lt;div&gt;   upper_to_lower 32&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   i : Integer&lt;/div&gt;&lt;div&gt;   result , check_char : String  &lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;result = ''&lt;/div&gt;&lt;div&gt;for i = 1 to len( the_string ) do&lt;/div&gt;&lt;div&gt;   check_char = substr( the_string , i , 1 )&lt;/div&gt;&lt;div&gt;   if( is_upper( check_char ) ) then&lt;/div&gt;&lt;div&gt;      check_char = chr( asc( check_char ) + 32 )&lt;/div&gt;&lt;div&gt;   endif&lt;/div&gt;&lt;div&gt;   result = result + check_char&lt;/div&gt;&lt;div&gt;endfor&lt;/div&gt;&lt;div&gt;return result&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-8319076774715083066?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/8319076774715083066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=8319076774715083066' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8319076774715083066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/8319076774715083066'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/09/upper-lower-case.html' title='upper &amp; lower case'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-498602079252491207</id><published>2008-09-19T14:24:00.015-04:00</published><updated>2008-09-19T15:21:40.067-04:00</updated><title type='text'>Inquire Element Location</title><content type='html'>The QUEST BCL Language has a command called "Inquire Element Location", which just takes the specified element's location and prints it to the BCL output window.  It may not seem at first to be of much use there, but we can make use of a special variable declaration in SCL to access this output text.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To illustrate using the BCL output from SCL here's an example SCL macro which will print the location of every element in the current model to a tab-delimited text file, and launch that file for viewing in Excel.  I have another macro which I may share that will let you read this format back into QUEST, modifying element locations as read from the text file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Handling 6 Degree of Freedom data in SCL&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;QUEST elements are located in 3D space in the QUEST world, and can be rotated about 3 axes, giving a total of six pieces of information required to completely locate some element in 3D space in QUEST.  In order to give our SCL code some degree of modularity and elegance, we need an easy way of passing all the location information.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We can settle for just passing all six parameters around every time we want to work with QUEST locations.  Over time this can get old, especially if you work a lot with locating elements in QUEST.  Also it helps to have a good methodology in place for dealing with locations, like having a routine for pulling the location of an element, or a procedure for locating an element with little hassle.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The solution I use is to have an SCL Structure for a 3D location.  From the QUEST SCL docs:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 12pt;font-size:100%;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;A structure is a group of variables which can be manipulated collectively or individually. &lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;A structure is analogous to a record which consists of many fields. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What this means to me is that I can have as much information stored in a structure as I need, and move that information around by passing just a single variable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The name I chose for my 3D location structure was "spot", and here's how I've defined a spot in SCL:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;structure spot&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;x : Real&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;y : Real &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;z : Real&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;yaw : Real&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;pitch : Real&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;roll : Real&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;elem_there : Element&lt;/div&gt;&lt;div&gt;endstructure&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Basically the spot is just keeping track of 3D location and orientation, storing these values as type real.  I also have a handle to an element, which you would set when inquiring about en element's location.  My thinking there was that some day I might need a way to populate locations in a QUEST model without overlapping items, so I added the elem_there field.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One thing to note about using structures, is that you can work with a structure variable, or a pointer to a structure variable.  Those of you with experience in C probably know the distinctions and caveats to each technique, but I usually use a pointer to a structure, just because it's a little less confusing thinking about whether or not the structure I'm using is what I think it is.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Moving forward, we now need a way to inquire the location of an element in QUEST and return a pointer to a spot structure, after populating a spot.  The routine itself makes use of a bcl command called "INQUIRE ELEMENT LOCATION", which simply places the location of the element in a comma-delimited text string on the BCL command output window.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Accessing the text in the BCL command output window is pretty simple, just declare a variable at the top of your scl file in a declaration section called "BCL_VAR".  The string to declare for the BCL command output window is "bcl_msg : String".  The only other BCL_VAR is "bcl_status : Real" which will tell you the result of a BCL command.  More on that another time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So your BCL_VAR declaration should look like this:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;BCL_VAR&lt;/div&gt;&lt;div&gt;   bcl_msg : String&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Now for the inquire_loaction routine:&lt;/div&gt;&lt;div&gt;&lt;div&gt;routine inquire_location( the_element : Element ) : @spot&lt;/div&gt;&lt;div&gt;Const&lt;/div&gt;&lt;div&gt;   the_delim ','&lt;/div&gt;&lt;div&gt;Var&lt;/div&gt;&lt;div&gt;   bcl_err : Integer&lt;/div&gt;&lt;div&gt;   the_loc : String&lt;/div&gt;&lt;div&gt;   result : @spot&lt;/div&gt;&lt;div&gt;Begin&lt;/div&gt;&lt;div&gt;   result = new()&lt;/div&gt;&lt;div&gt;   if( the_element &lt;&gt; NULL ) then&lt;/div&gt;&lt;div&gt;      bcl_err = BCL( "INQUIRE ELEMENT '" + the_element-&gt;name + "' LOCATION" )&lt;/div&gt;&lt;div&gt;      the_loc = bcl_msg&lt;/div&gt;&lt;div&gt;      parse_str( the_loc , the_delim , result-&gt;x , result-&gt;y , result-&gt;z , result-&gt;yaw , result-&gt;pitch , result-&gt;roll )&lt;/div&gt;&lt;div&gt;   endif&lt;/div&gt;&lt;div&gt;   return result&lt;/div&gt;&lt;div&gt;End&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A few things to note:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;result is declared as being of type @spot, which is a pointer to a spot structure&lt;/li&gt;&lt;li&gt;We make use of the new() routine to allocate memory for a spot structure.  We have to remember to free this portion of memory later using the free() procedure.&lt;/li&gt;&lt;li&gt;We make use of the parse_str routine for parsing the string into chunks for us.  This is a built in routine in SCL.&lt;/li&gt;&lt;li&gt;We use the -&gt; symbol as a member pointer rather than a dot because we're working with a pointer to a structure.  If we were using a straight structure, we'd us a dot.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;The routine basically just executes the "INQUIRE ELEMENT LOCATION" BCL command, extracts the output text from the BCL output window, and parses it to a new pointer to a spot structure, and returns the pointer to the calling function.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To tie it all together, see the &lt;a href="http://fournier.jonathan.googlepages.com/write_elem_locs.scl"&gt;write_elem_locs.scl&lt;/a&gt; file to see how we can build a tab-delimited text file of all our element names and locations, and launch the file in Excel.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can execute the macro by saving it to an SCLMACROS folder in a QUEST library, or you can compile the file and execute the write_all_locations function through BCL.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-498602079252491207?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/498602079252491207/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=498602079252491207' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/498602079252491207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/498602079252491207'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/09/inquire-element-location.html' title='Inquire Element Location'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-5289267192649006419</id><published>2008-06-05T20:38:00.007-04:00</published><updated>2008-06-05T20:44:47.048-04:00</updated><title type='text'>Select A Process</title><content type='html'>QUEST has a pretty powerful construct that I haven't really seen in any other simulation packages: processes.  A process is a data structure in QUEST that holds pretty much all the information you need to run a process in a simulation.&lt;br /&gt;&lt;br /&gt;SCL exposes a lot of the information in a process, which you can see in the SCL documentation.  However, selecting a process interactively in SCL is not built in (as far as I can tell).  So here's a routine for selecting a process in a QUEST model.&lt;br /&gt;&lt;br /&gt;routine select_a_process() : Process&lt;br /&gt;Const&lt;br /&gt;   max_process 200&lt;br /&gt;Var&lt;br /&gt;   result , the_process : Process&lt;br /&gt;   num_processes_found , pick_process , list_picked : Integer&lt;br /&gt;   the_processes : Array[ max_process ] of String&lt;br /&gt;Begin&lt;br /&gt;&lt;br /&gt;   num_processes_found = 0&lt;br /&gt;   the_process = first_process&lt;br /&gt;   while( the_process &lt;&gt; NULL and num_processes_found &lt; max_process ) do&lt;br /&gt;      the_processes[ num_processes_found ] = the_process-&gt;name&lt;br /&gt;      num_processes_found = num_processes_found + 1&lt;br /&gt;      the_process = the_process-&gt;next&lt;br /&gt;   endwhile&lt;br /&gt;   list_picked = item_pop_up( 'Select a process' , the_processes , pick_process )&lt;br /&gt;   return get_process( the_processes[ pick_process ] )&lt;br /&gt;End&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Basically the macro traverses the QUEST model's linked list of processes and adds them to an array.  Then we use the item_pop_up routine to select a process from a list generated by our array.  The item_pop_up returns the index of the selected process in the array, and we return that process pointer.  You can use this routine to select a process that you want to act on in a SCL macro.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-5289267192649006419?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/5289267192649006419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=5289267192649006419' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5289267192649006419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5289267192649006419'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/06/select-process.html' title='Select A Process'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-7308367707252406653</id><published>2008-06-04T18:14:00.045-04:00</published><updated>2009-02-26T09:20:58.777-05:00</updated><title type='text'>File I/O</title><content type='html'>QUEST SCL has a set of easy to use subroutines for dealing with file input and output.  If you've done file I/O in VB or VBA you'll see the syntax is very similar.&lt;br /&gt;&lt;br /&gt;File I/O is performed in SCL using file streams.  This basically means that you use SCL to open a file and either read it or write to it.  To open a file you first need to determine the file stream you want to use.  This is just an integer value unique to the file you want to access.  If you're planning to open a file stream and close it within a single subroutine the file stream should be an integer between 1 and 15.  Anything above that is a global stream, which can be manipulated from any subroutine you're running.  This complicates things a bit, and I personally don't use global streams very often.  This is because you can pretty easily just append data to a file if you prefer.&lt;br /&gt;&lt;br /&gt;There are two ways to pick a stream.  You can use a literal integer value and just keep an eye on which you use (in case you decide to manipulate several files at once).  Or you can do what I do and use an integer variable so it's easy to change things around, and it makes the code easier to read.&lt;br /&gt;&lt;br /&gt;There is a way to ensure you always have a good file stream to use, which is to check file streams starting with one until you find one that's not opened yet.  This is facilitated with a while loop and the QUEST built in function is_open.&lt;br /&gt;&lt;br /&gt;The is_open function just takes in an integer value and returns true if it's in use as a file stream and false if it's not.  Here's the start of a procedure for writing data to a file:&lt;br /&gt;&lt;br /&gt;  procedure print_data_to_file()&lt;br /&gt;  Var&lt;br /&gt;  out_stream : Integer&lt;br /&gt;  Begin&lt;br /&gt;      out_stream = 1&lt;br /&gt;      while( is_open( out_stream ) ) do&lt;br /&gt;          out_stream = out_stream + 1&lt;br /&gt;      endwhile&lt;br /&gt;  End&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When this procedure gets to the end, out_stream will have a value that is acceptable for use in manipulating file operations.  But how do we start file manipulation?  With the "open" procedure.  This procedure is a little different in that arguments are not passed in parenthesis, but instead the command is built like a sentence.  The syntax is:&lt;br /&gt;&lt;br /&gt; OPEN FILE name FOR [ BINARY | TEXT ] { OUTPUT | APPEND | INPUT } AS unit_no&lt;br /&gt;&lt;br /&gt;In this procedure we can leave out the binary/text declaration, as SCL will default to text.  We need to declare how we're opening the file, though.  We have the option of: output, append, or input.  If we output, then if the file exists it will be wiped clean and started new.  If we choose append we have to make sure the file exists to begin with or we'll get an error.  If we do append, then any data we write to the file just gets appended to the end of the file.  Lastly, if we open for input then we can't make any changes to the file; we're just reading its contents.&lt;br /&gt;&lt;br /&gt;From this point on things are pretty straightforward if you're writing out to the file.  You simply use the "write" procedure and specify the output stream in order to output to that stream.  Here's an example procedure:&lt;br /&gt;&lt;br /&gt;  procedure print_machine_class_names()&lt;br /&gt;  Var&lt;br /&gt;   out_stream : Integer&lt;br /&gt;   check_class : Element_Class&lt;br /&gt;  Begin&lt;br /&gt;   out_stream = 1&lt;br /&gt;   while( is_open( out_stream ) ) do&lt;br /&gt;      out_stream = out_stream + 1&lt;br /&gt;   endwhile&lt;br /&gt;   OPEN FILE 'C:/Tmp/machine_names.txt' FOR OUTPUT AS out_stream&lt;br /&gt;   check_eclass = first_element_class&lt;br /&gt;   while( check_eclass &lt;&gt; NULL ) do&lt;br /&gt;      if( check_eclass-&gt;type == MACHINE ) then&lt;br /&gt;         write( #out_stream , check_eclass-&gt;name , cr )&lt;br /&gt;      endif&lt;br /&gt;      check_eclass = check_eclass-&gt;next_eclass&lt;br /&gt;   endwhile&lt;br /&gt;   close #out_stream&lt;br /&gt;  End&lt;br /&gt;&lt;br /&gt;This is a very straightforward example that first creates/resets the machine_names.txt file, and then proceeds to print out the name of every machine encountered in the model.  The last thing it does is close the file stream using the close procedure.&lt;br /&gt;&lt;br /&gt;Reading data from a text file is a little less straightforward but not much harder to do.  We need to start the same way as writing: find a valid file stream and open the file.  Here's the base code:&lt;br /&gt;&lt;br /&gt;  procedure read_data_from_file()&lt;br /&gt;  Var&lt;br /&gt;   in_stream : Integer&lt;br /&gt;   Begin&lt;br /&gt;   in_stream = 1&lt;br /&gt;   while( is_open( in_stream ) ) do&lt;br /&gt;      in_stream = in_stream + 1&lt;br /&gt;   endwhile&lt;br /&gt;   OPEN FILE 'C:\Tmp\file_read_example.txt' FOR INPUT AS in_stream&lt;br /&gt;   End&lt;br /&gt;&lt;br /&gt;Once the file is open, we need to start reading the file.  We can do this using the read_line procedure.  The syntax is as follows:&lt;br /&gt;&lt;br /&gt;  READ_LINE ( [ #unit_no,]  lvalue )&lt;br /&gt;&lt;br /&gt;where lvalue is a string variable we pass in whose value gets assigned as the next line read from the specified file stream.  One thing to note here, is that when SCL gets to the end of the file, read_line will return a special predefined string called $EOF.  We just keep reading until read_line gives us the $EOF string.&lt;br /&gt;&lt;br /&gt;Here is some sample code for reading lines from a file and writing them to the screen.&lt;br /&gt;&lt;br /&gt;  procedure read_data_from_file()&lt;br /&gt;  Var&lt;br /&gt;   in_stream : Integer&lt;br /&gt;   curr_line : String&lt;br /&gt;    Begin&lt;br /&gt;   in_stream = 1&lt;br /&gt;   while( is_open( in_stream ) ) do&lt;br /&gt;      in_stream = in_stream + 1&lt;br /&gt;   endwhile&lt;br /&gt;   OPEN FILE 'C:\Tmp\file_read_example.txt' FOR INPUT AS in_stream&lt;br /&gt;   read_line( #in_stream , curr_line )&lt;br /&gt;   while( not curr_line == $EOF ) do&lt;br /&gt;      write( curr_line , cr )&lt;br /&gt;      read_line( #in_stream , curr_line )&lt;br /&gt;   endwhile&lt;br /&gt;   close #in_stream&lt;br /&gt;    End&lt;br /&gt;&lt;br /&gt;File I/O is a powerful tool for use in QUEST.  You can use this to read in a tab-delimited data file with any number of possible uses.  For example you can read in process cycle times and assign those times to the specified processes.  The possibilities here are really endless, and hopefully this will give you a good idea of how to get started.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-7308367707252406653?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/7308367707252406653/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=7308367707252406653' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7308367707252406653'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/7308367707252406653'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/06/file-io.html' title='File I/O'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-431854745152521633</id><published>2008-06-03T22:15:00.000-04:00</published><updated>2008-06-03T23:00:52.072-04:00</updated><title type='text'>Simulation Control Language (SCL)</title><content type='html'>Simulation Control Lanugage (SCL) is the runtime language used in QUEST for defining logics.  It's pretty similar to Visual Basic and Pascal as far as I can tell, in terms of syntax.  It's a fairly high level language allowing easy manipulation of files, and even execution of Windows API functions.&lt;br /&gt;&lt;br /&gt;SCL is not only used for defining logics in a model (init, process, route, etc), but can also be used to build QUEST macros that you run using custom buttons or even remote execution through QUEST's Batch Control Lanugage (BCL).  The possibilities with SCL aren't necessarily limitless, but it's a very robust language and it takes a lot of effort to run into its limitations.&lt;br /&gt;&lt;br /&gt;SCL files are stored in text files and are not embedded within a simulation model like some other simulation packages do.  This makes it easy to apply SCL code to different models, but it also means you can destroy the functionality of any number of models just by modifying a single logic file to fit a single case.&lt;br /&gt;&lt;br /&gt;To get you started with SCL, I'll go with the old standby and just create a simple "Hello World" program to illustrate some basic SCL concepts.&lt;br /&gt;&lt;br /&gt;To start, you first need to open a text editor and start your scl file.  You can use notepad or any text editor.  I prefer to use RJ-TextEd (&lt;a href="http://groups.google.com/group/delmia_quest/t/db859470c0248e5"&gt;See here&lt;/a&gt;) because it allows code folding and syntax highlighting; so if you have a large number of subroutines in a file you can more easily navigate the file than using notepad.&lt;br /&gt;&lt;br /&gt;With your text editor of choice open, first create a new subroutine by defining it:&lt;br /&gt;&lt;br /&gt;    procedure hello_world()&lt;br /&gt;&lt;br /&gt;The word "procedure" tells the scl compiler that this is a subroutine that does not return anything.  If you want to return a value you replace the word "procedure" with "routine".  I'll cover routines in more detail at a later time.  You're also able to pass in different arguments to subroutines, but we don't need to worry about that just yet.  We just want to display "hello world" in QUEST.&lt;br /&gt;&lt;br /&gt;With your procedure name defined, we can finish defining the procedure by defining the start and end of the program:&lt;br /&gt;&lt;br /&gt;    procedure hello_world()&lt;br /&gt;    Begin&lt;br /&gt;&lt;br /&gt;    End&lt;br /&gt;&lt;br /&gt;All code that you execute must fall between the Begin and End lines of the subroutine you're using.  Each line of code represents one command (unless you use the line continuation character, "\").&lt;br /&gt;&lt;br /&gt;QUEST has some decent documentation on SCL built in subroutines.  From this documentation under the I/O Routines section we can find a procedure called "write" that will let us print a message to the QUEST user screen.  The syntax is:&lt;br /&gt;&lt;br /&gt;    WRITE ( #unit_no, pr_expr [ , pr_expr,... ] )&lt;br /&gt;&lt;br /&gt;where "#unit_no" is an optional argument which can specify a file or window or tcp/ip stream to write to.  Disregard this for now.  "pr_expr" is the message we want to write, which can be a variable of just about any type (although some types just print their memory address), though we should stick to printing simple data types( String , Real , Integer ).  So the "[ , pr_expr ]" means we can specify any number of variables we want.&lt;br /&gt;&lt;br /&gt;We don't need to pass a variable to the "write" procedure; we can pass literal strings or integer/double values as well.  To write "hello world" in QUEST, we'd simply call:&lt;br /&gt;&lt;br /&gt;    write( 'hello world' , cr )&lt;br /&gt;&lt;br /&gt;where cr is a built in QUEST variable that is basically a carriage return and line feed.&lt;br /&gt;&lt;br /&gt;You can see I used a single quote to define a literal string, "hello world".  This is the SCL compiler's preferred way of defining a literal string, but you can use double quotes if you want, as long as you are consistent in a single string definition (you can't say "hello world').&lt;br /&gt;&lt;br /&gt;The finished procedure reads as follows:&lt;br /&gt;&lt;br /&gt;    procedure hello_world()&lt;br /&gt;    Begin&lt;br /&gt;        write( 'hello world' , cr )&lt;br /&gt;    End&lt;br /&gt;&lt;br /&gt;Save your scl file into the "SCLMACROS" folder of any QUEST library you have appended.  You can save with a txt or scl extension, it really doesn't matter.  As long as the information is present in ASCII text the SCL compiler won't care.&lt;br /&gt;&lt;br /&gt;We don't need to create a user button to run this macro, and so it'll probably be easier for now to just compile and run the file using BCL.  To execute BCL go to File-&gt;BCL.  You will be given a BCL prompt where you can type or paste a command to execute.  The first line of BCL to execute is:&lt;br /&gt;&lt;br /&gt;    SCL_COMPILE 'hello_world.scl' 0&lt;br /&gt;&lt;br /&gt;Replace 'hello_world.scl' with whatever you named your file.  Don't worry about the full file path; as long as it's in an "SCLMACROS" folder QUEST should be able to find it.  If the file is not found, make sure the library it's in is appended.&lt;br /&gt;&lt;br /&gt;The next line of BCL will read:&lt;br /&gt;&lt;br /&gt;    SCL_EXEC hello_world&lt;br /&gt;&lt;br /&gt;This line will execute the hello_world procedure stored in memory after compiling your logic file.  When you run this a window should pop up in QUEST that says "hello world".&lt;br /&gt;&lt;br /&gt;That was a bit long winded for a hello world type subroutine, but hopefully it explains how you need to define subroutines for QUEST SCL files.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-431854745152521633?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/431854745152521633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=431854745152521633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/431854745152521633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/431854745152521633'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/06/simulation-control-language-scl.html' title='Simulation Control Language (SCL)'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5908847836728425526.post-5379993222822543357</id><published>2008-06-03T22:01:00.000-04:00</published><updated>2008-06-03T22:15:42.180-04:00</updated><title type='text'>Introduction Post</title><content type='html'>The purpose of this blog will primarily be somewhere for me to put some of my knowledge of DELMIA QUEST (QUeueing Event Simulation Tool) out on the Internet.  This is for two main reasons: one, I'd like to have somewhere to keep some of the tools I've written for QUEST, and two, maybe someone somewhere will get some value out of what I leave here.&lt;br /&gt;&lt;br /&gt;I spend a lot of my time these days working on ways to automate the use of QUEST through QUEST's Batch Control Language (BCL) and Simulation Control Language (SCL), so that's probably what most posts will focus on for now.&lt;br /&gt;&lt;br /&gt;I'm always looking to learn more about QUEST and simulation packages in general, so leave a comment or send an email (if that's available).&lt;br /&gt;&lt;br /&gt;I run a Google Group on DELMIA QUEST, which at the moment doesn't have a lot of activity.  If you're interested in joining go to &lt;a href="http://groups.google.com/group/delmia_quest"&gt;http://groups.google.com/group/delmia_quest&lt;/a&gt; and join, and I'll more than likely approve you.&lt;br /&gt;&lt;br /&gt;Happy simulating.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5908847836728425526-5379993222822543357?l=delmiaquest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://delmiaquest.blogspot.com/feeds/5379993222822543357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5908847836728425526&amp;postID=5379993222822543357' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5379993222822543357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5908847836728425526/posts/default/5379993222822543357'/><link rel='alternate' type='text/html' href='http://delmiaquest.blogspot.com/2008/06/introduction-post.html' title='Introduction Post'/><author><name>Jon Fournier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
