<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-8764109705492068977</atom:id><lastBuildDate>Sun, 08 Sep 2024 17:01:59 +0000</lastBuildDate><category>Intralink</category><category>Java</category><category>Pro/ENGINEER</category><category>Intralink Scripting</category><category>WebLink</category><category>Javascript</category><category>Intralink Oracle SQL</category><category>Excel</category><category>Trail Files</category><category>protk.dat</category><category>Drawings</category><category>J-Link</category><category>Perl</category><category>Pro/Toolkit</category><category>VB API</category><category>VBScript</category><category>Visual Basic</category><category>Books</category><title>Inversion Consulting&#39;s CAD/PDM Automation Blog</title><description>Discussion of automation tools and how to use them.  Specializing in Java, Javascript, Perl, C, C++ with Pro/Engineer, Pro/Toolkit, Intralink, Intralink Scripting, JLink, WebLink, and more.</description><link>http://inversionconsulting.blogspot.com/</link><managingEditor>noreply@blogger.com (Marc Mettes)</managingEditor><generator>Blogger</generator><openSearch:totalResults>47</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-6910435114423252028</guid><pubDate>Thu, 01 Oct 2009 09:30:00 +0000</pubDate><atom:updated>2009-10-01T03:00:21.391-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Drawings</category><category domain="http://www.blogger.com/atom/ns#">Javascript</category><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">WebLink</category><title>Pro/WebLink: Replace Drawing Formats</title><description>Jürgen from Germany was asking me recently about replacing formats with Pro/WebLink.  In the process of providing a solution, I found an interesting combination of disappointments, curiosities, and finally a very nice solution.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;SetSheetFormat()&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Looking through the API documentation, it&#39;s not too hard to find that the method call to replace drawing formats is SetSheetFormat() in the pfcSheetOwner class.  One of the primary arguments is the drawing format object in the form of a pfcDrawingFormat object.  Unfortunately, this object&#39;s class is not obviously documented.  The docs say only that its parent class is a pfcModel.  So how to you get a drawing format object when it seems to have no methods?&lt;br /&gt;&lt;br /&gt;Since it&#39;s a subclass of pfcModel, you use pfcBaseSession methods such as OpenFile(), GetModel, and RetrieveModel().  Here&#39;s where the J-Link docs are bit better, because they list the methods inherited from parent classes and interfaces, just making it that much more obvious.  To use RetrieveModel(), a pfcModelDescriptor object needs to be created which specifies what is to be retrieved and how.&lt;br /&gt;&lt;br /&gt;Here is the core sequence of steps, assuming the current model is a drawing:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;var session = pfcGetProESession();&lt;br /&gt;var drawing = session.CurrentModel;&lt;br /&gt;var drwSheetNum = drawing.CurrentSheetNumber; // use current sheet&lt;br /&gt;&lt;br /&gt;var frmName = &amp;quot;c_size.frm&amp;quot;;&lt;br /&gt;var frmSheetNum = 1;&lt;br /&gt;var frmDescr = pfcCreate(&amp;quot;pfcModelDescriptor&amp;quot;).CreateFromFileName(frmName);&lt;br /&gt;var format = session.RetrieveModel(frmDescr);&lt;br /&gt;&lt;br /&gt;var drwModel = null;&lt;br /&gt;drawing.SetSheetFormat(drwSheetNum, format, frmSheetNum, drwModel);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Format Folder&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;You&#39;ll notice that the folder where the format is stored was not specified.  Why?  According to the docs, you can&#39;t specify the path to a folder containing a pfcModel when using RetrieveModel().  Although the pfcModelDescriptor object contains a Path property, it is ignored.&lt;br /&gt;&lt;br /&gt;How does Pro/Engineer know where to find the format?  It just does.  Well, if the PRO_FORMAT_DIR config.pro option is set properly, then it just does.  Fortunately, this config.pro option can handle folder paths, Intralink 3.x folders, and PDMLink folders.  That should cover most scenarios.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Format Sheets&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;SetSheetFormat() also allows you to specify the sheet number of the format to use (should your format have more than one sheet).  Unfortunately, since the pfcDrawing Format object does not implement the pfcSheetOwner interface, the developer has no way to determine how many sheets are in the format.  You&#39;ll just have to know how many sheet your formats have ahead of time, not a major tragedy.&lt;br /&gt;&lt;br /&gt;To be fair this is a Pro/Toolkit limitation first and foremost.  The PFC APIs merely inherit Pro/Toolkit&#39;s limitations.&lt;br /&gt;&lt;br /&gt;Drawings, layouts, and Pro/Report files (who uses these anyway?!) all are defined as pfcModel2D objects, which gives lots of info about sheets, tables, and detail items.  Formats, although pretty much the same thing, are not pfcModel2D objects.  As a result, we can get none of these things.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Drawing Model&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The drawing model is the part or assembly documented on the current sheet.  Although this can be specified as the last argument to SetSheetFormat(), we don&#39;t have the ability to know what the current model is (at least until WF4).  null is used to here to indicate the current drawing model.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Format Tables&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Just as with interactive use of Pro/Engineer, when drawing formats are replaced, the drawing tables from the previous format have to be dealt with.  Typically, this involves deleting the tables.  Since SetSheetFormat() does not provide a mechanism or option for removing the old format tables, this will have to be done with more code.&lt;br /&gt;&lt;br /&gt;This is where it gets a little tricky.  While there is a CheckIfIsFromFormat() method call that will tell us if a table came from a format, we&#39;ll need the table object first.  To get the table object, first we&#39;ll have to use ListTables() from the pfcTableOwner class to get all of the tables for the entire drawing.  ListTables() takes no argument, meaning that we have no way to pre-filter the collection of tables.  It really should take a sheet number argument to return only the tables on that sheet.  As an alternatives, had the pfcTable class been a pfcDetailItem (in addition to a pfcModelItem), we could have gathered the tables by sheet number using ListDetailItems(), from pfcDetailItemOwner.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;var tables = drawing.ListTables();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;The workflow for CheckIfIsFromFormat() is a bit odd as well.  To check if a table is from a format, we need the pfcTableObject, and then we need to specify the sheet number.  Now wait a minute, the function returns a boolean so logically the table is from the format or it is not.  What does the sheet number have to do with that?  Even if the table had been segmented, it&#39;s still going to be from the format or not.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;if (table.CheckIfIsFromFormat(drwSheetNum) == true) {&lt;br /&gt;  // table is from format, delete it&lt;br /&gt;  drawing.DeleteTable(table, false);&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;This quirkiness turns out to be very useful because it&#39;s rather difficult to tell on what sheet the table exists.  The pfcTableInfo class does not contain this info.  While it&#39;s true that the GetSegmentSheet() method can be used for this, we would have to assume that segment zero is the proper segment to use.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Full Example: Replacing Formats&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This example shows a complete code set for obtaining the drawing object, the format object, and their related info.  It then procedes to call the ReplaceFormat() function, which removes the old format tables prior to replacing the format.  The code replaces the format and tables very quickly.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;// get current drawing and sheet number&lt;br /&gt;var session = pfcGetProESession();&lt;br /&gt;var drawing = session.CurrentModel;&lt;br /&gt;var drwSheetNum = drawing.CurrentSheetNumber;&lt;br /&gt;&lt;br /&gt;// get format name from html text field&lt;br /&gt;var frmName = document.getElementById(&amp;quot;frmName&amp;quot;).value&lt;br /&gt;&lt;br /&gt;// use format sheet 2 if drawing sheet is not sheet 1&lt;br /&gt;var frmSheetNum = 1;&lt;br /&gt;if (drwSheetNum &amp;gt; 1) { frmSheetNum = 2; }&lt;br /&gt;&lt;br /&gt;// get the format&lt;br /&gt;var frmDescr = pfcCreate(&amp;quot;pfcModelDescriptor&amp;quot;).CreateFromFileName(frmName);&lt;br /&gt;var format = session.RetrieveModel(frmDescr);&lt;br /&gt;&lt;br /&gt;// replace the format&lt;br /&gt;ReplaceFormat(drawing, drwSheetNum, format, frmSheetNum);&lt;br /&gt;&lt;br /&gt;// update the display (optional)&lt;br /&gt;// session.CurrentWindow.Repaint();&lt;br /&gt;// drawing.Regenerate();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;function ReplaceFormat ( drawing, drwSheetNum, format, frmSheetNum ) {&lt;br /&gt;&lt;br /&gt;  var tables = null;&lt;br /&gt;&lt;br /&gt;  try {&lt;br /&gt;    // get sequence of tables in the drawing&lt;br /&gt;    tables = drawing.ListTables();&lt;br /&gt;    for (var i=0; i&amp;lt;tables.Count; i++) {&lt;br /&gt;      var table = tables.Item(i);&lt;br /&gt;      if (table.CheckIfIsFromFormat(drwSheetNum) == true) {&lt;br /&gt;        // table is from format, delete it&lt;br /&gt;        drawing.DeleteTable(table, false);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  catch (e) {&lt;br /&gt;    // ignore, no tables in drawing&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  drawing.SetSheetFormat(drwSheetNum, format, frmSheetNum, null);&lt;br /&gt;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Another step to perform (marked as optional in the example) is to update the display using either Repaint() or Regenerate().  They both should accomplish the same goal, but one may work better in certain drawings than the other.  You can be sure that if a large drawing is slow to repaint when performed in Pro/Engineer interactively, it will be just as slow via Pro/Web.Link.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/10/proe-weblink-replace-drawing-formats.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-3999122893435541382</guid><pubDate>Mon, 15 Jun 2009 10:48:00 +0000</pubDate><atom:updated>2009-06-15T03:56:25.685-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Java</category><title>Java: JOptionPane Examples Part 4 - Complex</title><description>&lt;strong&gt;Break out of the JOptionPane Limitations with JDialog&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In the final article in my JOptionPane example series, I will show how to eliminate a JOptionPane limitation that you may encounter.  The limitation is size.  Sure, the dialog automatically sizes itself to fit your GUI elements.  However, there is no way to allow a user to resize the standard JOptionPane dialog.&lt;br /&gt;&lt;br /&gt;The way to eliminate this problem is to embed a JOptionPane object within a JDialog.  It&#39;s very simple and requires very little change to existing code you may have.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example 1: Resizable and Editable JTextArea with JScrollPane scrollbars&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This example expands upon Example 2 (from &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/05/java-joptionpane-examples-part-2-int.html&quot;&gt;Part 2&lt;/a&gt;).  A JTextArea is used, but the dialog is not resizable.  By embedding with a JDialog, this limitation can be overcome.&lt;br /&gt;&lt;br /&gt;The definition of the JTextArea and Object array remains the same:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    JTextArea area = new JTextArea();&lt;br /&gt;    area.setText(&amp;quot;line1\nline2\nline3\nline4\nline5\nline6&amp;quot;);&lt;br /&gt;    area.setRows(5);&lt;br /&gt;    area.setColumns(10);&lt;br /&gt;    area.setEditable(true);&lt;br /&gt;    JScrollPane scrollpane = new JScrollPane(area);&lt;br /&gt;&lt;br /&gt;    Object[] array = {&lt;br /&gt;        new JLabel(&amp;quot;Enter some text:&amp;quot;),&lt;br /&gt;        scrollpane,&lt;br /&gt;    };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Instead of using one of the static methods of JOptionPane, a JOptionPane object is created using its constructor.  The Object array and the message type are passed as arguments to the constructor.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    JOptionPane pane = new JOptionPane(array, JOptionPane.PLAIN_MESSAGE);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Once the JOptionPane object has been created, the createDialog() method is called, which returns a JDialog object.  null is passed to createDialog() to center the dialog on the screen, while the string argument will be the title of the dialog.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    JDialog dialog = pane.createDialog(null, &amp;quot;Result Data&amp;quot;);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Before the setVisible() method is called, setResizable() is called to allow the dialog to be resized.  When setVisible() is called, the dialog will exhibit the same general behavior as when using the static methods of JOptionPane.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    dialog.setResizable(true);&lt;br /&gt;    dialog.setVisible(true);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Once the user has closed the dialog, control returns to the program.  As with the original version of the program, the JTextArea object still exists and its value can be obtained using getText().&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    String newtext = area.getText();&lt;br /&gt;    System.out.println( &amp;quot;newtext: &amp;quot; + newtext );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;With JDialog, many new options are available.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/06/java-joptionpane-examples-part-4.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-6088654501387010736</guid><pubDate>Thu, 11 Jun 2009 03:56:00 +0000</pubDate><atom:updated>2009-06-10T21:12:10.824-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">J-Link</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">protk.dat</category><title>J-Link: Getting Started with Java and Pro/Engineer, Part 2</title><description>&lt;strong&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;J-Link Java Code Requirements&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;J-Link requires that you have static methods with names matching the java_app_start and java_app_stop options from the registry file. Using the example registry file from &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/06/proe-java-jlink-getting-started-1.html&quot;&gt;Part 1&lt;/a&gt;, the required signatures for the &quot;start&quot; and &quot;stop&quot; methods would look like this:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    public static void startApp();&lt;br /&gt;    public static void stopApp();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;As you&#39;ll see from the code that follows, these static methods don&#39;t do much but call other methods where all the important stuff happens. This approach seems to work well, but there are certainly other ways to approach J-Link.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;Method Summary:&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Here are the other methods used by the program, none of which are static:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Constructor JLinkHelloWorld()&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The constructor sets up the needed utility items, such as the program name (based on the class name), a FileWriter object for the log file, and the platform specific newline character.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Method startupApplication()&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The startupApplication() method gets the Pro/Engineer session object, defines a UI command, registers the UI command in the GUI (in the &#39;Tools&#39; menu), and then announces to the user that the program is operational.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Method shutdownApplication()&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The shutdownApplication() method closes out the log file&#39;s FileWriter object.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Method writeLog(String mesg)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A log file can be used for debugging and reporting purposes. A developer will use it for debugging an application, while an end user will be able to see what the program is doing internally.&lt;br /&gt;&lt;br /&gt;Although using the log file is definitely optional, you&#39;ll find that there are all sorts of bizarre things in Pro/Engineer models that you will never have anticipated. With the use of proper logging, a developer increases the chances that these anomalies can be reported back by the end user.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Method closeLog()&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;As you might expect, this closes the log file.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Method DisplayMessage(String mesg)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;DisplayMessage() writes an arbitrary message to the Pro/Engineer message area for the user to see. The example uses of DisplayMessage() that I have provided is not really the best approach for internationalization, but it serves the purpose of showing how to write message to the Pro/Engineer GUI. This method also writes the same output to the log file.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;UI Command Registration and UI Listeners&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A program is not going to be useful to an end user unless they can run the program. The user is not going to be able to run a J-Link program unless it registers itself with the Pro/Engineer GUI via a new menu or new menu option.&lt;br /&gt;&lt;br /&gt;UI command registration is a multistep action requiring a couple of different pieces. The pieces required are a UICommandActionListener and a callback method, while the actions involve creating a command using UICreateCommand() and adding the command to the GUI using UIAddButton(). The text strings used as arguments to the UI methods are either found in the application&#39;s text message file (i.e. &quot;JLHW Btn1 Label&quot;) or are known by Pro/Engineer (i.e. &quot;Utilities&quot; which represents the &quot;Tools&quot; menu).&lt;br /&gt;&lt;br /&gt;The example program implements the listener by defining an inner class that extends the DefaultUICommandActionListener class. The inner class has a single method OnCommand() that is triggered when the user clicks on the command in the GUI. OnCommand() calls Btn1_callback() which is in the main class. Btn1_callback() then gets the current model object, if any, and displays the name in the message window using DisplayMessage().&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The J-Link &quot;Hello World&quot; Java Code:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;// JLinkHelloWorld.java&lt;br /&gt;// Copyright 2009, MarcMettes@InversionConsulting.com&lt;br /&gt;&lt;br /&gt;// imports required&lt;br /&gt;import com.ptc.cipjava.*;&lt;br /&gt;import com.ptc.pfc.pfcCommand.*;&lt;br /&gt;import com.ptc.pfc.pfcGlobal.*;&lt;br /&gt;import com.ptc.pfc.pfcModel.*;&lt;br /&gt;import com.ptc.pfc.pfcSession.*;&lt;br /&gt;import java.io.*;&lt;br /&gt;&lt;br /&gt;public class JLinkHelloWorld {&lt;br /&gt;&lt;br /&gt;    static JLinkHelloWorld App = null;&lt;br /&gt;    String programName = null;&lt;br /&gt;    Session session = null;&lt;br /&gt;    FileWriter log = null;&lt;br /&gt;    String msgFile = &quot;msg_jlinkhelloworld.txt&quot;;&lt;br /&gt;    String newline = null;&lt;br /&gt;&lt;br /&gt;    // constructor&lt;br /&gt;    //&lt;br /&gt;    public JLinkHelloWorld () {&lt;br /&gt;        programName = this.getClass().getName();&lt;br /&gt;        try {&lt;br /&gt;            log = new FileWriter(programName + &quot;.log&quot;);&lt;br /&gt;            newline = System.getProperty(&quot;line.separator&quot;);&lt;br /&gt;        }&lt;br /&gt;        catch (Exception e) {&lt;br /&gt;            // couldn&#39;t create log file, ignore&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Display message in Pro/Engineer&lt;br /&gt;    //&lt;br /&gt;    public void DisplayMessage ( String mesg ) throws Exception {&lt;br /&gt;        stringseq seq = stringseq.create();&lt;br /&gt;        seq.set(0, mesg);&lt;br /&gt;        session.UIDisplayMessage(msgFile, &quot;JLHW %s&quot;, seq);&lt;br /&gt;        seq.clear();&lt;br /&gt;        writeLog(mesg);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Write text to log file&lt;br /&gt;    //&lt;br /&gt;    public void writeLog ( String mesg ) {&lt;br /&gt;        try {&lt;br /&gt;            if (log == null) { return; }&lt;br /&gt;            log.write(mesg + newline);&lt;br /&gt;            log.flush();&lt;br /&gt;        }&lt;br /&gt;        catch (Exception e) {&lt;br /&gt;            // ignore&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Close log file&lt;br /&gt;    //&lt;br /&gt;    public void closeLog () {&lt;br /&gt;        try {&lt;br /&gt;            if (log == null) { return; }&lt;br /&gt;            log.close();&lt;br /&gt;        }&lt;br /&gt;        catch (Exception e) {&lt;br /&gt;            // ignore&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Called by Pro/Engineer when starting the application&lt;br /&gt;    //&lt;br /&gt;    public static void startApp () {&lt;br /&gt;        try {&lt;br /&gt;            App = new JLinkHelloWorld();&lt;br /&gt;            App.startupApplication();&lt;br /&gt;        }&lt;br /&gt;        catch (Exception e) {&lt;br /&gt;            App.writeLog(&quot;Problem running startupApplication method&quot; + e.toString());&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Called by Pro/Engineer when stopping the application&lt;br /&gt;    //&lt;br /&gt;    public static void stopApp () {&lt;br /&gt;        try {&lt;br /&gt;            App.shutdownApplication();&lt;br /&gt;        }&lt;br /&gt;        catch (Exception e) {&lt;br /&gt;            App.writeLog(&quot;Problem running shutdownApplication method&quot; + e.toString());&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Perform some steps when shutting down the application&lt;br /&gt;    //&lt;br /&gt;    public void shutdownApplication () throws Exception {&lt;br /&gt;        writeLog(&quot;Application &#39;&quot; + programName + &quot;&#39; stopped&quot;);&lt;br /&gt;        closeLog();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Perform some steps when starting the application&lt;br /&gt;    //&lt;br /&gt;    public void startupApplication () throws Exception {&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            writeLog(&quot;Application &#39;&quot; + programName + &quot;&#39; started.&quot;);&lt;br /&gt;            session = pfcGlobal.GetProESession();&lt;br /&gt;        }&lt;br /&gt;        catch (jxthrowable x) {&lt;br /&gt;            writeLog(&quot;ERROR: Problem getting session object.&quot;);&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        UICommand btn1_cmd = null;&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            // Define a UI command&lt;br /&gt;            btn1_cmd = session.UICreateCommand(&lt;br /&gt;                      &quot;JLHW Btn1 Cmd&quot;, new JLHW_Btn1_CmdListener()&lt;br /&gt;                  );&lt;br /&gt;        }&lt;br /&gt;        catch (jxthrowable x) {&lt;br /&gt;            writeLog(&quot;ERROR: Problem creating uicmd.&quot;);&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            // Add UI command to &#39;Tools&#39; menu&lt;br /&gt;            session.UIAddButton(&lt;br /&gt;                btn1_cmd, &quot;Utilities&quot;, null,&lt;br /&gt;                &quot;JLHW Btn1 Label&quot;, &quot;JLHW Btn1 Help&quot;,&lt;br /&gt;                 &quot;msg_jlinkhelloworld.txt&quot;&lt;br /&gt;            );&lt;br /&gt;        }&lt;br /&gt;        catch (jxthrowable x) {&lt;br /&gt;            writeLog(&quot;ERROR: Problem creating menu: &quot; + x.toString());&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        DisplayMessage(programName + &quot; application started.&quot;);&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Callback for the &#39;Tools&#39; menu button&lt;br /&gt;    //&lt;br /&gt;    public void Btn1_callback ( ) throws Exception {&lt;br /&gt;&lt;br /&gt;        String mesg = null;&lt;br /&gt;        Model model = session.GetCurrentModel();&lt;br /&gt;&lt;br /&gt;        if (model == null) {&lt;br /&gt;            mesg = &quot;Hello!&quot;;&lt;br /&gt;        }&lt;br /&gt;        else {&lt;br /&gt;            mesg = &quot;Hello! The model is: &quot; + model.GetFileName();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        DisplayMessage(mesg);&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Inner class for UI Command Listener&lt;br /&gt;    //&lt;br /&gt;    public class JLHW_Btn1_CmdListener extends DefaultUICommandActionListener {&lt;br /&gt;&lt;br /&gt;        // Handler for button push&lt;br /&gt;        //&lt;br /&gt;        public void OnCommand () {&lt;br /&gt;            try {&lt;br /&gt;                Btn1_callback();&lt;br /&gt;            }&lt;br /&gt;            catch (Exception e) {&lt;br /&gt;                writeLog(&quot;Exception thrown by Btn1_callback method: &quot; + e.toString());&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As you can see, there are a number of non-trivial steps involved in creating J-Link applications.  However, creating simple programs is really easy.&lt;br /&gt;&lt;br /&gt;If you need a J-Link program written for you, please contact me at MarcMettes@InversionConsulting.com to discuss your requirements.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/06/proe-java-jlink-getting-started-2.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-1468054606431118286</guid><pubDate>Mon, 08 Jun 2009 10:12:00 +0000</pubDate><atom:updated>2009-06-08T03:31:30.062-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Java</category><title>Java: JOptionPane Examples Part 3 - Advanced</title><description>&lt;strong&gt;Using Event Listeners and JPanels with JOptionPane Dialogs&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In my JOptionPane Examples &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/01/java-joptionpane-examples-part-1-basic.html&quot;&gt;Part 1&lt;/a&gt; and &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/05/java-joptionpane-examples-part-2-int.html&quot;&gt;Part 2&lt;/a&gt;, I covered many ways to use the JOptionPane, some ordinary, some surprising.  Now you may be thinking that the JOptionPane is great, but that you need a level of interactivity that is cannot support.  Well, think again.&lt;br /&gt;&lt;br /&gt;I was recently asked about Example 3 (from Part 2), which shows the use of JRadioButtons (tied together with a ButtonGroup) and a JTextField.  I was asked if the JTextField could have the keyboard focus by default, so that the user could immediately start typing in the JTextField, accepting the default JRadioButton.&lt;br /&gt;&lt;br /&gt;Since the JOptionPane tends to take control of the dialog once it starts, a more subtle approach is required.  One way to achieve this is to use an event listener.  By adding the appropriate event listener to the JTextField object, an action can be performed after the dialog has initialized.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example 1: Adding Event Listeners to a JTextField&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is an enhancement to the code example in Part 2, Example 3.  In order to force keyboard focus into the JTextField, the use of event listeners is required.  Also the array argument to showConfirmDialog() is replaced with a JPanel that will be populated with all needed components.&lt;br /&gt;&lt;br /&gt;This example requires the following imports in addition to the imports from Part 2:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    import java.awt.event.*;&lt;br /&gt;    import javax.swing.event.*;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;As in the previous version, a couple of labels, some JRadioButtons, a ButtonGroup, and a JTextField are defined.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    JLabel option_label = new JLabel(&amp;quot;Select an option:&amp;quot;);&lt;br /&gt;&lt;br /&gt;    JRadioButton b1 = new JRadioButton(&amp;quot;Option 1&amp;quot;);&lt;br /&gt;    JRadioButton b2 = new JRadioButton(&amp;quot;Option 2&amp;quot;);&lt;br /&gt;    JRadioButton b3 = new JRadioButton(&amp;quot;Option 3&amp;quot;);&lt;br /&gt;    b1.setSelected(true);&lt;br /&gt;&lt;br /&gt;    ButtonGroup group = new ButtonGroup();&lt;br /&gt;    group.add(b1);&lt;br /&gt;    group.add(b2);&lt;br /&gt;    group.add(b3);&lt;br /&gt;&lt;br /&gt;    JLabel name_label = new JLabel(&amp;quot;Enter a name:&amp;quot;);&lt;br /&gt;&lt;br /&gt;    JTextField name = new JTextField(30);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;In this version, two listeners are added, a ComponentListener and an AncestorListener.  Both of these attempt to perform a requestFocus(), when the event is triggered.&lt;br /&gt;&lt;br /&gt;Why are both needed?  The ComponentListener approach seems to work great until Java 6.0.  Unfortunately, Java 6.0 seems to have broken it, which is why the AncestorListener is used as well.  Also unfortunately, the AncestorListener approach doesn&#39;t work in JVMs prior to 6.0.  Fortunately, both approaches can exist together, if you need a solution for both sets of JVMs.&lt;br /&gt;&lt;br /&gt;Adding the ComponentListener to the JTextField component (for JVMs prior to Java 6.0):&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    name.addComponentListener(new ComponentListener() {&lt;br /&gt;        public void componentHidden(ComponentEvent ce) {}&lt;br /&gt;        public void componentMoved(ComponentEvent ce) {&lt;br /&gt;            ce.getComponent().requestFocus();&lt;br /&gt;        }&lt;br /&gt;        public void componentResized(ComponentEvent ce) {&lt;br /&gt;            ce.getComponent().requestFocus();&lt;br /&gt;        }&lt;br /&gt;        public void componentShown(ComponentEvent ce) {}&lt;br /&gt;    });&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Adding the AncestorListener to the JTextField component (for Java 6.0 JVM):&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    name.addAncestorListener(new AncestorListener(){   &lt;br /&gt;        public void ancestorAdded(AncestorEvent ae){   &lt;br /&gt;            ae.getComponent().requestFocus();   &lt;br /&gt;        }   &lt;br /&gt;        public void ancestorRemoved(AncestorEvent ae){}   &lt;br /&gt;        public void ancestorMoved(AncestorEvent ae){}   &lt;br /&gt;    });&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Now the JPanel is defined and populated.  A BoxLayout is used to position the components vertically.  The components are placed in the order that they are added to the panel, which is done by using the add() method.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    JPanel panel = new JPanel();&lt;br /&gt;    panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));&lt;br /&gt;    panel.add(option_label);&lt;br /&gt;    panel.add(b1);&lt;br /&gt;    panel.add(b2);&lt;br /&gt;    panel.add(b3);&lt;br /&gt;    panel.add(name_label);&lt;br /&gt;    panel.add(name);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The only other change to the previous version is that the second argument to showConfirmDialog() is changed from an array to the JPanel, which is called panel.&lt;br /&gt;    &lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    int res = JOptionPane.showConfirmDialog(null, panel, &amp;quot;Select&amp;quot;, &lt;br /&gt;                                            JOptionPane.OK_CANCEL_OPTION);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The existing result processing code can be used unchanged and therefore will not be duplicated here.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example 2: Adding an Event Listener to a JPasswordField&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Another example that could use an event listener is the JPasswordField.  In Example 1 (Part 2), I discussed creating a login/password dialog box using JOptionPane.  In this example, the previous code will be enhanced to demonstrate dynamic use of the setEchoChar() method.&lt;br /&gt;&lt;br /&gt;Lotus Notes has had a curious password entry feature for a long time.  When entering a password, the password masking character changes with each key press.  The value of this is debatable, but reproducing this feature presents an interesting challenge.  This phenomenon can be achieved in Java by using a KeyListener.&lt;br /&gt;&lt;br /&gt;This example requires the following imports in addition to the imports from Part 2:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    import java.awt.event.*;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The code for defining the dialog components, is identical.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    JLabel label_loginname = new JLabel(&amp;quot;Enter your login name:&amp;quot;);&lt;br /&gt;    JTextField loginname = new JTextField(15);&lt;br /&gt;&lt;br /&gt;    JLabel label_password = new JLabel(&amp;quot;Enter your password:&amp;quot;);&lt;br /&gt;    JPasswordField password = new JPasswordField();&lt;br /&gt;&lt;br /&gt;    JCheckBox rememberCB = new JCheckBox(&amp;quot;Remember me&amp;quot;);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Now a KeyListener is added to the password field.  First a list of characters to use for the password masking is defined as a char array.  Then each of the KeyListener methods must be defined, even if they are not used.&lt;br /&gt;&lt;br /&gt;The keyTyped() method is using for the activity.  First the source component is extracted using the getSource() method.  Then the setEchoChar() method of the JPasswordField is called.  A random char from the char array is passed to setEchoChar() as its only argument.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    password.addKeyListener(new KeyListener() {&lt;br /&gt;        char[] mask = { &#39;@&#39;, &#39;#&#39;, &#39;$&#39;, &#39;%&#39;, &#39;&amp;amp;&#39;, &#39;*&#39; };&lt;br /&gt;        public void keyPressed(java.awt.event.KeyEvent ke) {}&lt;br /&gt;        public void keyReleased(java.awt.event.KeyEvent ke) {}&lt;br /&gt;        public void keyTyped(java.awt.event.KeyEvent ke) {&lt;br /&gt;            JPasswordField source = (JPasswordField)ke.getSource();&lt;br /&gt;            source.setEchoChar(mask[(int)(mask.length*Math.random())]);&lt;br /&gt;        }&lt;br /&gt;    });&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;As each character is typed into the password field, that event is fired, which is caught by the listener.  The listener then executes and changes the masking character using setEchoChar().&lt;br /&gt;&lt;br /&gt;The array definition and call to showConfirmDialog() are repeated here for reference, but are unchanged from the original example.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    Object[] array = { label_loginname, &lt;br /&gt;                       loginname,&lt;br /&gt;                       label_password,&lt;br /&gt;                       password,&lt;br /&gt;                       rememberCB };&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    int res = JOptionPane.showConfirmDialog(null, array, &amp;quot;Login&amp;quot;, &lt;br /&gt;                                            JOptionPane.OK_CANCEL_OPTION,&lt;br /&gt;                                            JOptionPane.PLAIN_MESSAGE);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As you can see there are many ways to add interactivity to JOptionPane dialogs.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/06/java-joptionpane-examples-part-3-adv.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-80661696310875810</guid><pubDate>Fri, 05 Jun 2009 10:49:00 +0000</pubDate><atom:updated>2009-06-12T09:12:54.764-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">J-Link</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">protk.dat</category><title>J-Link: Getting Started with Java and Pro/Engineer, Part 1</title><description>J-Link can seem intimidating at first, but once you have all the little pieces in hand to get started, it&#39;s actually pretty simple.  In this article, I&#39;ll walk you through all the pieces that you need to create a basic J-Link application.&lt;br /&gt;&lt;br /&gt;Even a simplistic J-Link program requires several files, including your Java code compiled to class file(s), a text-based &quot;message file&quot;, and an auxiliary application &quot;registry file&quot;.  I&#39;ll explain the required content of each file and how to put them all together.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Registry File&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The registry file is used to instruct Pro/Engineer on how to load an auxiliary application, such as a Pro/Toolkit or J-Link program.  Pro/Engineer uses this to find all of the program&#39;s pieces.  The actual name of the file is not that important, but &quot;protk.dat&quot; will be used as the filename in this example.&lt;br /&gt;&lt;br /&gt;An auxiliary application can be started by Pro/Engineer automatically by using the PROTKDAT config.pro option, or by placing the registry file in certain special locations (i.e. the working directory, within the Pro/Engineer install, etc).  Auxiliary applications can also be started manually.&lt;br /&gt;&lt;br /&gt;Here is an example registry file for the J-Link &quot;Hello World&quot; application:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;name               JLinkHelloWorld-App&lt;br /&gt;startup            java&lt;br /&gt;java_app_class     JLinkHelloWorld&lt;br /&gt;java_app_start     startApp&lt;br /&gt;java_app_stop      stopApp&lt;br /&gt;allow_stop         true&lt;br /&gt;delay_start        false&lt;br /&gt;text_dir           M:/apps/JLinkHelloWorld/text&lt;br /&gt;java_app_classpath M:/apps/JLinkHelloWorld&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The &quot;name&quot; will appear in the auxiliary application dialog to aid in identifying the program and can be as descriptive (or cryptic) as you need.  The &quot;startup java&quot; entry is required for J-Link apps.&lt;br /&gt;&lt;br /&gt;&quot;java_app_class&quot; indentifies the primary class of the application where the &quot;java_app_start&quot; and &quot;java_app_stop&quot; methods are contained.  The program is required to have static &quot;stop&quot; and &quot;start&quot; methods matching the names given in the registry file (more on that later).&lt;br /&gt;&lt;br /&gt;The &quot;allow_stop&quot; option allows the user to stop the program if it is running.  The &quot;delay_start&quot; option (if set to &quot;true&quot;) can disable automatic startup allowing the user to do this later, manually, if desired.&lt;br /&gt;&lt;br /&gt;The &quot;text_dir&quot; option identifies the folder hierarchy containing your application&#39;s message files.  Although the inclusion of the &quot;text&quot; folder in the path is not always required, it doesn&#39;t cause any problems.  Unix style paths work just fine here, as they do with config.pro files.  Consult &lt;a href=&quot;http://inversionconsulting.blogspot.com/search/label/protk.dat&quot;&gt;my other articles&lt;/a&gt; about cool stuff with registry files.&lt;br /&gt;&lt;br /&gt;&quot;java_app_classpath&quot; is generally used to find other class and jar files that you may use in your application.  It&#39;s like having a private CLASSPATH environment variable for each program.  As an alternative, this option can be replaced by using the ADD_JAVA_CLASS_PATH config.pro option, using the same value.  However, keeping the option in the registry file is generally the simpler approach.&lt;br /&gt;&lt;br /&gt;Not every entry is required, but it&#39;s usually a good idea to use the above set for greater flexibility.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The config.pro File&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;To initiate the program upon startup of Pro/Engineer, you can use a PROTKDAT config.pro option.  The value of this option is the full path to the registry file.&lt;br /&gt;&lt;br /&gt;Using the above example, the option might look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;PROTKDAT M:/apps/JLinkHelloWorld/protk.dat&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Text Message File&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The text message file is used primarily to support internationalization.  However, it also enables &quot;code vs data&quot; separation by relocating static text to standalone files.  A text message file is needed for even the most basic J-Link program.&lt;br /&gt;&lt;br /&gt;Each &quot;entry&quot; in a text message file is comprised of four lines.  Typically only the first two are used, the last two are placeholders.  The first line is the &quot;message id&quot; that you use in your code, and the second line is the text that will generally appear for that message id.&lt;br /&gt;&lt;br /&gt;In this example, the text message file msg_jlinkhelloworld.txt will contain three entries as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;JLHW Btn1 Label&lt;br /&gt;JLink Hello World&lt;br /&gt;#&lt;br /&gt;#&lt;br /&gt;JLHW Btn1 Help&lt;br /&gt;Run the JLink Hello World Application&lt;br /&gt;#&lt;br /&gt;#&lt;br /&gt;JLHW %s&lt;br /&gt;%0s&lt;br /&gt;#&lt;br /&gt;#&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Be sure to leave an extra blank line at the end of the file to avoid one of the many strange problems with text message files.&lt;br /&gt;&lt;br /&gt;The text message file must be placed within the folder structure specified by &quot;text_dir&quot; in the registry file.  In this example application, the text message file will be placed in:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    M:/apps/JLinkHelloWorld/text/usascii&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Proper location of the text message file is very critical.  Putting the file in the wrong folder is the source of confusion and frustation to new Pro/Engineer API developers.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Read &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/06/proe-java-jlink-getting-started-2.html&quot;&gt;Part 2&lt;/a&gt; for the Java code&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/06/proe-java-jlink-getting-started-1.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-8535812262729978869</guid><pubDate>Mon, 01 Jun 2009 10:12:00 +0000</pubDate><atom:updated>2009-06-01T03:27:35.318-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Intralink</category><category domain="http://www.blogger.com/atom/ns#">Intralink Scripting</category><category domain="http://www.blogger.com/atom/ns#">Java</category><title>Intralink Scripting: Commonspace Folder Info - Part 3</title><description>In &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/04/intralink-script-java-cs-folder-info-1.html&quot;&gt;Part 1&lt;/a&gt;, I discussed how to use the ILFolderTreeModel class to recursively descend through your Commonspace folders to generate a folder list.  In &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/05/intralink-script-java-cs-folder-info-2.html&quot;&gt;Part 2&lt;/a&gt;, I discussed how to use CSFolderObjectInfo to perform actions and obtain information on your folders.  Now I&#39;m going to discuss yet another data model class to get even more extensive information from your folders.&lt;br /&gt;&lt;br /&gt;Intralink classes that extend ILTableModel are the core data presentation classes of the Intralink client.  While the ObjectInfo classes represent a chunk of metadata for a specific object, the ILTabelModel presents the data model that is actually displayed in the GUI.  Interrogating these classes lets you get data exactly as you would expect to see it in Intralink.&lt;br /&gt;&lt;br /&gt;Two folder related data presentation classes that I&#39;ll now discuss are ILFolderAuthTableModel and ILPromoteDemoteTableModel.  As you might expect from the name, ILFolderAuthTableModel represents the data presentation model of folder authorizations, while ILPromoteDemoteTableModel represents folder release procedures.&lt;br /&gt;&lt;br /&gt;To utilize these classes, we need an ILAppObject representation of the folder.  The static method getObjectByKey() of the ObjectInfo class allows us to create this object.  Here is an example of instantiating an ILFolderAuthTableModel object:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    String folderName = &amp;quot;Root Folder/ProjectX&amp;quot;;&lt;br /&gt;    ILAppObject fol_ao = ObjectInfo.getObjectByKey(ObjectInfo.tFolder, folderName);&lt;br /&gt;    ILFolderAuthTableModel fa_tm = new ILFolderAuthTableModel(false, fol_ao);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The table of data contained in the ILTableModel based object can be accessed with generic methods and other methods specific to the data type.  Examples of generic methods include getRowCount(), getColumnCount(), getColumnName(), and getValueAt().&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example: Reporting Authorizations and Release Procedures&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This example further expands upon the code in &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/05/intralink-script-java-cs-folder-info-2.html&quot;&gt;Part 2&lt;/a&gt;, by adding the output of folder authorizations, release level authorizations, and release procedures associated with each folder.&lt;br /&gt;&lt;br /&gt;Just as in the GUI, the example shows output only if something was explicitly set for that folder.  If a folder authorizations was set only in a parent folder, that authorization will not appear in the output for subfolders.  The same applies to release procedures.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    CSFolderObjectInfo fol_oi = null;&lt;br /&gt;    ILAppObject fol_ao = null;&lt;br /&gt;    ILFolderAuthTableModel fa_tm = null;&lt;br /&gt;    ILPromoteDemoteTableModel pd_tm = null;&lt;br /&gt;&lt;br /&gt;    for (int i=0; i&amp;lt;folders.size(); i++) {&lt;br /&gt;&lt;br /&gt;        String folderName = folders.get(i).toString();&lt;br /&gt;        System.out.println( &amp;quot;  &amp;quot; + (i+1) + &amp;quot;: &amp;quot; + folderName );&lt;br /&gt;&lt;br /&gt;        fol_oi = (CSFolderObjectInfo)ObjectInfo.createByKey( ObjectInfo.tFolder, folderName );&lt;br /&gt;        fol_ao = ObjectInfo.getObjectByKey( ObjectInfo.tFolder, folderName);&lt;br /&gt;&lt;br /&gt;        System.out.println( &amp;quot;    &amp;quot; + &amp;quot;Release Scheme: &amp;quot; + fol_oi.getReleaseScheme() );&lt;br /&gt;        System.out.println( &amp;quot;    &amp;quot; + &amp;quot;File Space: &amp;quot; + fol_oi.getFilespace() );&lt;br /&gt;        &lt;br /&gt;        fa_tm = new ILFolderAuthTableModel(false, fol_ao);&lt;br /&gt;        System.out.println( &amp;quot;    &amp;quot; + &amp;quot;Authorizations: &amp;quot;);&lt;br /&gt;&lt;br /&gt;        if (fa_tm.getRowCount() &amp;gt; 0) {&lt;br /&gt;&lt;br /&gt;            // output column info&lt;br /&gt;            for (int col=0; col&amp;lt;fa_tm.getColumnCount(); col++) {&lt;br /&gt;                String colName = fa_tm.getColumnName(col);&lt;br /&gt;                if (col == 0) {&lt;br /&gt;                    System.out.print( &amp;quot;    &amp;quot; + &amp;quot;  &amp;quot; + colName );&lt;br /&gt;                }&lt;br /&gt;                else {&lt;br /&gt;                    System.out.print( &amp;quot; / &amp;quot; + colName );&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            System.out.println();&lt;br /&gt;&lt;br /&gt;            // output row info&lt;br /&gt;            for (int row=0; row&amp;lt;fa_tm.getRowCount(); row++) {&lt;br /&gt;                for (int col=0; col&amp;lt;fa_tm.getColumnCount(); col++) {&lt;br /&gt;                    String val = fa_tm.getValueAt(row,col).toString();&lt;br /&gt;                    if (col == 0) {&lt;br /&gt;                        System.out.print( &amp;quot;    &amp;quot; + &amp;quot;  &amp;quot; + val );&lt;br /&gt;                    }&lt;br /&gt;                    else {&lt;br /&gt;                        System.out.print( &amp;quot; / &amp;quot; + val );&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                System.out.println();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        else {&lt;br /&gt;            System.out.println( &amp;quot;    &amp;quot; + &amp;quot;  None&amp;quot; );&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        pd_tm = new ILPromoteDemoteTableModel(fol_ao);&lt;br /&gt;        System.out.println( &amp;quot;    &amp;quot; + &amp;quot;Release Procedures: &amp;quot;);&lt;br /&gt;        &lt;br /&gt;        if (pd_tm.getRowCount() &amp;gt; 0) {&lt;br /&gt;&lt;br /&gt;            // output column info&lt;br /&gt;            for (int col=0; col&amp;lt;pd_tm.getColumnCount(); col++) {&lt;br /&gt;                String colName = pd_tm.getColumnName(col);&lt;br /&gt;                if (col == 0) {&lt;br /&gt;                    System.out.print( &amp;quot;    &amp;quot; + &amp;quot;  &amp;quot; + colName );&lt;br /&gt;                }&lt;br /&gt;                else {&lt;br /&gt;                    System.out.print( &amp;quot; / &amp;quot; + colName );&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            System.out.println();&lt;br /&gt;&lt;br /&gt;            // output row info&lt;br /&gt;            for (int row=0; row&amp;lt;pd_tm.getRowCount(); row++) {&lt;br /&gt;                String rellevel = pd_tm.getValueAt(row,pd_tm.RELLEVEL_COLUMN).toString();&lt;br /&gt;                String promote_rp = pd_tm.getValueAt(row,pd_tm.PROMOTE_COLUMN).toString();&lt;br /&gt;                String demote_rp = pd_tm.getValueAt(row,pd_tm.DEMOTE_COLUMN).toString();&lt;br /&gt;                System.out.println( &amp;quot;    &amp;quot; + &amp;quot;  &amp;quot; + rellevel + &amp;quot; / &amp;quot; + promote_rp + &amp;quot; / &amp;quot; + demote_rp );&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        else {&lt;br /&gt;            System.out.println( &amp;quot;    &amp;quot; + &amp;quot;  None&amp;quot; );&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        pd_tm = null;&lt;br /&gt;        fa_tm = null;&lt;br /&gt;&lt;br /&gt;        fol_oi = null;&lt;br /&gt;        fol_ao = null;&lt;br /&gt;&lt;br /&gt;        System.out.println();&lt;br /&gt;        System.out.flush();&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The output should look something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;  1: Root Folder/Project X&lt;br /&gt;    Release Scheme: ReleaseScheme-ProjectX&lt;br /&gt;    File Space: Filespace_ProjectX&lt;br /&gt;    Authorizations:&lt;br /&gt;      Name / Folder Role / WIP / Detail / Prototype / Manufacturing / Obsolete&lt;br /&gt;      *Admin / FolAdmin / Admin / Admin / Admin / Admin / Admin&lt;br /&gt;      *Engr / FolEngr / Engr / Engr / Engr / Engr / Engr&lt;br /&gt;      *Mgr / FolMgr / Mgr / Mgr / Mgr / Mgr / Mgr&lt;br /&gt;      *View / FolView / View / View / View / View / View&lt;br /&gt;    Release Procedures:&lt;br /&gt;      Name / Release Procedure Promote To / Release Procedure Demote From&lt;br /&gt;      WIP /  /&lt;br /&gt;      Detail /  /&lt;br /&gt;      Prototype / ProjectX_Mgr / ProjectX_Mgr&lt;br /&gt;      Manufacturing / ProjectX_Mgr / ProjectX_Mgr&lt;br /&gt;      Obsolete /  /&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;As you can see, you can extract very specific information from Intralink quite easily with Java.  This information would be very difficult, if not impossible, to extract using the GUI itself.  A little bit of Intralink Scripting can often save you lots of time.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Need a program for data mining your Intralink metadata?  Migrating from Intralink 3.x to PDM.Link or TeamCenter and need to extract metadata quickly?  Contact me at &lt;a href=&quot;mailto:MarcMettes@InversionConsulting.com&quot;&gt;MarcMettes@InversionConsulting.com&lt;/a&gt; to get an inexpensive application right now.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/06/intralink-script-java-cs-folder-info-3.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-6285021378223161554</guid><pubDate>Tue, 19 May 2009 10:26:00 +0000</pubDate><atom:updated>2009-05-19T03:41:40.423-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Intralink</category><category domain="http://www.blogger.com/atom/ns#">Intralink Scripting</category><category domain="http://www.blogger.com/atom/ns#">Java</category><title>Intralink Scripting: Commonspace Folder Info - Part 2</title><description>In &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/04/intralink-script-java-cs-folder-info-1.html&quot;&gt;Part 1&lt;/a&gt;, I discussed how to use ILFolderTreeModel to recursively descend through your Commonspace folders to generate a folder list.  Coupled with other classes, you can generate even more data about your folders.&lt;br /&gt;&lt;br /&gt;In a &lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/04/intralink-scripting-to-be-or-not-to-be.html&quot;&gt;previous article&lt;/a&gt;, I discussed the ObjectInfo subclasses and how to use them to get object metadata.  In this article, I&#39;ll discuss how to use the ObjectInfo subclass pertaining to Commonspace folders called CSFolderObjectInfo.&lt;br /&gt;&lt;br /&gt;The CSFolderObjectInfo class contains many methods to interact with Commonspace folders.  The ObjectInfo class are extremely powerful as they let you bypass the user interface and talk directly with the data model of the Intralink client.  Despite its name, the CSFolderObjectInfo class contains many methods to perform actions upon Commonspace folders, not just to get information about them.&lt;br /&gt;&lt;br /&gt;Examples of methods specific to the CSFolderObjectInfo are: getParent(), getFullPath(), setDescription(), createFolder(), deleteFolder(), moveFolder(), getFilespace(), getReleaseLevel(), getReleaseScheme(), setRelScheme(), etc.  Not all of these are guaranteed to work as you may hope.  Caution must be exercised before experimenting on your production system.  Do so at your own risk.&lt;br /&gt;&lt;br /&gt;Before you can apply these methods, you need a CSFolderObjectInfo object.  One way to instantiate a CSFolderObjectInfo object is with the static method createByKey() in the ObjectInfo class, although sometimes there are other ways.  Here is an example, using the static field tFolder to specify the ObjectInfo object type and a String value for the folder name:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    CSFolderObjectInfo fol_oi = null;&lt;br /&gt;    fol_oi = (CSFolderObjectInfo)ObjectInfo.createByKey( ObjectInfo.tFolder, &amp;quot;Root Folder/ProjectX&amp;quot; );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;This is a very generic technique that can be applied to most other ObjectInfo data types, even though there are specific createByKey() methods for specific object types.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example:&lt;/strong&gt; Release Scheme, File Space, and Release Levels&lt;br /&gt;&lt;br /&gt;This example expands upon the code in &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/04/intralink-script-java-cs-folder-info-1.html&quot;&gt;Part 1&lt;/a&gt;, by adding the output of the Release Scheme name, the File Space used, and the Release Levels associated with each folder.  Both getReleaseScheme() and getFilespace() return String values of their respective outputs.  getReleaseLevel() returns a String array of Release Levels.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    CSFolderObjectInfo fol_oi = null;&lt;br /&gt;    List folders = getFolderList(tm, tree);&lt;br /&gt;&lt;br /&gt;    for (int i=0; i&amp;lt;folders.size(); i++) {&lt;br /&gt;&lt;br /&gt;        String folderName = folders.get(i).toString();&lt;br /&gt;        System.out.println( &amp;quot;  &amp;quot; + (i+1) + &amp;quot;: &amp;quot; + folderName );&lt;br /&gt;&lt;br /&gt;        fol_oi = (CSFolderObjectInfo)ObjectInfo.createByKey( ObjectInfo.tFolder, folderName );&lt;br /&gt;&lt;br /&gt;        System.out.println( &amp;quot;    &amp;quot; + &amp;quot;Release Scheme: &amp;quot; + fol_oi.getReleaseScheme() );&lt;br /&gt;        System.out.println( &amp;quot;    &amp;quot; + &amp;quot;File Space: &amp;quot; + fol_oi.getFilespace() );&lt;br /&gt;&lt;br /&gt;        System.out.println( &amp;quot;    &amp;quot; + &amp;quot;Release Levels: &amp;quot;);&lt;br /&gt;        String[] fol_rellevels = fol_oi.getReleaseLevel();&lt;br /&gt;&lt;br /&gt;        // release level array values start at 1, but still has element zero&lt;br /&gt;        for (int j=1; j&amp;lt;fol_rellevels.length; j++) {&lt;br /&gt;            System.out.println( &amp;quot;    &amp;quot; + &amp;quot;  &amp;quot; + j + &amp;quot;: &amp;quot; + fol_rellevels[j] );&lt;br /&gt;        }&lt;br /&gt;  &lt;br /&gt;        fol_oi = null;&lt;br /&gt;&lt;br /&gt;        System.out.println(); // blank line for readability&lt;br /&gt;        System.out.flush(); // flush to see data in output file immediately&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the next installment, I&#39;ll show yet more information about folders that can be gathered, including folder and role based authorizations.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/05/intralink-script-java-cs-folder-info-2.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-6448280083067060033</guid><pubDate>Mon, 04 May 2009 10:41:00 +0000</pubDate><atom:updated>2009-05-26T03:35:59.724-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Java</category><title>Java: JOptionPane Examples Part 2 - Intermediate</title><description>In my previous JOptionPane article, &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/01/java-joptionpane-examples-part-1-basic.html&quot;&gt;JOptionPane Examples Part 1 - Basic&lt;/a&gt;, I covered several examples of basic usage of the JOptionPane dialog.  In this installment, we go beyond basic usage and into some functionality that is documented, but not quite so obviously.&lt;br /&gt;&lt;br /&gt;In most examples of the JOptionPane dialog, you&#39;ll see a String value used for the &quot;message&quot; argument, which is usually the 2nd argument.  In the JOptonPane documentation, the &quot;message&quot; argument is listed generically as type Object in the list of methods.&lt;br /&gt;&lt;br /&gt;However, if you read at the beginning where the parameters are discussed, the docs state that &quot;message&quot; can not only be a String, but also any subclassed object of the Component class, which is just about any GUI object you could hope to use!  But wait there&#39;s more!&lt;br /&gt;&lt;br /&gt;Not only can it accept practically any GUI object, but it also can accept an array of GUI objects!  If an array is provided, the elements of the array are displayed vertically in the dialog box.  This is not a very flexible layout, but it is simple and straightforward.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example 1: Login/Password Dialog&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;To create a login/password dialog box, we need more than just the login and password fields, but also label fields so the user knows where to type and what goes there.&lt;br /&gt;&lt;br /&gt;Here the two field are defined using a JTextField for the login name and a JPassword field for the password.  Each field has a corresponding JLabel.  Also included, just for fun, is a &quot;remember me&quot; checkbox.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    // Components related to &amp;quot;login&amp;quot; field&lt;br /&gt;    JLabel label_loginname = new JLabel(&amp;quot;Enter your login name:&amp;quot;);&lt;br /&gt;    JTextField loginname = new JTextField(15);&lt;br /&gt;    // loginname.setText(&amp;quot;EnterLoginNameHere&amp;quot;); // Pre-set some text&lt;br /&gt;&lt;br /&gt;    // Components related to &amp;quot;password&amp;quot; field&lt;br /&gt;    JLabel label_password = new JLabel(&amp;quot;Enter your password:&amp;quot;);&lt;br /&gt;    JPasswordField password = new JPasswordField();&lt;br /&gt;    // password.setEchoChar(&#39;@&#39;); // Sets @ as masking character&lt;br /&gt;    // password.setEchoChar(&#39;\000&#39;); // Turns off masking&lt;br /&gt;&lt;br /&gt;    JCheckBox rememberCB = new JCheckBox(&amp;quot;Remember me&amp;quot;);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The components are wrapped up into an Object array.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    Object[] array = { label_loginname, &lt;br /&gt;                       loginname,&lt;br /&gt;                       label_password,&lt;br /&gt;                       password,&lt;br /&gt;                       rememberCB };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Then the dialog is initiated using showConfirmDialog(), with &quot;OK&quot; and &quot;Cancel&quot; buttons, and without any icon decorations.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    int res = JOptionPane.showConfirmDialog(null, array, &amp;quot;Login&amp;quot;, &lt;br /&gt;                                            JOptionPane.OK_CANCEL_OPTION,&lt;br /&gt;                                            JOptionPane.PLAIN_MESSAGE);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;We can respond properly to the user&#39;s input, by analyzing the int return value of showConfirmDialog().&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    // User hit OK&lt;br /&gt;    if (res == JOptionPane.OK_OPTION) { System.out.println( &amp;quot;OK_OPTION&amp;quot; ); }&lt;br /&gt;&lt;br /&gt;    // User hit CANCEL&lt;br /&gt;    if (res == JOptionPane.CANCEL_OPTION) { System.out.println( &amp;quot;CANCEL_OPTION&amp;quot; ); }&lt;br /&gt;&lt;br /&gt;    // User closed the window without hitting any button&lt;br /&gt;    if (res == JOptionPane.CLOSED_OPTION) { System.out.println( &amp;quot;CLOSED_OPTION&amp;quot; ); }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Even though, at this point, the dialog is gone, we can still interact with the GUI components.  We can determine if the user entered values, regardless if the user hit OK, Cancel, or just closed the window without hitting any buttons, by using the methods of the various objects.&lt;br /&gt;&lt;br /&gt;For example, we&#39;ll use getText() to get the login name from the &quot;login name&quot; JTextField object.  The password is obtained using getPassword() from the &quot;password&quot; JPasswordField object.  The state of the &quot;remember me&quot; checkbox can be determined using the isSelected() method.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    // Output data in &amp;quot;login&amp;quot; field, if any&lt;br /&gt;    String newloginname = loginname.getText();&lt;br /&gt;    System.out.println( &amp;quot;newloginname: &amp;quot; + newloginname );&lt;br /&gt;&lt;br /&gt;    // Output data in &amp;quot;password&amp;quot; field, if any&lt;br /&gt;    String newpassword = new String(password.getPassword());&lt;br /&gt;    System.out.println( &amp;quot;newpassword: &amp;quot; + newpassword );&lt;br /&gt;&lt;br /&gt;    // Output state of &amp;quot;remember me&amp;quot; check box&lt;br /&gt;    boolean selectedCB = rememberCB.isSelected();&lt;br /&gt;    System.out.println( &amp;quot;selectedCB: &amp;quot; + selectedCB );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example 2: Editable JTextArea with JScrollPane scrollbars&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In this example, the showMessageDialog() method of the JOptionPane class is used to display a JTextArea, which is going to be pre-populated with some sample text.  The size will be set to show 5 rows and 10 columns.  The JTextArea is then set to be editable, so the user can change the data.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    JTextArea area = new JTextArea();&lt;br /&gt;    area.setText(&amp;quot;line1\nline2\nline3\nline4\nline5\nline6&amp;quot;);&lt;br /&gt;    area.setRows(5);&lt;br /&gt;    area.setColumns(10);&lt;br /&gt;    area.setEditable(true);&lt;br /&gt;    JScrollPane scrollpane = new JScrollPane(area);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Along with a JLabel, the JScrollPane object is added to an Object[] array.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    Object[] array = {&lt;br /&gt;        new JLabel(&amp;quot;Enter some text:&amp;quot;),&lt;br /&gt;        scrollpane,&lt;br /&gt;    };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The showMessageDialog() method produces a dialog with only an &quot;OK&quot; button and does not return any value.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    JOptionPane.showMessageDialog(null, array, &amp;quot;Text&amp;quot;, &lt;br /&gt;                                  JOptionPane.PLAIN_MESSAGE);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The JTextArea can still be interrogated to see if the user changed the value, if desired.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    String newtext = area.getText();&lt;br /&gt;    System.out.println( &amp;quot;newtext: &amp;quot; + newtext );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example 3: JRadioButton and ButtonGroup&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In this example, a dialog will be created consisting of three JRadioButtons and a JTextField.  The radio buttons will be associated with a ButtonGroup, which will cause only one of them to be selected at a time.&lt;br /&gt;&lt;br /&gt;Create the button objects and make the first button selected by default.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    JRadioButton b1 = new JRadioButton(&amp;quot;Option 1&amp;quot;);&lt;br /&gt;    JRadioButton b2 = new JRadioButton(&amp;quot;Option 2&amp;quot;);&lt;br /&gt;    JRadioButton b3 = new JRadioButton(&amp;quot;Option 3&amp;quot;);&lt;br /&gt;    b1.setSelected(true);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Tie the JRadioButtons together into a group, allowing only one of the group to be selected.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    ButtonGroup group = new ButtonGroup();&lt;br /&gt;    group.add(b1);&lt;br /&gt;    group.add(b2);&lt;br /&gt;    group.add(b3);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Define a &quot;name&quot; field as well.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    JTextField name = new JTextField(30);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Add the elements together in an array with a few JLabels.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    Object[] array = {&lt;br /&gt;        new JLabel(&amp;quot;Select an option:&amp;quot;),&lt;br /&gt;        b1,&lt;br /&gt;        b2,&lt;br /&gt;        b3,&lt;br /&gt;        new JLabel(&amp;quot;Enter a name:&amp;quot;),&lt;br /&gt;        name&lt;br /&gt;    };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Make the dialog appear using showConfirmDialog().&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    int res = JOptionPane.showConfirmDialog(null, array, &amp;quot;Select&amp;quot;, &lt;br /&gt;                                            JOptionPane.OK_CANCEL_OPTION);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;As in the first example, we can analyze the int return value of showConfirmDialog().&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    // User hit OK&lt;br /&gt;    if (res == JOptionPane.OK_OPTION) { System.out.println( &amp;quot;OK_OPTION&amp;quot; ); }&lt;br /&gt;&lt;br /&gt;    // User hit CANCEL&lt;br /&gt;    if (res == JOptionPane.CANCEL_OPTION) { System.out.println( &amp;quot;CANCEL_OPTION&amp;quot; ); }&lt;br /&gt;&lt;br /&gt;    // User closed the window without hitting any button&lt;br /&gt;    if (res == JOptionPane.CLOSED_OPTION) { System.out.println( &amp;quot;CLOSED_OPTION&amp;quot; ); }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The selected button can be determined using the isSelected() method.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    // User selected button 1&lt;br /&gt;    if (b1.isSelected()) { System.out.println( &amp;quot;Selected: Option 1&amp;quot; ); }&lt;br /&gt;&lt;br /&gt;    // User selected button 2&lt;br /&gt;    if (b2.isSelected()) { System.out.println( &amp;quot;Selected: Option 2&amp;quot; ); }&lt;br /&gt;&lt;br /&gt;    // User selected button 3&lt;br /&gt;    if (b3.isSelected()) { System.out.println( &amp;quot;Selected: Option 3&amp;quot; ); }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The name field can be extracted using getText().&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    System.out.println( &amp;quot;name=&amp;quot; + name.getText() );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;These are just a few examples showing how the JOptionPane class was designed to be very versatile and flexible, allowing for moderately complicated GUI dialog to be created quite easily.  Perhaps this usage would have been more obvious if the documentation was clearer, but it is documented.&lt;br /&gt;&lt;br /&gt;next time ... part 3 advanced&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/05/java-joptionpane-examples-part-2-int.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-5857583182478078542</guid><pubDate>Mon, 27 Apr 2009 09:59:00 +0000</pubDate><atom:updated>2009-04-27T17:09:15.216-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Intralink</category><category domain="http://www.blogger.com/atom/ns#">Intralink Scripting</category><category domain="http://www.blogger.com/atom/ns#">Java</category><title>Intralink Scripting: Commonspace Folder Info, Part 1</title><description>A lot of administrative tasks in Intralink 3.x are much more difficult than necessary, and in some cases nearly impossible.  Folder information is one of those tasks.  Without running the DSMU, getting information on folders can be extremely tedious.&lt;br /&gt;&lt;br /&gt;Fortunately with the right Java code, we can put some of the internal features of the Intralink client to use.  These are the same data model classes that the client Java code uses, but now we can use them to get the information that you want, how you want it, and whenever you want it.  Remember, it&#39;s your data.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To traverse the Commonspace folder structure, my utility method getFolderList() will be used.  It uses an ILFolderTreeModel object, which is a folder tree data model class, and a TreeNode, which is a node within a tree structure.  The method calls itself recursively to traverse a folder tree, which need not start at the Commonspace root folder.&lt;br /&gt;&lt;br /&gt;Initially, the method builds a new ArrayList.  Then, the root node is added to the ArrayList.  The method then iterates over the children, if any, of the current node.  If there are child nodes, the method calls itself using the same ILFolderTreeModel object, but this time with the child node.  The resulting ArrayList of the child node recursion is added to the higher level ArrayList.  The child ArrayList is then cleared and nulled.  The first ArrayList is returned when recursion has completed.&lt;br /&gt;&lt;br /&gt;&lt;pre style=&quot;font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%&quot;&gt;&lt;code&gt;  public List getFolderList ( ILFolderTreeModel treemodel, TreeNode tree ) throws Exception {&lt;br /&gt;&lt;br /&gt;    List list = new ArrayList();&lt;br /&gt;    list.add(tree.getKeyName());&lt;br /&gt;&lt;br /&gt;    for (int i=0; i&amp;lt;treemodel.getChildCount(tree); i++) {&lt;br /&gt;&lt;br /&gt;        TreeNode child = (TreeNode)treemodel.getChild(tree,i);&lt;br /&gt;&lt;br /&gt;        List sublist = getFolderList(treemodel, child);&lt;br /&gt;        list.addAll(sublist);&lt;br /&gt;        sublist.clear();&lt;br /&gt;        sublist = null;&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return list;&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;In order to call this function, an ILFolderTreeModel and a TreeNode object are required.&lt;br /&gt;&lt;br /&gt;For the ILFolderTreeModel object, we can simply call the constructor:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    ILFolderTreeModel tm = new ILFolderTreeModel();&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;If the root node is the Commonspace Root Folder, then the TreeNode object is obtained as follows from the ILFolderTreeModel object:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    TreeNode tree = (TreeRootNode)tm.getRoot();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;If another folder is the root for the TreeNode, things get a bit more complicated.  First, an ILAppObject is created representing the folder of interest, then TreeObject.createCSTree() is executed using the ILAppObject.  Running the getRoot() method of the resulting TreeObject gives us a TreeNode that we can use.&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    String startFolderName = &amp;quot;Root Folder/ProjectX&amp;quot;;&lt;br /&gt;    ILAppObject start_fol_ao = ObjectInfo.getObjectByKey( ObjectInfo.tFolder, startFolderName );&lt;br /&gt;    TreeNode tree = TreeObject.createCSTree(start_fol_ao).getRoot();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;To get the ArrayList, getFolderList() is executed:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    List folders = getFolderList(tm, tree);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;To iterate over the resulting ArrayList, use code like this:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;    for (int i=0; i&amp;lt;folders.size(); i++) {&lt;br /&gt;        String folderName = folders.get(i).toString();&lt;br /&gt;        System.out.println( &amp;quot;  &amp;quot; + (i+1) + &amp;quot;: &amp;quot; + folderName );&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The output will appear in the .proi.log file on Unix or the most recent .pro.log.N file on Windows.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here is the complete program.  Please note the addition of three import statements beyong the typical two that Intralink provides in each Intralink Scripting application.&lt;br /&gt;&lt;br /&gt;&lt;pre style=&quot;font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%&quot;&gt;&lt;code&gt;import com.ptc.intralink.client.script.*;&lt;br /&gt;import com.ptc.intralink.script.*;&lt;br /&gt;&lt;br /&gt;import com.ptc.intralink.client.admin.folder.*;&lt;br /&gt;import com.ptc.intralink.ila.*;&lt;br /&gt;import java.util.*;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class Folder_List extends ILIntralinkScript { &lt;br /&gt;&lt;br /&gt;  ILIntralinkScriptInterface IL = (ILIntralinkScriptInterface)getScriptInterface();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  public void run () throws Exception {&lt;br /&gt;&lt;br /&gt;    TreeNode tree = null;&lt;br /&gt;    ILFolderTreeModel tm = new ILFolderTreeModel();&lt;br /&gt;&lt;br /&gt;    String startFolderName = null;&lt;br /&gt;    startFolderName = &amp;quot;&amp;quot;;&lt;br /&gt;    startFolderName = &amp;quot;/&amp;quot;;&lt;br /&gt;    startFolderName = &amp;quot;Root Folder&amp;quot;;&lt;br /&gt;    startFolderName = &amp;quot;Root Folder/ProjectX&amp;quot;;&lt;br /&gt;&lt;br /&gt;    if ( startFolderName == null &amp;#124;&amp;#124; startFolderName.matches(&amp;quot;^/?$&amp;quot;) ) {&lt;br /&gt;        tree = (TreeNode)tm.getRoot(); // Casting to TreeNode required&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;        ILAppObject start_fol_ao = ObjectInfo.getObjectByKey( ObjectInfo.tFolder, startFolderName );&lt;br /&gt;        tree = TreeObject.createCSTree(start_fol_ao).getRoot();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    System.out.println( &amp;quot;  tree: &amp;quot; + tree );&lt;br /&gt;    List folders = getFolderList(tm, tree);&lt;br /&gt;&lt;br /&gt;    for (int i=0; i&amp;lt;folders.size(); i++) {&lt;br /&gt;        String folderName = folders.get(i).toString();&lt;br /&gt;        System.out.println( &amp;quot;  &amp;quot; + (i+1) + &amp;quot;: &amp;quot; + folderName );&lt;br /&gt;        System.out.flush();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    folders.clear();&lt;br /&gt;    folders = null;&lt;br /&gt;    tm = null;&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  public List getFolderList ( ILFolderTreeModel treemodel, TreeNode tree ) throws Exception {&lt;br /&gt;&lt;br /&gt;    List list = new ArrayList();&lt;br /&gt;    list.add(tree.getKeyName());&lt;br /&gt;&lt;br /&gt;    for (int i=0; i&amp;lt;treemodel.getChildCount(tree); i++) {&lt;br /&gt;&lt;br /&gt;        TreeNode child = (TreeNode)treemodel.getChild(tree,i);&lt;br /&gt;&lt;br /&gt;        List sublist = getFolderList(treemodel, child);&lt;br /&gt;        list.addAll(sublist);&lt;br /&gt;        sublist.clear();&lt;br /&gt;        sublist = null;&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return list;&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the next installment, I&#39;ll show how more information about folders can be gathered, along with a more sophisticated presentation of the data.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/04/intralink-script-java-cs-folder-info-1.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-6016119474390046843</guid><pubDate>Tue, 31 Mar 2009 10:24:00 +0000</pubDate><atom:updated>2009-03-31T03:40:45.746-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Books</category><category domain="http://www.blogger.com/atom/ns#">Java</category><title>Book Review: Head First Java</title><description>&lt;a href=&quot;http://www.amazon.com/gp/product/0596009208?ie=UTF8&amp;tag=incoscapdaubl-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0596009208&quot;&gt;Head First Java, 2nd Edition&lt;/a&gt;&lt;img src=&quot;http://www.assoc-amazon.com/e/ir?t=incoscapdaubl-20&amp;l=as2&amp;o=1&amp;a=0596009208&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt; by Kathy Sierra and Bert Bates is the introductory Java entry in O&#39;Reilly Media&#39;s &lt;a href=&quot;http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fs%3Fie%3DUTF8%26ref%255F%3Dnb%255Fss%255Fb%26field-keywords%3Dhead%2520first%2520o%2527reilly%26url%3Dsearch-alias%253Dstripbooks&amp;tag=incoscapdaubl-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=390957&quot;&gt;Head First Series&lt;/a&gt;&lt;img src=&quot;https://www.assoc-amazon.com/e/ir?t=incoscapdaubl-20&amp;l=ur2&amp;o=1&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;.  The approach of this unique series is to inject humor, imagery, basic explanations, and a lot of fun into their subject matter.  While not for everyone, the series does provide a solid learning experience.&lt;br /&gt;&lt;br /&gt;The ideal reader of &lt;a href=&quot;http://www.amazon.com/gp/product/0596009208?ie=UTF8&amp;tag=incoscapdaubl-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0596009208&quot;&gt;Head First Java&lt;/a&gt;&lt;img src=&quot;http://www.assoc-amazon.com/e/ir?t=incoscapdaubl-20&amp;l=as2&amp;o=1&amp;a=0596009208&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt; is someone that has done some programming (maybe even some Java), but is fairly new to Java and/or Object Oriented programming. &lt;iframe src=&quot;http://rcm.amazon.com/e/cm?t=incoscapdaubl-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0596009208&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr&amp;nou=1&quot; style=&quot;width:120px;height:240px;&quot; scrolling=&quot;no&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; frameborder=&quot;0&quot; align=right&gt;&lt;/iframe&gt;  Advanced Java developers are probably not going to get a lot out of this book, but the topics covered are pretty extensive.  The topics include: objects and classes, object oriented design, inheritance, polymorphism, constructors, garbage collection, static classes and methods, swing, multithreading, generics, java web start, and RMI.  That may sound like a lot of topics, but each one is explained very effectively.&lt;br /&gt;&lt;br /&gt;The &lt;a href=&quot;http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fs%3Fie%3DUTF8%26ref%255F%3Dnb%255Fss%255Fb%26field-keywords%3Dhead%2520first%2520o%2527reilly%26url%3Dsearch-alias%253Dstripbooks&amp;tag=incoscapdaubl-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=390957&quot;&gt;Head First Series&lt;/a&gt;&lt;img src=&quot;https://www.assoc-amazon.com/e/ir?t=incoscapdaubl-20&amp;l=ur2&amp;o=1&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt; strives to break topics down into very easy to understand explanations, with numerous code examples and exercises.  In fact, complex topics are explained multiple times to cover all facets of the subject matter.  You won&#39;t become an expert, but you will have a very solid understanding and be able to code simple applications right away.  More importantly, you will understand why Java developers uses language features in specific ways.&lt;br /&gt;&lt;br /&gt;The authors of &lt;a href=&quot;http://www.amazon.com/gp/product/0596009208?ie=UTF8&amp;tag=incoscapdaubl-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0596009208&quot;&gt;Head First Java&lt;/a&gt;&lt;img src=&quot;http://www.assoc-amazon.com/e/ir?t=incoscapdaubl-20&amp;l=as2&amp;o=1&amp;a=0596009208&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt; avoid tool distractions by designing the book around using only the JDK and a simple text editor.  No other tools or applications are required to use the examples in the book.  The major code examples in the book concern two programs that are incrementaly developed through the chapters.  One is a very primitive battleship game, focusing on game design logic, rather than a GUI (there is no GUI).  The other is a beatbox midi sequencer, which includes functionality from the Java Sound API, a Swing GUI, and a client/server architecture.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Chapter Summary:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Chapter 1 (Breaking the Surface) discusses basic details on classes, and how to interface with the main() method.  Also included is more basic programming details on conditionals, looping and and other flow control mechanisms.&lt;br /&gt;&lt;br /&gt;Chapter 2 (A Trip to Objectville) gets into objects, object oriented principles, and the importance of unit testing.  Garbage collection is briefly discussed.&lt;br /&gt;&lt;br /&gt;Chapter 3 (Know Your Variables) covers variables including primitives and object references.  Both primitive and object arrays are mentioned and their limitations discussed.  More details on the garbage collection system is detaled.  There is also a useful table showing all of Java&#39;s reserved keywords.&lt;br /&gt;&lt;br /&gt;Chapter 4 (How Objects Behave) mentions more details on classes, methods (parameters vs arguments, return values, and pass-by-value), and encapsulation.  Included is a discussion on instance vs. local variables.&lt;br /&gt;&lt;br /&gt;Chapter 5 (Extra-Strength Methods) contains a more detailed discussion on object oriented design and unit testing.  The new Java 5 enhanced for loop syntax is mentioned along with type casting of primitives.&lt;br /&gt;&lt;br /&gt;Chapter 6 (Using the Java Library) dives into Java standard libraries with ArrayLists, importing, and packages.  Also mentioned are parameterized types and boolean expressions.&lt;br /&gt;&lt;br /&gt;Chapter 7 (Better Living in Objectville) continues the object oriented discussion with inheritance (both what it is and how to use it properly) and polymorphism.  Both method overriding and method overloading are covered as well.&lt;br /&gt;&lt;br /&gt;Chapter 8 (Serious Polymorphism) covers abstract classes and methods.  More details on polymorphism and object casting is discussed.  Java&#39;s version of multiple inheritance called interfaces is introduced.&lt;br /&gt;&lt;br /&gt;Chapter 9 (Life and Death of an Object) details the stack and the heap, and how they impact objects and local variables.  The chapter also discusses object constructors and superclass constructors, including the use of overloaded constructors.  This is followed by a decription of the scoping rules of local variables and factors affecting object lifetime and when garbage collection kicks in.&lt;br /&gt;&lt;br /&gt;Chapter 10 (Numbers Matter) provides details on the static and final, when used with both variables and methods.  Also included is a mention of wrapper classes for primitive to object conversion (and vice versa), how this conversion can be automatic with autoboxing in Java5.0+.  The discussion continues with number formatting, dates, and calendars.  Methods from the Math class are covered briefly at the beginning of the chapter.&lt;br /&gt;&lt;br /&gt;Chapter 11 (Risky Behavior) discusses details on exception handling, how to use try/catch/finally blocks to deal with exceptions, and how to declare that your method can throw exceptions.  Exception objects are explained including exception inheritance, polymorphism, and how to properly catch different types of exceptions.  Development on the MIDI application continues with details on the JavaSound API and MIDI events.&lt;br /&gt;&lt;br /&gt;Chapter 12 (A Very Graphic Story) gets into the swing of things with coverage of the Swing GUI library.  Included in the discussion is an introduction to frames, buttons, listening to events with event listeners, and drawing graphics with Graphics2D.  How to utilize inner classes with event listeners for increased flexibility is also covered.&lt;br /&gt;&lt;br /&gt;Chapter 13 (Work on Your Swing) gives examples of the use of a few different swing components and several GUI layout managers.  Components discussed include JButton, JTextField, JTextArea, JCheckBox, JList, and JPanel.  Detailed descriptions on the use of BorderLayout, FlowLayout, and BoxLayout are also included.&lt;br /&gt;&lt;br /&gt;Chapter 14 (Saving Objects) covers saving (and restoring) objects through serialization via Serializable.  Included is a discussion of the input and output streams of the Java I/O libraries.  The Java I/O File and BufferedReader classes are also mentioned.&lt;br /&gt;&lt;br /&gt;Chapter 15 (Make a Connection) has details on sockets, multithreading, and synchronization.  The chapter builds an example (client and server) chat program to illustrate use of the Socket class, specifically how to read from and write to a socket.  A excellent discussion of multithreading is covered in great detail with example code using the Runnable and Thread classes.  Also included are details on the unpredictability of the thread scheduler.  The chapter wraps up with solid coverge of concurrencies issues when using multithreading and how to avoid it with synchronization.&lt;br /&gt;&lt;br /&gt;Chapter 16 (Data Structures) mentions sorting of collection objects using the Comparable class.  The collections discussed include ArrayList, HashSet, TreeSet, and HashMap.  The concept of generics is explained in greater detail, along with generic method declaration syntax to support polymorphism.  Also included is brief mention on the difference between Sets and Maps.&lt;br /&gt;&lt;br /&gt;Chapter 17 (Release Your Code) is all about setting up your application for distribution.  This includes details on JAR files, how to structure them, what special files they need to contain, and how executable JAR files work.  The importance of using packages is covered as well, along with the command line compiler syntax required.  Use of Java Web Start to distribute your application to end users is discussed briefly.&lt;br /&gt;&lt;br /&gt;Chapter 18 (Distributed Computing) touches on distributed computing topics such as RMI (Remote Method Invocation), servlets, EJB, and Jini.  For RMI, the chapter provides a detailed explanation of how the proxy concept works and a dicussion of the process for setting up the remote implementation, the stubs and skeletons required, and the RMI registry.  The concept of servlets and EJB are covered but only very briefly (be sure to read Head First Servlets for extensive converage on servlets).  The chapter goes on to discuss Jini in great detail, including the discovery process and self-healing nature of the technology.  It covers what you need to make it work, then adds the necessary code to enable Jini in the beat box program, both client and server versions.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you&#39;re new to Java, &lt;a href=&quot;http://www.amazon.com/gp/product/0596009208?ie=UTF8&amp;tag=incoscapdaubl-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0596009208&quot;&gt;Head First Java&lt;/a&gt;&lt;img src=&quot;http://www.assoc-amazon.com/e/ir?t=incoscapdaubl-20&amp;l=as2&amp;o=1&amp;a=0596009208&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt; will get you started right away.  It&#39;s approach utilizing humor and imagery may seem childish at first, but once you get started, you&#39;ll realize how effective the &lt;a href=&quot;http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fs%3Fie%3DUTF8%26ref%255F%3Dnb%255Fss%255Fb%26field-keywords%3Dhead%2520first%2520o%2527reilly%26url%3Dsearch-alias%253Dstripbooks&amp;tag=incoscapdaubl-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=390957&quot;&gt;Head First Series&lt;/a&gt;&lt;img src=&quot;https://www.assoc-amazon.com/e/ir?t=incoscapdaubl-20&amp;l=ur2&amp;o=1&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt; learning series is.&lt;br /&gt;&lt;br /&gt;Other topics in the &lt;a href=&quot;http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fs%3Fie%3DUTF8%26ref%255F%3Dnb%255Fss%255Fb%26field-keywords%3Dhead%2520first%2520o%2527reilly%26url%3Dsearch-alias%253Dstripbooks&amp;tag=incoscapdaubl-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=390957&quot;&gt;Head First Series&lt;/a&gt;&lt;img src=&quot;https://www.assoc-amazon.com/e/ir?t=incoscapdaubl-20&amp;l=ur2&amp;o=1&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;:&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;iframe src=&quot;http://rcm.amazon.com/e/cm?t=incoscapdaubl-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=059610197X&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr&amp;nou=1&quot; style=&quot;width:120px;height:240px;&quot; scrolling=&quot;no&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&lt;br /&gt;&lt;iframe src=&quot;http://rcm.amazon.com/e/cm?t=incoscapdaubl-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0596008678&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr&amp;nou=1&quot; style=&quot;width:120px;height:240px;&quot; scrolling=&quot;no&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&lt;br /&gt;&lt;iframe src=&quot;http://rcm.amazon.com/e/cm?t=incoscapdaubl-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0596007124&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr&amp;nou=1&quot; style=&quot;width:120px;height:240px;&quot; scrolling=&quot;no&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&lt;br /&gt;&lt;iframe src=&quot;http://rcm.amazon.com/e/cm?t=incoscapdaubl-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0596516681&amp;md=10FE9736YVPPT7A0FBG2&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr&amp;nou=1&quot; style=&quot;width:120px;height:240px;&quot; scrolling=&quot;no&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/03/book-review-head-first-java.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-2472121337298721880</guid><pubDate>Thu, 22 Jan 2009 11:15:00 +0000</pubDate><atom:updated>2009-05-04T16:12:37.597-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Java</category><title>Java: JOptionPane Dialog Examples Part 1 - Basic</title><description>Java has a huge amount of functionality for creating GUI&#39;s for your applications.  Some of the more complex GUI&#39;s require lots of code.  However, sometimes you just need a plain old, nothing fancy, quick-and-dirty, keep it simple dialog.  In these situations, the JOptionPane works really well.  Basic JOptionPane dialog examples are the core of this article.&lt;br /&gt;&lt;br /&gt;Although it&#39;s Java&#39;s workhouse dialog, there are a few limitations.  It helps to understand those limitations such that it fulfills your expectations.  The first limitation (some consider this a feature) is modality.  The thread which creates the JOPtionPane dialog will wait until the user closes the dialog.  The other limitation is that it cannot be resized.  The user won&#39;t be able to make the dialog bigger in order to see its contents better.&lt;br /&gt;&lt;br /&gt;If these limitations are cramping your style, you&#39;ll need to move towards JDialog based dialogs.  Otherwise, read on for more JOptionPane information.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;The Methods&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are four commonly used static methods for JOPtionPane dialogs:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;showMessageDialog()&lt;/li&gt;&lt;li&gt;showInputDialog()&lt;/li&gt;&lt;li&gt;showConfirmDialog()&lt;/li&gt;&lt;li&gt;showOptionDialog()&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;All four methods allow for an icon on the left hand side and one or more buttons along the bottom.  Both of these are controllable and behave somewhat differently depending on which method is used.&lt;br /&gt;&lt;br /&gt;All three of showMessageDialog(), showConfirmDialog(), and showOptionDialog() are capable of displaying some form of information to the user, but each allows the user to respond in different ways.  showMessageDialog() allows for only for a message and an OK button.  showConfirmDialog() allows for various combinations of OK, YES, NO, and CANCEL buttons.  showOptionDialog() allows you to display buttons containing the text of your choice.&lt;br /&gt;&lt;br /&gt;Only showInputDialog() allows for the user to enter arbitrary information either in a text field or with a combo-box style list of values.  It provides only OK and CANCEL buttons.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Message Types&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;All four dialog types have options to display a predefined icon.  The following icon types are listed below, each of which is a static field of the JOptionPane class.  The actual icons displayed depends upon the java look and feel active at that time.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JOptionPane.ERROR_MESSAGE -- red letter x, or a &quot;no entry&quot; sign&lt;/li&gt;&lt;li&gt;JOptionPane.INFORMATION_MESSAGE -- letter i in a circle&lt;/li&gt;&lt;li&gt;JOptionPane.WARNING_MESSAGE -- excalamation point&lt;/li&gt;&lt;li&gt;JOptionPane.QUESTION_MESSAGE -- question mark&lt;/li&gt;&lt;li&gt;JOptionPane.PLAIN_MESSAGE -- no standard icon&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Option Types&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The showConfirmDialog() and showOptionDialog() methods have provisions for an &quot;option type&quot;, which are the buttons that will be displayed.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JOptionPane.DEFAULT_OPTION -- OK button&lt;/li&gt;&lt;li&gt;JOptionPane.YES_NO_OPTION -- YES and NO buttons&lt;/li&gt;&lt;li&gt;JOptionPane.YES_NO_CANCEL_OPTION -- YES, NO, and CANCEL buttons&lt;/li&gt;&lt;li&gt;JOptionPane.OK_CANCEL_OPTION -- OK and CANCEL buttons&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Return Values&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Both showConfirmDialog() and showOptionDialog() return an int that you can use to figure out how the user responded to the dialog.  Did they hit YES, NO, or OK?  Just analyze the value using the list below.  Perhaps the user closed the dialog window and did not hit one of your buttons?  It&#39;s an important piece of logic to add to your program.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JOptionPane.YES_OPTION -- YES button&lt;/li&gt;&lt;li&gt;JOptionPane.OK_OPTION -- OK button&lt;/li&gt;&lt;li&gt;JOptionPane.NO_OPTION -- NO button&lt;/li&gt;&lt;li&gt;JOptionPane.CANCEL_OPTION -- CANCEL button&lt;/li&gt;&lt;li&gt;JOptionPane.CLOSED_OPTION -- User closed the dialog without using a button&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;For what it&#39;s worth, YES_OPTION and OK_OPTION are actually the same value.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Parent Component&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In these examples, null is used for the parent component, which creates a standalone dialog, usually centered on the screen.  A parent UI component can be used to center the dialog on that component if that is desireable.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;User Specified Icon&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Some of the method signatures allow for a user specified icon to be used in the dialog box.  Even if a particular message type is requested, if a non-null ImageIcon is supplied, that icon will be used in the dialog.  This parameter is always optional.  null can be used wherever an icon needs to be specified.&lt;br /&gt;&lt;br /&gt;Beyond the scope of this article is placement of the icon file.  The presumption of this article is that the icon file is in the working directory of the java process.  In a more practical application, you will want to locate the icon file in your jar file or in a specific folder.  Each of these approaches has a different set of steps to define and will be discussed in a future article.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Method: showMessageDialog()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The dialog produced by showMessageDialog() is a basic dialog displaying a message to the user.  The user will see your message with only an &quot;OK&quot; button to close the dialog.  No value is returned.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 1a:&lt;/span&gt; Dialog displaying &quot;Hello!&quot;, with OK button, standard &quot;info&quot; icon, and title &quot;Message&quot;.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;JOptionPane.showMessageDialog(null, &amp;quot;Hello!&amp;quot;);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 1b:&lt;/span&gt; Dialog displaying &quot;Hello!&quot;, with OK button, no standard icon, and title &quot;Message Title&quot;.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon&lt;br /&gt;&lt;br /&gt;JOptionPane.showMessageDialog(null, &amp;quot;Hello!&amp;quot;, &amp;quot;Message Title&amp;quot;, messageType);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 1c:&lt;/span&gt; Dialog displaying &quot;Hello!&quot;, with OK button, non-standard icon from GIF file, and title &quot;Message Title&quot;.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon&lt;br /&gt;ImageIcon icon = new ImageIcon(&amp;quot;blob.gif&amp;quot;, &amp;quot;blob&amp;quot;);&lt;br /&gt;&lt;br /&gt;JOptionPane.showMessageDialog(null, &amp;quot;Hello!&amp;quot;, &amp;quot;Message Title&amp;quot;, messageType, icon);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Method: showInputDialog()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;showInputDialog() prompts the user for a value from a text field or within a dropdown combo-box style component.  The method returns a String.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 2a:&lt;/span&gt; Dialog with empty text field, &quot;Enter value:&quot; prompt string, plus OK and CANCEL buttons&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;String res = JOptionPane.showInputDialog(&amp;quot;Enter value:&amp;quot;);&lt;br /&gt;System.out.println( &amp;quot;showInputDialog: &amp;quot; + res );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 2b:&lt;/span&gt; Dialog with text field initialized to &quot;Hello!&quot;, &quot;Enter value:&quot; prompt string, plus OK and CANCEL buttons&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;String res = JOptionPane.showInputDialog(&amp;quot;Enter value:&amp;quot;, &amp;quot;Hello!&amp;quot;);&lt;br /&gt;System.out.println( &amp;quot;showInputDialog: &amp;quot; + res );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 2c:&lt;/span&gt; Dialog with empty text field, &quot;Enter value:&quot; prompt string, plus OK and CANCEL buttons&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;String res = JOptionPane.showInputDialog(null, &amp;quot;Enter value:&amp;quot;);&lt;br /&gt;System.out.println( &amp;quot;showInputDialog: &amp;quot; + res );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 2d:&lt;/span&gt; Dialog with text field initialized to &quot;Hello!&quot;, &quot;Enter value:&quot; prompt string, plus OK and CANCEL buttons&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;String res = JOptionPane.showInputDialog(null, &amp;quot;Enter value:&amp;quot;, &amp;quot;Hello!&amp;quot;);&lt;br /&gt;System.out.println( &amp;quot;showInputDialog: &amp;quot; + res );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 2e:&lt;/span&gt; Empty text field, &quot;Enter value:&quot; prompt string, plus OK and CANCEL buttons&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon&lt;br /&gt;&lt;br /&gt;String res = JOptionPane.showInputDialog(null, &amp;quot;Enter value:&amp;quot;, &amp;quot;Message Title&amp;quot;, messageType);&lt;br /&gt;System.out.println( &amp;quot;showInputDialog: &amp;quot; + res );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 2f:&lt;/span&gt; Combo box displaying values from selValues array with value initialized to selValues[0], &quot;Enter value:&quot; prompt string, plus OK and CANCEL buttons&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;Object[] selValues = { &amp;quot;abc&amp;quot;, &amp;quot;def&amp;quot;, &amp;quot;ghi&amp;quot; };&lt;br /&gt;int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon&lt;br /&gt;ImageIcon icon = new ImageIcon(&amp;quot;blob.gif&amp;quot;, &amp;quot;blob&amp;quot;);&lt;br /&gt;&lt;br /&gt;Object res = JOptionPane.showInputDialog(null, &amp;quot;Enter value:&amp;quot;, &amp;quot;Message Title&amp;quot;,&lt;br /&gt;                                         messageType, icon, selValues, selValues[0]);&lt;br /&gt;&lt;br /&gt;System.out.println( &amp;quot;showInputDialog: &amp;quot; + res );&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Method: showConfirmDialog()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;showConfirmDialog() produces a dialog similar to that from showMessageDialog(), except that it provides more options for buttons.  Button combinations available are OK, YES+NO, YES+NO+CANCEL, and OK+CANCEL.  The int return value indicates the button pressed, if any.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 3a:&lt;/span&gt; Dialog displaying &quot;Hello!&quot;, with YES+NO+CANCEL buttons, standard &quot;question mark&quot; icon, and title &quot;Select an Option&quot;.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;int res = JOptionPane.showConfirmDialog(null, &amp;quot;Hello!&amp;quot;);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 3b:&lt;/span&gt; Dialog displaying &quot;Hello!&quot;, with YES+NO+CANCEL buttons, standard &quot;question mark&quot; icon, and title &quot;Message Title&quot;.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;int optionType = JOptionPane.YES_NO_CANCEL_OPTION; // YES+NO+CANCEL&lt;br /&gt;int res = JOptionPane.showConfirmDialog(null, &amp;quot;Hello!&amp;quot;, &amp;quot;Message Title&amp;quot;, optionType);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 3c:&lt;/span&gt; Dialog displaying &quot;Hello!&quot;, with YES+NO+CANCEL buttons, no standard icon, and title &quot;Message Title&quot;.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;int optionType = JOptionPane.YES_NO_CANCEL_OPTION; // YES+NO+CANCEL&lt;br /&gt;int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon&lt;br /&gt;int res = JOptionPane.showConfirmDialog(null, &amp;quot;Hello!&amp;quot;, &amp;quot;Message Title&amp;quot;,&lt;br /&gt;                                        optionType, messageType);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 3d:&lt;/span&gt; Dialog displaying &quot;Hello!&quot;, with YES+NO+CANCEL buttons, &quot;blob&quot; icon, and title &quot;Message Title&quot;. XXX&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;int optionType = JOptionPane.YES_NO_CANCEL_OPTION; // YES+NO+CANCEL&lt;br /&gt;int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon&lt;br /&gt;ImageIcon icon = new ImageIcon(&amp;quot;blob.gif&amp;quot;, &amp;quot;blob&amp;quot;);&lt;br /&gt;int res = JOptionPane.showConfirmDialog(null, &amp;quot;Hello!&amp;quot;, &amp;quot;Message Title&amp;quot;,&lt;br /&gt;                                        optionType, messageType, icon);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 3e:&lt;/span&gt; Handling Return Values of showConfirmDialog()&lt;br /&gt;&lt;br /&gt;The int value returned by showConfirmDialog() tells you which button the users pressed, or if they simply closed the dialog without using any buttons at all.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;// User hit YES&lt;br /&gt;if (res == JOptionPane.YES_OPTION) { System.out.println( &amp;quot;YES_OPTION&amp;quot; ); }&lt;br /&gt;&lt;br /&gt;// User hit OK&lt;br /&gt;if (res == JOptionPane.OK_OPTION) { System.out.println( &amp;quot;OK_OPTION&amp;quot; ); }&lt;br /&gt;&lt;br /&gt;// User hit NO&lt;br /&gt;if (res == JOptionPane.NO_OPTION) { System.out.println( &amp;quot;NO_OPTION&amp;quot; ); }&lt;br /&gt;&lt;br /&gt;// User hit CANCEL&lt;br /&gt;if (res == JOptionPane.CANCEL_OPTION) { System.out.println( &amp;quot;CANCEL_OPTION&amp;quot; ); }&lt;br /&gt;&lt;br /&gt;// User closed the window without hitting any button&lt;br /&gt;if (res == JOptionPane.CLOSED_OPTION) { System.out.println( &amp;quot;CLOSED_OPTION&amp;quot; ); }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Method: showOptionDialog()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;showOptionDialog() displays buttons whose labels are based on the values in the input array, with one of the buttons being the default option.  If one of the buttons is selected, showOptionDialog() returns the array index number of the selected button.&lt;br /&gt;&lt;br /&gt;If the dialog is closed without selecting a button, showOptionDialog() returns -1.  It seems to ignore the &quot;option type&quot; parameter.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 4a:&lt;/span&gt; Dialog displaying &quot;Hello!&quot;, with button labels from selValues array, &quot;blob&quot; icon, and title &quot;Message Title&quot;.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;int optionType = JOptionPane.DEFAULT_OPTION;&lt;br /&gt;int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon&lt;br /&gt;ImageIcon icon = new ImageIcon(&amp;quot;blob.gif&amp;quot;, &amp;quot;blob&amp;quot;);&lt;br /&gt;Object[] selValues = { &amp;quot;abc&amp;quot;, &amp;quot;def&amp;quot;, &amp;quot;ghi&amp;quot; };&lt;br /&gt;&lt;br /&gt;// Shows message, choices appear as buttons&lt;br /&gt;int res = JOptionPane.showOptionDialog(null, &amp;quot;Hello!&amp;quot;, &amp;quot;Message Title&amp;quot;,&lt;br /&gt;                                       optionType, messageType, icon,&lt;br /&gt;                                       selValues, selValues[0]);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Example 4b:&lt;/span&gt; Handling Return Values of showOptionDialog()&lt;br /&gt;&lt;br /&gt;System.out.println( &quot;showOptionDialog: &quot; + res);&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;if (res &amp;gt;= 0) {&lt;br /&gt;    System.out.println( &amp;quot;showOptionDialog: &amp;quot; + res + &amp;quot; (&amp;quot; + selValues[res] + &amp;quot;)&amp;quot; );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if (res == JOptionPane.CLOSED_OPTION) { System.out.println( &amp;quot;CLOSED_OPTION&amp;quot; ); }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;These are the basic uses of the JOptionPane.  As you can see here, for a simple dialog, there are numerous options, and I have only described a fraction of it&#39;s capabilities.&lt;br /&gt;&lt;br /&gt;In &lt;a href=&quot;http://inversionconsulting.blogspot.com/2009/01/java-joptionpane-examples-part-1-basic.html&quot;&gt;Part 2&lt;/a&gt;, I&#39;ll discuss some poorly documented features of JOptionPane, but they may just blow your mind.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2009/01/java-joptionpane-examples-part-1-basic.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-596632320423241549</guid><pubDate>Tue, 11 Nov 2008 11:30:00 +0000</pubDate><atom:updated>2008-11-11T03:41:40.283-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Intralink</category><category domain="http://www.blogger.com/atom/ns#">Intralink Oracle SQL</category><title>Intralink SQL: User and Group Folder Authorizations</title><description>Intralink stores folder authorizations in four Oracle tables.  Two for user authorizations (PDM_USERFOLAUTH and PDM_USERFOLRLAUTH) and two for group authorizations (PDM_USERGRFOLAUTH and PDM_USERGRFOLRLAUTH).&lt;br /&gt;&lt;br /&gt;The PDM_USERFOLAUTH and PDM_USERGRFOLAUTH tables contain folder role authorizations.  The PDM_USERFOLRLAUTH and PDM_USERGRFOLRLAUTH tables contain folder authorizations by release level.  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Query for user folder role authorizations:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;-- user folder auth&lt;br /&gt;--&lt;br /&gt;set linesize 135&lt;br /&gt;col folpath format a60&lt;br /&gt;col userexpname format a12&lt;br /&gt;col rolename format a15&lt;br /&gt;--&lt;br /&gt;select &lt;br /&gt;  FOLPATH, &lt;br /&gt;  USEREXPNAME, &lt;br /&gt;  ROLENAME &lt;br /&gt;from &lt;br /&gt;  pdm.PDM_USERFOLAUTH ufa, &lt;br /&gt;  pdm.PDM_ROLE role, &lt;br /&gt;  pdm.PDM_FOLDER fol, &lt;br /&gt;  pdm.PDM_USER usr&lt;br /&gt;where&lt;br /&gt;  role.ROLEID=ufa.ROLEID and &lt;br /&gt;  ufa.FOLID=fol.FOLID and &lt;br /&gt;  ufa.USERID=usr.USERID&lt;br /&gt;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Query for user folder/releaselevel role authorizations:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;-- user folder/releaselevel auth&lt;br /&gt;--&lt;br /&gt;set linesize 135&lt;br /&gt;col folpath format a60&lt;br /&gt;col userexpname format a12&lt;br /&gt;col rlname format a15&lt;br /&gt;col rolename format a15&lt;br /&gt;--&lt;br /&gt;select &lt;br /&gt;  FOLPATH, &lt;br /&gt;  USEREXPNAME, &lt;br /&gt;  RLNAME, &lt;br /&gt;  ROLENAME &lt;br /&gt;from &lt;br /&gt;  pdm.PDM_USERFOLRLAUTH ufrla, &lt;br /&gt;  pdm.PDM_RELEASELEVEL rl, &lt;br /&gt;  pdm.PDM_ROLE role, &lt;br /&gt;  pdm.PDM_FOLDER fol, &lt;br /&gt;  pdm.PDM_USER usr&lt;br /&gt;where&lt;br /&gt;  role.ROLEID=ufrla.ROLEID and &lt;br /&gt;  ufrla.RLID=rl.RLID and &lt;br /&gt;  ufrla.FOLID=fol.FOLID and &lt;br /&gt;  ufrla.USERID=usr.USERID&lt;br /&gt;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Query for group folder role authorizations:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;-- group folder auth&lt;br /&gt;--&lt;br /&gt;set linesize 135&lt;br /&gt;col folpath format a60&lt;br /&gt;col rolename format a15&lt;br /&gt;col grexpname format a25&lt;br /&gt;--&lt;br /&gt;select &lt;br /&gt;  FOLPATH, &lt;br /&gt;  GREXPNAME &lt;br /&gt;  ROLENAME, &lt;br /&gt;from &lt;br /&gt;  pdm.PDM_USERGRFOLAUTH gfa, &lt;br /&gt;  pdm.PDM_ROLE role, &lt;br /&gt;  pdm.PDM_FOLDER fol, &lt;br /&gt;  pdm.PDM_USERGROUP grp &lt;br /&gt;where&lt;br /&gt;  role.ROLEID=gfa.ROLEID and &lt;br /&gt;  gfa.FOLID=fol.FOLID and &lt;br /&gt;  gfa.GRID=grp.GRID &lt;br /&gt;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Query for group folder/releaselevel role authorizations:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;-- group folder/releaselevel auth&lt;br /&gt;--&lt;br /&gt;set linesize 135&lt;br /&gt;col folpath format a60&lt;br /&gt;col grexpname format a25&lt;br /&gt;col rlname format a15&lt;br /&gt;col rolename format a15&lt;br /&gt;--&lt;br /&gt;select &lt;br /&gt;  FOLPATH, &lt;br /&gt;  GREXPNAME, &lt;br /&gt;  RLNAME, &lt;br /&gt;  ROLENAME &lt;br /&gt;from &lt;br /&gt;  pdm.PDM_USERGRFOLRLAUTH gfrla, &lt;br /&gt;  pdm.PDM_RELEASELEVEL rl, &lt;br /&gt;  pdm.PDM_ROLE role, &lt;br /&gt;  pdm.PDM_FOLDER fol, &lt;br /&gt;  pdm.PDM_USERGROUP grp&lt;br /&gt;where&lt;br /&gt;  role.ROLEID=gfrla.ROLEID and &lt;br /&gt;  gfrla.RLID=rl.RLID and &lt;br /&gt;  gfrla.FOLID=fol.FOLID and &lt;br /&gt;  gfrla.GRID=grp.GRID&lt;br /&gt;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Putting it all together&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;To streamline these queries, unions can be used to combine the output into one report.  In the following example, user and group names are reported under the &#39;ID&#39; column.  The final where clause can be used to filter for a specific user or group.  Leave it out to report authorizations for everyone.&lt;br /&gt;&lt;br /&gt;The report is also enhanced in that the order of the release levels in the output matches the output one would see in the folder authorization window in Intralink Admin.&lt;br /&gt;&lt;br /&gt;The syntax is somewhat inefficient because it is setup to allow outer joins based on folders (see end of article).  However, even for very large numbers of folders, user, and groups, the combined query is still pretty fast.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;-- user &amp;amp; group auth&lt;br /&gt;--&lt;br /&gt;set linesize 200&lt;br /&gt;column folpath format a70&lt;br /&gt;column rolename format a20&lt;br /&gt;column rlname format a15&lt;br /&gt;column id format a25&lt;br /&gt;--&lt;br /&gt;select FOLPATH,id,rlname,rolename,rlseqnum&lt;br /&gt;from&lt;br /&gt;  (&lt;br /&gt;    select&lt;br /&gt;      folpath,&lt;br /&gt;      (select userexpname from pdm.pdm_user where userid=ufa.userid) as id,&lt;br /&gt;      &#39;&#39; as rlname,&lt;br /&gt;      to_number(&#39;&#39;) as rlseqnum,&lt;br /&gt;      (select rolename from pdm.pdm_role where roleid=ufa.roleid) as rolename&lt;br /&gt;    from&lt;br /&gt;      pdm.pdm_userfolauth ufa,&lt;br /&gt;      pdm.pdm_folder fol&lt;br /&gt;    where&lt;br /&gt;      ufa.folid=fol.folid&lt;br /&gt;  UNION&lt;br /&gt;    select &lt;br /&gt;      FOLPATH,&lt;br /&gt;      (select userexpname from pdm.pdm_user where userid=ufrla.userid) as id,&lt;br /&gt;      (select rlname from pdm.pdm_releaselevel where rlid=ufrla.rlid) as rlname,&lt;br /&gt;      (select rlseqnum from pdm.pdm_releaselevel where rlid=ufrla.rlid) as rlseqnum,&lt;br /&gt;      (select rolename from pdm.pdm_role where roleid=ufrla.roleid) as rolename&lt;br /&gt;    from &lt;br /&gt;      pdm.PDM_USERFOLRLAUTH ufrla, &lt;br /&gt;      pdm.PDM_FOLDER fol&lt;br /&gt;    where&lt;br /&gt;      ufrla.FOLID=fol.FOLID&lt;br /&gt;  UNION&lt;br /&gt;    select&lt;br /&gt;      folpath,&lt;br /&gt;      (select grexpname from pdm.pdm_usergroup where grid=ugfa.grid) as id,&lt;br /&gt;      &#39;&#39; as rlname,&lt;br /&gt;      to_number(&#39;&#39;) as rlseqnum,&lt;br /&gt;      (select rolename from pdm.pdm_role where roleid=ugfa.roleid) as rolename&lt;br /&gt;    from&lt;br /&gt;      pdm.pdm_usergrfolauth ugfa,&lt;br /&gt;      pdm.pdm_folder fol&lt;br /&gt;    where&lt;br /&gt;      ugfa.folid=fol.folid&lt;br /&gt;  UNION&lt;br /&gt;    select &lt;br /&gt;      FOLPATH,&lt;br /&gt;      (select grexpname from pdm.pdm_usergroup where grid=gfrla.grid) as id, &lt;br /&gt;      (select rlname from pdm.pdm_releaselevel where rlid=gfrla.rlid) as rlname,&lt;br /&gt;      (select rlseqnum from pdm.pdm_releaselevel where rlid=gfrla.rlid) as rlseqnum,&lt;br /&gt;      (select rolename from pdm.pdm_role where roleid=gfrla.roleid) as rolename&lt;br /&gt;    from &lt;br /&gt;      pdm.PDM_USERGRFOLRLAUTH gfrla, &lt;br /&gt;      pdm.PDM_FOLDER fol&lt;br /&gt;    where&lt;br /&gt;      gfrla.FOLID=fol.FOLID&lt;br /&gt;  )&lt;br /&gt;where&lt;br /&gt;  id like &#39;%smith%&#39;&lt;br /&gt;order by folpath,id,rlseqnum&lt;br /&gt;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Outer Joins for More Information&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;To show all folders, regardless of whether they contain any authorization settings, add the following outer join syntax to the above:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;      ...folid(+)=fol.folid&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;There will be some minor duplications, but it does give a good sense of where the authorizations are set in your folder hierarchy.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/11/intralink-sql-user-group-folder-auths.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-9090705467828444385</guid><pubDate>Tue, 19 Aug 2008 10:22:00 +0000</pubDate><atom:updated>2008-08-19T04:17:03.820-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">Trail Files</category><title>Pro/ENGINEER: Anatomy of a Trail File, Part 3</title><description>&lt;em&gt;Read &lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/05/proe-anatomy-of-trail-file-part-2.html&quot;&gt;Part 2&lt;/a&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;In my experience, there are three main uses for trail files: Recovery, Benchmarking, and Templating. Generally speaking this series of articles is about templating trail files. Templating is the modification of trail files to perform actions that are not specific to a particular model.&lt;br /&gt;&lt;br /&gt;In more complex trail files, selection of items eventually becomes a necessity. Doing this in a repeatable way can become very challenging, especially if working with different models or models that are changing often.&lt;br /&gt;&lt;br /&gt;Selections of models, features, annotations, and notes can be accomplished in various ways, but selections of geometry items such as surfaces and edges are very difficult in such a manner that it works for different models. Trail file selections using the graphics window are almost never transferable for use with other models.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;&lt;strong&gt;Model Tree&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When you click on an item in the model tree, you&#39;ll see, for example, &quot;node4&quot; or &quot;node31&quot; appear. Here is an example of a trail file entry caused by selecting &#39;Note_1&#39;.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Select `main_dlg_cur` `PHTLeft.AssyTree` \&lt;br /&gt;1 `node6`&lt;br /&gt;!Note_1&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;These node numbers are assigned by Pro/ENGINEER on a first come, first served basis. When the model is first opened the node numbers are assigned in a bottom first, upwardly increasing sequence, based on what is displayed at that time.&lt;br /&gt;&lt;br /&gt;For example, if the model tree of a part is shown with features and annotations when the model is opened, the following table reflects the node number assignments. The top level item (the part itself) is node 0 (zero), then working up from the bottom the node numbers increase. As you can see, even the &#39;Insert Here&#39; pointer has a node number.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt; Item        Node #&lt;br /&gt;ABC.PRT        0&lt;br /&gt; Note_0        8&lt;br /&gt; Note_1        7&lt;br /&gt; Note_2        6&lt;br /&gt; Feat1         5&lt;br /&gt; Feat2         4&lt;br /&gt; Feat3         3&lt;br /&gt; Feat4         2&lt;br /&gt; Insert Here   1&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;The tricky part comes when new nodes are shown either through expansion of existing nodes (i.e. to show features of a component) or modification of the model tree filters. Regardless of where in the model tree they appear, the new nodes are given new node numbers based on the previous largest value.&lt;br /&gt;&lt;br /&gt;As an example, if your model tree initially shows nothing, then annotations are added, then features are added, you might get a result like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt; Item        Node #&lt;br /&gt;ABC.PRT        0&lt;br /&gt; Note_0        3&lt;br /&gt; Note_1        2&lt;br /&gt; Note_2        1&lt;br /&gt; Feat1         8&lt;br /&gt; Feat2         7&lt;br /&gt; Feat3         6&lt;br /&gt; Feat4         5&lt;br /&gt; Insert Here   4&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;The node numbers for a complex assembly might even appear to be randomly assigned. Disappointingly, use of &#39;Expand All&#39; doesn&#39;t produce very orderly node number assignments.&lt;br /&gt;&lt;br /&gt;Beyond the top level nodes, use of the model tree can be very complicated. It is definitely something that can be done, but requires some preprocessing to generate a trail file programmatically before it is run. Most likely, trail files making more than trivial use of the Model Tree will not be usable for other models.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:130%;&quot;&gt;&lt;strong&gt;Search Tool&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Another approach to selections with trail files is the &quot;Search&quot; tool (i.e. Edit -&gt; Find). The Search tool works very well when selecting items with a trail file. Selections of specific models, features, or numerous other entities can be accomplished easily.&lt;br /&gt;&lt;br /&gt;The downside to this approach is that you lose some control over where in an assembly hierarchy objects can be located. An option exists to search only in the top level, but an &#39;All Levels&#39; search will return results from any level.&lt;br /&gt;&lt;br /&gt;Another difficulty is that multiple results will be obtained when searching for common objects, such as hardware parts, shared subassemblies, and models with standard features, etc. There is a mechanism to select specific items, but this requires a great deal of information that has to be provided ahead of time.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Defaults&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Another thing to keep in mind is that the last option you use in the Search Tool may be the default option when the Search Tool is used a second time. A recommendation is always to set explicitly every option (even if it is the default) every time the Search Tool is used with a trail file. This will produce more robust trail files.&lt;br /&gt;&lt;br /&gt;It may be extra work to click on other options that you don&#39;t want in order to record the selection that you do want, however it&#39;s worth the effort. Extra baggage code in the trail file can usually be removed, if that is desirable.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A typical scenario is the need to select an item such as a component, a feature, or a note using its name. Here is an example of using the Search tool to search an assembly for a subassembly called &#39;A.ASM&#39;. I have added comments to indicate the major sections.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;!! Start the Search tool&lt;br /&gt;!!&lt;br /&gt;~ Select `main_dlg_cur` `MenuBar1` \&lt;br /&gt;1 `Edit`&lt;br /&gt;~ Close `main_dlg_cur` `MenuBar1`&lt;br /&gt;~ Activate `main_dlg_cur` `Edit.Find`&lt;br /&gt;!!&lt;br /&gt;!! Select entity type to be searched for&lt;br /&gt;!!&lt;br /&gt;~ Open `selspecdlg0` `SelOptionRadio`&lt;br /&gt;~ Close `selspecdlg0` `SelOptionRadio`&lt;br /&gt;~ Select `selspecdlg0` `SelOptionRadio` \&lt;br /&gt;1 `Prt_or_Asm`&lt;br /&gt;!!&lt;br /&gt;!! Limit search to top level&lt;br /&gt;!!&lt;br /&gt;~ Activate `selspecdlg0` `SelScopeCheck` \&lt;br /&gt;0&lt;br /&gt;!!&lt;br /&gt;!! Enter name&lt;br /&gt;!!&lt;br /&gt;~ Update `selspecdlg0` `ExtRulesLayout.ExtBasicNameLayout.BasicNameList` \&lt;br /&gt;`A.ASM`&lt;br /&gt;!!&lt;br /&gt;!! Perform search by clicking &#39;Find Now&#39; button&lt;br /&gt;!!&lt;br /&gt;~ Activate `selspecdlg0` `EvaluateBtn`&lt;br /&gt;!!&lt;br /&gt;!! Selecting item(s) in results&lt;br /&gt;!!&lt;br /&gt;~ Select `selspecdlg0` `ResultList` \&lt;br /&gt;1 `-1:69:[39]`&lt;br /&gt;!!&lt;br /&gt;!! Hit &#39;Close&#39; in Search dialog (even though it says &#39;CancelButton&#39;)&lt;br /&gt;!!&lt;br /&gt;~ Activate `selspecdlg0` `CancelButton`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;If you follow along in your trail file while performing the search, you can see that each action produces a certain output, which is mostly self explanatory. What is not so obvious is the syntax of the output when items are selected in the search results.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Selections&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The syntax used for selection of components differs from the selection of other types of entities, but it is similar. The `-1:69:[39]` specifier is a colon separated list of three fields: ID, Type, Component Path.&lt;br /&gt;&lt;br /&gt;The first field is an item ID field (i.e. feature id, note id, etc), except for components where it always shows -1. The second field is a numeric code corresponding to the type of entity in the search, whether that be &#39;Feature&#39;, &#39;Annotation&#39;, &#39;Component&#39;, etc. The third field specifies a &quot;Component Path&quot; which is a list of component feature IDs from a top level to a subassembly or component. The &quot;[39]&quot; indicates that the selected component is feature ID 39 in the top level assembly.&lt;br /&gt;&lt;br /&gt;A selected item generating this syntax `2:147:[40][40][41][61]`, is a note (or some other annotation) with id 2 and found through the component id sequence of 40 (level 1 component id), 40 (level 2 component id), 41 (level 3 component id), 61 (level 4 component id).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Select All&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The &quot;Select All&quot; action (Ctrl-A) can be used at any time and generates the following trail code. Even if a selection of an item is required for an interactive user prior to using &quot;Select All&quot;, this can be used without it in a trail file.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Select `selspecdlg0` `ResultList` \&lt;br /&gt;-1&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Depth&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The depth of the search is controlled by the &quot;Include submodels&quot; option in the Search Tool dialog. Checking or unchecking this option adds one of the following code sequences to the trail file.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;!! Limit search to top level (&#39;Include submodels&#39; is not checked)&lt;br /&gt;!!&lt;br /&gt;~ Activate `selspecdlg0` `SelScopeCheck` \&lt;br /&gt;0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;!! Search all levels (&#39;Include submodels&#39; is checked)&lt;br /&gt;!!&lt;br /&gt;~ Activate `selspecdlg0` `SelScopeCheck` \&lt;br /&gt;1&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Closing The Dialog&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;As you can see from my comment, hitting Close in the dialog adds a curiously named &quot;CancelButton&quot; entry. Just remember if you&#39;re editing the trail file, that this means &quot;Close&quot;.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;!! Hit &#39;Close&#39; in Search dialog (even though it says &#39;CancelButton&#39;)&lt;br /&gt;!!&lt;br /&gt;~ Activate `selspecdlg0` `CancelButton`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Types&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;One of the first things typically done when using the Search Tool is the choice of entity type. If you&#39;re familiar with the tool, you know that there is a very wide range of type options to choose from.&lt;br /&gt;&lt;br /&gt;Type selection generates code such as this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Open `selspecdlg0` `SelOptionRadio`&lt;br /&gt;~ Close `selspecdlg0` `SelOptionRadio`&lt;br /&gt;~ Select `selspecdlg0` `SelOptionRadio` \&lt;br /&gt;1 `TYPENAME`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;Some examples of `TYPENAME` are `Prt_or_Asm`, `Component`, `Feature`, `Annotation`, `Note`, `Location`, `Datum`, `3D Curve`.&lt;br /&gt;&lt;br /&gt;As discussed earlier, the numeric code for the type is reflected in the code generated when selecting items in the search results. The type code for `Annotation` and `Note` are both 147, while `Prt_or_Asm` (&quot;Solid Model&quot; from the GUI) and `Component` are both 69.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;By Name&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The Search Tool allows case-insensitive name searches, and wildcards can be used to make the search criteria more generic. The basic syntax is as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Select `selspecdlg0` `RuleTab` \&lt;br /&gt;1 `Attributes`&lt;br /&gt;~ Update `selspecdlg0` `ExtRulesLayout.ExtBasicNameLayout.BasicNameList` \&lt;br /&gt;`NAME`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;Examples of `NAME` with and without wildcards might be `12345678_OBSOLETE.PRT`, `DEFAULT`, `ASM_TOP`, `ASM_*`, `*65-5*`, `*side*`.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;By ID&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;If a specific feature ID or note ID is known, this can be searched for as well. This appears in the GUI under the &quot;History&quot; tab and generates the following entry:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Select `selspecdlg0` `RuleTab` \&lt;br /&gt;1 `Misc`&lt;br /&gt;~ Select `selspecdlg0` `RuleTypes` \&lt;br /&gt;1 `ID`&lt;br /&gt;~ Update `selspecdlg0` `ExtRulesLayout.ExtBasicIDLayout.InputIDPanel` \&lt;br /&gt;`IDENT`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;Where `IDENT` is an integer number such as `1`, `2`, `3`, etc. Note that the History tab goes by the name of Misc in the trail file. All other tabs follow their name in the trail file more directly.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;By Parameter Value&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In addition to entity name searches, the Search Tool can perform searches based on parameter values, using the &quot;Expression&quot; radio option in the &quot;Attributes&quot; tab. Keep in mind that there are differences in the behavior of &quot;Component&quot; searches versus &quot;Solid Model&quot; searches. Testing will ensure your searches produce the desired results.&lt;br /&gt;&lt;br /&gt;This sequences will prep the dialog box for searches based on parameter values:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Select `selspecdlg0` `RuleTab` \&lt;br /&gt;1 `Attributes`&lt;br /&gt;~ Select `selspecdlg0` `RuleTypes` \&lt;br /&gt;1 `Expression`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;The type must be selected first (real number, string, integer, yes/no), then the name of the parameter. Be careful when selecting the parameter name from the drop down list, because only a sequence number will be recorded. For a different set of models, the sequence number may not correspond to the same parameter name as when you recorded the trail files.&lt;br /&gt;&lt;br /&gt;This results from choosing a parameter from the list:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Open `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprTypesList`&lt;br /&gt;~ Close `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprTypesList`&lt;br /&gt;~ Select `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprTypesList` \&lt;br /&gt;1 `51`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;This results from typing in a parameter name:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Open `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprParamsList`&lt;br /&gt;~ Close `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprParamsList`&lt;br /&gt;~ Input `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprParamsList` \&lt;br /&gt;`DES`&lt;br /&gt;~ Input `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprParamsList` \&lt;br /&gt;`DESC`&lt;br /&gt;~ Update `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprParamsList` \&lt;br /&gt;`DESC`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;The typed syntax can be simplified, by removing the &#39;Input&#39; entries and leaving the &#39;Update&#39; entry, to this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Open `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprParamsList`&lt;br /&gt;~ Close `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprParamsList`&lt;br /&gt;~ Update `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprParamsList` \&lt;br /&gt;`DESC`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;The &#39;Value&#39; field in the dialog box corresponds to the &#39;ExprValuesList&#39;. Any value can be entered, and wildcards can be used as well. Note that string searches seem to be case insensitive only when used with wildcards.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Update `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprValuesList` \&lt;br /&gt;`brack*`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;The &quot;Comparison&quot; can be changed from the default of &quot;is equal to&quot;. There are seven operators available, with this being an example of greater than (more useful for numeric comparisons):&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Open `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprOperandLabel`&lt;br /&gt;~ Close `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprOperandLabel`&lt;br /&gt;~ Select `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprOperandLabel` \&lt;br /&gt;1 ` &amp;gt; `&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;The list of comparisons (for ExprOperandLabel) is:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;` == `   is equal to&lt;br /&gt;` != `   is not equal to&lt;br /&gt;` &amp;lt; `    is less than&lt;br /&gt;` &amp;gt; `    is greater than&lt;br /&gt;` &amp;lt;= `   is less than or equal to&lt;br /&gt;` &amp;gt;= `   is greater than or equal to&lt;br /&gt;` * `    exists&lt;br /&gt;` !* `   does not exist&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;When searching by parameter, the parameter type must be selected first.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Open `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprTypesList`&lt;br /&gt;~ Close `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprTypesList`&lt;br /&gt;~ Select `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprTypesList` \&lt;br /&gt;1 `TYPEID`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;Where `TYPEID` is 50, 51, 52, or 53 for Real Number, String, Integer, and Yes/No, respectively.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Look In&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The &#39;Look In&#39; drop down list allows for user control of the model (or hierarchy) to be searched. Here are some examples of selections made from the drop down list.&lt;br /&gt;&lt;br /&gt;Top level selected:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Input `selspecdlg0` `LookInDrop` \&lt;br /&gt;`12345678.ASM`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;Component selected:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Select `selspecdlg0` `LookInDrop` \&lt;br /&gt;1 `12345678_SKEL.PRT (12345678, id 43) (43)`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;It is also an editable field in which you can attempt to enter model names. Unfortunately, the rather strong autocomplete nature may prevent entering the correct model name, or stop at another model, or result in garbage entered. None of this will produce a useful trail file.&lt;br /&gt;&lt;br /&gt;The good news is that the syntax used for top level example can be used for any model at any level:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Input `selspecdlg0` `LookInDrop` \&lt;br /&gt;`23456789.ASM`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;This differs from other trail file entries in that typically the &quot;Update&quot; statement is kept while the &quot;Input&quot; entries are eliminated, because they are typically redundant. It is most likely the autocomplete functionality that makes this necessary.&lt;br /&gt;&lt;br /&gt;When using this syntax, which lacks the component path (list of component ids), you&#39;ll lose some control if the model is used multiple times in an assembly hierarchy. Not a major problem, just something to be aware of. Based on my testing, the Search Tool uses the model that appears last in the model tree, if multiples exist.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Tabs&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A specific tab in the Search Tool dialog can be selected using the following example:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Select `selspecdlg0` `RuleTab` \&lt;br /&gt;1 `TABNAME`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;Where `TABNAME` is `Attributes` for the Attribute tab, `Misc` for the History tab, `Status` for the Status tab, and `Geometry` for the Geometry tab.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Another Example&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Combining several of these elements, here is an example that searches for parts and assemblies within all levels of ASM0002.ASM that for parameter DESC have a value matching &quot;brack*&quot;, selects all found, and closes the dialog:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;!!&lt;br /&gt;!! Start the Search tool (via Ctrl+F)&lt;br /&gt;!!&lt;br /&gt;~ Activate `main_dlg_cur` `ProCmdMdlTreeSearch.edit_t`&lt;br /&gt;!!&lt;br /&gt;!! Select &amp;quot;Solid Model&amp;quot; as entity type to be searched for&lt;br /&gt;!!&lt;br /&gt;~ Open `selspecdlg0` `SelOptionRadio`&lt;br /&gt;~ Close `selspecdlg0` `SelOptionRadio`&lt;br /&gt;~ Select `selspecdlg0` `SelOptionRadio` \&lt;br /&gt;1 `Prt_or_Asm`&lt;br /&gt;!!&lt;br /&gt;!! Restrict search to a subassembly&lt;br /&gt;!!&lt;br /&gt;~ Input `selspecdlg0` `LookInDrop` \&lt;br /&gt;`ASM0002.ASM`&lt;br /&gt;!!&lt;br /&gt;!! Search all levels (&#39;Include submodels&#39; is checked)&lt;br /&gt;!!&lt;br /&gt;~ Activate `selspecdlg0` `SelScopeCheck` \&lt;br /&gt;1&lt;br /&gt;!!&lt;br /&gt;!! Go to &amp;quot;Attributes&amp;quot; tab, select &amp;quot;Expression&amp;quot; radio button&lt;br /&gt;!!&lt;br /&gt;~ Select `selspecdlg0` `RuleTab` \&lt;br /&gt;1 `Attributes`&lt;br /&gt;~ Activate `selspecdlg0` `selspecdlg0`&lt;br /&gt;~ Select `selspecdlg0` `RuleTypes` \&lt;br /&gt;1 `Expression`&lt;br /&gt;!!&lt;br /&gt;!! Select &amp;quot;String&amp;quot; from parameter value type pull down&lt;br /&gt;!!&lt;br /&gt;~ Open `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprTypesList`&lt;br /&gt;~ Close `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprTypesList`&lt;br /&gt;~ Select `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprTypesList` \&lt;br /&gt;1 `51`&lt;br /&gt;!!&lt;br /&gt;!! Enter parameter name&lt;br /&gt;!!&lt;br /&gt;~ Update `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprParamsList` \&lt;br /&gt;`DESC`&lt;br /&gt;!!&lt;br /&gt;!! Enter parameter value search string&lt;br /&gt;!!&lt;br /&gt;~ Update `selspecdlg0` `ExtRulesLayout.ExtExprLayout.ExprValuesList` \&lt;br /&gt;`brack*`&lt;br /&gt;!!&lt;br /&gt;!! Perform search by clicking &#39;Find Now&#39; button&lt;br /&gt;!!&lt;br /&gt;~ Activate `selspecdlg0` `EvaluateBtn`&lt;br /&gt;!!&lt;br /&gt;!! Select all in search results&lt;br /&gt;!!&lt;br /&gt;~ Select `selspecdlg0` `ResultList` \&lt;br /&gt;-1&lt;br /&gt;!!&lt;br /&gt;!! Hit &#39;Close&#39; in Search dialog (even though it says &#39;CancelButton&#39;)&lt;br /&gt;!!&lt;br /&gt;~ Activate `selspecdlg0` `CancelButton`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Both the Model Tree and Search Tool are useful when used in trail files. Use of the Model Tree is more limited because it requires knowledge of its contents before the trail file is generated. The Search Tool, when used properly, provides one of the most robust methods of performing selecting with trail files. With minor editing, trail files utilizing the Search Tool can be generated quickly, easily and can be applied to a wide range of models.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Next time:&lt;/strong&gt; &lt;em&gt;Mapkeys and Trail Files&lt;/em&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/08/proe-anatomy-of-trail-file-part-3.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-4316124624304231134</guid><pubDate>Wed, 02 Jul 2008 10:54:00 +0000</pubDate><atom:updated>2008-07-07T16:09:56.418-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Javascript</category><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">WebLink</category><title>Pro/WebLink: Tips On Getting Started</title><description>Pro/WebLink is one of the free PFC based API&#39;s available for automating Pro/Engineer. Although the documentation and marketing literature is focused on using Javascript with Pro/WebLink, &lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/04/weblink-what-is-it-anyway.html&quot;&gt;VBScript&lt;/a&gt; can be used if that is more to your taste.&lt;br /&gt;&lt;br /&gt;Developers interested in writing Pro/WebLink application have to overcome a number of hurdles. Most of these are related to the Internet Explorer and Mozilla security models, because Pro/WebLink applications typically must run within the context of the Pro/Engineer embedded web browser. This differs from the &lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/06/proe-visual-basic-api-first-look.html&quot;&gt;VB API&lt;/a&gt; (new with Wildfire 4.0), which runs outside of the Pro/Engineer process and has far fewer security issues to worry about.&lt;br /&gt;&lt;br /&gt;While security is not the only problem facing Pro/WebLink developers, it is the most common problem in my experience. In this article I&#39;ll discuss the necessary steps in setting up your environment to run Pro/WebLink applications.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Pro/ENGINEER Configuration&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Use of Pro/WebLink requires that the config.pro option WEB_ENABLE_JAVASCRIPT be set to ON (the default is OFF). In Windows, if this option is set to ON when Pro/ENGINEER is started, pfcscom.dll will be registered as a COM server. This contains all of the Pro/WebLink functionality.&lt;br /&gt;&lt;br /&gt;Generally this works very well, but I have seen problems where the DLL doesn&#39;t get registered, or some other similar problem occurs preventing the Pro/WebLink application from functioning. The workaround is to run the application as an administrative user first, then the program works for everyone. Fortunately, I have only seen one user affected like this, otherwise the workaround would get really annoying.&lt;br /&gt;&lt;br /&gt;None of that is relevant in Unix, as the required XPCOM technology is already present in the embedded Mozilla browser. However, I have seen rare instances where the Mozilla profile in the user&#39;s unix home directory has become corrupted. The resolution is to delete the profile. Pro/Engineer will recreate it upon startup.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;HTML SCRIPT Tag&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;When setting up your Pro/WebLink programs, you are likely to include one or more files containing your Javascript code. A common one to use, although it is not absolutely necessary, is the PTC supplied pfcUtils.js file. If you are going to use such functions as pfcCreate() and pfcGetProESession(), you need to make sure you include pfcUtils.js correctly to avoid confusing errors, such as &quot;Object Expected&quot;.&lt;br /&gt;&lt;br /&gt;You also need to ensure that the SCRIPT tag entry in your HTML code correctly locates the pfcUtils.js file. For example, this entry will find the bom2excel.js file if it is placed in the same folder as the HTML file, and the pfcUtils.js file if it is in the parent folder:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;&amp;lt;SCRIPT LANGUAGE=&quot;JavaScript&quot; type=text/javascript src=&quot;../pfcUtils.js&quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&lt;br /&gt;&amp;lt;SCRIPT LANGUAGE=&quot;JavaScript&quot; type=text/javascript src=&quot;bom2excel.js&quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Your web browser may not complain in an obvious way if it cannot find one of your Javascript programs, making the resulting errors hard to diagnose. If using a web server, make sure that the web server process has sufficient permissions to read the HTML and JS files, otherwise you&#39;ll wind up with the same problems, but it will that much harder to diagnose.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Web Browser Security Models&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Overcoming the security requirements of Wildfire&#39;s various supported web browsers is often frustrating because the requirements are not inherently obvious and the documentation can be hard to find. With Wildfire 4.0, Mozilla is the supported browser on Unix platforms and Internet Explorer is the browser for Windows. Both have different mechanisms and rules concerning security.&lt;br /&gt;&lt;br /&gt;Using digitally signed applications allow the developer to bypass some security roadblocks by requesting enhanced functionality based on the user&#39;s &quot;trust&quot; of the developer. Digital signatures are far beyond the scope of this article however.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Internet Explorer Security&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Internet Explorer security is based on zones: Internet, Local intranet, Trusted sites, and Restricted sites. Each zone has it own security settings enabling or disabling certain functionalities. Using the &quot;Custom Level&quot; button, each option can be enabled or disabled selectively. If you change any of the security options, you may need to restart Pro/Engineer for the changes to take effect in the embedded web browser.&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj478Dk3ND-C9SvHGPBNKmy9Ppf-yeqtcAH_3tLn7zsbOEJl0qDJaV3hZ6Ly1n0fn5Rbpvvb7iQlH1ETN8SpWVjzSuvlt_27W2VxgDanc0GwBs4Pe9J_euf33-DnkZLmUMz0KRie-lwx1B6/s1600-h/weblink-getting_started-1.bmp&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj478Dk3ND-C9SvHGPBNKmy9Ppf-yeqtcAH_3tLn7zsbOEJl0qDJaV3hZ6Ly1n0fn5Rbpvvb7iQlH1ETN8SpWVjzSuvlt_27W2VxgDanc0GwBs4Pe9J_euf33-DnkZLmUMz0KRie-lwx1B6/s400/weblink-getting_started-1.bmp&quot; border=&quot;0&quot; alt=&quot;&quot;id=&quot;BLOGGER_PHOTO_ID_5218373316372314930&quot; /&gt;&lt;/a&gt;&lt;br /&gt;It is recommended that you do not reduce security for the Internet zone. It would be better to add the web site to the Trusted sites zone, then adjust the security for that zone.&lt;br /&gt;&lt;br /&gt;Internet Explorer will decide to which zone your application applies depending on how you access it. If you access your program from a web server using a fully qualified domain name (i.e. www.yahoo.com) for a site that is not in your Trusted sites list, Internet Explorer will consider it part of the Internet zone. Using an internal web server (i.e. without top level domain: .com, .org, .co.uk, etc) or accessing the program from your hard drive or a network hard drive, will cause Internet Explorer to use the Local intranet zone. Not surprisingly, the Trusted sites zone will apply to a site that is in the Trusted sites list, even if it is an internal web server.&lt;br /&gt;&lt;br /&gt;Pro/WebLink applications need a couple of settings defined for the zone that will be used by your application. Some of these may already be the default for you. As PTC recommends in the documentation, the option &quot;Initialize and script ActiveX controls not marked safe for scripting&quot; should be set to &quot;Prompt&quot;. If you are interacting with Excel from Pro/WebLink, this option may need to be set to &quot;Enable&quot;.&lt;br /&gt;&lt;p&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0SaMld79O0E6oILFgum_0GKUZdncn73_dXVnjmJJZ6-JxmuqryZ0bqZq7gkXnwo-klt0gliIqFRNzFu67o7Sdyn1aE-DTlO_-jKRyD1HtSAWgR-ZV-hTVoXkRyLhPSQzbEOvSNIIsekCy/s1600-h/weblink-getting_started-2final.bmp&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5218370330556771554&quot; style=&quot;DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0SaMld79O0E6oILFgum_0GKUZdncn73_dXVnjmJJZ6-JxmuqryZ0bqZq7gkXnwo-klt0gliIqFRNzFu67o7Sdyn1aE-DTlO_-jKRyD1HtSAWgR-ZV-hTVoXkRyLhPSQzbEOvSNIIsekCy/s400/weblink-getting_started-2final.bmp&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;Ensure that the option &quot;Active Scripting&quot; is set to &quot;Enable&quot;.&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi__-lipw79jrYZvJl4hu3rrDoc0z33ndr4UU5HUfwuL0sfuG6QfKPeVKTeocciSz4c7VXQQrTENhVX4GqMcIKhyplB93SO_ykexAHF_2ko6miGkWsmThuB7mVnBVc1XpasCaZcn4sIsK4g/s1600-h/weblink-getting_started-3final.bmp&quot;&gt;&lt;img id=&quot;BLOGGER_PHOTO_ID_5218370583047301266&quot; style=&quot;DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi__-lipw79jrYZvJl4hu3rrDoc0z33ndr4UU5HUfwuL0sfuG6QfKPeVKTeocciSz4c7VXQQrTENhVX4GqMcIKhyplB93SO_ykexAHF_2ko6miGkWsmThuB7mVnBVc1XpasCaZcn4sIsK4g/s400/weblink-getting_started-3final.bmp&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;strong&gt;Mozilla Security&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Mozilla has some good security functionality in which a script can request enhanced functionality allowing the user to accept or deny the request. That&#39;s why you see some UniversalXPConnect requests in Pro/WebLink examples. The code has to ask for enhanced privileges to connect to Pro/Engineer and do something useful.&lt;br /&gt;&lt;br /&gt;When the Pro/WebLink application is served from a web server, the code and HTML must be digitally signed (together) for this request process to work. To make matters worse, a very unusual jar:http: URL must be used to interact with the resulting JAR file that contains the code and HTML.&lt;br /&gt;&lt;br /&gt;A workaround is not to use a web server, but instead access the code and HTML from the file system using a file: type URL. For Pro/WebLink applications, the user is generally prompted only once for enhanced privileges, then is good to from then on.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Review&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Keeping some of these issues in mind will help you get up and running with Pro/WebLink avoiding many of the pitfalls and frustrations.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Set WEB_ENABLE_JAVASCRIPT to ON in your config.pro file&lt;/li&gt;&lt;li&gt;Ensure that HTML and JS files are located correctly&lt;/li&gt;&lt;li&gt;Make sure that the web browser security requirements are satisfied&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/07/proe-weblink-getting-started-tips.html</link><author>noreply@blogger.com (Marc Mettes)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj478Dk3ND-C9SvHGPBNKmy9Ppf-yeqtcAH_3tLn7zsbOEJl0qDJaV3hZ6Ly1n0fn5Rbpvvb7iQlH1ETN8SpWVjzSuvlt_27W2VxgDanc0GwBs4Pe9J_euf33-DnkZLmUMz0KRie-lwx1B6/s72-c/weblink-getting_started-1.bmp" height="72" width="72"/><thr:total>5</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-4207765361364321931</guid><pubDate>Wed, 18 Jun 2008 10:22:00 +0000</pubDate><atom:updated>2008-06-18T03:40:34.217-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Excel</category><category domain="http://www.blogger.com/atom/ns#">Javascript</category><category domain="http://www.blogger.com/atom/ns#">Perl</category><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">VB API</category><category domain="http://www.blogger.com/atom/ns#">VBScript</category><category domain="http://www.blogger.com/atom/ns#">Visual Basic</category><category domain="http://www.blogger.com/atom/ns#">WebLink</category><title>Pro/E VB API: Not Just for Visual Basic Anymore</title><description>In a previous article entitled &quot;&lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/04/weblink-what-is-it-anyway.html&quot;&gt;WebLink: What is it anyway&lt;/a&gt;?&quot;, I discussed Pro/WebLink and how it&#39;s not exactly a Javascript interface.  Now it&#39;s the VB API&#39;s turn.  The VB API is newly released by PTC with Wildfire 4.  It is billed as a Visual Basic interface to PTC&#39;s PFC libraries, which is the same core that J-Link and Pro/WebLink are built upon.  &lt;br /&gt;&lt;br /&gt;While this is true, it&#39;s not that limited.  Don&#39;t let the name scare you away from using your favorite COM accessible programming or scripting language to write Pro/Engineer applications.  This is a good thing because it opens the API to a much wider range of applications.&lt;br /&gt;&lt;br /&gt;In this article, I&#39;ll walk through sample applications written in Visual Basic, VBScript (using Windows Script Host), Perl, and Javascript (in a HyperText Application), all using the VB API.  The sample application will connect to a Pro/Engineer session, obtain the session object, display the name of the current model, then disconnect from the Pro/Engineer session.  Each program will display the model name in a different way.&lt;br /&gt;&lt;br /&gt;Suggested reading is the section on the importance of disconnecting from Pro/Engineer in &lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/06/proe-visual-basic-api-first-look.html&quot;&gt;Pro/E VB API: A First Look&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Excel Macro&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is the standard and documented approach to the sample program.  Objects are declared up front, the connection to Pro/Engineer is made, then the session object is obtained.  The model name is displayed both in cell A1 and in a MsgBox.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;Sub Macro1()&lt;br /&gt;&lt;br /&gt;Dim asynconn As New pfcls.CCpfcAsyncConnection&lt;br /&gt;Dim conn As pfcls.IpfcAsyncConnection&lt;br /&gt;Dim session As pfcls.IpfcBaseSession&lt;br /&gt;Dim mdlname&lt;br /&gt;&lt;br /&gt;Set conn = asynconn.Connect(&amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;.&amp;quot;, 5)&lt;br /&gt;Set session = conn.session&lt;br /&gt;&lt;br /&gt;mdlname = session.CurrentModel.Filename&lt;br /&gt;Range(&amp;quot;A1&amp;quot;).Select&lt;br /&gt;ActiveCell.FormulaR1C1 = mdlname&lt;br /&gt;MsgBox (&amp;quot;Name: &amp;quot; &amp;amp; mdlname)&lt;br /&gt;conn.Disconnect(2)&lt;br /&gt;&lt;br /&gt;End Sub&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;VBScript&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The VBScript code is almost identical except that VBScript doesn&#39;t seem to allow for the type declaration of the objects.  As a result, the CreateObject() call is used to instantiate a pfcAsyncConnection object.&lt;br /&gt;&lt;br /&gt;The program is executed using the following command line:&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;  cscript vbapi_script.vbs&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;Dim asynconn&lt;br /&gt;Dim conn&lt;br /&gt;Dim session&lt;br /&gt;Dim mdlname&lt;br /&gt;&lt;br /&gt;Set asynconn = CreateObject(&amp;quot;pfcls.pfcAsyncConnection&amp;quot;)&lt;br /&gt;Set conn = asynconn.Connect(&amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;.&amp;quot;, 5)&lt;br /&gt;Set session = conn.session&lt;br /&gt;&lt;br /&gt;mdlname = session.CurrentModel.Filename&lt;br /&gt;MsgBox (&amp;quot;Name: &amp;quot; &amp;amp; mdlname)&lt;br /&gt;conn.Disconnect(2)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Perl&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;As with most COM applications, the Perl syntax is also very similar to the VBScript code, but with Perl&#39;s own syntactical flavor.  Win32::OLE-&gt;new() is the Perl equivalent to VBScript&#39;s CreateObject().  The Perl program outputs the model name to the command prompt (or standard output).&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;use Win32::OLE;&lt;br /&gt;$asynconn = Win32::OLE-&amp;gt;new(&amp;quot;pfcls.pfcAsyncConnection&amp;quot;);&lt;br /&gt;$conn = $asynconn-&amp;gt;Connect( &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;.&amp;quot;, 5 );&lt;br /&gt;$session = $conn-&amp;gt;Session;&lt;br /&gt;$mdlName = $session-&amp;gt;CurrentModel-&amp;gt;FileName;&lt;br /&gt;&lt;br /&gt;print &amp;quot;mdlName: $mdlName&amp;quot;, &amp;quot;\n&amp;quot;;&lt;br /&gt;$conn-&amp;gt;Disconnect(2);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Javascript&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Pro/WebLink applications can finally break out of the embedded browser jail using the VB API.  This example uses a &quot;Hypertext Application&quot;, which is a web page with a special HTA tag and with a file extension of &quot;.hta&quot; instead of &quot;.htm&quot;.  The pfcUtils.js file cannot be used as-is because it tries to use COM objects with &quot;pfc.&quot; prefixes, instead of those associated with VB API which have &quot;pfcls.&quot; prefixes.&lt;br /&gt;&lt;br /&gt;Other than those differences, it&#39;s essentially a Pro/WebLink application.  As with the other examples, because it&#39;s an asynchronous application, the code must connect to the Pro/Engineer session.  This is a step that embedded browser based Pro/WebLink applications don&#39;t have to worry about.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;title&amp;gt;VB API Test&amp;lt;/title&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;HTA:APPLICATION &lt;br /&gt;     ID=&amp;quot;vbapi-test&amp;quot;&lt;br /&gt;     APPLICATIONNAME=&amp;quot;VB API Test&amp;quot;&lt;br /&gt;     SCROLL=&amp;quot;auto&amp;quot;&lt;br /&gt;     SINGLEINSTANCE=&amp;quot;yes&amp;quot;&lt;br /&gt;&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;SCRIPT LANGUAGE=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;function HitMe ( ) {&lt;br /&gt;    var obj = null;&lt;br /&gt;    var elem = document.getElementById(&amp;quot;mesg&amp;quot;);&lt;br /&gt;&lt;br /&gt;    if (obj == null) {&lt;br /&gt;        try {&lt;br /&gt;            obj = new ActiveXObject(&amp;quot;pfcls.pfcAsyncConnection&amp;quot;);&lt;br /&gt;        }&lt;br /&gt;        catch (e) {&lt;br /&gt;            elem.innerHTML = &amp;quot;Failed to create object&amp;quot;;&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    var conn = obj.Connect( &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;.&amp;quot;, 5 );&lt;br /&gt;    var session = conn.Session;&lt;br /&gt;    var mdlName = session.CurrentModel.FileName;&lt;br /&gt;&lt;br /&gt;    elem.innerHTML = &amp;quot;mdlName: &amp;quot; + mdlName;&lt;br /&gt;    conn.Disconnect(2);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&amp;lt;/SCRIPT&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form name=&amp;quot;f&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;INPUT name=&amp;quot;a&amp;quot; type=button value=&amp;quot;Hit me!&amp;quot; onclick=&amp;quot;HitMe()&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;br&amp;gt;&amp;lt;a id=&amp;quot;mesg&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;These are just a few of the possibilities.  As you can see, there is nothing really Visual Basic specific about the VB API.  It&#39;s just an API.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/06/proe-vb-api-not-just-for-visual-basic.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>10</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-1863708611194258874</guid><pubDate>Tue, 17 Jun 2008 10:02:00 +0000</pubDate><atom:updated>2008-06-18T03:24:44.232-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Drawings</category><category domain="http://www.blogger.com/atom/ns#">Excel</category><category domain="http://www.blogger.com/atom/ns#">Javascript</category><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">WebLink</category><title>Pro/WebLink: Send Excel Data To Pro/ENGINEER Drawing Tables, and Back Again - Part 2</title><description>In &lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/06/weblink-excel-to-proe-drw-tables-part-1.html&quot;&gt;part 1&lt;/a&gt;, the transfering of data from Excel to Pro/ENGINEER drawing tables was discussed.  In this second part, the discussion will focus on the other direction, sending Pro/ENGINEER drawing table data to an Excel workbook.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;TableToExcel Function&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The TableToExcel() function is also pretty simple.  After resetting the status fields, it uses ArrayFromProETable() to obtain an array of data from a user selected drawing table, then uses ArrayToExcel() to populate a new Excel workbook with the data from the array.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function TableToExcel ( ) {&lt;br /&gt;&lt;br /&gt;    var mesg = document.getElementById(&amp;quot;mesg&amp;quot;);&lt;br /&gt;    var errmesg = document.getElementById(&amp;quot;errmesg&amp;quot;);&lt;br /&gt;    mesg.innerHTML = &amp;quot;&amp;quot;;&lt;br /&gt;    errmesg.innerHTML = &amp;quot;&amp;quot;;&lt;br /&gt;&lt;br /&gt;    var array = ArrayFromProETable();&lt;br /&gt;    if (array == null) {&lt;br /&gt;        mesg.innerHTML = &amp;quot;null array&amp;quot;;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (array != null) { ArrayToExcel(array); }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ArrayFromProETable Function&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The ArrayFromProETable() function gathers drawing table data into an array.  It&#39;s main steps are: Get the Pro/Engineer session object, obtaining the current model object and ensure a drawing is active, request a drawing table selection from the user, and iterate through the table cells to populate the array elements.  After the table is selected by the user, UnHighlight() is used to repaint the table with its normal colors.&lt;br /&gt;&lt;br /&gt;The table cell iteration code cycles first through the table rows, then the columns of each row, then through the lines of text in each cell.  When there is more than one line of text in a table cell, a linefeed character is added as a line separator.  This is correctly interpreted by Excel as multi-line data.&lt;br /&gt;&lt;br /&gt;It&#39;s important to note that while in Javascript (as in many programming languages) arrays are indexed starting with zero, both drawing tables and Excel cells are indexed starting with one.&lt;br /&gt;&lt;br /&gt;Once the iteration of the table cells has completed and the array has been populated, the array is returned.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function ArrayFromProETable ( ) {&lt;br /&gt;&lt;br /&gt;    var mesg = document.getElementById(&amp;quot;mesg&amp;quot;);&lt;br /&gt;    var errmesg = document.getElementById(&amp;quot;errmesg&amp;quot;);&lt;br /&gt;    var session = null;&lt;br /&gt;    var drawing = null;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Get ProE session object&lt;br /&gt;    //&lt;br /&gt;    try {&lt;br /&gt;        session = pfcGetProESession();&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        errmesg.innerHTML = &amp;quot;Unable to connect to Pro/Engineer&amp;quot;;&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Get model object and ensure it&#39;s a drawing&lt;br /&gt;    //&lt;br /&gt;    try {&lt;br /&gt;        drawing = session.CurrentModel;&lt;br /&gt;&lt;br /&gt;        if (drawing == null &amp;#124;&amp;#124; drawing.Type != pfcCreate(&amp;quot;pfcModelType&amp;quot;).MDL_DRAWING) {&lt;br /&gt;            errmesg.innerHTML = &amp;quot;A drawing must be active!&amp;quot;;&lt;br /&gt;            return null;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        errmesg.innerHTML = &amp;quot;A drawing must be active.&amp;quot;;&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Prompt user to select an existing table&lt;br /&gt;    //&lt;br /&gt;    var selections = null;&lt;br /&gt;    var table = null;&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;        selections = selectItems(&amp;quot;dwg_table&amp;quot;, 1);&lt;br /&gt;        var tabnum = selections.Item(0).SelItem;&lt;br /&gt;        table = drawing.GetTable(tabnum.Id);&lt;br /&gt;    }&lt;br /&gt;    catch (e) { // nothing selected&lt;br /&gt;        errmesg.innerHTML = &amp;quot;A drawing table was not selected.&amp;quot;;&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    selections.Item(0).UnHighlight();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    mesg.innerHTML = &amp;quot;Selected Table: &amp;quot; &lt;br /&gt;                     + table.GetRowCount() + &amp;quot; rows, &amp;quot; &lt;br /&gt;                     + table.GetColumnCount() + &amp;quot; columns&amp;quot;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Gather data from table and populate into array&lt;br /&gt;    //&lt;br /&gt;&lt;br /&gt;    var array = new Array();&lt;br /&gt;&lt;br /&gt;    for (var i=0; i&amp;lt;table.GetRowCount(); i++) {&lt;br /&gt;&lt;br /&gt;        array[i] = new Array();&lt;br /&gt;&lt;br /&gt;        for (var j=0; j&amp;lt;table.GetColumnCount(); j++) {&lt;br /&gt;&lt;br /&gt;            // Table cell indexes start with one, arrays with zero&lt;br /&gt;            var cell = pfcCreate(&amp;quot;pfcTableCell&amp;quot;).Create(i+1,j+1);&lt;br /&gt;            var mode = pfcCreate(&amp;quot;pfcParamMode&amp;quot;).DWGTABLE_NORMAL;&lt;br /&gt;            array[i][j] = &amp;quot;&amp;quot;;&lt;br /&gt;&lt;br /&gt;            try {&lt;br /&gt;                var textseq = table.GetText(cell, mode);&lt;br /&gt;&lt;br /&gt;                for (var k=0; k&amp;lt;textseq.Count; k++) {&lt;br /&gt;                    var textitem = textseq.Item(k);&lt;br /&gt;                    if (k &amp;gt; 0) { array[i][j] += &amp;quot;\n&amp;quot;; }&lt;br /&gt;                    array[i][j] += textitem;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            catch (e) { // cell has no value&lt;br /&gt;                // ignore&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return array;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ArrayToExcel Function&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The ArrayToExcel() function takes the two dimensional array and populates cells in a new Excel workbook.  There are only three steps in this function: Get the Excel session object, Create a new workbook and get the active sheet object, Populate cells of the active sheet from data in the array.&lt;br /&gt;&lt;br /&gt;As an alternative, a new Excel session could be started if an existing one can not be found.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function ArrayToExcel ( array ) {&lt;br /&gt;&lt;br /&gt;    var oXL;&lt;br /&gt;    var errmesg = document.getElementById(&amp;quot;errmesg&amp;quot;);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Try to access Excel and get Application object.&lt;br /&gt;    //&lt;br /&gt;    try {&lt;br /&gt;        oXL = GetObject(&amp;quot;&amp;quot;,&amp;quot;Excel.Application&amp;quot;);&lt;br /&gt;        if (oXL == null) {&lt;br /&gt;            errmesg.innerHTML = &amp;quot;Failed to get Excel session object.&amp;quot;;&lt;br /&gt;            return null;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        // oXL = new ActiveXObject(&amp;quot;Excel.Application&amp;quot;);&lt;br /&gt;        errmesg.innerHTML = &amp;quot;Excel must be running!&amp;quot;;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Make session visible, get Sheet object&lt;br /&gt;    //&lt;br /&gt;    try {&lt;br /&gt;        oXL.Visible = true;&lt;br /&gt;        var oWB = oXL.Workbooks.Add();&lt;br /&gt;        var oSheet = oWB.ActiveSheet;&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        errmesg.innerHTML = &amp;quot;Problem creating new workbook.&amp;quot;;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Put the array data into the cells of the active sheet&lt;br /&gt;    //&lt;br /&gt;    for (var i=0; i &amp;lt; array.length; i++ ) {&lt;br /&gt;        for (var j=0; j &amp;lt; array[i].length; j++ ) {&lt;br /&gt;            // Excel cell indexes start with one, arrays with zero&lt;br /&gt;            oSheet.Cells(i+1, j+1).Value = array[i][j];&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;selectItems Function&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The selectItems() function is largely based on selectItems() from an example in the Pro/WebLink documentation.  It is changed here to be slightly more generic.  The function builds a pfcSelectionOptions object that defines the type and number of allowable items that can be selected.  It also minimizes the browser window during the selection process.&lt;br /&gt;&lt;br /&gt;A sequence of selections (or null if nothing was selected) is returned.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function selectItems ( options, max ) {&lt;br /&gt;&lt;br /&gt;    // Setup options object&lt;br /&gt;    selOptions = pfcCreate(&amp;quot;pfcSelectionOptions&amp;quot;).Create(options);&lt;br /&gt;    selOptions.MaxNumSels = parseInt(max);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    var session = pfcGetProESession();&lt;br /&gt;    var browserSize = session.CurrentWindow.GetBrowserSize();&lt;br /&gt;    session.CurrentWindow.SetBrowserSize(0.0);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    var selections = null;&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;        selections = session.Select(selOptions, null);&lt;br /&gt;        session.CurrentWindow.SetBrowserSize(browserSize);&lt;br /&gt;    }&lt;br /&gt;    catch (err) {&lt;br /&gt;        session.CurrentWindow.SetBrowserSize(browserSize);&lt;br /&gt;        // In case user didn&#39;t select expected item&lt;br /&gt;        var errstr = pfcGetExceptionType(err);&lt;br /&gt;        if (errstr == &amp;quot;pfcXToolkitUserAbort&amp;quot; &amp;#124;&amp;#124; errstr == &amp;quot;pfcXToolkitPickAbove&amp;quot;) {&lt;br /&gt;            return null;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (selections == null &amp;#124;&amp;#124; selections.Count == 0)&lt;br /&gt;        return null;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    return selections;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As I&#39;ve mentioned, interaction with Excel is easy and straightforward.  Although the Pro/Engineer interaction code is much more complex, the PFC API&#39;s contain a rich set a classes and methods making automation, such as I have shown here, possible.  It&#39;s a quantum leap beyond relying upon mapkeys.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/06/weblink-excel-to-proe-drw-tables-part-2.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-1560491165341535396</guid><pubDate>Thu, 12 Jun 2008 01:57:00 +0000</pubDate><atom:updated>2008-06-11T19:06:03.542-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Intralink</category><category domain="http://www.blogger.com/atom/ns#">Intralink Oracle SQL</category><title>Intralink SQL: Searching Based on Attribute Values</title><description>Searching based on attribute values can be performed using Oracle SQL, but a little investigation work needs to be done beforehand.&lt;br /&gt;&lt;br /&gt;Attributes and their characteristics are contained in the pdm.PDM_CLASSATTR table in the Oracle database. The first step that needs to be done is to identify the &#39;id&#39; number of the attribute.&lt;br /&gt;&lt;br /&gt;The following query shows, for the &quot;file based&quot; attributes, the &#39;id&#39;, the name, and the &#39;type&#39;. Also included is the CLADEFVALU column which would show any default values for the attributes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;-- show file based attributes&lt;br /&gt;--&lt;br /&gt;select CLAID,CLANAME,CLADEFVALUE,CLATYPE&lt;br /&gt;from pdm.PDM_CLASSATTR&lt;br /&gt;where CLAUSERDEF=1 and CLAFILEBASED=1&lt;br /&gt;order by CLANAME;&lt;br /&gt;&lt;br /&gt;     CLAID CLANAME              CLADEFVALU    CLATYPE&lt;br /&gt;---------- -------------------- ---------- ----------&lt;br /&gt;       123 Desc                                     5&lt;br /&gt;       234 Matl                                     5&lt;br /&gt;       345 Mc_Config                                5&lt;br /&gt;       456 Mc_Errors                                2&lt;br /&gt;       567 Mc_Mode                                  5&lt;br /&gt;       678 Model_Check                              5&lt;br /&gt;       789 Weight                                   3&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The CLATYPE numbers correspond to these data types:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;2: Integer&lt;/li&gt;&lt;li&gt;3: Real&lt;/li&gt;&lt;li&gt;4: Boolean&lt;/li&gt;&lt;li&gt;5: String&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;If the &#39;Desc&#39; attribute is needed, we take the CLAID value and prepend &quot;UDA&quot; to form the column name in the pdm.PDM_PRODUCTITEM_VUDA1 table. In this example, the Desc attribute corresponds to the &quot;UDA123&quot; column.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Putting this into an example, the following query searches for Intralink PIV&#39;s with the Desc attribute matching &quot;...some string...&quot;.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;-- search based on attribute values &lt;br /&gt;-- &lt;br /&gt;column piname format a35 &lt;br /&gt;column UDA123 format a40 &lt;br /&gt;column REVVER format a7 &lt;br /&gt;&lt;br /&gt;SELECT &lt;br /&gt;piv.pivid, PINAME, PIVREV&#39;.&#39;PIVVER as REVVER, UDA123 &lt;br /&gt;FROM &lt;br /&gt;PDM.PDM_PRODUCTITEM pi, &lt;br /&gt;PDM.PDM_BRANCH br, &lt;br /&gt;PDM.PDM_PRODUCTITEMVERSION piv, &lt;br /&gt;pdm.PDM_PRODUCTITEM_VUDA1 vuda &lt;br /&gt;WHERE &lt;br /&gt;pi.PIID = br.PIID &lt;br /&gt;AND br.BRID = piv.BRID &lt;br /&gt;AND piv.pivid = vuda.pivid &lt;br /&gt;AND UDA123 like &#39;%some string%&#39; &lt;br /&gt;;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For an exact match, use this as the last condition in the &quot;WHERE&quot; clause instead:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;AND UDA123 = &#39;some string&#39;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/06/intralink-sql-search-attribute-values.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-116524552077282703</guid><pubDate>Thu, 12 Jun 2008 01:07:00 +0000</pubDate><atom:updated>2008-06-11T18:19:27.604-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">VB API</category><category domain="http://www.blogger.com/atom/ns#">Visual Basic</category><title>Pro/E VB API: A First Look</title><description>&lt;strong&gt;A peek under the hood of the new API for Wildfire 4&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;In case you didn&#39;t know about it, PTC introduced a new PFC based API for Pro/Engineer, starting with Wildfire 4.  It&#39;s called the VB API and it allows code to be written in Visual Basic that can communicate with Pro/Engineer.  (For the curious, it does not work with older versions of Pro/Engineer, sorry)&lt;br /&gt;&lt;br /&gt;Unlike Pro/WebLink, it is not limited to running in the embedded web browser.  Applications written with the VB API can be run almost anywhere that supports a Visual Basic environment (i.e. in an Excel macro).  It&#39;s important to understand how this new API works in order to understand some of its limitations and to write robust applications.&lt;br /&gt;&lt;br /&gt;The API is an asynchronous PFC API, which means that it shares a set of core classes and methods which are mostly identical to Pro/WebLink and J-Link.  It is asynchronous in that VB API applications run outside of the Pro/Engineer process (i.e. in Excel, Word, etc), but still can communicate and control the Pro/Engineer session.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;EXE COM Server?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Similar to Pro/WebLink, it is implemented as a COM server, but (interestingly) not as a DLL.  While a VB API application is running, an executable called &quot;pfclscom.exe&quot; starts and runs in the background.  This introduces a major limitation.&lt;br /&gt;&lt;br /&gt;Only one VB API program can run at a time, even if there are multiple Pro/Engineer sessions.  If a second VB API application tries to start, it won&#39;t be able to connect to any Pro/Engineer session if the first one is still connected.  As long as the first application has disconnected, the second connection will be successful.&lt;br /&gt;&lt;br /&gt;This is a little disappointing, because one can have several asynchronous Pro/Toolkit applications connected to a single Pro/Engineer process at the same time.  In fact, there could be any number of Pro/Toolkit applications connecting to any number of Pro/Engineer sessions.  There is really no underlying technical restriction causing this limitation.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;You had me at goodbye&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Those familiar with asynchronous Pro/Toolkit and J-Link applications probably already know that the main steps in an asynchronous application are: 1) Connect to the Pro/Engineer session, 2) Do some stuff, 3) Disconnect.  While step 2 is somewhat optional, step 3 is absolutely critical.&lt;br /&gt;&lt;br /&gt;The primary reason is that Pro/Engineer keeps track of all asynchronous connections, and considers connections that have not disconnected as &quot;open&quot;.  Unfortunately, there is a limit to the number of &quot;open&quot; connections, and that limit is surpisingly low.&lt;br /&gt;&lt;br /&gt;If you have an asynchronous application that connects over and over with no disconnect, Pro/Engineer will eventually refuse any further connections.  It doesn&#39;t matter if it&#39;s a Pro/Toolkit, J-Link, or VB API application.  The limit is around 58-60 connections.  That might sound a little high, but if you run VB API programs from an Excel macro over and over again, you might hit that limit pretty quick.  If you disconnect properly, there should be no limit to the number of times you can connect to a Pro/Engineer session.&lt;br /&gt;&lt;br /&gt;You&#39;d think that with disconnecting being so important for asynchronous applications, it would deserve some special mention in the documentation.  Well, you&#39;d be wrong.  Sure, the Disconnect() method is mentioned along with the various flavors of the Connect() method, but there is no mention of the importance of disconnecting.  You have been warned.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;It it weren&#39;t broke, they wouldn&#39;t have fixed it&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;All is not perfect in Pro/Engineer VB land however.  Don&#39;t waste your time with the C000 build of Wildfire 4.  The COM server that comes with the install won&#39;t allow any connections.&lt;br /&gt;&lt;br /&gt;Another more minor issue has to do with &quot;text message&quot; files that nearly all Pro/Engineer API&#39;s use.  The &quot;text&quot; directory containing these files would normally be defined in a protk.dat file.  This is not used for asynchronous applications.  Instead, it is specified as part of the connection process.  All of the Connect() methods have an argument that is supposed to identify the &quot;text&quot; directory.&lt;br /&gt;&lt;br /&gt;For some reason, this argument is ignored by the VB API.  As a result, only files in subdirectories of the Pro/Engineer install can be used (Proe/text/usascii if your language is english).  It&#39;s not a major problem, but definitely an inconvenience if distributing your code to other users and/or companies.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&quot;Happiness equals reality minus expectations&quot; -Tom Magliozzi&lt;/strong&gt;&lt;br /&gt; &lt;br /&gt;Although I question the choice of an EXE based COM server, on the whole, PTC did a great job making the VB API fully functional and very consistent with its sibling API&#39;s (Pro/WebLink and J-Link).  While I find that Visual Basic has a kludgey syntax and a somewhat broken object model, the API itself gets the job done.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/06/proe-visual-basic-api-first-look.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>8</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-2139959116249060871</guid><pubDate>Mon, 09 Jun 2008 09:52:00 +0000</pubDate><atom:updated>2008-06-18T03:24:44.233-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Drawings</category><category domain="http://www.blogger.com/atom/ns#">Excel</category><category domain="http://www.blogger.com/atom/ns#">Javascript</category><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">WebLink</category><title>Pro/WebLink: Send Excel Data To Pro/ENGINEER Drawing Tables and Back Again - Part 1</title><description>In previous articles (&lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/04/proweblink-sending-your-proengineer.html&quot;&gt;BOM Data to Excel&lt;/a&gt;, &lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/04/weblink-send-proe-pnt-data-to-excel.html&quot;&gt;Point Data to Excel&lt;/a&gt;), I&#39;ve discussed the transfer of data from Pro/ENGINEER to Excel.  Of course, transfering the data in the other direction, from Excel to Pro/Engineer, is not only possible, but it&#39;s just as easy.&lt;br /&gt;&lt;br /&gt;In this two part article series, I will be discussing how to take data from a selected range in Excel and transfer that into a new table in a Pro/ENGINEER drawing, and vice versa.  Part 1 concerns the Excel to Pro/Engineer transfer, and part 2 concerns the Pro/Engineer to Excel transfer.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;HTML Page&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The HTML page for this application is very simple: two javascript files, two buttons, and two status fields.  pfcUtils.js is provided by PTC (see my &lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/03/optimizing-weblink-better-pfccreate.html&quot;&gt;pfcCreate optimization&lt;/a&gt; article).&lt;br /&gt;&lt;br /&gt;All remaining code from this article is in the excel2table.js file.  One of the buttons allows transfer from Excel to ProEngineer using the ExcelToTable() function, while the other allows transfer in the other direction using the TableToExcel() function.  The two div fields allow for the display of error and general status information.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;&amp;lt;HTML&amp;gt;&lt;br /&gt;&amp;lt;SCRIPT LANGUAGE=&amp;quot;JavaScript&amp;quot; type=text/javascript src=&amp;quot;pfcUtils.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&lt;br /&gt;&amp;lt;SCRIPT LANGUAGE=&amp;quot;JavaScript&amp;quot; type=text/javascript src=&amp;quot;excel2table.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&lt;br /&gt;&amp;lt;BODY&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;form name=&amp;quot;f&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;table border=1&amp;gt;&lt;br /&gt;      &amp;lt;tr&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;Excel&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&lt;br /&gt;          &amp;lt;INPUT name=&amp;quot;button1&amp;quot; type=button value=&amp;quot;&amp;gt;&amp;gt;&amp;quot; onclick=&amp;quot;ExcelToTable()&amp;quot;&amp;gt;&lt;br /&gt;          &amp;lt;br&amp;gt;&lt;br /&gt;          &amp;lt;INPUT name=&amp;quot;button2&amp;quot; type=button value=&amp;quot;&amp;lt;&amp;lt;&amp;quot; onclick=&amp;quot;TableToExcel()&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;Drawing Table&amp;lt;/td&amp;gt;&lt;br /&gt;      &amp;lt;/tr&amp;gt;&lt;br /&gt;    &amp;lt;/table&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;br&amp;gt;&amp;lt;font color=&#39;red&#39;&amp;gt;&amp;lt;a id=&amp;quot;errmesg&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;    &amp;lt;br&amp;gt;&amp;lt;a id=&amp;quot;mesg&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;  &amp;lt;/form&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/BODY&amp;gt;&lt;br /&gt;&amp;lt;/HTML&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ExcelToTable Function&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The core of ExcelToTable() is pretty basic.  Other than resetting the status fields, it uses ArrayFromExcel() to obtain an array of Excel data and ArrayToProETable() to create a drawing table from the array.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function ExcelToTable ( ) {&lt;br /&gt;    var mesg = document.getElementById(&amp;quot;mesg&amp;quot;);&lt;br /&gt;    var errmesg = document.getElementById(&amp;quot;errmesg&amp;quot;);&lt;br /&gt;    mesg.innerHTML = &amp;quot;&amp;quot;;&lt;br /&gt;    errmesg.innerHTML = &amp;quot;&amp;quot;;&lt;br /&gt;&lt;br /&gt;    var array = ArrayFromExcel();&lt;br /&gt;&lt;br /&gt;    if (array == null) {&lt;br /&gt;        mesg.innerHTML = &amp;quot;null array&amp;quot;;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (array != null) { ArrayToProETable(array); }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ArrayFromExcel Function&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The ArrayFromExcel() function has three main tasks: get the Excel session object using GetObject(), get the current range selection object, then loop through the rows and columns of the selection and extract the cell values.&lt;br /&gt;&lt;br /&gt;Looping through the selection is done using Enumerator objects, one for rows and one for columns.  The rows Enumerator is created using the &#39;rows&#39; property of the selection object, then a for loop is used to iterate over the rows.  For each row, a columns Enumerator is created using the &#39;columns&#39; property, which references the selected columns of the row.  The second for loop iterates over those columns, which in this case are cells.&lt;br /&gt;&lt;br /&gt;The Enumerator has an item() method which is used to obtain the row object from the row Enumerator and the cell object from the column Enumerator.  The &#39;value&#39; property returns the cell value, which would usually be of type &#39;Number&#39; or &#39;String&#39;.  Regardless of the type, the value is coerced into a String for ease of processing later.  Pro/ENGINEER treats all table cell values as strings anyway, so it doesn&#39;t really matter too much what the type is.&lt;br /&gt;&lt;br /&gt;The array used is two dimensional, populated in the iteration of the selection.  A two dimensional array is created by first constructing an Array object, then populating it with array objects.  The elements of the internal arrays contain the cell values.  In the iteration, as a new row is processed, a new Array object is created and then assigned to the top level array.  In Javascript, elements can be added to an Array object by a simple assignment statement, almost endlessly.&lt;br /&gt;&lt;br /&gt;Once the iteration of the selection via Enumerator&#39;s has completed and the array has been populated, the array is returned.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function ArrayFromExcel ( ) {&lt;br /&gt;&lt;br /&gt;    var oXL = null;&lt;br /&gt;    var mesg = document.getElementById(&amp;quot;mesg&amp;quot;);&lt;br /&gt;    var errmesg = document.getElementById(&amp;quot;errmesg&amp;quot;);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Try to access Excel and get Application object.&lt;br /&gt;    //&lt;br /&gt;    try {&lt;br /&gt;        oXL = GetObject(&amp;quot;&amp;quot;,&amp;quot;Excel.Application&amp;quot;);&lt;br /&gt;        if (oXL == null) {&lt;br /&gt;            errmesg.innerHTML = &amp;quot;Failed to get Excel session object.&amp;quot;;&lt;br /&gt;            return null;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        errmesg.innerHTML = &amp;quot;Excel must be running!&amp;quot;;&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Get Selection object&lt;br /&gt;    var sel = null;&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;        sel = oXL.ActiveWindow.Selection;&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        errmesg.innerHTML = &amp;quot;Could not get Selection object.&amp;quot;;&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (sel.columns.count &amp;lt;= 1 &amp;amp;&amp;amp; sel.rows.count &amp;lt;= 1) {&lt;br /&gt;        errmesg.innerHTML = &amp;quot;A range of cells must be selected in Excel.&amp;quot;;&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    mesg.innerHTML = &amp;quot;Selection: &amp;quot; + sel.rows.count + &amp;quot; rows, &amp;quot; + sel.columns.count + &amp;quot; columns&amp;quot;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    var i_row = 0;&lt;br /&gt;    var e_rows = new Enumerator(sel.rows);&lt;br /&gt;    var array = new Array();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Loop through each row of the selection&lt;br /&gt;    //&lt;br /&gt;    for ( ; !e_rows.atEnd(); e_rows.moveNext() ) {&lt;br /&gt;&lt;br /&gt;        var i_col = 0;&lt;br /&gt;        var row = e_rows.item();&lt;br /&gt;        var e_cols = new Enumerator(row.columns);&lt;br /&gt;&lt;br /&gt;        array[i_row] = new Array();&lt;br /&gt;&lt;br /&gt;        // Within the row, loop through each column&lt;br /&gt;        //&lt;br /&gt;        for ( ; !e_cols.atEnd(); e_cols.moveNext() ) {&lt;br /&gt;&lt;br /&gt;            var cell = e_cols.item();&lt;br /&gt;            var val = cell.value;&lt;br /&gt;&lt;br /&gt;            if (val == null) { val = &amp;quot;-&amp;quot;; }&lt;br /&gt;            array[i_row][i_col] = &amp;quot;&amp;quot; + val;&lt;br /&gt;            i_col++;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        i_row++;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return array;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ArrayToProETable Function&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The ArrayToProETable() function takes an array and creates a drawing table.  Its main steps are: get the ProE session object, prompt the user for the table location, create the table creation instructions object, create the row and column specification objects, create the table, add content to the table cells, and display the table.  As you can see, the ProE portion is quite a bit more complicated than the Excel part.&lt;br /&gt;&lt;br /&gt;Included in the function, part of the row and column specs, are calculations to auto-size the rows and columns to fit the data in Excel.  This is primarily for readability of the resulting table making it optional, but very helpful.&lt;br /&gt;&lt;br /&gt;Also included is a workaround for a table creation bug that limits the size of a table to no more than 50 rows and/or no more than 50 columns.  This is a bug in all Pro/Engineer API&#39;s, even Pro/Toolkit and J-Link.  It doesn&#39;t mean that a huge table can&#39;t be created, just that it can&#39;t be created in one shot.&lt;br /&gt;&lt;br /&gt;The workaround in the function is to create the table with a single row or column then add more rows or columns as necessary to get the table to the requested size.  With the adjustment step (adding rows and/or columns) coming after the table creation step, but before the table display step, the time required by the workaround is hardly noticable, except with huge tables.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function ArrayToProETable ( array ) {&lt;br /&gt;&lt;br /&gt;    var errmesg = document.getElementById(&amp;quot;errmesg&amp;quot;);&lt;br /&gt;    var session = null;&lt;br /&gt;    var drawing = null;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Get ProE session object&lt;br /&gt;    //&lt;br /&gt;    try {&lt;br /&gt;        session = pfcGetProESession();&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        errmesg.innerHTML = &amp;quot;Unable to connect to Pro/Engineer&amp;quot;;&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Get model object and ensure it&#39;s a drawing&lt;br /&gt;    //&lt;br /&gt;    try {&lt;br /&gt;        drawing = session.CurrentModel;&lt;br /&gt;&lt;br /&gt;        if (drawing == null &amp;#124;&amp;#124; drawing.Type != pfcCreate(&amp;quot;pfcModelType&amp;quot;).MDL_DRAWING) {&lt;br /&gt;            errmesg.innerHTML = &amp;quot;A drawing must be active!&amp;quot;;&lt;br /&gt;            return null;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        errmesg.innerHTML = &amp;quot;A drawing must be active.&amp;quot;;&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Get location for new table by mouse click&lt;br /&gt;    //&lt;br /&gt;    var location = getMousePickPosition(&amp;quot;Select location for table&amp;quot;, true);&lt;br /&gt;    if (location == null) { return null; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Setup the table creation instructions object&lt;br /&gt;    //&lt;br /&gt;    var instrs = new pfcCreate(&amp;quot;pfcTableCreateInstructions&amp;quot;).Create(location);&lt;br /&gt;    instrs.SizeType = pfcCreate(&amp;quot;pfcTableSizeType&amp;quot;).TABLESIZE_BY_NUM_CHARS;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Figure out max sizes to auto-expand the table&lt;br /&gt;    var ArrayMaxData = getArrayMaxData(array);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Generate column data (for table creation instructions object)&lt;br /&gt;    //   API Bug: Can&#39;t create table with more than 50 columns&lt;br /&gt;    //   Workaround: Create with one column, add more later&lt;br /&gt;    //&lt;br /&gt;&lt;br /&gt;    var column_just = pfcCreate(&amp;quot;pfcColumnJustification&amp;quot;).COL_JUSTIFY_LEFT;&lt;br /&gt;    var columnData = pfcCreate(&amp;quot;pfcColumnCreateOptions&amp;quot;);&lt;br /&gt;    var columnOption = pfcCreate(&amp;quot;pfcColumnCreateOption&amp;quot;);&lt;br /&gt;    var maxOneShotCols = 50; // Most columns that can be created without workaround&lt;br /&gt;&lt;br /&gt;    if (ArrayMaxData.cols &amp;lt; maxOneShotCols) {&lt;br /&gt;        // Number of columns is ok, setup instructions to create table as-is.&lt;br /&gt;        // Use max column widths to auto-size columns&lt;br /&gt;        for (var i=0; i &amp;lt; ArrayMaxData.max_col_width.length; i++ ) {&lt;br /&gt;            var column = columnOption.Create(column_just, ArrayMaxData.max_col_width[i]);&lt;br /&gt;            columnData.Append(column);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;        // Too many columns to create table as-is, setup instructions&lt;br /&gt;        // to create table with one column, expand after creation&lt;br /&gt;        var column = columnOption.Create(column_just, ArrayMaxData.max_col_width[0]);&lt;br /&gt;        columnData.Append(column);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Add column data object to table creation instructions&lt;br /&gt;    instrs.ColumnData = columnData;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Generate row data (for table creation instructions object)&lt;br /&gt;    //   API Bug: Can&#39;t create table with more than 50 rows&lt;br /&gt;    //   Workaround: Create with one row, add more later&lt;br /&gt;    //&lt;br /&gt;&lt;br /&gt;    var rowData = pfcCreate(&amp;quot;realseq&amp;quot;);&lt;br /&gt;    var maxOneShotRows = 50; // Most rows that can be created without workaround&lt;br /&gt;&lt;br /&gt;    if (ArrayMaxData.rows &amp;lt; maxOneShotRows) {&lt;br /&gt;        // Number of rows is ok, setup instructions to create table as-is.&lt;br /&gt;        // Use max row heights to auto-size rows&lt;br /&gt;        for (var i = 0; i &amp;lt; array.length; i++) {&lt;br /&gt;            rowData.Append(ArrayMaxData.max_row_height[i]);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;        // Too many rows to create table as-is, setup instructions&lt;br /&gt;        // to create table with one row, expand after creation&lt;br /&gt;        rowData.Append(ArrayMaxData.max_row_height[0]);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Add row data object to table creation instructions&lt;br /&gt;    instrs.RowHeights = rowData;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Create the table (no contents yet, and won&#39;t be visible yet)&lt;br /&gt;    //&lt;br /&gt;    var dwgTable = null;&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;        dwgTable = drawing.CreateTable(instrs);&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        errmesg.innerHTML += &amp;quot;Cannot create table: &amp;quot; + e.message;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Add rows if data had more than allowed to create in one shot&lt;br /&gt;    //&lt;br /&gt;    try {&lt;br /&gt;        if (ArrayMaxData.rows &amp;gt;= maxOneShotRows) {&lt;br /&gt;            for (var i=1; i &amp;lt; array.length; i++ ) {&lt;br /&gt;                // Add remaining rows needed. Index starts &lt;br /&gt;                //   at 1 because one row already exists&lt;br /&gt;                dwgTable.InsertRow(ArrayMaxData.max_row_height[i], null, false)&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        errmesg.innerHTML += &amp;quot;Cannot add rows: &amp;quot; + e.message;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Add columns if data had more than allowed to create in one shot&lt;br /&gt;    //&lt;br /&gt;    try {&lt;br /&gt;        if (ArrayMaxData.cols &amp;gt;= maxOneShotCols) {&lt;br /&gt;            for (var i=1; i &amp;lt; ArrayMaxData.max_col_width.length; i++ ) {&lt;br /&gt;                // Add remaining columns needed. Index starts &lt;br /&gt;                //   at 1 because one column already exists&lt;br /&gt;                dwgTable.InsertColumn(ArrayMaxData.max_col_width[i], null, false);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        errmesg.innerHTML += &amp;quot;Cannot add columns: &amp;quot; + e.message;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Fill in each cell with data&lt;br /&gt;    //&lt;br /&gt;    for (var i=0; i &amp;lt; array.length; i++ ) {&lt;br /&gt;        for (var j=0; j &amp;lt; array[i].length; j++ ) {&lt;br /&gt;            // Table cell indexes start with one, arrays with zero&lt;br /&gt;            writeTextInCell(dwgTable, i+1, j+1, array[i][j]);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // Display the table&lt;br /&gt;    dwgTable.Display ();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;getMousePickPosition Function&lt;/strong&gt; &lt;br /&gt;&lt;br /&gt;The getMousePickPosition() function is used to prompt the user for a position by using the left mouse button.  It uses the UIGetNextMousePick() method of the pfcSession object to accomplish this.  The function also hides the browser window, displays an alert dialog to prompt the user, and then restores the browser window to its previous size.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function getMousePickPosition ( prompt, hideBrowser ) {&lt;br /&gt;&lt;br /&gt;    var browserSize = null;&lt;br /&gt;    var session = pfcGetProESession();&lt;br /&gt;&lt;br /&gt;    if (hideBrowser) {&lt;br /&gt;        // Minimize browser, remember browser size for later restoration&lt;br /&gt;        browserSize = session.CurrentWindow.GetBrowserSize();&lt;br /&gt;        session.CurrentWindow.SetBrowserSize(0.0);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Prompt user and get user specified location&lt;br /&gt;    alert(prompt);&lt;br /&gt;    var mouseButton = pfcCreate(&amp;quot;pfcMouseButton&amp;quot;);&lt;br /&gt;    var mouseClick = session.UIGetNextMousePick(mouseButton.MOUSE_BTN_LEFT);&lt;br /&gt;&lt;br /&gt;    if (hideBrowser) {&lt;br /&gt;        // Restore browser window&lt;br /&gt;        session.CurrentWindow.SetBrowserSize(browserSize);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return mouseClick.Position;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;getArrayMaxData Function&lt;/strong&gt; &lt;br /&gt;&lt;br /&gt;The getArrayMaxData function analyzes an array and returns an object containing four properties.  Two properties are the number of rows and columns in the array, which is expected to be two dimensional.  The other two properties are maximum column widths for each column and maximum row heights for each row.&lt;br /&gt;&lt;br /&gt;If a row in excel contains a cell with a single linefeed character, that row will have a maximum row height of at least two characters.  Similarly, if a column contains a cell with 50 characters, the maximum column width for that column will be at least 50 characters.&lt;br /&gt;&lt;br /&gt;Once these values are populated, the object is returned to the calling function.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function getArrayMaxData ( array ) {&lt;br /&gt;&lt;br /&gt;    var obj = new Object();&lt;br /&gt;&lt;br /&gt;    // Figure out max size for each row and column to auto-expand&lt;br /&gt;    //&lt;br /&gt;    obj.max_col_width = new Array();&lt;br /&gt;    obj.max_row_height = new Array();&lt;br /&gt;&lt;br /&gt;    for (var i=0; i &amp;lt; array.length; i++ ) {&lt;br /&gt;        obj.max_row_height[i] = 0;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    for (var i=0; i &amp;lt; array[0].length; i++ ) {&lt;br /&gt;        obj.max_col_width[i] = 0;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    obj.rows = array.length;&lt;br /&gt;    obj.cols = 0;&lt;br /&gt;&lt;br /&gt;    // populate arrays of max column widths and max row heights&lt;br /&gt;    //&lt;br /&gt;    for (var i=0; i &amp;lt; array.length; i++) {&lt;br /&gt;&lt;br /&gt;        for (var j=0; j &amp;lt; array[i].length; j++) {&lt;br /&gt;&lt;br /&gt;            if (obj.cols &amp;lt; array[i].length) { obj.cols = array[i].length; }&lt;br /&gt;&lt;br /&gt;            var lines = array[i][j].split(&amp;quot;\n&amp;quot;);&lt;br /&gt;&lt;br /&gt;            if (lines.length &amp;gt; obj.max_row_height[i]) {&lt;br /&gt;                obj.max_row_height[i] = lines.length;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            for (var k=0; k &amp;lt; lines.length; k++ ) {&lt;br /&gt;                if (lines[k].length &amp;gt; obj.max_col_width[j]) {&lt;br /&gt;                    obj.max_col_width[j] = lines[k].length;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return obj;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;writeTextInCell Function&lt;/strong&gt; &lt;br /&gt;&lt;br /&gt;The writeTextInCell() function writes text to a specific table cell.  If the cell data in Excel contains linefeeds, the result will be a table cell that matches with the same number of lines of text.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function writeTextInCell ( table, row, col, text ) {&lt;br /&gt;&lt;br /&gt;    var cell = pfcCreate(&amp;quot;pfcTableCell&amp;quot;).Create(row, col);&lt;br /&gt;    var lines = pfcCreate(&amp;quot;stringseq&amp;quot;);&lt;br /&gt;&lt;br /&gt;    var cell_lines = text.split(&amp;quot;\n&amp;quot;);&lt;br /&gt;&lt;br /&gt;    for (var i=0; i &amp;lt; cell_lines.length; i++ ) {&lt;br /&gt;        lines.Append(cell_lines[i]);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    table.SetText(cell, lines);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There may be strange issues if &quot;zombie&quot; or multiple Excel sessions are running.  If Excel is clearly running, but unexpected error messages are received, it may be best to kill all Excel sessions, then start it over again.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/06/weblink-excel-to-proe-drw-tables-part-2.html&quot;&gt;Part 2: Sending drawing table data to Excel&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/06/weblink-excel-to-proe-drw-tables-part-1.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>23</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-3818267266774380948</guid><pubDate>Wed, 28 May 2008 10:17:00 +0000</pubDate><atom:updated>2008-05-28T03:40:06.466-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">Trail Files</category><title>Pro/ENGINEER: Anatomy of a Trail File, Part 2</title><description>&lt;em&gt;Read &lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/05/proe-anatomy-of-trail-file-part-1.html&quot;&gt;Part 1&lt;/a&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Recording/Editing Techniques&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Trail files are often touted as a crash recovery mechanism.  While they can serve this function in very limited circumstances, they are usually not that helpful for this activity.  For repetitive tasks, however, trail files are extraordinarily helpful.&lt;br /&gt;&lt;br /&gt;To make them extraordinarily helpful, trail files must be recorded and edited very carefully.  Right out of the box, Pro/ENGINEER doesn&#39;t record very efficient trail files.  They will function, but can be excessively verbose and difficult to edit.&lt;br /&gt;&lt;br /&gt;Here is an example of a trail file segment that opens a part file.  It&#39;s a good example of how not to record trail files.  Generally speaking, avoid typing in names when you can select them.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Select `main_dlg_cur` `MenuBar1` \&lt;br /&gt;1  `File`&lt;br /&gt;~ Close `main_dlg_cur` `MenuBar1`&lt;br /&gt;~ Activate `main_dlg_cur` `File.psh_open`&lt;br /&gt;&amp;lt; 2 0.256000&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `a`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `ab`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `abc`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `abc.`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `abc.p`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `abc.pr`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `abc.prt`&lt;br /&gt;~ Update `file_open` `Inputname` \&lt;br /&gt; `abc.prt`&lt;br /&gt;~ Activate `file_open` `Inputname`&lt;br /&gt;!Command ProCmdModelOpenExe was pushed from the software.&lt;br /&gt;!15-May-08 17:39:09  Start ./abc.prt.2&lt;br /&gt;!15-May-08 17:39:11  End   ./abc.prt.2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;Compare this against a trail recorded by selecting (not typing) the name of the model to open, and using the config.pro option CMDMGR_TRAIL_OUTPUT set to YES.  This option is meant to simplify trail file output and make the menu picks less dependent on the menus.  If Tools / Customize Screen is used to move menus around, this mapkey will continue to work, but the previous one might fail.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Command `ProCmdModelOpen` &lt;br /&gt;&amp;lt; 2 0.256000&lt;br /&gt;~ Select `file_open` `Ph_list.Filelist` \&lt;br /&gt;1  `abc.prt`&lt;br /&gt;~ Activate `file_open` `Open`&lt;br /&gt;!Command ProCmdModelOpenExe was pushed from the software.&lt;br /&gt;!15-May-08 17:36:11  Start ./abc.prt.2&lt;br /&gt;!15-May-08 17:36:16  End   ./abc.prt.2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;As you can see the results are much simpler.  In fact, following the rules from Part 1, four of the eight lines can additionally be reduced:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Command `ProCmdModelOpen` &lt;br /&gt;~ Select `file_open` `Ph_list.Filelist` \&lt;br /&gt;1  `abc.prt`&lt;br /&gt;~ Activate `file_open` `Open`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;There will be times when you need to automate something using an existing trail file but you either don&#39;t have the luxury or the desire to re-record the trail file.  In this case you want to eliminate the fluff, but keep the necessary elements.  From the verbosely recorded sequence, the following can be completely eliminated:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `a`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `ab`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `abc`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `abc.`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `abc.p`&lt;br /&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `abc.pr`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Of the remaining lines, the first two can typically be eliminated.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Input `file_open` `Inputname` \&lt;br /&gt; `abc.prt`&lt;br /&gt;~ Update `file_open` `Inputname` \&lt;br /&gt; `abc.prt`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Which leaves this as a result:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Update `file_open` `Inputname` \&lt;br /&gt; `abc.prt`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;When you are replaying a trail file without changing the model used (i.e. for running a benchmark), a lot of these edits are not required.  When you are using the trail file as a template for different models, these type of edits are very important, making it much easier to adapt the trail file.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Next time:&lt;/strong&gt; &lt;em&gt;Robust selection techniques with trail files&lt;/em&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/05/proe-anatomy-of-trail-file-part-2.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-1235873731117095788</guid><pubDate>Thu, 22 May 2008 10:20:00 +0000</pubDate><atom:updated>2008-05-22T03:47:22.477-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">WebLink</category><title>Pro/WebLink: Changing Model Relations Quickly with Wildfire 4</title><description>Changing relations is often a frustratingly difficult task to perform in a Pro/ENGINEER model. This is especially true for assemblies, even ones with only a few dozen parts.&lt;br /&gt;&lt;br /&gt;Up until Wildfire 4, there were many ways to accomplish this involving some kind of file export/import process. These include mapkeys, J-Link, and Pro/WebLink, each having its own complications.&lt;br /&gt;&lt;br /&gt;Starting with Wildfire 4, the PFC API&#39;s (Pro/WebLink, J-Link, VB API) have been enhanced to allow more direct access to relations. Relations can be read into a string sequence (a form of dynamic array), modified within the sequence, then re-applied to the model very quickly. This makes programmatic editing of relations very simple, fast, and easy.&lt;br /&gt;&lt;br /&gt;While using the PFC API&#39;s to perform this action on a single part model may seem overkill compared to using mapkeys, consider that mapkeys don&#39;t scale well. If you&#39;re doing a one-off task, mapkeys work great. When you need to perform the task for all components of an assembly, whether large or small, the API&#39;s can accomplish the task much more quickly and reliably. For assemblies with thousands of components, mapkeys just won&#39;t get the job done.&lt;br /&gt;&lt;br /&gt;What follows is an example of a Pro/WebLink function to add relations to a model from an array. First, existing relations are obtained from the model using the &quot;Relations&quot; property (a stringseq object), then elements of the array are appended to the stringseq using the Append() method. Finally, the modified stringseq is reassociated to the model. The change is immediate and does not require a regeneration.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function addRelations ( model, array ) {&lt;br /&gt;&lt;br /&gt;    // get relations as stringseq object&lt;br /&gt;    var rel_seq = model.Relations;&lt;br /&gt;&lt;br /&gt;    // append array elements to stringseq&lt;br /&gt;    for (var i=0; i&amp;lt;array.length; i++) {&lt;br /&gt;        rel_seq.Append(array[i]);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // assign modified stringseq to model relations&lt;br /&gt;    model.Relations = rel_seq;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;Code to call the function is also pretty basic. Using the CurrentModel property of the session object, the model object can is obtained. Here an array is defined, but even better would be to pull the values from an HTML TextArea or some other data source. Lastly, the addRelations() function is called with the model object and the relations array.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;// get current model&lt;br /&gt;var session = pfcGetProESession();&lt;br /&gt;var model = session.CurrentModel;&lt;br /&gt;&lt;br /&gt;// define new relations as array&lt;br /&gt;var array = new Array( &quot;abc=123&quot;, &quot;def=456&quot; );&lt;br /&gt;&lt;br /&gt;// add relations&lt;br /&gt;addRelations(model, array);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;A recursive procedure to apply relations to assembly components is only moderately more complicated. See my other examples only how to rcursively process assembly components with Pro/WebLink.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/04/weblink-sending-data-from-proengineer.html&quot;&gt;Sending Data from Pro/ENGINEER to Microsoft Excel with JavaScript&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/04/weblink-send-proe-pnt-data-to-excel.html&quot;&gt;Sending Pro/ENGINEER Point Data to Excel&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/04/proweblink-sending-your-proengineer.html&quot;&gt;Sending Your Pro/ENGINEER Assembly BOM to Excel&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Comments and questions are always welcome, either here on my blog or via email at &lt;a href=&quot;mailto:MarcMettes@InversionConsulting.com&quot;&gt;MarcMettes@InversionConsulting.com&lt;/a&gt;. &lt;p&gt;&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/05/weblink-edit-relations-proe-wildfire4.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>3</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-5995022280652811998</guid><pubDate>Tue, 20 May 2008 10:00:00 +0000</pubDate><atom:updated>2008-05-28T03:39:46.926-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">Trail Files</category><title>Pro/ENGINEER: Anatomy of a Trail File, Part 1</title><description>&lt;strong&gt;Trail File Basics&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Despite a diverse set of API&#39;s, Pro/ENGINEER trail files represent a reliable and robust method of automating Pro/ENGINEER activities.  They are not the perfect fit for every application, but for many needs they work great.&lt;br /&gt;&lt;br /&gt;Trail files are best used after recording specific actions, then combining the resulting content to create the finished trail file.  In order to edit trail files it is important to understand their content.&lt;br /&gt;&lt;br /&gt;Here is an example of a trail file header.  These entries are generated by Pro/E upon startup without any action from the user.  The first line is always present and always required in your trail files.  Some other lines that stand out indicate that Wildfire 2 was used and the ProE to JT Translator is started via a protk.dat file.  Both of these are status messages and are not required.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;!trail file version No. 1301&lt;br /&gt;!Pro/ENGINEER  TM  Wildfire 2.0  (c) 2004 by Parametric Technology Corporation  All Rights Reserved.&lt;br /&gt;&amp;lt; 0 1.135407&lt;br /&gt;&amp;lt; 0 0.964741&lt;br /&gt;&amp;lt; 0 0.879000&lt;br /&gt;&amp;lt; 0 0.842000&lt;br /&gt;!Application (VisProducts): started via registry.&lt;br /&gt;!    exec path: /opt/UGS_JtTranslators/ProE/EAI_Proe/proe/sun/proclientWF2&lt;br /&gt;!    type: synchronous Pro/TOOLKIT EXE&lt;br /&gt;&amp;lt; 0 0.846000&lt;br /&gt;~ Move `splash_dlg` `splash_dlg` \&lt;br /&gt;2 7.472141 6.432063&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp; &lt;br /&gt;&lt;br /&gt;I have never needed to keep lines that start with the &#39;less than&#39; symbol and typically always remove them if piecing together a trail file:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;&amp;lt; 0 1.135407&lt;br /&gt;&amp;lt; 0 0.964741&lt;br /&gt;&amp;lt; 0 0.879000&lt;br /&gt;&amp;lt; 0 0.842000&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;As the lines relative to the &#39;splash_dlg&#39; are unnecessary, all that is needed from the above is this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;!trail file version No. 1301&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Although we don&#39;t need the lines associated with the &#39;splash_dlg&#39;, the syntax is important to understand as it is used throughout trail files.  The trail file &#39;interpreter&#39; sees the backslash continuation character (\) as an instruction to treat the following as a single line:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;~ Move `splash_dlg` `splash_dlg` \&lt;br /&gt;2 7.472141 6.432063&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;If the entry is to be removed, both lines should be removed, or the trail file will not work.  Don&#39;t try to combine the lines.  That won&#39;t work either.  If you need the entry, leave it as is.  The interpreter can handle it, and you shouldn&#39;t worry about it consuming more than one line.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Another note in the JT Translator startup messages is that they start with an exclamation point.  This is the &#39;comment&#39; indicator, instructing the interpreter to ignore the line.  All lines starting with an exclamation point are not needed and can be removed, if desired.  In some cases, I&#39;ll leave a comment in place to help identify the end of an action, but typically they are removed.&lt;br /&gt;&lt;br /&gt;To assist in editing trail files, I usually add comment lines before and after sections.  This makes it very easy to copy or move sections within the file.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;!!!&lt;br /&gt;!!! Run massprop calculation&lt;br /&gt;!!!&lt;br /&gt;~ Select `main_dlg_cur` `MenuBar1` \&lt;br /&gt;1  `Analysis`&lt;br /&gt;~ Close `main_dlg_cur` `MenuBar1`&lt;br /&gt;~ Activate `main_dlg_cur` `Analysis.psh_analysis_modelanl`&lt;br /&gt;~ Activate `modelprop` `Compute`&lt;br /&gt;!%CIMass Properties calculation completed.&lt;br /&gt;~ Activate `modelprop` `Close`&lt;br /&gt;!!!&lt;br /&gt;!!! Exit session&lt;br /&gt;!!!&lt;br /&gt;~ Select `main_dlg_cur` `MenuBar1` \&lt;br /&gt;1  `File`&lt;br /&gt;~ Close `main_dlg_cur` `MenuBar1`&lt;br /&gt;~ Activate `main_dlg_cur` `File.psh_exit`&lt;br /&gt;! Message Dialog: Warning&lt;br /&gt;!               : Do you really want to exit?&lt;br /&gt;~ Move `UI Message Dialog` `UI Message Dialog` \&lt;br /&gt;2 14.561095 12.836755 &lt;br /&gt;~ FocusIn `UI Message Dialog` `no`&lt;br /&gt;~ FocusIn `UI Message Dialog` `yes`&lt;br /&gt;~ Activate `UI Message Dialog` `yes`&lt;br /&gt;!End of Trail File&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/05/proe-anatomy-of-trail-file-part-2.html&quot;&gt;&lt;strong&gt;Part 2:&lt;/strong&gt; &lt;em&gt;Recording robust trail files&lt;/em&gt;&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/05/proe-anatomy-of-trail-file-part-1.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-850488150786397422</guid><pubDate>Thu, 01 May 2008 10:43:00 +0000</pubDate><atom:updated>2009-06-05T04:01:45.956-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">Pro/Toolkit</category><category domain="http://www.blogger.com/atom/ns#">protk.dat</category><title>Pro/Toolkit: Simplifying Your protk.dat File with Environment Variables</title><description>If you find yourself editing your protk.dat files because you are changing the location of the application or you are using multiple hardware architectures (i.e. Unix and Windows, Win32 and Win64, etc), STOP!  Put down the mouse, and slowly step away from the keyboard.&lt;br /&gt;&lt;br /&gt;If you use environment variable creatively, you will need one protk.dat file for all of your installations.  That&#39;s it, just one.  Unix and Windows you ask?  YES!  32 bit and 64 bit Windows?  YES!&lt;br /&gt;&lt;br /&gt;The first thing you need to do is to setup an environment variable  for the install folder of your application.  Call it what you want, but be consistent.  I am going to give examples here about the open source Pro/ENGINEER to BRL CAD converter.  I&#39;ll use the environment variable PROE2BRL_INSTALL for the install folder.&lt;br /&gt;&lt;br /&gt;The resulting protk.dat file looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;name PROE2BRL&lt;br /&gt;startup dll&lt;br /&gt;exec_file $PROE2BRL_INSTALL/proe2brl.dll&lt;br /&gt;text_dir $PROE2BRL_INSTALL/text&lt;br /&gt;allow_stop TRUE&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;I know what you&#39;re thinking, you think you&#39;ll have to change those paths for Windows machines.  WRONG!  It&#39;s a little known secret that Pro/ENGINEER on Windows can handle unix style pathing and environment variable syntax, and not just in protk.dat files.  This includes the config.pro file.  It may seem strange to those die-hard Windows guys, but it works.&lt;br /&gt;&lt;br /&gt;Now the 64 bit Windows guy in the audience (I&#39;ll call him Dustin), shouts out &quot;What if we have 32 bit and 64 bit DLL&#39;s?!&quot;  Well Dustin, no problem there either because Pro/ENGINEER sets some platform specific environment variables that we can use.&lt;br /&gt;&lt;br /&gt;We can separate the 32 bit and 64 bit DLL&#39;s into two folders.  For Windows, this would be &quot;i486_nt&quot; for 32 bit DLL&#39;s and &quot;x86e_win64&quot; for 64 bit DLL&#39;s.  If we plug in the MC environment variable, Pro/ENGINEER uses the correct DLL based on the current architecture.&lt;br /&gt;&lt;br /&gt;The resulting protk.dat file looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;name PROE2BRL&lt;br /&gt;startup dll&lt;br /&gt;exec_file $PROE2BRL_INSTALL/$mc/proe2brl.dll&lt;br /&gt;text_dir $PROE2BRL_INSTALL/text&lt;br /&gt;allow_stop TRUE&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;Now the Unix guys, bored with talk of mere a 32 bit application, rant &quot;On Unix, our DLL&#39;s are called shared objects and have a .so extension and ... blah blah blah ...&quot;.  Again, not a problem.  If that&#39;s a concern, setup another environment variable, let&#39;s call it PROE2BRL_EXEC.  On Unix this can be set to &quot;proe2brl.so&quot; and on Windows &quot;proe2brl.dll&quot;.  (Or, just call it &quot;proe2brl.dll&quot; and skip this step)&lt;br /&gt;&lt;br /&gt;The resulting protk.dat file looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;name PROE2BRL&lt;br /&gt;startup dll&lt;br /&gt;exec_file $PROE2BRL_INSTALL/$mc/$PROE2BRL_EXEC&lt;br /&gt;text_dir $PROE2BRL_INSTALL/text&lt;br /&gt;allow_stop TRUE&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;In the config.pro, we can use this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;protkdat $PROE2BRL_INSTALL/protk.dat&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;These techniques get us much closer to the mythical &quot;one install&quot; for all platforms.  Also be sure to check out &lt;a href=&quot;http://inversionconsulting.blogspot.com/2008/03/conditional-loading-of-protoolkit.html&quot;&gt;my previous article&lt;/a&gt; on how to conditionally load your Pro/Toollkit applications.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Questions and comments are always welcome, either here on my blog or at  &lt;a href=&quot;mailto:MarcMettes@InversionConsulting.com&quot;&gt;MarcMettes@InversionConsulting.com&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/05/protk-simplify-protkdat-with-env-vars.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-3420454011291932242</guid><pubDate>Wed, 30 Apr 2008 00:38:00 +0000</pubDate><atom:updated>2008-04-29T17:50:53.472-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Excel</category><category domain="http://www.blogger.com/atom/ns#">Pro/ENGINEER</category><category domain="http://www.blogger.com/atom/ns#">WebLink</category><title>WebLink: Sending Pro/ENGINEER Point Data to Excel</title><description>Extracting point data from your Pro/ENGINEER models can be a cumbersome task, especially if you follow the suggested PTC export/import process.  This can be streamlined significantly using Pro/WebLink, but also with J-Link and Pro/Toolkit.&lt;br /&gt;&lt;br /&gt;I&#39;ve discussed, in previous articles, obtaining lists of features and recursing through assemblies.  What&#39;s different here is that a transformation matrix will be used to obtain the XYZ position of the point with respect to the default coordinate system of the assembly.  This is the position data that will be output to Excel.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The HTML page has a single button, which initiates the point data extraction, and a single div field for some results.  Library files pfcUtils.js and pnts2excel.js contain Javascript code.  pfcUtils.js is a utility library provided by PTC.  The code discuss in this article would be contained in the pnts2excel.js file.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;&amp;lt;HTML&amp;gt;&lt;br /&gt;&amp;lt;SCRIPT LANGUAGE=&amp;quot;JavaScript&amp;quot; type=text/javascript src=&amp;quot;pfcUtils.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&lt;br /&gt;&amp;lt;SCRIPT LANGUAGE=&amp;quot;JavaScript&amp;quot; type=text/javascript src=&amp;quot;pnts2excel.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&lt;br /&gt;&amp;lt;BODY&amp;gt;&lt;br /&gt;&amp;lt;form name=&amp;quot;f&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;INPUT name=&amp;quot;a&amp;quot; type=button value=&amp;quot;Get Point Data!&amp;quot; onclick=&amp;quot;GetPoints()&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;br&amp;gt;&amp;lt;div id=&amp;quot;mesg&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/BODY&amp;gt;&lt;br /&gt;&amp;lt;/HTML&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;After the GetPoints() function has obtained the session object and verified that a model is active, it sets up an object used for some persistent data and for returning an array of points.&lt;br /&gt;&lt;br /&gt;The object has the following properties: modelsFound (array), points (array), root (top-level model object), comppath_seq (intseq object) and transform (assembly tranformation matrix).  GetPointData() is called using the current model and appdata object to obtain the point data.  Then PntArrayToExcel() is used to send the data to Excel.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function GetPoints () {&lt;br /&gt;&lt;br /&gt;    if (!pfcIsWindows())&lt;br /&gt;        netscape.security.PrivilegeManager.enablePrivilege(&amp;quot;UniversalXPConnect&amp;quot;);&lt;br /&gt;&lt;br /&gt;    var elem = document.getElementById(&amp;quot;mesg&amp;quot;);&lt;br /&gt;&lt;br /&gt;    var modelname = &amp;quot;no model&amp;quot;;&lt;br /&gt;    var session = null;&lt;br /&gt;    var model = null;&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;        session = pfcGetProESession();&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        elem.innerHTML = &amp;quot;ERROR: Cannot connect to Pro/Engineer session!&amp;quot;;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;        model = session.CurrentModel;&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        // probably no model&lt;br /&gt;        elem.innerHTML = &amp;quot;Problem getting current model info.&amp;quot;;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    elem.innerHTML = &amp;quot;&amp;lt;br&amp;gt;&amp;quot; + &amp;quot;Top Level Model: &amp;quot; + model.FileName;&lt;br /&gt;&lt;br /&gt;    // Create appdata object&lt;br /&gt;    //&lt;br /&gt;    var appdata = new Object();&lt;br /&gt;    appdata.modelsFound = new Array();&lt;br /&gt;    appdata.points = new Array();&lt;br /&gt;    appdata.root = model;&lt;br /&gt;    appdata.comppath_seq = new pfcCreate(&amp;quot;intseq&amp;quot;); // need &#39;new&#39;, this is an instance object&lt;br /&gt;    appdata.transform = null;&lt;br /&gt;&lt;br /&gt;    GetPointData(model, appdata);&lt;br /&gt;    PntArrayToExcel(appdata.points);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;There are two main actions in the GetPointData() function: point extraction, and recursing (for subassemblies).  The modelsFound array is used in both actions, and helps to avoid extracting data from a model more than once.  In the assignment statement, it is flagging the currently encountered model as having been processed, so that it will not get processed again.&lt;br /&gt;&lt;br /&gt;After that, a sequence of points is obtained using the current model and the ListItem() method specifying ITEM_POINT.  This will return all points in the model, not just a single feature, which is important if point array features are present in the model.  Using the &#39;Point&#39; property of the point, we can get a Point3D object which has the XYZ info.  If there is a transform matrix available, it is applied to the point data first.  The model name and XYZ data of the point are assigned to an object, which is then push into the &#39;points&#39; array property of the appdata object.&lt;br /&gt;&lt;br /&gt;In the recursing action, if the encountered model is a subassembly, the code iterates over the component features, if any.  If the component is active, the feature id is appended to the comppath_seq sequence, which is used to get the model object from the feature object and the transformation matrix from the root assembly&#39;s default coordinate system.  The matrix is saved into the appdata object.&lt;br /&gt;&lt;br /&gt;If the component has not been encountered already, GetPointData() is called recursively with the component model info.  After the function returns, the last element of the comppath_seq is removed.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function GetPointData ( model, appdata ) {&lt;br /&gt;&lt;br /&gt;    var elem = document.getElementById(&amp;quot;mesg&amp;quot;);&lt;br /&gt;    appdata.modelsFound[model.FileName] = 1;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;    // Get points in current model&lt;br /&gt;    //&lt;br /&gt;    var points = model.ListItems( pfcCreate(&amp;quot;pfcModelItemType&amp;quot;).ITEM_POINT );&lt;br /&gt;  &lt;br /&gt;    for (var i = 0; i &amp;lt; points.Count; i++) {&lt;br /&gt;        var point = points.Item(i);&lt;br /&gt;        var pnt3d = null;&lt;br /&gt;  &lt;br /&gt;        if (appdata.transform == null) {&lt;br /&gt;            pnt3d = point.Point;&lt;br /&gt;        }&lt;br /&gt;        else {&lt;br /&gt;            pnt3d = appdata.transform.TransformPoint(point.Point);&lt;br /&gt;        }&lt;br /&gt;  &lt;br /&gt;        // send pnt data to the browser&lt;br /&gt;        elem.innerHTML += &amp;quot;&amp;lt;br&amp;gt; &amp;quot; + model.FileName + &amp;quot;: &amp;quot;&lt;br /&gt;                          + point.GetName() + &amp;quot; (Id &amp;quot; + point.Id + &amp;quot;)&amp;quot;&lt;br /&gt;                          + &amp;quot;, XYZ= ( &amp;quot;&lt;br /&gt;                                    + pnt3d.Item(0) + &amp;quot;, &amp;quot;&lt;br /&gt;                                    + pnt3d.Item(1) + &amp;quot;, &amp;quot;&lt;br /&gt;                                    + pnt3d.Item(2) + &amp;quot; )&amp;quot;&lt;br /&gt;                          ;&lt;br /&gt;  &lt;br /&gt;        var object = new Object();&lt;br /&gt;        object.Owner = model;&lt;br /&gt;        object.Point = pnt3d;&lt;br /&gt;  &lt;br /&gt;        appdata.points.push(object);&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;    // Recurse into components, if model is an assembly&lt;br /&gt;    //&lt;br /&gt;    if ( model.Type == pfcCreate(&amp;quot;pfcModelType&amp;quot;).MDL_ASSEMBLY ) {&lt;br /&gt;  &lt;br /&gt;        var components = model.ListFeaturesByType( false, pfcCreate(&amp;quot;pfcFeatureType&amp;quot;).FEATTYPE_COMPONENT );&lt;br /&gt;  &lt;br /&gt;        for (var i = 0; i &amp;lt; components.Count; i++) {&lt;br /&gt;  &lt;br /&gt;            var compFeat = components.Item(i);&lt;br /&gt;  &lt;br /&gt;            if (compFeat.Status != pfcCreate(&amp;quot;pfcFeatureStatus&amp;quot;).FEAT_ACTIVE) {&lt;br /&gt;                continue;&lt;br /&gt;            }&lt;br /&gt;  &lt;br /&gt;            // Append id for use in building comppath&lt;br /&gt;            appdata.comppath_seq.Append(compFeat.Id);&lt;br /&gt;  &lt;br /&gt;            try {&lt;br /&gt;                // Create ComponentPath object to get pfcModel object of component and transform&lt;br /&gt;                var cp = pfcCreate(&amp;quot;MpfcAssembly&amp;quot;).CreateComponentPath( appdata.root, appdata.comppath_seq );&lt;br /&gt;                var compMdl = cp.Leaf;&lt;br /&gt;                appdata.transform = cp.GetTransform(true);&lt;br /&gt;            } catch (e) {&lt;br /&gt;                elem.innerHTML += &amp;quot;&amp;lt;br&amp;gt; CreateComponentPath() exception: &amp;quot; + pfcGetExceptionType(e);&lt;br /&gt;            }&lt;br /&gt;  &lt;br /&gt;            // Descend into subassembly&lt;br /&gt;            if ( !(compMdl.FileName in appdata.modelsFound) ) {&lt;br /&gt;                GetPointData(compMdl, appdata);&lt;br /&gt;            }&lt;br /&gt;  &lt;br /&gt;            // Remove id (last in seq), not needed anymore&lt;br /&gt;            try {&lt;br /&gt;                appdata.comppath_seq.Remove( (appdata.comppath_seq.Count-1), (appdata.comppath_seq.Count) );&lt;br /&gt;            } catch (e) {&lt;br /&gt;                elem.innerHTML += &amp;quot;&amp;lt;br&amp;gt; comppath_seq.Remove exception: &amp;quot; + pfcGetExceptionType(e);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        } // Loop: components&lt;br /&gt;  &lt;br /&gt;    } // model.Type&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;The PntArrayToExcel() function sends the data to Excel.  The code first tries to use an existing Excel session, but will start a new one if necessary.  Certain IE security settings may result in a new session being started every time.&lt;br /&gt;&lt;br /&gt;Once an Excel session is available and a new workbook has been created, the code iterates over the &#39;points&#39; array property of the appdata object to write the data into the active sheet.  Four columns are used in the output, which include the model name, X position, Y position, and Z position.  Since a particular coordinate system was not referenced, the default coordinate system of the top-level assembly is used.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;function PntArrayToExcel ( array ) {&lt;br /&gt;&lt;br /&gt;    var oXL;&lt;br /&gt;    var elem = document.getElementById(&amp;quot;mesg&amp;quot;);&lt;br /&gt;&lt;br /&gt;    // Get/Create Excel Object Reference&lt;br /&gt;    try {&lt;br /&gt;        oXL = GetObject(&amp;quot;&amp;quot;,&amp;quot;Excel.Application&amp;quot;); // Use current Excel session&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        // couldn&#39;t get an excel session, try starting a new one&lt;br /&gt;        try {&lt;br /&gt;            oXL = new ActiveXObject(&amp;quot;Excel.Application&amp;quot;); // Open new Excel session&lt;br /&gt;        }&lt;br /&gt;        catch (e) {&lt;br /&gt;            // couldn&#39;t start a new excel session either&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (oXL == null) {&lt;br /&gt;        elem.innerHTML = &amp;quot;Could not get or start Excel session!&amp;quot;;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;        oXL.Visible = true;&lt;br /&gt;        var oWB = oXL.Workbooks.Add();&lt;br /&gt;        var oSheet = oWB.ActiveSheet;&lt;br /&gt;    }&lt;br /&gt;    catch (e) {&lt;br /&gt;        elem.innerHTML = &amp;quot;Problem creating new workbook.&amp;quot;;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    for (var i=0; i &amp;lt; array.length; i++ ) {&lt;br /&gt;        var pnt3d = array[i].Point;&lt;br /&gt;        var ownerMdl = array[i].Owner;&lt;br /&gt;&lt;br /&gt;        oSheet.Cells(i+1, 1).Value = ownerMdl.FileName;&lt;br /&gt;        oSheet.Cells(i+1, 2).Value = &amp;quot;&amp;quot; + pnt3d.Item(0);&lt;br /&gt;        oSheet.Cells(i+1, 3).Value = &amp;quot;&amp;quot; + pnt3d.Item(1);&lt;br /&gt;        oSheet.Cells(i+1, 4).Value = &amp;quot;&amp;quot; + pnt3d.Item(2);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Other than the transformation matrix, the code is pretty straightforward and easily adaptable to other data sets (i.e. parameters, layers, feature lists, etc).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Questions and comments are always welcome, either here on my blog or at  &lt;a href=&quot;mailto:MarcMettes@InversionConsulting.com&quot;&gt;MarcMettes@InversionConsulting.com&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/04/weblink-send-proe-pnt-data-to-excel.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>5</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8764109705492068977.post-8094860699305242091</guid><pubDate>Tue, 29 Apr 2008 03:46:00 +0000</pubDate><atom:updated>2008-06-10T09:58:10.218-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Intralink</category><category domain="http://www.blogger.com/atom/ns#">Intralink Scripting</category><category domain="http://www.blogger.com/atom/ns#">J-Link</category><category domain="http://www.blogger.com/atom/ns#">Java</category><title>J-Link: Compile Your Pro/ENGINEER Java Application with Intralink!</title><description>If you&#39;ve wanted to try some Pro/ENGINEER programming using J-Link (the free Java API), but didn&#39;t know how to compile your program, then this article is for you.  Forget Netbeans, forget Eclipse, and forget downloading and installing the JDK.  Just use Intralink&#39;s Java Runtime Environment to compile your apps.&lt;br /&gt;&lt;br /&gt;Seriously though, those IDE&#39;s are really great programs, but sometimes you can&#39;t install them, or they&#39;re not available on your system, or you just need something minimal and fast.  Fortunately, Intralink contains everything we need to compile J-Link applications: a JRE and tools.jar.  tools.jar is the codebase from Javasoft that contains Java compilation code.&lt;br /&gt;&lt;br /&gt;Here is a batch file that will compile J-Link Java code on Windows:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;@echo off&lt;br /&gt;rem jlink_javac.bat - Compile JLink Apps using Intralink JDK&lt;br /&gt;&lt;br /&gt;set Proe_Install_Dir=c:\ptc\proeWildfire2.0_m200&lt;br /&gt;set IL_Install_Dir=c:\ptc\proiclient3.3_m021&lt;br /&gt;set CLASSPATH=%IL_Install_Dir%\i486_nt\lib\tools.jar&lt;br /&gt;set path=%IL_Install_Dir%\i486_nt\jre\bin;%path%&lt;br /&gt;&lt;br /&gt;java sun.tools.javac.Main -classpath %Proe_Install_Dir%\text\java\pfc.jar -d . %*&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;Run it like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;jlink_javac.bat Abc.java Def.java Ghi.java&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;Here is a C shell script that will compile J-Link Java code on Unix:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;#!/bin/csh&lt;br /&gt;# jlink_javac.csh - Compile JLink Apps using Intralink JDK&lt;br /&gt;&lt;br /&gt;setenv Proe_Install_Dir /opt/proeWildfire2.0_m200&lt;br /&gt;setenv IL_Install_Dir /opt/proiclient3.3_m021&lt;br /&gt;setenv CLASSPATH $IL_Install_Dir/sun4_solaris/lib/tools.jar&lt;br /&gt;set path=( $IL_Install_Dir/sun4_solaris/jre/bin $path )&lt;br /&gt;&lt;br /&gt;java sun.tools.javac.Main -classpath $Proe_Install_Dir/text/java/pfc.jar -d . $*&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;Run it like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;&lt;code&gt;jlink_javac.csh Abc.java Def.java Ghi.java&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &amp;nbsp;&lt;br /&gt;&lt;br /&gt;The resulting class files will be in the current directory.  While I do use this for my own J-Link code which is typically targeted at Java 1.4.2, it may not work with newer Java versions, nor take advantage of their full capabilities.  However, for you command line junkies out there, this is just the recipe.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
google_ad_client = &quot;pub-9808432778316631&quot;;
/* 728x90, created 4/16/08, feed */
google_ad_slot = &quot;1630634568&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;
src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;
&lt;/script&gt;
&lt;!-- START CUSTOM WIDGETBUCKS CODE --&gt;&lt;div&gt;&lt;script src=&quot;http://api.widgetbucks.com/script/ads.js?uid=Eo3fa8SOWCVfxwYX&quot;&gt;&lt;/script&gt;&lt;/div&gt;&lt;!-- END CUSTOM WIDGETBUCKS CODE --&gt;&lt;/div&gt;</description><link>http://inversionconsulting.blogspot.com/2008/04/jlink-compile-proe-app-with-ilink.html</link><author>noreply@blogger.com (Marc Mettes)</author><thr:total>2</thr:total></item></channel></rss>